bool Handle(TemplateValueParameter p, ISemantic arg) { // Handle default arg case if (arg == null) { if (p.DefaultExpression != null) { var eval = Evaluation.EvaluateValue(p.DefaultExpression, ctxt); if (eval == null) { return(false); } return(Set(p, eval)); } else { return(false); } } var valueArgument = arg as ISymbolValue; // There must be a constant expression given! if (valueArgument == null) { return(false); } // Check for param type <-> arg expression type match var paramType = TypeDeclarationResolver.Resolve(p.Type, ctxt); if (paramType == null || paramType.Length == 0) { return(false); } if (valueArgument.RepresentedType == null || !ResultComparer.IsImplicitlyConvertible(paramType[0], valueArgument.RepresentedType)) { return(false); } // If spec given, test for equality (only ?) if (p.SpecializationExpression != null) { var specVal = Evaluation.EvaluateValue(p.SpecializationExpression, ctxt); if (specVal == null || !SymbolValueComparer.IsEqual(specVal, valueArgument)) { return(false); } } return(Set(p, arg)); }
/// <summary> /// Checks given results for type equality /// </summary> public static bool IsEqual(ISemantic r1, ISemantic r2) { if (r1 is ISymbolValue && r2 is ISymbolValue) { return(SymbolValueComparer.IsEqual((ISymbolValue)r1, (ISymbolValue)r2)); } else if (r1 is TemplateIntermediateType && r2 is TemplateIntermediateType) { var tr1 = (TemplateIntermediateType)r1; var tr2 = (TemplateIntermediateType)r2; if (tr1.Definition != tr2.Definition) { return(false); } //TODO: Compare deduced types return(true); } else if (r1 is PrimitiveType && r2 is PrimitiveType) { return(((PrimitiveType)r1).TypeToken == ((PrimitiveType)r2).TypeToken); } else if (r1 is ArrayType && r2 is ArrayType) { var ar1 = (ArrayType)r1; var ar2 = (ArrayType)r2; if (!IsEqual(ar1.KeyType, ar2.KeyType)) { return(false); } return(IsEqual(ar1.Base, ar2.Base)); } //TODO: Handle other types return(false); }
bool HandleDecl(TemplateTypeParameter parameterRef, ArrayDecl arrayDeclToCheckAgainst, AssocArrayType argumentArrayType) { if (argumentArrayType == null) { return(false); } // Handle key type var at = argumentArrayType as ArrayType; if ((arrayDeclToCheckAgainst.ClampsEmpty == (at == null)) && (at == null || !at.IsStaticArray || arrayDeclToCheckAgainst.KeyExpression == null)) { return(false); } bool result; if (arrayDeclToCheckAgainst.KeyExpression != null) { // Remove all surrounding parentheses from the expression var x_param = arrayDeclToCheckAgainst.KeyExpression; while (x_param is SurroundingParenthesesExpression) { x_param = ((SurroundingParenthesesExpression)x_param).Expression; } var ad_Argument = argumentArrayType.DeclarationOrExpressionBase as ArrayDecl; /* * This might be critical: * the [n] part in class myClass(T:char[n], int n) {} * will be seen as an identifier expression, not as an identifier declaration. * So in the case the parameter expression is an identifier, * test if it's part of the parameter list */ var id = x_param as IdentifierExpression; if (id != null && id.IsIdentifier && Contains(id.ValueStringHash)) { // If an expression (the usual case) has been passed as argument, evaluate its value, otherwise is its type already resolved. ISemantic finalArg = null; if (ad_Argument != null && ad_Argument.KeyExpression != null) { ISymbolValue val = null; int len = -1; finalArg = TypeDeclarationResolver.ResolveKey(ad_Argument, out len, out val, ctxt); if (val != null) { finalArg = val; } } else { finalArg = argumentArrayType.KeyType; } //TODO: Do a type convertability check between the param type and the given argument's type. // The affected parameter must also be a value parameter then, if an expression was given. // and handle it as if it was an identifier declaration.. result = Set(parameterRef, finalArg, id.ValueStringHash); } else if (ad_Argument != null && ad_Argument.KeyExpression != null) { // Just test for equality of the argument and parameter expression, e.g. if both param and arg are 123, the result will be true. result = SymbolValueComparer.IsEqual(arrayDeclToCheckAgainst.KeyExpression, ad_Argument.KeyExpression, new StandardValueProvider(ctxt)); } else { result = false; } if (!result) { return(false); } } else if (arrayDeclToCheckAgainst.KeyType != null) { // If the array we're passing to the decl check that is static (i.e. has a constant number as key 'type'), // pass that number instead of type 'int' to the check. if (argumentArrayType != null && at != null && at.IsStaticArray) { result = HandleDecl(parameterRef, arrayDeclToCheckAgainst.KeyType, new PrimitiveValue(D_Parser.Parser.DTokens.Int, (decimal)at.FixedLength, null)); } else { result = HandleDecl(parameterRef, arrayDeclToCheckAgainst.KeyType, argumentArrayType.KeyType); } if (!result) { return(false); } } // Handle inner type return(HandleDecl(parameterRef, arrayDeclToCheckAgainst.InnerDeclaration, argumentArrayType.Base)); }
/// <summary> /// Checks given results for type equality /// </summary> public static bool IsEqual(ISemantic r1, ISemantic r2) { if (r1 == r2) { return(true); } if (r1 is TemplateParameterSymbol) { var tps1 = r1 as TemplateParameterSymbol; var tps2 = r2 as TemplateParameterSymbol; if (tps2 != null && tps1.Parameter == tps2.Parameter) { return((tps1.Base == null && tps2.Base == null) || IsEqual(tps1.Base, tps2.Base)); } if (TemplateInstanceHandler.IsNonFinalArgument(r2)) { return(true); } r1 = tps1.Base; } if (r2 is TemplateParameterSymbol) { r2 = ((TemplateParameterSymbol)r2).Base; } if (r1 is ISymbolValue && r2 is ISymbolValue) { return(SymbolValueComparer.IsEqual((ISymbolValue)r1, (ISymbolValue)r2)); } else if (r1 is TemplateIntermediateType && r2 is TemplateIntermediateType) { var tr1 = (TemplateIntermediateType)r1; var tr2 = (TemplateIntermediateType)r2; if (tr1.Definition != tr2.Definition) { return(false); } //TODO: Compare deduced types return(true); } else if (r1 is PrimitiveType && r2 is PrimitiveType) { return(((PrimitiveType)r1).TypeToken == ((PrimitiveType)r2).TypeToken); } else if (r1 is ArrayType && r2 is ArrayType) { var ar1 = (ArrayType)r1; var ar2 = (ArrayType)r2; if (!IsEqual(ar1.KeyType, ar2.KeyType)) { return(false); } return(IsEqual(ar1.Base, ar2.Base)); } else if (r1 is DelegateType && r2 is DelegateType) { var dg1 = r1 as DelegateType; var dg2 = r2 as DelegateType; if (dg1.IsFunctionLiteral != dg2.IsFunctionLiteral || !IsEqual(dg1.ReturnType, dg2.ReturnType)) { return(false); } if (dg1.Parameters == null || dg1.Parameters.Length == 0) { return(dg2.Parameters == null || dg2.Parameters.Length == 0); } else if (dg2.Parameters == null) { return(dg1.Parameters == null || dg1.Parameters.Length == 0); } else if (dg1.Parameters.Length == dg2.Parameters.Length) { for (int i = dg1.Parameters.Length - 1; i != 0; i--) { if (!IsEqual(dg1.Parameters[i], dg2.Parameters[i])) { return(false); } } return(true); } } //TODO: Handle other types return(false); }