Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
ParadoxClassInstanciator.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 
7 using SiliconStudio.Paradox.Shaders.Parser.Ast;
8 using SiliconStudio.Paradox.Shaders.Parser.Utility;
9 using SiliconStudio.Shaders.Ast;
10 using SiliconStudio.Shaders.Ast.Hlsl;
11 using SiliconStudio.Shaders.Utility;
12 using SiliconStudio.Shaders.Visitor;
13 
15 
16 namespace SiliconStudio.Paradox.Shaders.Parser.Mixins
17 {
18  internal class ParadoxClassInstanciator : ShaderVisitor
19  {
20  private ShaderClassType shaderClassType;
21 
22  private LoggerResult logger;
23 
24  private Dictionary<string, Variable> variableGenerics;
25 
26  private Dictionary<string, Expression> expressionGenerics;
27 
28  private Dictionary<string, Identifier> identifiersGenerics;
29 
30  private Dictionary<string, string> stringGenerics;
31 
32  private ParadoxClassInstanciator(ShaderClassType classType, Dictionary<string, Expression> expressions, Dictionary<string, Identifier> identifiers, LoggerResult log)
33  : base(false, false)
34  {
35  shaderClassType = classType;
36  expressionGenerics = expressions;
37  identifiersGenerics = identifiers;
38  logger = log;
39  variableGenerics = shaderClassType.ShaderGenerics.ToDictionary(x => x.Name.Text, x => x);
40  }
41 
42  public static void Instanciate(ShaderClassType classType, Dictionary<string, Expression> expressions, Dictionary<string, Identifier> identifiers, LoggerResult log)
43  {
44  var instanciator = new ParadoxClassInstanciator(classType, expressions, identifiers, log);
45  instanciator.Run();
46  }
47 
48  private void Run()
49  {
50  stringGenerics = identifiersGenerics.ToDictionary(x => x.Key, x => x.Value.ToString());
51 
52  foreach (var baseClass in shaderClassType.BaseClasses)
53  VisitDynamic(baseClass); // look for IdentifierGeneric
54 
55  foreach (var member in shaderClassType.Members)
56  VisitDynamic(member); // look for IdentifierGeneric and Variable
57 
58  foreach (var variable in shaderClassType.ShaderGenerics)
59  {
60  variable.InitialValue = expressionGenerics[variable.Name.Text];
61 
62  if (variable.Type is SemanticType || variable.Type is LinkType)
63  continue;
64 
65  // TODO: be more precise
66 
67  if (!(variable.InitialValue is VariableReferenceExpression || variable.InitialValue is MemberReferenceExpression))
68  {
69  variable.Qualifiers |= StorageQualifier.Const;
70  variable.Qualifiers |= SiliconStudio.Shaders.Ast.Hlsl.StorageQualifier.Static;
71  }
72  shaderClassType.Members.Add(variable);
73  }
74  }
75 
76  [Visit]
77  protected void Visit(Variable variable)
78  {
79  Visit((Node)variable);
80  //TODO: check types
81 
82  // no call on base
83  foreach (var sem in variable.Qualifiers.Values.OfType<Semantic>())
84  {
85  string replacementSemantic;
86  if (stringGenerics.TryGetValue(sem.Name, out replacementSemantic))
87  {
88  if (logger != null && !(variableGenerics[sem.Name].Type is SemanticType))
89  logger.Warning(ParadoxMessageCode.WarningUseSemanticType, variable.Span, variableGenerics[sem.Name]);
90  sem.Name = replacementSemantic;
91  }
92  }
93 
94  foreach (var annotation in variable.Attributes.OfType<AttributeDeclaration>().Where(x => x.Name == "Link" && x.Parameters.Count > 0))
95  {
96  var linkName = (string)annotation.Parameters[0].Value;
97 
98  if (String.IsNullOrEmpty(linkName))
99  continue;
100 
101  var replacements = new List<Tuple<string, int>>();
102 
103  foreach (var generic in variableGenerics.Where(x => x.Value.Type is LinkType))
104  {
105  var index = linkName.IndexOf(generic.Key, 0);
106  if (index >= 0)
107  replacements.Add(Tuple.Create(generic.Key, index));
108  }
109 
110  if (replacements.Count > 0)
111  {
112  var finalString = "";
113  var currentIndex = 0;
114  foreach (var replacement in replacements.OrderBy(x => x.Item2))
115  {
116  var replacementIndex = replacement.Item2;
117  var stringToReplace = replacement.Item1;
118 
119  if (replacementIndex - currentIndex > 0)
120  finalString += linkName.Substring(currentIndex, replacementIndex - currentIndex);
121  finalString += stringGenerics[stringToReplace];
122  currentIndex = replacementIndex + stringToReplace.Length;
123  }
124 
125  if (currentIndex < linkName.Length)
126  finalString += linkName.Substring(currentIndex);
127 
128  annotation.Parameters[0] = new Literal(finalString);
129  }
130  }
131  }
132 
133  [Visit]
134  protected void Visit(IdentifierGeneric identifierGeneric)
135  {
136  Visit((Node)identifierGeneric);
137 
138  for (var i = 0; i < identifierGeneric.Identifiers.Count; ++i)
139  {
140  Identifier replacement;
141  if (identifiersGenerics.TryGetValue(identifierGeneric.Identifiers[i].ToString(), out replacement))
142  identifierGeneric.Identifiers[i] = replacement;
143  }
144  }
145  }
146 }
SourceSpan Span
Gets or sets the source span.
Definition: Node.cs:37
Qualifier Qualifiers
Gets or sets the qualifiers.
Definition: Variable.cs:53
A class to collect parsing/expression messages.
Definition: LoggerResult.cs:13
Abstract node.
Definition: Node.cs:15
A variable declaration.
Definition: Variable.cs:11
A member reference in the form {this}.{Name}
A generic identifier in the form Typename
List< AttributeBase > Attributes
Definition: Variable.cs:45
OrderedSet< CompositeEnum > Values
Gets or sets the values.
override string ToString()
Definition: Node.cs:133
SiliconStudio.Shaders.Ast.StorageQualifier StorageQualifier
A field of a struct.
Definition: Literal.cs:13