Esempio n. 1
0
        public ISymbolValue Visit(TemplateInstanceExpression tix)
        {
            var ImplicitlyExecute = this.ImplicitlyExecute;

            this.ImplicitlyExecute = true;

            return(TryDoCTFEOrGetValueRefs(AmbiguousType.Get(ExpressionTypeEvaluation.GetOverloads(tix, ctxt), tix), tix, ImplicitlyExecute));
        }
Esempio n. 2
0
        public ISymbolValue Visit(TemplateInstanceExpression tix)
        {
            var ImplicitlyExecute = this.ImplicitlyExecute;

            this.ImplicitlyExecute = true;

            var o = DResolver.StripAliasSymbols(ExpressionTypeEvaluation.GetOverloads(tix, ctxt));

            return(TryDoCTFEOrGetValueRefs(o, tix, ImplicitlyExecute));
        }
Esempio n. 3
0
        public static AbstractType EvaluateType(IExpression x, ResolutionContext ctxt)
        {
            var ev = new ExpressionTypeEvaluation(ctxt);

            if (!Debugger.IsAttached)
            {
                try { return(x.Accept(ev)); }
                catch { return(null); }
            }
            else
            {
                return(x.Accept(ev));
            }
        }
Esempio n. 4
0
        void GetRawCallOverloads(ResolutionContext ctxt, IExpression callForeExpression,
                                 out AbstractType[] baseExpression,
                                 out TemplateInstanceExpression tix)
        {
            tix = null;

            if (callForeExpression is PostfixExpression_Access)
            {
                var pac = (PostfixExpression_Access)callForeExpression;
                tix = pac.AccessExpression as TemplateInstanceExpression;

                baseExpression = Evaluation.EvalPostfixAccessExpression(this, ctxt, pac, null, false, false);
            }
            else
            {
                // Explicitly don't resolve the methods' return types - it'll be done after filtering to e.g. resolve template types to the deduced one
                var optBackup = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;

                if (callForeExpression is TokenExpression)
                {
                    baseExpression = ExpressionTypeEvaluation.GetResolvedConstructorOverloads((TokenExpression)callForeExpression, ctxt);
                }
                else
                {
                    if (callForeExpression is TemplateInstanceExpression)
                    {
                        baseExpression = ExpressionTypeEvaluation.GetOverloads(tix = (TemplateInstanceExpression)callForeExpression, ctxt, null, false);
                    }
                    else if (callForeExpression is IdentifierExpression)
                    {
                        baseExpression = ExpressionTypeEvaluation.GetOverloads(callForeExpression as IdentifierExpression, ctxt, deduceParameters: false);
                    }
                    else
                    {
                        baseExpression = new[] { callForeExpression != null?AbstractType.Get(callForeExpression.Accept(this)) : null }
                    };
                }

                ctxt.CurrentContext.ContextDependentOptions = optBackup;
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Since most expressions should return a single type only, it's not needed to use this function unless you might
        /// want to pay attention on (illegal) multiple overloads.
        /// </summary>
        public static AbstractType[] EvaluateTypes(IExpression x, ResolutionContext ctxt)
        {
            var          ev = new ExpressionTypeEvaluation(ctxt);
            AbstractType t;

            if (!Debugger.IsAttached)
            {
                try { t = x.Accept(ev); }
                catch { t = null; }
            }
            else
            {
                t = x.Accept(ev);
            }

            if (t is AmbiguousType)
            {
                return(((AmbiguousType)t).Overloads);
            }

            return(t == null ? null : new[] { t });
        }
        /// <summary>
        /// Returns either all unfiltered and undeduced overloads of a member of a base type/value (like b from type a if the expression is a.b).
        /// if <param name="EvalAndFilterOverloads"></param> is false.
        /// If true, all overloads will be deduced, filtered and evaluated, so that (in most cases,) a one-item large array gets returned
        /// which stores the return value of the property function b that is executed without arguments.
        /// Also handles UFCS - so if filtering is wanted, the function becom
        /// </summary>
        public static R[] EvalPostfixAccessExpression <R>(ExpressionVisitor <R> vis, ResolutionContext ctxt, PostfixExpression_Access acc,
                                                          ISemantic resultBase = null, bool EvalAndFilterOverloads = true, bool ResolveImmediateBaseType = true, AbstractSymbolValueProvider ValueProvider = null)
            where R : class, ISemantic
        {
            if (acc == null)
            {
                return(null);
            }

            var baseExpression = resultBase ?? (acc.PostfixForeExpression != null ? acc.PostfixForeExpression.Accept(vis) as ISemantic : null);

            if (acc.AccessExpression is NewExpression)
            {
                /*
                 * This can be both a normal new-Expression as well as an anonymous class declaration!
                 */
                //TODO!
                return(null);
            }


            AbstractType[] overloads;
            var            optBackup = ctxt.CurrentContext.ContextDependentOptions;

            if (acc.AccessExpression is TemplateInstanceExpression)
            {
                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;
                }

                var tix = (TemplateInstanceExpression)acc.AccessExpression;
                // Do not deduce and filter if superior expression is a method call since call arguments' types also count as template arguments!
                overloads = ExpressionTypeEvaluation.GetOverloads(tix, ctxt, new[] { AbstractType.Get(baseExpression) }, EvalAndFilterOverloads);

                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions = optBackup;
                }
            }

            else if (acc.AccessExpression is IdentifierExpression)
            {
                var id = acc.AccessExpression as IdentifierExpression;

                if (ValueProvider != null && EvalAndFilterOverloads && baseExpression != null)
                {
                    var staticPropResult = StaticProperties.TryEvalPropertyValue(ValueProvider, baseExpression, id.ValueStringHash);
                    if (staticPropResult != null)
                    {
                        return new[] { (R)staticPropResult }
                    }
                    ;
                }

                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;
                }

                overloads = ExpressionTypeEvaluation.GetOverloads(id, ctxt, AmbiguousType.TryDissolve(AbstractType.Get(baseExpression)), EvalAndFilterOverloads);

                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions = optBackup;
                }
            }
            else
            {            /*
                          *     if (eval){
                          *             EvalError(acc, "Invalid access expression");
                          *             return null;
                          *     }*/
                ctxt.LogError(acc, "Invalid post-dot expression");
                return(null);
            }

            // If evaluation active and the access expression is stand-alone, return a single item only.
            if (EvalAndFilterOverloads && ValueProvider != null)
            {
                return new[] { (R) new Evaluation(ValueProvider).TryDoCTFEOrGetValueRefs(AmbiguousType.Get(overloads, acc.AccessExpression), acc.AccessExpression) }
            }
            ;

            return(overloads as R[]);
        }

        ISymbolValue EvalForeExpression(PostfixExpression ex)
        {
            return(ex.PostfixForeExpression != null?ex.PostfixForeExpression.Accept(this) : null);
        }
        void GetRawCallOverloads(ResolutionContext ctxt, PostfixExpression_MethodCall call,
                                 out AbstractType[] baseExpression,
                                 out ISymbolValue baseValue,
                                 out TemplateInstanceExpression tix)
        {
            baseValue = null;
            tix       = null;

            if (call.PostfixForeExpression is PostfixExpression_Access)
            {
                var pac = (PostfixExpression_Access)call.PostfixForeExpression;
                tix = pac.AccessExpression as TemplateInstanceExpression;

                var vs = EvalPostfixAccessExpression(this, ctxt, pac, null, false, false);

                baseExpression = TypeDeclarationResolver.Convert(vs);
            }
            else
            {
                // Explicitly don't resolve the methods' return types - it'll be done after filtering to e.g. resolve template types to the deduced one
                var optBackup = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;

                if (call.PostfixForeExpression is TokenExpression)
                {
                    baseExpression = ExpressionTypeEvaluation.GetResolvedConstructorOverloads((TokenExpression)call.PostfixForeExpression, ctxt);
                }
                else
                {
                    var fore = call.PostfixForeExpression;
                    if (fore is TemplateInstanceExpression)
                    {
                        ImplicitlyExecute = false;
                        tix = call.PostfixForeExpression as TemplateInstanceExpression;
                    }
                    else if (fore is IdentifierExpression)
                    {
                        ImplicitlyExecute = false;
                    }

                    if (call.PostfixForeExpression != null)
                    {
                        baseValue = call.PostfixForeExpression.Accept(this) as ISymbolValue;
                    }

                    if (baseValue is InternalOverloadValue)
                    {
                        baseExpression = ((InternalOverloadValue)baseValue).Overloads;
                    }
                    else if (baseValue != null)
                    {
                        baseExpression = new[] { baseValue.RepresentedType }
                    }
                    ;
                    else
                    {
                        baseExpression = null;
                    }
                }

                ctxt.CurrentContext.ContextDependentOptions = optBackup;
            }
        }
        public static AbstractType EvalMethodCall(AbstractType[] baseExpression, ISymbolValue baseValue, TemplateInstanceExpression tix,
                                                  ResolutionContext ctxt,
                                                  PostfixExpression_MethodCall call, out List <ISemantic> callArguments, out ISymbolValue delegateValue,
                                                  bool returnBaseTypeOnly, AbstractSymbolValueProvider ValueProvider = null)
        {
            //TODO: Refactor this crap!

            delegateValue = null;
            callArguments = null;

            var methodOverloads = new List <AbstractType>();

            #region Search possible methods, opCalls or delegates that could be called
            bool requireStaticItems = true;             //TODO: What if there's an opCall and a foreign method at the same time? - and then this variable would be bullshit
            IEnumerable <AbstractType> scanResults = baseExpression;
            var nextResults = new List <AbstractType>();

            while (scanResults != null)
            {
                foreach (var b in scanResults)
                {
                    if (b is AmbiguousType)
                    {
                        nextResults.AddRange((b as AmbiguousType).Overloads);
                    }
                    else if (b is TemplateParameterSymbol)
                    {
                        nextResults.Add((b as TemplateParameterSymbol).Base);
                    }
                    else if (b is MemberSymbol)
                    {
                        var mr = (MemberSymbol)b;

                        if (mr.Definition is DMethod)
                        {
                            methodOverloads.Add(mr);
                            continue;
                        }
                        else if (mr.Definition is DVariable)
                        {
                            // If we've got a variable here, get its base type/value reference
                            if (ValueProvider != null)
                            {
                                var dgVal = ValueProvider[(DVariable)mr.Definition] as DelegateValue;

                                if (dgVal != null)
                                {
                                    nextResults.Add(dgVal.Definition);
                                    continue;
                                }
                                else
                                {
                                    ValueProvider.LogError(call, "Variable must be a delegate, not anything else");
                                    return(null);
                                }
                            }
                            else
                            {
                                var bt = mr.Base ?? TypeDeclarationResolver.ResolveSingle(mr.Definition.Type, ctxt);

                                // Must be of type delegate
                                if (bt is DelegateType)
                                {
                                    var ret = HandleCallDelegateType(ValueProvider, bt as DelegateType, methodOverloads, returnBaseTypeOnly);
                                    if (ret is ISymbolValue)
                                    {
                                        delegateValue = ret as ISymbolValue;
                                        return(null);
                                    }
                                    else if (ret is AbstractType)
                                    {
                                        return(ret as AbstractType);
                                    }
                                }
                                else
                                {
                                    /*
                                     * If mr.Node is not a method, so e.g. if it's a variable
                                     * pointing to a delegate
                                     *
                                     * class Foo
                                     * {
                                     *	string opCall() {  return "asdf";  }
                                     * }
                                     *
                                     * Foo f=new Foo();
                                     * f(); -- calls opCall, opCall is not static
                                     */
                                    nextResults.Add(bt);
                                    requireStaticItems = false;
                                }
                                //TODO: Can other types work as function/are callable?
                            }
                        }
                    }
                    else if (b is DelegateType)
                    {
                        var ret = HandleCallDelegateType(ValueProvider, b as DelegateType, methodOverloads, returnBaseTypeOnly);
                        if (ret is ISymbolValue)
                        {
                            delegateValue = ret as ISymbolValue;
                            return(null);
                        }
                        else if (ret is AbstractType)
                        {
                            return(ret as AbstractType);
                        }
                    }
                    else if (b is ClassType || b is StructType)
                    {
                        var tit = (TemplateIntermediateType)b;

                        /*
                         * auto a = MyStruct(); -- opCall-Overloads can be used
                         */
                        var classDef = tit.Definition;

                        if (classDef == null)
                        {
                            continue;
                        }

                        foreach (var i in ExpressionTypeEvaluation.GetOpCalls(tit, requireStaticItems))
                        {
                            methodOverloads.Add(TypeDeclarationResolver.HandleNodeMatch(i, ctxt, b, call) as MemberSymbol);
                        }

                        /*
                         * Every struct can contain a default ctor:
                         *
                         * struct S { int a; bool b; }
                         *
                         * auto s = S(1,true); -- ok
                         * auto s2= new S(2,false); -- error, no constructor found!
                         */
                        if (b is StructType && methodOverloads.Count == 0)
                        {
                            //TODO: Deduce parameters
                            return(b);
                        }
                    }

                    /*
                     * If the overload is a template, it quite exclusively means that we'll handle a method that is the only
                     * child inside a template + that is named as the template.
                     */
                    else if (b is TemplateType)
                    {
                        methodOverloads.Add(b);
                    }
                    else if (b is PrimitiveType)                     // dmd 2.066: Uniform Construction Syntax. creal(3) is of type creal.
                    {
                        methodOverloads.Add(b);
                    }
                }

                scanResults = nextResults.Count == 0 ? null : nextResults.ToArray();
                nextResults.Clear();
            }
            #endregion

            if (methodOverloads.Count == 0)
            {
                return(null);
            }

            // Get all arguments' types
            callArguments = new List <ISemantic>();

            if (call.Arguments != null)
            {
                if (ValueProvider != null)
                {
                    foreach (var arg in call.Arguments)
                    {
                        callArguments.Add(arg != null ? Evaluation.EvaluateValue(arg, ValueProvider) : null);
                    }
                }
                else
                {
                    foreach (var arg in call.Arguments)
                    {
                        callArguments.Add(arg != null ? ExpressionTypeEvaluation.EvaluateType(arg, ctxt) : null);
                    }
                }
            }

            #region If explicit template type args were given, try to associate them with each overload
            if (tix != null)
            {
                var args             = TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt);
                var deducedOverloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(methodOverloads, args, true, ctxt);
                methodOverloads.Clear();
                if (deducedOverloads != null)
                {
                    methodOverloads.AddRange(deducedOverloads);
                }
            }
            #endregion

            #region Filter by parameter-argument comparison
            var          argTypeFilteredOverloads   = new List <AbstractType>();
            bool         hasHandledUfcsResultBefore = false;
            AbstractType untemplatedMethodResult    = null;

            foreach (var ov in methodOverloads)
            {
                if (ov is MemberSymbol)
                {
                    HandleDMethodOverload(ctxt, ValueProvider != null, baseValue, callArguments, returnBaseTypeOnly, argTypeFilteredOverloads, ref hasHandledUfcsResultBefore,
                                          ov as MemberSymbol, ref untemplatedMethodResult);
                }
                else if (ov is DelegateType)
                {
                    var dg = ov as DelegateType;
                    var bt = dg.Base ?? TypeDeclarationResolver.GetMethodReturnType(dg, ctxt);

                    //TODO: Param-Arg check

                    if (returnBaseTypeOnly)
                    {
                        argTypeFilteredOverloads.Add(bt);
                    }
                    else
                    {
                        if (dg.Base == null)
                        {
                            if (dg.IsFunctionLiteral)
                            {
                                dg = new DelegateType(bt, dg.DeclarationOrExpressionBase as FunctionLiteral, dg.Parameters);
                            }
                            else
                            {
                                dg = new DelegateType(bt, dg.DeclarationOrExpressionBase as DelegateDeclaration, dg.Parameters);
                            }
                        }
                        argTypeFilteredOverloads.Add(new DelegateCallSymbol(dg, call));
                    }
                }
                else if (ov is PrimitiveType)                 // dmd 2.066: Uniform Construction Syntax. creal(3) is of type creal.
                {
                    if (ValueProvider != null)
                    {
                        if (callArguments == null || callArguments.Count != 1)
                        {
                            ValueProvider.LogError(call, "Uniform construction syntax expects exactly one argument");
                        }
                        else
                        {
                            var pv = callArguments[0] as PrimitiveValue;
                            if (pv == null)
                            {
                                ValueProvider.LogError(call, "Uniform construction syntax expects one built-in scalar value as first argument");
                            }
                            else
                            {
                                delegateValue = new PrimitiveValue(pv.Value, ov as PrimitiveType, pv.ImaginaryPart);
                            }
                        }
                    }

                    argTypeFilteredOverloads.Add(ov);
                }
            }

            // Prefer untemplated methods over templated ones
            if (untemplatedMethodResult != null)
            {
                return(untemplatedMethodResult);
            }
            #endregion

            return(AmbiguousType.Get(argTypeFilteredOverloads, tix));
        }
Esempio n. 9
0
        public ISymbolValue Visit(IdentifierExpression id)
        {
            var ImplicitlyExecute = this.ImplicitlyExecute;

            this.ImplicitlyExecute = true;

            if (id.IsIdentifier)
            {
                var o = ExpressionTypeEvaluation.EvaluateTypes(id, ctxt);

                if (o == null || o.Length == 0)
                {
                    EvalError(id, "Symbol could not be found");
                    return(null);
                }

                return(TryDoCTFEOrGetValueRefs(o, id, ImplicitlyExecute));
            }

            byte tt;

            switch (id.Format)
            {
            case Parser.LiteralFormat.CharLiteral:
                var tk = id.Subformat == LiteralSubformat.Utf32 ? DTokens.Dchar :
                         id.Subformat == LiteralSubformat.Utf16 ? DTokens.Wchar :
                         DTokens.Char;

                return(new PrimitiveValue(tk, Convert.ToDecimal((int)(char)id.Value), id));

            case LiteralFormat.FloatingPoint | LiteralFormat.Scalar:
                var im = id.Subformat.HasFlag(LiteralSubformat.Imaginary);

                tt = im ? DTokens.Idouble : DTokens.Double;

                if (id.Subformat.HasFlag(LiteralSubformat.Float))
                {
                    tt = im ? DTokens.Ifloat : DTokens.Float;
                }
                else if (id.Subformat.HasFlag(LiteralSubformat.Real))
                {
                    tt = im ? DTokens.Ireal : DTokens.Real;
                }

                var v = Convert.ToDecimal(id.Value);

                return(new PrimitiveValue(tt, im ? 0 : v, id, im ? v : 0));

            case LiteralFormat.Scalar:
                var unsigned = id.Subformat.HasFlag(LiteralSubformat.Unsigned);

                if (id.Subformat.HasFlag(LiteralSubformat.Long))
                {
                    tt = unsigned ? DTokens.Ulong : DTokens.Long;
                }
                else
                {
                    tt = unsigned ? DTokens.Uint : DTokens.Int;
                }

                return(new PrimitiveValue(tt, Convert.ToDecimal(id.Value), id));

            case Parser.LiteralFormat.StringLiteral:
            case Parser.LiteralFormat.VerbatimStringLiteral:
                return(new ArrayValue(GetStringType(id.Subformat), id));

            default:
                return(null);
            }
        }
 public ISymbolValue Visit(NewExpression nex)
 {
     //TODO: Create virtual object and call the appropriate ctor, then return the object
     return(TryDoCTFEOrGetValueRefs(ExpressionTypeEvaluation.EvaluateType(nex, ctxt, false), nex));
 }
Esempio n. 11
0
        public ISymbolValue Visit(TraitsExpression te)
        {
            switch (te.Keyword)
            {
            case "":
            case null:
                return(null);

            case "hasMember":
                bool ret           = false;
                var  optionsBackup = ctxt.ContextIndependentOptions;
                ctxt.ContextIndependentOptions = ResolutionOptions.IgnoreAllProtectionAttributes;

                AbstractType t;
                var          pfa = ExpressionTypeEvaluation.prepareMemberTraitExpression(ctxt, te, out t, ValueProvider);

                if (pfa != null && t != null)
                {
                    ignoreErrors = true;
                    ret          = EvalPostfixAccessExpression(this, ctxt, pfa, t, false) != null;
                    ignoreErrors = false;
                }
                ctxt.ContextIndependentOptions = optionsBackup;
                return(new PrimitiveValue(ret, te));


            case "identifier":
                if (te.Arguments != null && te.Arguments.Length == 1)
                {
                    return(new ArrayValue(GetStringType(), te.Arguments[0].ToString()));
                }
                break;


            case "getMember":
                pfa = ExpressionTypeEvaluation.prepareMemberTraitExpression(ctxt, te, out t, ValueProvider);

                if (pfa == null || t == null)
                {
                    break;
                }

                var vs = EvalPostfixAccessExpression(this, ctxt, pfa, t, ValueProvider: ValueProvider);
                if (vs == null || vs.Length == 0)
                {
                    return(null);
                }
                return(vs[0]);


            case "getOverloads":
                optionsBackup = ctxt.ContextIndependentOptions;
                ctxt.ContextIndependentOptions = ResolutionOptions.IgnoreAllProtectionAttributes;

                pfa = ExpressionTypeEvaluation.prepareMemberTraitExpression(ctxt, te, out t, ValueProvider);

                if (pfa != null && t != null)
                {
                    vs = EvalPostfixAccessExpression(this, ctxt, pfa, t);
                }
                else
                {
                    vs = null;
                }

                ctxt.ContextIndependentOptions = optionsBackup;

                return(new TypeValue(new DTuple(te, vs)));


            case "getProtection":
                optionsBackup = ctxt.ContextIndependentOptions;
                ctxt.ContextIndependentOptions = ResolutionOptions.IgnoreAllProtectionAttributes;

                var prot = "public";

                if (te.Arguments == null || te.Arguments.Length != 1 || te.Arguments[0] == null)
                {
                    EvalError(te, "First trait argument must be a symbol identifier");
                }
                else
                {
                    t = ExpressionTypeEvaluation.ResolveTraitArgument(ctxt, te.Arguments[0]);

                    if (t is DSymbol)
                    {
                        var dn = (t as DSymbol).Definition;

                        if (dn.ContainsAttribute(DTokens.Private))
                        {
                            prot = "private";
                        }
                        else if (dn.ContainsAttribute(DTokens.Protected))
                        {
                            prot = "protected";
                        }
                        else if (dn.ContainsAttribute(DTokens.Package))
                        {
                            prot = "package";
                        }
                        else if (dn.ContainsAttribute(DTokens.Export))
                        {
                            prot = "export";
                        }
                    }
                    else
                    {
                        EvalError(te, "First argument must evaluate to an existing code symbol");
                    }
                }

                ctxt.ContextIndependentOptions = optionsBackup;
                return(new ArrayValue(GetStringType(), prot));

            case "getVirtualFunctions":
                break;

            case "getVirtualMethods":
                break;

            case "parent":
                break;

            case "classInstanceSize":
                break;

            case "allMembers":
                break;

            case "derivedMembers":
                break;

            case "isSame":
                ret = false;

                if (te.Arguments == null || te.Arguments.Length < 2)
                {
                    EvalError(te, "isSame requires two arguments to compare");
                }
                else
                {
                    t = ExpressionTypeEvaluation.ResolveTraitArgument(ctxt, te.Arguments[0]);

                    if (t != null)
                    {
                        var t2 = ExpressionTypeEvaluation.ResolveTraitArgument(ctxt, te.Arguments[1]);

                        if (t2 != null)
                        {
                            ret = Resolver.ResultComparer.IsEqual(t, t2);
                        }
                    }
                }

                return(new PrimitiveValue(ret, te));

            case "compiles":
                ret = false;

                if (te.Arguments != null)
                {
                    foreach (var arg in te.Arguments)
                    {
                        ret = arg == null || ExpressionTypeEvaluation.ResolveTraitArgument(ctxt, arg) != null;

                        if (!ret)
                        {
                            break;
                        }
                    }
                }

                return(new PrimitiveValue(ret, te));
            }

            #region isXYZ-traits
            if (te.Keyword.StartsWith("is"))
            {
                var optionsBackup = ctxt.ContextIndependentOptions;
                ctxt.ContextIndependentOptions = ResolutionOptions.IgnoreAllProtectionAttributes;
                bool ret = false;

                if (te.Arguments != null)
                {
                    foreach (var arg in te.Arguments)
                    {
                        var t = ExpressionTypeEvaluation.ResolveTraitArgument(ctxt, arg);

                        bool tested = true;

                        switch (te.Keyword)
                        {
                        case "isVirtualFunction":
                        case "isVirtualMethod":
                            var ms = t as MemberSymbol;
                            if (ms == null || !(ms.Definition is DMethod))
                            {
                                break;
                            }

                            var dm = ms.Definition as DMethod;
                            var dc = dm.Parent as DClassLike;
                            if (dc != null && dc.ClassType != DTokens.Struct)
                            {
                                bool includeFinalNonOverridingMethods = te.Keyword == "isVirtualFunction";
                                ret = !dm.ContainsAttribute(includeFinalNonOverridingMethods ? (byte)0 : DTokens.Final, DTokens.Static);
                            }
                            break;

                        case "isAbstractFunction":
                            ms = t as MemberSymbol;

                            ret = ms != null &&
                                  ms.Definition is DMethod &&
                                  ms.Definition.ContainsAttribute(DTokens.Abstract);
                            break;

                        case "isFinalFunction":
                            ms = t as MemberSymbol;

                            if (ms != null && ms.Definition is DMethod)
                            {
                                ret = ms.Definition.ContainsAttribute(DTokens.Abstract) ||
                                      (ms.Definition.Parent is DClassLike && (ms.Definition.Parent as DClassLike).ContainsAttribute(DTokens.Final));
                            }
                            break;

                        case "isStaticFunction":
                            ms = t as MemberSymbol;

                            ret = ms != null && ms.Definition is DMethod && ms.Definition.IsStatic;
                            break;

                        case "isRef":
                            ret = t is MemberSymbol && (t as MemberSymbol).Definition.ContainsAttribute(DTokens.Ref);
                            break;

                        case "isOut":
                            ret = t is MemberSymbol && (t as MemberSymbol).Definition.ContainsAttribute(DTokens.Out);
                            break;

                        case "isLazy":
                            ret = t is MemberSymbol && (t as MemberSymbol).Definition.ContainsAttribute(DTokens.Lazy);
                            break;

                        default:
                            tested = false;
                            break;
                        }

                        t = DResolver.StripMemberSymbols(t);

                        if (!tested)
                        {
                            switch (te.Keyword)
                            {
                            case "isArithmetic":
                                var pt = t as PrimitiveType;
                                ret = pt != null && (
                                    DTokens.IsBasicType_Integral(pt.TypeToken) ||
                                    DTokens.IsBasicType_FloatingPoint(pt.TypeToken));
                                break;

                            case "isFloating":
                                pt  = t as PrimitiveType;
                                ret = pt != null && DTokens.IsBasicType_FloatingPoint(pt.TypeToken);
                                break;

                            case "isIntegral":
                                pt  = t as PrimitiveType;
                                ret = pt != null && DTokens.IsBasicType_Integral(pt.TypeToken);
                                break;

                            case "isScalar":
                                pt  = t as PrimitiveType;
                                ret = pt != null && DTokens.IsBasicType(pt.TypeToken);
                                break;

                            case "isUnsigned":
                                pt  = t as PrimitiveType;
                                ret = pt != null && DTokens.IsBasicType_Unsigned(pt.TypeToken);
                                break;

                            case "isAbstractClass":
                                ret = t is ClassType && (t as ClassType).Definition.ContainsAttribute(DTokens.Abstract);
                                break;

                            case "isFinalClass":
                                ret = t is ClassType && (t as ClassType).Definition.ContainsAttribute(DTokens.Final);
                                break;

                            case "isAssociativeArray":
                                ret = t is AssocArrayType && !(t is ArrayType);
                                break;

                            case "isStaticArray":
                                ret = t is ArrayType && (t as ArrayType).IsStaticArray;
                                break;
                            }
                        }

                        if (!ret)
                        {
                            break;
                        }
                    }
                }

                ctxt.ContextIndependentOptions = optionsBackup;
                return(new PrimitiveValue(ret, te));
            }
            else
            {
                EvalError(te, "Illegal trait token");
                return(null);
            }
            #endregion
        }