4 using System.Collections.Generic;
6 using SiliconStudio.Shaders.Ast;
7 using SiliconStudio.Shaders.Parser;
8 using SiliconStudio.Shaders.Utility;
9 using SiliconStudio.Shaders.Visitor;
11 namespace SiliconStudio.Shaders.Analysis
18 protected static string TagBuiltinUserDefined =
"TagBuiltinUserDefined";
20 #region Constructors and Destructors
40 protected bool IsSkippingMode {
get; set; }
42 #region Public Methods
45 public override void Run()
57 Visit((
Node)assignmentExpression);
60 assignmentExpression.TypeInference = (
TypeInference)assignmentExpression.Target.TypeInference.Clone();
72 Visit((
Node)binaryExpression);
74 var leftType = binaryExpression.Left.TypeInference.TargetType;
75 var rightType = binaryExpression.Right.TypeInference.TargetType;
78 if (leftType == null || rightType == null)
return;
80 switch (binaryExpression.Operator)
82 case BinaryOperator.Multiply:
83 binaryExpression.TypeInference.TargetType = GetMultiplyImplicitConversionType(binaryExpression.
Span, leftType, rightType);
85 case BinaryOperator.Divide:
86 binaryExpression.TypeInference.TargetType = GetDivideImplicitConversionType(binaryExpression.
Span, leftType, rightType);
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);
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);
119 Visit((
Node)conditionalExpression);
122 var leftType = conditionalExpression.Left.TypeInference.TargetType;
123 var rightType = conditionalExpression.Right.TypeInference.TargetType;
125 conditionalExpression.TypeInference.TargetType = leftType;
129 conditionalExpression.TypeInference.TargetType = rightType;
140 Visit((
Node)indexerExpression);
142 ProcessIndexerExpression(indexerExpression);
152 var targetType = indexerExpression.Target.TypeInference.TargetType;
156 var arrayType = (ArrayType)targetType;
157 if (arrayType.Dimensions.Count == 1)
159 type = arrayType.Type.ResolveType();
163 var dimensions =
new List<Expression>(arrayType.Dimensions);
164 dimensions.RemoveAt(0);
165 type =
new ArrayType(arrayType.Type, dimensions.ToArray());
170 type = ((VectorType)targetType).Type.ResolveType();
174 type =
new VectorType((
ScalarType)((MatrixType)targetType).Type.ResolveType(), ((MatrixType)targetType).ColumnCount);
177 indexerExpression.TypeInference.TargetType = type;
189 Visit((
Node)literalExpression);
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;
204 if (literalExpression.TypeInference.TargetType == null)
214 Visit((
Node)returnStatement);
216 if (returnStatement.Value != null)
219 returnStatement.Value.TypeInference.ExpectedType = function.ReturnType.ResolveType();
227 Visit((
Node)ifStatement);
229 ifStatement.Condition.TypeInference.ExpectedType = ScalarType.Bool;
242 var argumentTypeInferences = expression.Arguments.Select(x => x.TypeInference).ToArray();
243 var argumentTypes = expression.Arguments.Select(x => x.TypeInference.TargetType).ToArray();
246 if (argumentTypes.Any(x => x == null))
249 var overloads =
new List<FunctionOverloadScore>();
255 for (
int i = 0; i < methodsDeclared.Count - 1; i++)
257 var leftMethod = methodsDeclared[i];
258 for (
int j = i + 1; j < methodsDeclared.Count; j++)
260 if (leftMethod.IsSameSignature(methodsDeclared[j]))
262 methodsDeclared.RemoveAt(i);
270 foreach (var methodDeclaration
in methodsDeclared)
272 var returnType = methodDeclaration.ReturnType.ResolveType();
273 var parameterTypes = methodDeclaration.Parameters.Select(x => x.Type.ResolveType()).ToArray();
276 if (argumentTypes.Length > parameterTypes.Length)
continue;
279 if (argumentTypes.Length < parameterTypes.Length)
281 bool allRemainingParametersHaveDefaultValues =
true;
283 for (
int i = argumentTypes.Length; i < parameterTypes.Length; i++)
285 if (methodDeclaration.Parameters[i].InitialValue == null)
287 allRemainingParametersHaveDefaultValues =
false;
293 if (!allRemainingParametersHaveDefaultValues)
continue;
298 bool validOverload =
true;
301 for (
int i = 0; i < argumentTypes.Length && validOverload; ++i)
303 var argType = argumentTypes[i];
304 var expectedType = parameterTypes[i];
306 var argTypeBase = TypeBase.GetBaseType(argType);
307 var expectedTypeBase = TypeBase.GetBaseType(expectedType);
311 var genericParameterType = (GenericParameterType)expectedTypeBase;
314 if (methodDeclaration.CheckConstraint(genericParameterType, argType))
320 validOverload =
false;
328 var fromScalarType = argTypeBase as
ScalarType;
329 var toScalarType = expectedTypeBase as ScalarType;
331 if (fromScalarType != null && toScalarType != null)
333 if (ScalarType.IsFloat(fromScalarType) && !ScalarType.IsFloat(toScalarType))
338 else if (fromScalarType != toScalarType)
344 if (!fromScalarType.IsUnsigned && toScalarType.IsUnsigned)
352 if (argTypeBase != expectedTypeBase && expectedTypeBase is ScalarType)
354 if (!(argTypeBase is ScalarType))
358 argType = TypeBase.CreateWithBaseType(argType, (ScalarType)expectedTypeBase);
361 validOverload = TestMethodInvocationArgument(argTypeBase, expectedTypeBase, argType, expectedType, ref score);
367 new FunctionOverloadScore { Declaration = methodDeclaration, ParameterTypes = parameterTypes, ReturnType = returnType, Score = score });
371 var bestOverload = overloads.OrderBy(x => x.Score).FirstOrDefault();
373 if (bestOverload != null)
375 expression.TypeInference.TargetType = bestOverload.ReturnType.ResolveType();
378 expression.Target.TypeInference.Declaration = bestOverload.Declaration;
381 for (
int i = 0; i < argumentTypes.Length; ++i)
383 argumentTypeInferences[i].ExpectedType = (bestOverload.ParameterTypes[i] is
GenericParameterType)
385 : bestOverload.ParameterTypes[i].ResolveType();
405 var validOverload =
true;
410 if (argType != expectedType)
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);
420 if (argDim1 == expectedDim1 && argDim2 == expectedDim2)
425 && (argDim1 == expectedDim2 && argDim2 == expectedDim1))
430 else if (argDim1 == 1 && argDim2 == 1)
435 else if (argDim1 >= expectedDim1 && argDim2 >= expectedDim2)
439 score += 100 * (argDim1 + argDim2 - expectedDim1 - expectedDim2);
444 validOverload =
false;
450 var argArrayType = (ArrayType)argType;
451 var expectedArrayType = (ArrayType)expectedType;
453 if (argArrayType != expectedArrayType)
454 validOverload =
false;
458 var argStructType = (StructType)argType;
459 var expectedStructType = (StructType)expectedType;
461 if (argStructType.Name != expectedStructType.Name)
462 validOverload =
false;
464 else if (!((argType is
ObjectType && expectedType is
ObjectType) || (argType is StructType && expectedType is StructType)))
467 validOverload =
false;
470 return validOverload;
480 Visit((
Node)expression);
490 if (methodAsVariable != null)
492 methodName = methodAsVariable.Name.Text;
493 declarationsIterator = FindDeclarations(methodAsVariable.Name);
495 else if (methodAsType != null)
497 var returnType = methodAsType.Type.ResolveType();
498 expression.TypeInference.TargetType = returnType;
510 var memberReferenceExpression = target;
512 declarationsIterator = FindDeclarationsFromObject(memberReferenceExpression.Target.TypeInference.TargetType, memberReferenceExpression.Member.Text);
513 methodName = string.Format(
"{0}", target);
518 methodName = string.Format(
"{0}", expression.Target);
523 if (declarationsIterator == null)
530 var declarations = declarationsIterator.ToList();
531 ProcessMethodInvocation(expression, methodName, declarations);
546 Visit((
Node)memberReference);
548 CommonVisit(memberReference);
562 Visit((
Node)methodDefinition);
565 foreach (var declaration
in FindDeclarations(methodDefinition.Name))
568 if (methodDeclaration != null && !ReferenceEquals(declaration, methodDefinition))
570 if (methodDeclaration.IsSameSignature(methodDefinition))
572 methodDefinition.Declaration = methodDeclaration;
574 if (methodDeclaration.GetTag(TagBuiltinUserDefined) != null)
580 return methodDefinition;
589 var thisType = memberReference.Target.TypeInference.TargetType;
592 FindMemberTypeReference((StructType)thisType, memberReference);
594 FindMemberTypeReference((ScalarType)thisType, memberReference);
596 FindMemberTypeReference((VectorType)thisType, memberReference);
606 Visit((
Node)parenthesizedExpression);
609 parenthesizedExpression.TypeInference = (
TypeInference)parenthesizedExpression.Content.TypeInference.Clone();
619 Visit((
Node)expressionList);
622 expressionList.TypeInference = (
TypeInference)expressionList[expressionList.Count - 1].TypeInference.Clone();
632 Visit((
Node)arrayType);
635 if (arrayType.TypeInference.TargetType == null
640 var results = arrayType.Dimensions.Select(evaluator.Evaluate).ToArray();
642 if (results.Any(x => x.HasErrors))
644 foreach (var result
in results.Where(x => x.HasErrors))
663 Visit((
Node)typeName);
665 if (typeName.TypeInference.TargetType == null)
667 if (typeName.Name.Text ==
"void")
669 typeName.TypeInference.TargetType = TypeBase.Void;
671 else if (typeName.Name.Text ==
"string")
673 typeName.TypeInference.TargetType = TypeBase.String;
677 var declaration = FindDeclaration(typeName.Name);
678 if (declaration != null)
681 var typeReference = typeName.TypeInference;
682 typeReference.Declaration = declaration;
683 typeReference.TargetType = ResolveTypeFromDeclaration(typeReference.Declaration);
701 Visit((
Node)variableReferenceExpression);
703 var typeReference = variableReferenceExpression.TypeInference;
704 typeReference.Declaration = FindDeclaration(variableReferenceExpression.Name);
705 typeReference.TargetType = ResolveTypeFromDeclaration(typeReference.Declaration);
715 Visit((
Node)unaryExpression);
718 unaryExpression.TypeInference = (
TypeInference)unaryExpression.Expression.TypeInference.Clone();
721 var subType = unaryExpression.Expression.TypeInference.TargetType;
722 if (subType != null && unaryExpression.Operator ==
UnaryOperator.LogicalNot)
723 unaryExpression.TypeInference.TargetType = TypeBase.CreateWithBaseType(subType, ScalarType.Bool);
737 foreach (var field
in structType.Fields)
739 foreach (var variableDeclarator
in field.Instances())
741 if (variableDeclarator.Name == memberReference.Member)
743 memberReference.TypeInference.Declaration = variableDeclarator;
744 memberReference.TypeInference.TargetType = variableDeclarator.Type.ResolveType();
758 var scalarType = vectorType.Type.ResolveType();
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')
767 memberReference.TypeInference.TargetType = components.Length == 1 ? scalarType :
new VectorType((
ScalarType)scalarType, components.Length);
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')
785 memberReference.TypeInference.TargetType = components.Length == 1 ? (
TypeBase)scalarType :
new VectorType(scalarType, components.Length);
802 var variableDeclaration = (Variable)declaration;
803 type = variableDeclaration.Type.ResolveType();
807 type = ((TypeBase)declaration).ResolveType();
811 var genericDeclaration = (GenericDeclaration)declaration;
812 type = genericDeclaration.Holder.GenericParameters[genericDeclaration.Index].ResolveType();
823 class FunctionOverloadScore
826 public TypeBase ReturnType {
get; set; }
827 public TypeBase[] ParameterTypes {
get; set; }
828 public int Score {
get; set; }
830 public override string ToString()
832 return string.Format(
"#{0} {1}", Score, Declaration);
Base class for all vector types
static readonly MessageCode ErrorNoReferencedMethod
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.
UnaryOperator
Unary operator used in all binary expressions (except assignment expression).
TypeInference TypeInference
Gets or sets the resolved reference.
SourceSpan Span
Gets or sets the source span.
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
static bool HasDimensions(TypeBase typeDeclaration)
An expression surrounded by parenthesis.
A method definition with a body of statements.
virtual void Visit(IfStatement ifStatement)
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.
A reference to a variable.
virtual void ProcessMethodInvocation(MethodInvocationExpression expression, string methodName, List< IDeclaration > declarations)
Pres the process method invocation.
virtual IEnumerable< IDeclaration > FindDeclarationsFromObject(TypeBase typeBase, string memberName)
virtual void Visit(UnaryExpression unaryExpression)
Visits the specified unary expression.
static readonly MessageCode ErrorIndexerType
virtual void Visit(ConditionalExpression conditionalExpression)
Visits the specified conditional expression.
static readonly MessageCode WarningTypeAsConstructor
virtual void Visit(ExpressionList expressionList)
Visits the specified expression list.
A member reference in the form {this}.{Name}
Defines a generic parameter type.
HRESULT Convert(_In_ const Image &srcImage, _In_ DXGI_FORMAT format, _In_ DWORD filter, _In_ float threshold, _Out_ ScratchImage &image)
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.
A reference to a variable.
static readonly MessageCode ErrorNoTypeReferenceTypename
static readonly MessageCode ErrorNoOverloadedMethod
Toplevel interface for a declaration.
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
A Type reference analysis is building type references.
static readonly MessageCode ErrorNoTypeReferenceMember
virtual void Visit(IndexerExpression indexerExpression)
Visits the specified indexer expression.