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));
        }
Ejemplo n.º 2
0
        /// <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));
        }
Ejemplo n.º 4
0
        /// <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);
        }