Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
SemanticAnalysis.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 using SiliconStudio.Shaders.Ast;
7 using SiliconStudio.Shaders.Parser;
8 using SiliconStudio.Shaders.Utility;
9 using SiliconStudio.Shaders.Visitor;
10 
11 namespace SiliconStudio.Shaders.Analysis
12 {
13  /// <summary>
14  /// A Type reference analysis is building type references.
15  /// </summary>
17  {
18  protected static string TagBuiltinUserDefined = "TagBuiltinUserDefined";
19 
20  #region Constructors and Destructors
21 
22  /// <summary>
23  /// Initializes a new instance of the <see cref="SemanticAnalysis"/> class.
24  /// </summary>
25  /// <param name="result">
26  /// The result.
27  /// </param>
29  : base(result)
30  {
31  }
32  #endregion
33 
34  /// <summary>
35  /// Gets or sets a value indicating whether the analysis is in skipping mode.
36  /// </summary>
37  /// <value>
38  /// <c>true</c> if the analysis is in skipping mode; otherwise, <c>false</c>.
39  /// </value>
40  protected bool IsSkippingMode { get; set; }
41 
42  #region Public Methods
43 
44  /// <inheritdoc/>
45  public override void Run()
46  {
47  Visit(ParsingResult.Shader);
48  }
49 
50  /// <summary>
51  /// Visits the specified assignement expression.
52  /// </summary>
53  /// <param name="assignmentExpression">The assignement expression.</param>
55  protected virtual void Visit(AssignmentExpression assignmentExpression)
56  {
57  Visit((Node)assignmentExpression);
58 
59  // An assignment expression get the
60  assignmentExpression.TypeInference = (TypeInference)assignmentExpression.Target.TypeInference.Clone();
61 
62  // TODO: check if types are compatible?
63  }
64 
65  /// <summary>
66  /// Visits the specified binary expression.
67  /// </summary>
68  /// <param name="binaryExpression">The binary expression.</param>
70  protected virtual void Visit(BinaryExpression binaryExpression)
71  {
72  Visit((Node)binaryExpression);
73 
74  var leftType = binaryExpression.Left.TypeInference.TargetType;
75  var rightType = binaryExpression.Right.TypeInference.TargetType;
76 
77  // No need to log an error as it has been done by the initial Visit((Node)
78  if (leftType == null || rightType == null) return;
79 
80  switch (binaryExpression.Operator)
81  {
82  case BinaryOperator.Multiply:
83  binaryExpression.TypeInference.TargetType = GetMultiplyImplicitConversionType(binaryExpression.Span, leftType, rightType);
84  break;
85  case BinaryOperator.Divide:
86  binaryExpression.TypeInference.TargetType = GetDivideImplicitConversionType(binaryExpression.Span, leftType, rightType);
87  break;
88  case BinaryOperator.Minus:
89  case BinaryOperator.Plus:
90  case BinaryOperator.Modulo:
91  case BinaryOperator.LogicalAnd:
92  case BinaryOperator.LogicalOr:
93  case BinaryOperator.BitwiseOr:
94  case BinaryOperator.BitwiseAnd:
95  case BinaryOperator.BitwiseXor:
96  case BinaryOperator.RightShift:
97  case BinaryOperator.LeftShift:
98  binaryExpression.TypeInference.TargetType = GetBinaryImplicitConversionType(binaryExpression.Span, leftType, rightType, false);
99  break;
100  case BinaryOperator.Less:
101  case BinaryOperator.LessEqual:
102  case BinaryOperator.Greater:
103  case BinaryOperator.GreaterEqual:
104  case BinaryOperator.Equality:
105  case BinaryOperator.Inequality:
106  var returnType = GetBinaryImplicitConversionType(binaryExpression.Span, leftType, rightType, true);
107  binaryExpression.TypeInference.TargetType = TypeBase.CreateWithBaseType(returnType, ScalarType.Bool);
108  break;
109  }
110  }
111 
112  /// <summary>
113  /// Visits the specified conditional expression.
114  /// </summary>
115  /// <param name="conditionalExpression">The conditional expression.</param>
117  protected virtual void Visit(ConditionalExpression conditionalExpression)
118  {
119  Visit((Node)conditionalExpression);
120 
121  // Type inference for conditional expression is using the left result
122  var leftType = conditionalExpression.Left.TypeInference.TargetType;
123  var rightType = conditionalExpression.Right.TypeInference.TargetType;
124 
125  conditionalExpression.TypeInference.TargetType = leftType;
126 
127  if (leftType == null || (leftType is ScalarType && !(rightType is ScalarType)))
128  {
129  conditionalExpression.TypeInference.TargetType = rightType;
130  }
131  }
132 
133  /// <summary>
134  /// Visits the specified indexer expression.
135  /// </summary>
136  /// <param name="indexerExpression">The indexer expression.</param>
138  protected virtual void Visit(IndexerExpression indexerExpression)
139  {
140  Visit((Node)indexerExpression);
141 
142  ProcessIndexerExpression(indexerExpression);
143  }
144 
145  /// <summary>
146  /// Find the type of the expression
147  /// </summary>
148  /// <param name="indexerExpression">the indexer expression</param>
149  protected virtual void ProcessIndexerExpression(IndexerExpression indexerExpression)
150  {
151  TypeBase type = null;
152  var targetType = indexerExpression.Target.TypeInference.TargetType;
153 
154  if (targetType is ArrayType)
155  {
156  var arrayType = (ArrayType)targetType;
157  if (arrayType.Dimensions.Count == 1)
158  {
159  type = arrayType.Type.ResolveType();
160  }
161  else
162  {
163  var dimensions = new List<Expression>(arrayType.Dimensions);
164  dimensions.RemoveAt(0);
165  type = new ArrayType(arrayType.Type, dimensions.ToArray());
166  }
167  }
168  else if (targetType is VectorType)
169  {
170  type = ((VectorType)targetType).Type.ResolveType();
171  }
172  else if (targetType is MatrixType)
173  {
174  type = new VectorType((ScalarType)((MatrixType)targetType).Type.ResolveType(), ((MatrixType)targetType).ColumnCount);
175  }
176 
177  indexerExpression.TypeInference.TargetType = type;
178  if (type == null)
179  Error(MessageCode.ErrorIndexerType, indexerExpression.Span, indexerExpression);
180  }
181 
182  /// <summary>
183  /// Visits the specified literal expression.
184  /// </summary>
185  /// <param name="literalExpression">The literal expression.</param>
187  protected virtual void Visit(LiteralExpression literalExpression)
188  {
189  Visit((Node)literalExpression);
190 
191  if (literalExpression.Value is int)
192  literalExpression.TypeInference.TargetType = ScalarType.Int;
193  if (literalExpression.Value is uint)
194  literalExpression.TypeInference.TargetType = ScalarType.UInt;
195  if (literalExpression.Value is float)
196  literalExpression.TypeInference.TargetType = ScalarType.Float;
197  if (literalExpression.Value is double)
198  literalExpression.TypeInference.TargetType = ScalarType.Double;
199  if (literalExpression.Value is bool)
200  literalExpression.TypeInference.TargetType = ScalarType.Bool;
201  if (literalExpression.Value is string)
202  literalExpression.TypeInference.TargetType = TypeBase.String;
203 
204  if (literalExpression.TypeInference.TargetType == null)
205  {
206  Error(MessageCode.ErrorLiteralType, literalExpression.Span, literalExpression.Text);
207  }
208  }
209 
211  protected virtual void Visit(ReturnStatement returnStatement)
212  {
213  // First, dispatch to resolve type of node at deeper level
214  Visit((Node)returnStatement);
215 
216  if (returnStatement.Value != null)
217  {
218  var function = NodeStack.OfType<MethodDefinition>().Last();
219  returnStatement.Value.TypeInference.ExpectedType = function.ReturnType.ResolveType();
220  }
221  }
222 
224  protected virtual void Visit(IfStatement ifStatement)
225  {
226  // First, dispatch to resolve type of node at deeper level
227  Visit((Node)ifStatement);
228 
229  ifStatement.Condition.TypeInference.ExpectedType = ScalarType.Bool;
230  }
231 
232  /// <summary>
233  /// Pres the process method invocation.
234  /// </summary>
235  /// <param name="expression">The expression.</param>
236  /// <param name="methodName">Name of the method.</param>
237  /// <param name="declarations">The declarations.</param>
238  /// <returns></returns>
239  protected virtual void ProcessMethodInvocation(MethodInvocationExpression expression, string methodName, List<IDeclaration> declarations)
240  {
241  // Get all arguments types infered
242  var argumentTypeInferences = expression.Arguments.Select(x => x.TypeInference).ToArray();
243  var argumentTypes = expression.Arguments.Select(x => x.TypeInference.TargetType).ToArray();
244 
245  // If any type could not be resolved previously, there is already an error, so return immediately
246  if (argumentTypes.Any(x => x == null))
247  return;
248 
249  var overloads = new List<FunctionOverloadScore>();
250 
251  // Use the most overriden method
252  // TODO: Temporary workaround for user methods overriding builtin methods
253  // Remove the builtin methods if there is any overriding
254  var methodsDeclared = declarations.OfType<MethodDeclaration>().ToList();
255  for (int i = 0; i < methodsDeclared.Count - 1; i++)
256  {
257  var leftMethod = methodsDeclared[i];
258  for (int j = i + 1; j < methodsDeclared.Count; j++)
259  {
260  if (leftMethod.IsSameSignature(methodsDeclared[j]))
261  {
262  methodsDeclared.RemoveAt(i);
263  i--;
264  break;
265  }
266  }
267  }
268 
269  // Try to match the function arguments with every overload
270  foreach (var methodDeclaration in methodsDeclared)
271  {
272  var returnType = methodDeclaration.ReturnType.ResolveType();
273  var parameterTypes = methodDeclaration.Parameters.Select(x => x.Type.ResolveType()).ToArray();
274 
275  // Number of parameters doesn't match
276  if (argumentTypes.Length > parameterTypes.Length) continue;
277 
278  // Check for method calls that is using implicit parameter value
279  if (argumentTypes.Length < parameterTypes.Length)
280  {
281  bool allRemainingParametersHaveDefaultValues = true;
282  // Check for default values
283  for (int i = argumentTypes.Length; i < parameterTypes.Length; i++)
284  {
285  if (methodDeclaration.Parameters[i].InitialValue == null)
286  {
287  allRemainingParametersHaveDefaultValues = false;
288  break;
289  }
290  }
291 
292  // If remaining parameters doesn't have any default values, then continue
293  if (!allRemainingParametersHaveDefaultValues) continue;
294  }
295 
296  // Higher score = more conversion (score == 0 is perfect match)
297  int score = 0;
298  bool validOverload = true;
299 
300  // Check parameters
301  for (int i = 0; i < argumentTypes.Length && validOverload; ++i)
302  {
303  var argType = argumentTypes[i];
304  var expectedType = parameterTypes[i];
305 
306  var argTypeBase = TypeBase.GetBaseType(argType);
307  var expectedTypeBase = TypeBase.GetBaseType(expectedType);
308 
309  if (expectedTypeBase is GenericParameterType)
310  {
311  var genericParameterType = (GenericParameterType)expectedTypeBase;
312 
313  // TODO handle dynamic score from constraint.
314  if (methodDeclaration.CheckConstraint(genericParameterType, argType))
315  {
316  score++;
317  }
318  else
319  {
320  validOverload = false;
321  }
322  }
323  else
324  {
325  // TODO, improve the whole test by using TypeBase equality when possible
326 
327  // Then work on scalar type conversion ( float to int, signed to unsigned, different type)
328  var fromScalarType = argTypeBase as ScalarType;
329  var toScalarType = expectedTypeBase as ScalarType;
330 
331  if (fromScalarType != null && toScalarType != null)
332  {
333  if (ScalarType.IsFloat(fromScalarType) && !ScalarType.IsFloat(toScalarType))
334  {
335  // Truncation from float to int
336  score += 7;
337  }
338  else if (fromScalarType != toScalarType)
339  {
340  // else different type (implicit cast is usually working)
341  score += 1;
342  }
343 
344  if (!fromScalarType.IsUnsigned && toScalarType.IsUnsigned)
345  {
346  // int to unsigned
347  score += 2;
348  }
349  }
350 
351  // First, try to fix the base type (i.e. the "float" of float3x1)
352  if (argTypeBase != expectedTypeBase && expectedTypeBase is ScalarType)
353  {
354  if (!(argTypeBase is ScalarType))
355  {
356  score++; // +1 for type conversion
357  }
358  argType = TypeBase.CreateWithBaseType(argType, (ScalarType)expectedTypeBase);
359  }
360 
361  validOverload = TestMethodInvocationArgument(argTypeBase, expectedTypeBase, argType, expectedType, ref score);
362  }
363  }
364 
365  if (validOverload)
366  overloads.Add(
367  new FunctionOverloadScore { Declaration = methodDeclaration, ParameterTypes = parameterTypes, ReturnType = returnType, Score = score });
368  }
369 
370  // In-place sort using List.Sort would be lighter
371  var bestOverload = overloads.OrderBy(x => x.Score).FirstOrDefault();
372 
373  if (bestOverload != null)
374  {
375  expression.TypeInference.TargetType = bestOverload.ReturnType.ResolveType();
376 
377  // Override declaration to match exactly the declaration found by method overloaded resolution
378  expression.Target.TypeInference.Declaration = bestOverload.Declaration;
379 
380  // Add appropriate cast
381  for (int i = 0; i < argumentTypes.Length; ++i)
382  {
383  argumentTypeInferences[i].ExpectedType = (bestOverload.ParameterTypes[i] is GenericParameterType)
384  ? argumentTypes[i]
385  : bestOverload.ParameterTypes[i].ResolveType();
386  }
387  }
388  else
389  {
390  Error(MessageCode.ErrorNoOverloadedMethod, expression.Span, methodName);
391  }
392  }
393 
394  /// <summary>
395  /// Tests the arguments of the method
396  /// </summary>
397  /// <param name="argTypeBase">the argument typebase</param>
398  /// <param name="expectedTypeBase">the expected typebase</param>
399  /// <param name="argType">the argument type</param>
400  /// <param name="expectedType">the expected type</param>
401  /// <param name="score">the score of the overload</param>
402  /// <returns>true if the overload is correct, false otherwise</returns>
403  protected virtual bool TestMethodInvocationArgument(TypeBase argTypeBase, TypeBase expectedTypeBase, TypeBase argType, TypeBase expectedType, ref int score)
404  {
405  var validOverload = true;
406 
407  // If Scalar, Vector or Matrix, check types
408  if (TypeBase.HasDimensions(argType) && TypeBase.HasDimensions(expectedType))
409  {
410  if (argType != expectedType)
411  {
412  int argDim1 = TypeBase.GetDimensionSize(argType, 0);
413  int argDim2 = TypeBase.GetDimensionSize(argType, 1);
414  int expectedDim1 = TypeBase.GetDimensionSize(expectedType, 0);
415  int expectedDim2 = TypeBase.GetDimensionSize(expectedType, 1);
416 
417  // float3<=>float1x3 and float3<=>float3x1 implicit conversion are allowed,
418  // but float3x1<=>float1x3 should not be allowed
419  // float3<=>float1x3 and float1x1<=>float1<=>float
420  if (argDim1 == expectedDim1 && argDim2 == expectedDim2)
421  {
422  score++;
423  }
424  else if (((argType is VectorType && expectedType is MatrixType) || (argType is MatrixType && expectedType is VectorType))
425  && (argDim1 == expectedDim2 && argDim2 == expectedDim1))
426  {
427  // float3<=>float3x1
428  score++;
429  }
430  else if (argDim1 == 1 && argDim2 == 1)
431  {
432  // allow float=>float3x2 and float=>float3
433  score += 10; // +10 for scalar=>vector or scalar=>matrix expansion
434  }
435  else if (argDim1 >= expectedDim1 && argDim2 >= expectedDim2)
436  {
437  // Truncation
438  // +100 for truncation (by rank difference)
439  score += 100 * (argDim1 + argDim2 - expectedDim1 - expectedDim2);
440  }
441  else
442  {
443  // Could not find any matching implicit conversion
444  validOverload = false;
445  }
446  }
447  }
448  else if (argType is ArrayType && expectedType is ArrayType)
449  {
450  var argArrayType = (ArrayType)argType;
451  var expectedArrayType = (ArrayType)expectedType;
452 
453  if (argArrayType != expectedArrayType)
454  validOverload = false;
455  }
456  else if (argType is StructType && expectedType is StructType)
457  {
458  var argStructType = (StructType)argType;
459  var expectedStructType = (StructType)expectedType;
460 
461  if (argStructType.Name != expectedStructType.Name)
462  validOverload = false;
463  }
464  else if (!((argType is ObjectType && expectedType is ObjectType) || (argType is StructType && expectedType is StructType)))
465  {
466  // Could not find any matching implicit conversion
467  validOverload = false;
468  }
469 
470  return validOverload;
471  }
472 
473  /// <summary>
474  /// Visits the specified method invocation expression.
475  /// </summary>
476  /// <param name="expression">The method invocation expression.</param>
478  protected virtual void Visit(MethodInvocationExpression expression)
479  {
480  Visit((Node)expression);
481 
482  var methodAsVariable = expression.Target as VariableReferenceExpression;
483  var methodAsType = expression.Target as TypeReferenceExpression;
484 
485  IEnumerable<IDeclaration> declarationsIterator = null;
486 
487  string methodName;
488 
489  // Check if this is a Variable or Typename
490  if (methodAsVariable != null)
491  {
492  methodName = methodAsVariable.Name.Text;
493  declarationsIterator = FindDeclarations(methodAsVariable.Name);
494  }
495  else if (methodAsType != null)
496  {
497  var returnType = methodAsType.Type.ResolveType();
498  expression.TypeInference.TargetType = returnType;
499 
500  if (!(returnType is ScalarType || returnType is VectorType || returnType is MatrixType))
501  Warning(MessageCode.WarningTypeAsConstructor, expression.Span, expression.Target);
502 
503  return;
504  }
505  else
506  {
507  var target = expression.Target as MemberReferenceExpression;
508  if (target != null)
509  {
510  var memberReferenceExpression = target;
511 
512  declarationsIterator = FindDeclarationsFromObject(memberReferenceExpression.Target.TypeInference.TargetType, memberReferenceExpression.Member.Text);
513  methodName = string.Format("{0}", target);
514  }
515  else
516  {
517  Warning(MessageCode.WarningTypeInferenceUnknownExpression, expression.Span, expression.Target);
518  methodName = string.Format("{0}", expression.Target);
519  }
520  }
521 
522  // If no declarations were found, this is an error
523  if (declarationsIterator == null)
524  {
525  Error(MessageCode.ErrorNoReferencedMethod, expression.Span, methodName);
526  return;
527  }
528 
529  // Grab the declarations
530  var declarations = declarationsIterator.ToList();
531  ProcessMethodInvocation(expression, methodName, declarations);
532  }
533 
534  protected virtual IEnumerable<IDeclaration> FindDeclarationsFromObject(TypeBase typeBase, string memberName)
535  {
536  return null;
537  }
538 
539  /// <summary>
540  /// Visits the specified member reference.
541  /// </summary>
542  /// <param name="memberReference">The member reference.</param>
544  protected virtual void Visit(MemberReferenceExpression memberReference)
545  {
546  Visit((Node)memberReference);
547 
548  CommonVisit(memberReference);
549 
550  // If member reference is used from method invocation expression, let the method invocation resolve the type
551  if (!(ParentNode is MethodInvocationExpression) && memberReference.TypeInference.TargetType == null)
552  Error(MessageCode.ErrorNoTypeReferenceMember, memberReference.Span, memberReference);
553  }
554 
555  /// <summary>
556  /// Visits the specified member reference.
557  /// </summary>
558  /// <param name="memberReference">The member reference.</param>
560  protected virtual MethodDefinition Visit(MethodDefinition methodDefinition)
561  {
562  Visit((Node)methodDefinition);
563 
564  // Check that this method definition doesn't have a method declaration before
565  foreach (var declaration in FindDeclarations(methodDefinition.Name))
566  {
567  var methodDeclaration = declaration as MethodDeclaration;
568  if (methodDeclaration != null && !ReferenceEquals(declaration, methodDefinition))
569  {
570  if (methodDeclaration.IsSameSignature(methodDefinition))
571  {
572  methodDefinition.Declaration = methodDeclaration;
573  // Remove the definition if the declaration is tagged as builtin special (user defined)
574  if (methodDeclaration.GetTag(TagBuiltinUserDefined) != null)
575  return null;
576  break;
577  }
578  }
579  }
580  return methodDefinition;
581  }
582 
583  /// <summary>
584  /// Visits the specified member reference.
585  /// </summary>
586  /// <param name="memberReference">The member reference.</param>
587  protected virtual void CommonVisit(MemberReferenceExpression memberReference)
588  {
589  var thisType = memberReference.Target.TypeInference.TargetType;
590 
591  if (thisType is StructType)
592  FindMemberTypeReference((StructType)thisType, memberReference);
593  else if (thisType is ScalarType)
594  FindMemberTypeReference((ScalarType)thisType, memberReference);
595  else if (thisType is VectorType)
596  FindMemberTypeReference((VectorType)thisType, memberReference);
597  }
598 
599  /// <summary>
600  /// Visits the specified parenthesized expression.
601  /// </summary>
602  /// <param name="parenthesizedExpression">The parenthesized expression.</param>
604  protected virtual void Visit(ParenthesizedExpression parenthesizedExpression)
605  {
606  Visit((Node)parenthesizedExpression);
607 
608  // Get the type from the last item
609  parenthesizedExpression.TypeInference = (TypeInference)parenthesizedExpression.Content.TypeInference.Clone();
610  }
611 
612  /// <summary>
613  /// Visits the specified expression list.
614  /// </summary>
615  /// <param name="expressionList">The expression list.</param>
617  protected virtual void Visit(ExpressionList expressionList)
618  {
619  Visit((Node)expressionList);
620 
621  // Get the type from the last item
622  expressionList.TypeInference = (TypeInference)expressionList[expressionList.Count - 1].TypeInference.Clone();
623  }
624 
625  /// <summary>
626  /// Visits the specified array type.
627  /// </summary>
628  /// <param name="arrayType">Array type.</param>
630  protected virtual ArrayType Visit(ArrayType arrayType)
631  {
632  Visit((Node)arrayType);
633 
634  // Process only if there is non-literal expressions
635  if (arrayType.TypeInference.TargetType == null
636  && arrayType.Dimensions.Any(x => !(x is LiteralExpression || x is EmptyExpression)))
637  {
638  // Try to evaluate each dimension into a Literal expression (i.e. float4[3 * 2] should become float4[6])
639  var evaluator = new ExpressionEvaluator();
640  var results = arrayType.Dimensions.Select(evaluator.Evaluate).ToArray();
641 
642  if (results.Any(x => x.HasErrors))
643  {
644  foreach (var result in results.Where(x => x.HasErrors))
645  result.CopyTo(ParsingResult);
646  }
647  else
648  {
649  arrayType.TypeInference.TargetType = new ArrayType(arrayType.Type, results.Select(x => new LiteralExpression(Convert.ToInt32(x.Value))).ToArray());
650  }
651  }
652 
653  return arrayType;
654  }
655 
656  /// <summary>
657  /// Visits the specified type name.
658  /// </summary>
659  /// <param name="typeName">Name of the type.</param>
661  protected virtual TypeBase Visit(TypeName typeName)
662  {
663  Visit((Node)typeName);
664 
665  if (typeName.TypeInference.TargetType == null)
666  {
667  if (typeName.Name.Text == "void")
668  {
669  typeName.TypeInference.TargetType = TypeBase.Void;
670  }
671  else if (typeName.Name.Text == "string")
672  {
673  typeName.TypeInference.TargetType = TypeBase.String;
674  }
675  else
676  {
677  var declaration = FindDeclaration(typeName.Name);
678  if (declaration != null)
679  {
680  // Setup a type reference for this typeName
681  var typeReference = typeName.TypeInference;
682  typeReference.Declaration = declaration;
683  typeReference.TargetType = ResolveTypeFromDeclaration(typeReference.Declaration);
684  }
685  else
686  {
687  Error(MessageCode.ErrorNoTypeReferenceTypename, typeName.Span, typeName);
688  }
689  }
690  }
691  return typeName;
692  }
693 
694  /// <summary>
695  /// Visits the specified variable reference expression.
696  /// </summary>
697  /// <param name="variableReferenceExpression">The variable reference expression.</param>
699  protected virtual void Visit(VariableReferenceExpression variableReferenceExpression)
700  {
701  Visit((Node)variableReferenceExpression);
702 
703  var typeReference = variableReferenceExpression.TypeInference;
704  typeReference.Declaration = FindDeclaration(variableReferenceExpression.Name);
705  typeReference.TargetType = ResolveTypeFromDeclaration(typeReference.Declaration);
706  }
707 
708  /// <summary>
709  /// Visits the specified unary expression.
710  /// </summary>
711  /// <param name="unaryExpression">The unary expression.</param>
713  protected virtual void Visit(UnaryExpression unaryExpression)
714  {
715  Visit((Node)unaryExpression);
716 
717  // TODO check for
718  unaryExpression.TypeInference = (TypeInference)unaryExpression.Expression.TypeInference.Clone();
719 
720  // If this is a logical not, transform the value to a bool (bool2 bool3 bool4 / matrix<bool,1,1> matrix<bool,1,2> ..etc.
721  var subType = unaryExpression.Expression.TypeInference.TargetType;
722  if (subType != null && unaryExpression.Operator == UnaryOperator.LogicalNot)
723  unaryExpression.TypeInference.TargetType = TypeBase.CreateWithBaseType(subType, ScalarType.Bool);
724  }
725 
726  #endregion
727 
728  #region Methods
729 
730  /// <summary>
731  /// Finds the member type reference.
732  /// </summary>
733  /// <param name="structType">Type of the struct.</param>
734  /// <param name="memberReference">The member reference.</param>
735  protected virtual void FindMemberTypeReference(StructType structType, MemberReferenceExpression memberReference)
736  {
737  foreach (var field in structType.Fields)
738  {
739  foreach (var variableDeclarator in field.Instances())
740  {
741  if (variableDeclarator.Name == memberReference.Member)
742  {
743  memberReference.TypeInference.Declaration = variableDeclarator;
744  memberReference.TypeInference.TargetType = variableDeclarator.Type.ResolveType();
745  return;
746  }
747  }
748  }
749  }
750 
751  /// <summary>
752  /// Finds the member type reference.
753  /// </summary>
754  /// <param name="vectorType">Type of the vector.</param>
755  /// <param name="memberReference">The member reference.</param>
756  protected virtual void FindMemberTypeReference(VectorType vectorType, MemberReferenceExpression memberReference)
757  {
758  var scalarType = vectorType.Type.ResolveType();
759 
760  var components = memberReference.Member.Text;
761  if (components.Length <= 4 && (
762  components.All(x => x == 'x' || x == 'y' || x == 'z' || x == 'w') ||
763  components.All(x => x == 'r' || x == 'g' || x == 'b' || x == 'a') ||
764  components.All(x => x == 's' || x == 't' || x == 'u' || x == 'v')
765  ))
766  {
767  memberReference.TypeInference.TargetType = components.Length == 1 ? scalarType : new VectorType((ScalarType)scalarType, components.Length);
768  }
769  }
770 
771  /// <summary>
772  /// Finds the member type reference.
773  /// </summary>
774  /// <param name="scalarType">Type of the scalar.</param>
775  /// <param name="memberReference">The member reference.</param>
776  protected virtual void FindMemberTypeReference(ScalarType scalarType, MemberReferenceExpression memberReference)
777  {
778  var components = memberReference.Member.Text;
779  if (components.Length <= 4 && (
780  components.All(x => x == 'x' || x == 'y' || x == 'z' || x == 'w') ||
781  components.All(x => x == 'r' || x == 'g' || x == 'b' || x == 'a') ||
782  components.All(x => x == 's' || x == 't' || x == 'u' || x == 'v')
783  ))
784  {
785  memberReference.TypeInference.TargetType = components.Length == 1 ? (TypeBase)scalarType : new VectorType(scalarType, components.Length);
786  }
787  }
788 
789  /// <summary>
790  /// Resolves the type from declaration.
791  /// </summary>
792  /// <param name="declaration">The declaration.</param>
793  /// <returns>
794  /// A type
795  /// </returns>
797  {
798  TypeBase type = null;
799 
800  if (declaration is Variable)
801  {
802  var variableDeclaration = (Variable)declaration;
803  type = variableDeclaration.Type.ResolveType();
804  }
805  else if (declaration is TypeBase)
806  {
807  type = ((TypeBase)declaration).ResolveType();
808  }
809  else if (declaration is GenericDeclaration)
810  {
811  var genericDeclaration = (GenericDeclaration)declaration;
812  type = genericDeclaration.Holder.GenericParameters[genericDeclaration.Index].ResolveType();
813  }
814 
815  if (type is TypeName)
816  {
817  type = ResolveTypeFromDeclaration(type.TypeInference.Declaration);
818  }
819 
820  return type;
821  }
822 
823  class FunctionOverloadScore
824  {
825  public MethodDeclaration Declaration { get; set; }
826  public TypeBase ReturnType { get; set; }
827  public TypeBase[] ParameterTypes { get; set; }
828  public int Score { get; set; }
829 
830  public override string ToString()
831  {
832  return string.Format("#{0} {1}", Score, Declaration);
833  }
834  }
835 
836  #endregion
837  }
838 }
Base class for all vector types
Definition: VectorType.cs:10
static readonly MessageCode ErrorNoReferencedMethod
Definition: MessageCode.cs:44
virtual bool TestMethodInvocationArgument(TypeBase argTypeBase, TypeBase expectedTypeBase, TypeBase argType, TypeBase expectedType, ref int score)
Tests the arguments of the method
Describes a binary expression.
Tag a visitable method with this attribute.
Definition: VisitorBase.cs:295
UnaryOperator
Unary operator used in all binary expressions (except assignment expression).
A typeless reference.
Definition: TypeName.cs:10
TypeInference TypeInference
Gets or sets the resolved reference.
Definition: TypeBase.cs:69
SourceSpan Span
Gets or sets the source span.
Definition: Node.cs:37
virtual void Visit(BinaryExpression binaryExpression)
Visits the specified binary expression.
virtual void ProcessIndexerExpression(IndexerExpression indexerExpression)
Find the type of the expression
virtual void Visit(AssignmentExpression assignmentExpression)
Visits the specified assignement expression.
virtual void FindMemberTypeReference(VectorType vectorType, MemberReferenceExpression memberReference)
Finds the member type reference.
A generic declaration. This is used internally to identify a generic declaration. ...
virtual void Visit(ReturnStatement returnStatement)
Shader Shader
Gets or sets the shader.
static readonly MessageCode WarningTypeInferenceUnknownExpression
Definition: MessageCode.cs:34
static bool HasDimensions(TypeBase typeDeclaration)
Definition: TypeBase.cs:134
An expression surrounded by parenthesis.
A method definition with a body of statements.
virtual void Visit(IfStatement ifStatement)
Abstract node.
Definition: Node.cs:15
virtual void Visit(LiteralExpression literalExpression)
Visits the specified literal expression.
IDeclaration Declaration
Gets or sets the declaration.
virtual TypeBase Visit(TypeName typeName)
Visits the specified type name.
virtual void Visit(MemberReferenceExpression memberReference)
Visits the specified member reference.
override void Run()
Runs this instance.
virtual ArrayType Visit(ArrayType arrayType)
Visits the specified array type.
virtual void Visit(ParenthesizedExpression parenthesizedExpression)
Visits the specified parenthesized expression.
virtual void ProcessMethodInvocation(MethodInvocationExpression expression, string methodName, List< IDeclaration > declarations)
Pres the process method invocation.
virtual IEnumerable< IDeclaration > FindDeclarationsFromObject(TypeBase typeBase, string memberName)
A variable declaration.
Definition: Variable.cs:11
virtual void Visit(UnaryExpression unaryExpression)
Visits the specified unary expression.
static readonly MessageCode ErrorIndexerType
Definition: MessageCode.cs:41
virtual void Visit(ConditionalExpression conditionalExpression)
Visits the specified conditional expression.
static readonly MessageCode WarningTypeAsConstructor
Definition: MessageCode.cs:33
virtual void Visit(ExpressionList expressionList)
Visits the specified expression list.
A member reference in the form {this}.{Name}
HRESULT Convert(_In_ const Image &srcImage, _In_ DXGI_FORMAT format, _In_ DWORD filter, _In_ float threshold, _Out_ ScratchImage &image)
Base type for all types.
Definition: TypeBase.cs:11
virtual void Visit(MethodInvocationExpression expression)
Visits the specified method invocation expression.
SemanticAnalysis(ParsingResult result)
Initializes a new instance of the SemanticAnalysis class.
virtual void CommonVisit(MemberReferenceExpression memberReference)
Visits the specified member reference.
static readonly MessageCode ErrorNoTypeReferenceTypename
Definition: MessageCode.cs:46
static readonly MessageCode ErrorNoOverloadedMethod
Definition: MessageCode.cs:43
Toplevel interface for a declaration.
Definition: IDeclaration.cs:8
virtual void FindMemberTypeReference(StructType structType, MemberReferenceExpression memberReference)
Finds the member type reference.
virtual void Visit(VariableReferenceExpression variableReferenceExpression)
Visits the specified variable reference expression.
virtual void FindMemberTypeReference(ScalarType scalarType, MemberReferenceExpression memberReference)
Finds the member type reference.
TypeBase ResolveTypeFromDeclaration(IDeclaration declaration)
Resolves the type from declaration.
virtual MethodDefinition Visit(MethodDefinition methodDefinition)
Visits the specified member reference.
static readonly MessageCode ErrorLiteralType
Definition: MessageCode.cs:42
A Type reference analysis is building type references.
static readonly MessageCode ErrorNoTypeReferenceMember
Definition: MessageCode.cs:45
virtual void Visit(IndexerExpression indexerExpression)
Visits the specified indexer expression.