Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
ExpressionEvaluator.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 SiliconStudio.Shaders.Ast;
6 
7 namespace SiliconStudio.Shaders.Visitor
8 {
9  /// <summary>
10  /// An expression evaluator.
11  /// </summary>
13  {
14  private static readonly List<string> hlslScalarTypeNames =
15  new List<string>
16  {
17  "bool",
18  "int",
19  "uint",
20  "dword",
21  "half",
22  "float",
23  "double",
24  "min16float",
25  "min10float",
26  "min16int",
27  "min12int",
28  "min16uint"
29  };
30 
31  private readonly Stack<double> values;
32 
33  private ExpressionResult result;
34 
35  /// <summary>
36  /// Initializes a new instance of the <see cref="ExpressionEvaluator"/> class.
37  /// </summary>
38  public ExpressionEvaluator() : base(false, false)
39  {
40  values = new Stack<double>();
41  }
42 
43  /// <summary>
44  /// Evaluates the specified expression.
45  /// </summary>
46  /// <param name="expression">The expression.</param>
47  /// <returns>Result of the expression evaluated</returns>
49  {
50  values.Clear();
51  result = new ExpressionResult();
52 
53  // Small optim, if LiteralExpression, we perform a direct eval.
54  if (expression is LiteralExpression)
55  {
56  Visit((LiteralExpression) expression);
57  }
58  else
59  {
60  VisitDynamic(expression);
61  }
62 
63  if (values.Count == 1)
64  result.Value = values.Pop();
65  else
66  {
67  result.Error("Cannot evaluate expression {0}", expression.Span, expression);
68  }
69  return result;
70  }
71 
72  /// <inheritdoc/>
73  [Visit]
74  protected virtual void Visit(Expression expression)
75  {
76  result.Warning("Expression evaluation [{0}] is not supported", expression.Span, expression);
77  }
78 
79  /// <inheritdoc/>
80  [Visit]
81  protected virtual void Visit(BinaryExpression binaryExpression)
82  {
83  Visit((Node) binaryExpression);
84 
85  var rightValue = values.Pop();
86  var leftValue = values.Pop();
87 
88  switch (binaryExpression.Operator)
89  {
90  case BinaryOperator.Plus:
91  values.Push(leftValue + rightValue);
92  break;
93  case BinaryOperator.Minus:
94  values.Push(leftValue - rightValue);
95  break;
96  case BinaryOperator.Multiply:
97  values.Push(leftValue*rightValue);
98  break;
99  case BinaryOperator.Divide:
100  values.Push(leftValue/rightValue);
101  break;
102  case BinaryOperator.Modulo:
103  values.Push(leftValue%rightValue);
104  break;
105  case BinaryOperator.LeftShift:
106  values.Push((int) leftValue << (int) rightValue);
107  break;
108  case BinaryOperator.RightShift:
109  values.Push((int) leftValue >> (int) rightValue);
110  break;
111  case BinaryOperator.BitwiseOr:
112  values.Push(((int) leftValue) | ((int) rightValue));
113  break;
114  case BinaryOperator.BitwiseAnd:
115  values.Push(((int) leftValue) & ((int) rightValue));
116  break;
117  case BinaryOperator.BitwiseXor:
118  values.Push(((int) leftValue) ^ ((int) rightValue));
119  break;
120  default:
121  result.Error("Binary operator [{0}] is not supported", binaryExpression.Span, binaryExpression);
122  values.Push(0);
123  break;
124  }
125  }
126 
127  /*
128  //[Visit]
129  //protected virtual void Visit(IndexerExpression indexerExpression)
130  //{
131  // Visit((Node)indexerExpression);
132  // // TODO implement indexer expression eval
133  // result.Error("Indexer expression evaluation [{0}] is not supported", indexerExpression.Span, indexerExpression);
134  //}
135  //[Visit]
136  //protected virtual void Visit(MemberReferenceExpression memberReferenceExpression)
137  //{
138  // Visit((Node)memberReferenceExpression);
139 
140  // // TODO implement member reference expression eval
141  // result.Error("Member reference expression evaluation [{0}] is not supported", memberReferenceExpression.Span, memberReferenceExpression);
142  //}
143  */
144 
145  /// <inheritdoc/>
146  [Visit]
147  protected virtual void Visit(MethodInvocationExpression methodInvocationExpression)
148  {
149  if (methodInvocationExpression.Target is TypeReferenceExpression)
150  {
151  var methodName = (methodInvocationExpression.Target as TypeReferenceExpression).Type.Name.Text;
152  if (hlslScalarTypeNames.Contains(methodName))
153  {
154  var evaluator = new ExpressionEvaluator();
155  var subResult = evaluator.Evaluate(methodInvocationExpression.Arguments[0]);
156 
157  if (subResult.Value == null)
158  result.Error("Unable to evaluate cast [{0}]", methodInvocationExpression.Span, methodInvocationExpression);
159  else
160  {
161  try
162  {
163  values.Push(Convert.ToDouble(subResult.Value));
164  }
165  catch (Exception e)
166  {
167  result.Error(e.Message, methodInvocationExpression.Span);
168  result.Error("Unable to cast the value [{0}]", methodInvocationExpression.Span, methodInvocationExpression);
169  }
170  }
171  }
172  else
173  result.Error("Method invocation expression evaluation [{0}] is not supported", methodInvocationExpression.Span, methodInvocationExpression);
174  }
175  }
176 
177  /// <inheritdoc/>
178  [Visit]
179  protected virtual void Visit(VariableReferenceExpression variableReferenceExpression)
180  {
181  Visit((Node)variableReferenceExpression);
182 
183  var variableDeclaration = variableReferenceExpression.TypeInference.Declaration as Variable;
184  if (variableDeclaration == null)
185  {
186  result.Error("Unable to find variable [{0}]", variableReferenceExpression.Span, variableReferenceExpression);
187  }
188  else if (variableDeclaration.InitialValue == null)
189  {
190  result.Error("Variable [{0}] used in expression is not constant", variableReferenceExpression.Span, variableDeclaration);
191  }
192  else
193  {
194  var evaluator = new ExpressionEvaluator();
195  var subResult = evaluator.Evaluate(variableDeclaration.InitialValue);
196  subResult.CopyTo(result);
197 
198  if (subResult.HasErrors)
199  {
200  values.Push(0.0f);
201  }
202  else
203  {
204  values.Push(Convert.ToDouble(subResult.Value));
205  }
206  }
207  }
208 
209  /// <inheritdoc/>
210  [Visit]
211  protected virtual void Visit(LiteralExpression literalExpression)
212  {
213  values.Push(Convert.ToDouble(literalExpression.Literal.Value));
214  }
215 
216  /// <inheritdoc/>
217  [Visit]
218  protected virtual void Visit(ParenthesizedExpression parenthesizedExpression)
219  {
220  // value stack is unchanged
221  Visit((Node)parenthesizedExpression);
222  }
223 
224  /// <inheritdoc/>
225  [Visit]
226  protected virtual void Visit(UnaryExpression unaryExpression)
227  {
228  Visit((Node)unaryExpression);
229 
230  var value = values.Pop();
231 
232  switch (unaryExpression.Operator)
233  {
234  case UnaryOperator.Plus:
235  values.Push(value);
236  break;
237  case UnaryOperator.Minus:
238  values.Push(-value);
239  break;
240  case UnaryOperator.PreIncrement:
241  case UnaryOperator.PostIncrement:
242  // TODO Pre/Post increment/decrement are not correctly handled
243  value++;
244  values.Push(value);
245  break;
246  case UnaryOperator.PreDecrement:
247  case UnaryOperator.PostDecrement:
248  value--;
249  values.Push(value);
250  break;
251  default:
252  result.Error("Unary operator [{0}] is not supported", unaryExpression.Span, unaryExpression);
253  values.Push(0);
254  break;
255  }
256  }
257  }
258 }
ExpressionResult Evaluate(Expression expression)
Evaluates the specified expression.
Describes a binary expression.
virtual void Visit(BinaryExpression binaryExpression)
virtual void Visit(LiteralExpression literalExpression)
An expression surrounded by parenthesis.
virtual void Visit(MethodInvocationExpression methodInvocationExpression)
Abstract node.
Definition: Node.cs:15
A variable declaration.
Definition: Variable.cs:11
virtual void Visit(ParenthesizedExpression parenthesizedExpression)
ExpressionEvaluator()
Initializes a new instance of the ExpressionEvaluator class.
virtual void Visit(UnaryExpression unaryExpression)
document false
virtual void Visit(VariableReferenceExpression variableReferenceExpression)