public override Node Visit(AssignmentExpression assignmentExpression) { var variable = GetUniform(assignmentExpression.Target); bool isMemberExpression = assignmentExpression.Target is MemberReferenceExpression; if (variable != null) { // Default == operator is the only write only operators if (assignmentExpression.Operator == AssignmentOperator.Default && !uniformReadList.Contains(variable) && !this.UniformUsedWriteFirstList.Contains(variable)) { // Handle the case where the assignment operator is partial like vect.xy = 5; and later vect.zw += 6; // In this case, the variable is considered as read and write (and not only write first) if (isMemberExpression) { var variableType = variable.Type.ResolveType(); if (variableType is VectorType || variableType is MatrixType) { var dim = Math.Max(TypeBase.GetDimensionSize(variableType, 0), TypeBase.GetDimensionSize(variableType, 1)); var memberRef = assignmentExpression.Target as MemberReferenceExpression; var numberOfMembers = memberRef.Member.Text.Length; // If the variable is a global uniform, non static/const and is not already in the list used then if (numberOfMembers < dim) { if (!uniformReadList.Contains(variable)) { uniformReadList.Add(variable); } } else { UniformUsedWriteFirstList.Add(variable); } } } else { UniformUsedWriteFirstList.Add(variable); } } if (assignmentExpression.Operator != AssignmentOperator.Default) { if (!UniformReadWriteList.Contains(variable)) { UniformReadWriteList.Add(variable); } } } return(assignmentExpression); }
/// <summary> /// Tests the arguments of the method /// </summary> /// <param name="argTypeBase">the argument typebase</param> /// <param name="expectedTypeBase">the expected typebase</param> /// <param name="argType">the argument type</param> /// <param name="expectedType">the expected type</param> /// <param name="score">the score of the overload</param> /// <returns>true if the overload is correct, false otherwise</returns> protected virtual bool TestMethodInvocationArgument(TypeBase argTypeBase, TypeBase expectedTypeBase, TypeBase argType, TypeBase expectedType, ref int score) { var validOverload = true; // If Scalar, Vector or Matrix, check types if (TypeBase.HasDimensions(argType) && TypeBase.HasDimensions(expectedType)) { if (argType != expectedType) { int argDim1 = TypeBase.GetDimensionSize(argType, 0); int argDim2 = TypeBase.GetDimensionSize(argType, 1); int expectedDim1 = TypeBase.GetDimensionSize(expectedType, 0); int expectedDim2 = TypeBase.GetDimensionSize(expectedType, 1); // float3<=>float1x3 and float3<=>float3x1 implicit conversion are allowed, // but float3x1<=>float1x3 should not be allowed // float3<=>float1x3 and float1x1<=>float1<=>float if (argDim1 == expectedDim1 && argDim2 == expectedDim2) { score++; } else if (((argType is VectorType && expectedType is MatrixType) || (argType is MatrixType && expectedType is VectorType)) && (argDim1 == expectedDim2 && argDim2 == expectedDim1)) { // float3<=>float3x1 score++; } else if (argDim1 == 1 && argDim2 == 1) { // allow float=>float3x2 and float=>float3 score += 10; // +10 for scalar=>vector or scalar=>matrix expansion } else if (argDim1 >= expectedDim1 && argDim2 >= expectedDim2) { // Truncation // +100 for truncation (by rank difference) score += 100 * (argDim1 + argDim2 - expectedDim1 - expectedDim2); } else { // Could not find any matching implicit conversion validOverload = false; } } } else if (argType is ArrayType && expectedType is ArrayType) { var argArrayType = (ArrayType)argType; var expectedArrayType = (ArrayType)expectedType; if (argArrayType != expectedArrayType) { validOverload = false; } } else if (argType is StructType && expectedType is StructType) { var argStructType = (StructType)argType; var expectedStructType = (StructType)expectedType; if (argStructType.Name != expectedStructType.Name) { validOverload = false; } } else if (!((argType is ObjectType && expectedType is ObjectType) || (argType is StructType && expectedType is StructType))) { // Could not find any matching implicit conversion validOverload = false; } return(validOverload); }