Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
CastAnalysis.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 SiliconStudio.Shaders.Ast;
5 using SiliconStudio.Shaders.Parser;
6 
7 namespace SiliconStudio.Shaders.Analysis
8 {
9  public class CastAnalysis : Analysis.AnalysisBase
10  {
11  public CastAnalysis(ParsingResult result) : base(result)
12  {
13  }
14 
15  [Visit]
16  protected Expression Visit(UnaryExpression expression)
17  {
18  // First, dispatch to resolve type of node at deeper level
19  Visit((Node)expression);
20 
21  var unaryType = expression.TypeInference.TargetType;
22  var inputType = expression.Expression.TypeInference.TargetType;
23  if (unaryType == null || inputType == null)
24  return expression;
25 
26  if (unaryType == ScalarType.Bool && inputType != ScalarType.Bool && expression.Operator == UnaryOperator.LogicalNot)
27  expression.Expression = new MethodInvocationExpression(new TypeReferenceExpression(ScalarType.Bool), expression.Expression) { TypeInference = { TargetType = ScalarType.Bool } };
28  return expression;
29  }
30 
31  [Visit]
32  protected Expression Visit(BinaryExpression expression)
33  {
34  // First, dispatch to resolve type of node at deeper level
35  Visit((Node)expression);
36 
37  var leftType = expression.Left.TypeInference.TargetType;
38  var rightType = expression.Right.TypeInference.TargetType;
39  var returnType = expression.TypeInference.ExpectedType ?? expression.TypeInference.TargetType;
40 
41  bool isNumericOperator = true;
42 
43  switch (expression.Operator)
44  {
45  case BinaryOperator.LogicalAnd:
46  case BinaryOperator.LogicalOr:
47  isNumericOperator = false;
48  returnType = GetBinaryImplicitConversionType(expression.Span, leftType, rightType, true);
49  expression.TypeInference.TargetType = returnType;
50  break;
51  case BinaryOperator.Less:
52  case BinaryOperator.LessEqual:
53  case BinaryOperator.Greater:
54  case BinaryOperator.GreaterEqual:
55  case BinaryOperator.Equality:
56  case BinaryOperator.Inequality:
57  isNumericOperator = false;
58  returnType = GetBinaryImplicitConversionType(expression.Span, leftType, rightType, false);
59 
60  TypeBase resultType = ScalarType.Bool;
61  if (returnType is VectorType)
62  {
63  resultType = new VectorType(ScalarType.Bool, ((VectorType)returnType).Dimension);
64  }
65  else if (returnType is MatrixType)
66  {
67  var matrixType = (MatrixType)returnType;
68  resultType = new MatrixType(ScalarType.Bool, matrixType.RowCount, matrixType.ColumnCount);
69  }
70  expression.TypeInference.TargetType = resultType;
71  break;
72  }
73 
74  if (returnType != null)
75  {
76  if (returnType == ScalarType.Bool && isNumericOperator)
77  {
78  var typeToCheck = leftType ?? rightType;
79  if (typeToCheck != null)
80  return ConvertExpressionToBool(expression, typeToCheck);
81  }
82  }
83 
84  if (!isNumericOperator || CastHelper.NeedConvertForBinary(leftType, returnType))
85  expression.Left = Cast(leftType, returnType, expression.Left);
86  if (!isNumericOperator || CastHelper.NeedConvertForBinary(rightType, returnType))
87  expression.Right = Cast(rightType, returnType, expression.Right);
88 
89  return expression;
90  }
91 
92  private Expression ConvertExpressionToBool(Expression expression, TypeBase typeToCheck)
93  {
94  if (typeToCheck != ScalarType.Bool)
96  return expression;
97  }
98 
99 
100  [Visit]
101  protected virtual void Visit(IfStatement ifStatement)
102  {
103  // First, dispatch to resolve type of node at deeper level
104  Visit((Node)ifStatement);
105 
106  var conditionType = ifStatement.Condition.TypeInference.TargetType;
107  if (!(ifStatement.Condition is BinaryExpression || ifStatement.Condition is UnaryExpression))
108  {
109  ifStatement.Condition = ConvertExpressionToBool(ifStatement.Condition, conditionType);
110  }
111  }
112 
113  [Visit]
114  protected void Visit(ConditionalExpression conditionalExpression)
115  {
116  // First, dispatch to resolve type of node at deeper level
117  Visit((Node)conditionalExpression);
118 
119  var leftType = conditionalExpression.Left.TypeInference.TargetType;
120  var rightType = conditionalExpression.Right.TypeInference.TargetType;
121 
122  if (leftType == null || (leftType is ScalarType && !(rightType is ScalarType)))
123  {
124  conditionalExpression.Left = Cast(leftType, rightType, conditionalExpression.Left);
125  }
126  else
127  {
128  conditionalExpression.Right = Cast(rightType, leftType, conditionalExpression.Right);
129  }
130  }
131 
132 
133  private Expression Cast(TypeBase fromType, TypeBase toType, Expression expression)
134  {
135  if (fromType != null && toType != null)
136  {
137  if (fromType != toType)
138  {
139  var castMethod = new MethodInvocationExpression(new TypeReferenceExpression(toType));
140  castMethod.Arguments.Add(expression);
141  expression = castMethod;
142  expression.TypeInference.TargetType = toType;
143  }
144  }
145 
146  return expression;
147  }
148 
149  [Visit]
150  protected void Visit(ReturnStatement returnStatement)
151  {
152  // First, dispatch to resolve type of node at deeper level
153  Visit((Node)returnStatement);
154 
155  if (returnStatement.Value != null)
156  {
157  var expressionType = returnStatement.Value.TypeInference.TargetType;
158  if (expressionType != null)
159  returnStatement.Value = Cast(expressionType, returnStatement.Value.TypeInference.ExpectedType ?? expressionType, returnStatement.Value);
160  }
161  }
162 
163  [Visit]
164  protected void Visit(Variable variable)
165  {
166  // First, dispatch to resolve type of node at deeper level
167  Visit((Node)variable);
168 
169  if (variable.InitialValue != null)
170  {
171  var expressionType = variable.InitialValue.TypeInference.TargetType;
172  if (!(expressionType is ObjectType))
173  {
174  variable.InitialValue = Cast(expressionType, variable.Type.ResolveType(), variable.InitialValue);
175  }
176  }
177  }
178 
179  [Visit]
180  protected void Visit(AssignmentExpression expression)
181  {
182  // First, dispatch to resolve type of node at deeper level
183  Visit((Node)expression);
184 
185  var expressionType = expression.Target.TypeInference.TargetType;
186  var targetType = expression.Target.TypeInference.ExpectedType ?? expressionType;
187  expression.Value = Cast(expression.Value.TypeInference.TargetType, targetType, expression.Value);
188  }
189 
190  [Visit]
191  protected void Visit(IndexerExpression expression)
192  {
193  // First, dispatch to resolve type of node at deeper level
194  Visit((Node)expression);
195 
196  var indexerType = expression.Index.TypeInference.TargetType;
197  if (indexerType != null)
198  {
199  var baseType = TypeBase.GetBaseType(indexerType);
200  if (baseType == ScalarType.Float || baseType == ScalarType.Double)
201  expression.Index = Cast(indexerType, ScalarType.Int, expression.Index);
202  }
203  }
204 
205  [Visit]
206  protected void Visit(MethodInvocationExpression expression)
207  {
208  // First, dispatch to resolve type of node at deeper level
209  Visit((Node)expression);
210 
211  // Add appropriate cast for all arguments
212  for (int i = 0; i < expression.Arguments.Count; ++i)
213  {
214  var argument = expression.Arguments[i];
215  var targetType = argument.TypeInference.TargetType;
216  if (targetType != null && !(targetType is ObjectType))
217  expression.Arguments[i] = Cast(targetType, argument.TypeInference.ExpectedType ?? targetType, argument);
218  }
219  }
220 
221  /// <inheritdoc/>
222  public override void Run()
223  {
224  Visit(ParsingResult.Shader);
225  }
226  }
227 }
Base class for all vector types
Definition: VectorType.cs:10
static readonly ScalarType Bool
Scalar bool.
Definition: ScalarType.cs:17
Describes a binary expression.
static readonly ScalarType Int
Scalar int.
Definition: ScalarType.cs:37
UnaryOperator
Unary operator used in all binary expressions (except assignment expression).
SourceSpan Span
Gets or sets the source span.
Definition: Node.cs:37
void Visit(AssignmentExpression expression)
Shader Shader
Gets or sets the shader.
virtual void Visit(IfStatement ifStatement)
Abstract node.
Definition: Node.cs:15
static readonly ScalarType Float
Sclar float.
Definition: ScalarType.cs:27
Expression Visit(BinaryExpression expression)
Definition: CastAnalysis.cs:32
A variable declaration.
Definition: Variable.cs:11
void Visit(IndexerExpression expression)
Expression Visit(UnaryExpression expression)
Definition: CastAnalysis.cs:16
void Visit(MethodInvocationExpression expression)
Base type for all types.
Definition: TypeBase.cs:11
static readonly ScalarType Double
Scalar double.
Definition: ScalarType.cs:22
override void Run()
Runs this instance.
void Visit(ReturnStatement returnStatement)
void Visit(ConditionalExpression conditionalExpression)