public override void Visit(TraitsExpression x)
 {
     if (x.Keyword == DTokens.IncompleteId)
     {
         prv  = new TraitsExpressionCompletionProvider(cdgen);
         halt = true;
     }
     else
     {
         base.Visit(x);
     }
 }
Exemple #2
0
        /// <summary>
        /// Used when evaluating traits.
        /// Evaluates the first argument to <param name="t">t</param>,
        /// takes the second traits argument, tries to evaluate it to a string, and puts it + the first arg into an postfix_access expression
        /// </summary>
        PostfixExpression_Access prepareMemberTraitExpression(TraitsExpression te, out AbstractType t)
        {
            if (te.Arguments != null && te.Arguments.Length == 2)
            {
                var tEx = te.Arguments[0];
                t = DResolver.StripMemberSymbols(E(tEx, te));

                if (t == null)
                {
                    EvalError(te, "First argument didn't resolve to a type");
                }
                else if (te.Arguments[1].AssignExpression != null)
                {
                    var litEx       = te.Arguments[1].AssignExpression;
                    var eval_Backup = eval;
                    eval = true;
                    var v = E(litEx);
                    eval = eval_Backup;

                    if (v is ArrayValue && (v as ArrayValue).IsString)
                    {
                        var av = v as ArrayValue;

                        // Mock up a postfix_access expression to ensure static properties & ufcs methods are checked either
                        return(new PostfixExpression_Access {
                            PostfixForeExpression = tEx.AssignExpression ?? new TypeDeclarationExpression(tEx.Type),
                            AccessExpression = new IdentifierExpression(av.StringValue)
                            {
                                Location = litEx.Location,
                                EndLocation = litEx.EndLocation
                            },
                            EndLocation = litEx.EndLocation
                        });
                    }
                    else
                    {
                        EvalError(te.Arguments[1].AssignExpression, "Second traits argument must evaluate to a string literal", v);
                    }
                }
                else
                {
                    EvalError(te, "Second traits argument must be an expression");
                }
            }

            t = null;
            return(null);
        }
Exemple #3
0
 AbstractType E(TraitsArgument arg, TraitsExpression te)
 {
     if (arg.Type != null)
     {
         return(TypeDeclarationResolver.ResolveSingle(arg.Type, ctxt));
     }
     else if (arg.AssignExpression != null)
     {
         return(DResolver.StripAliasSymbol(EvaluateType(arg.AssignExpression, ctxt)));
     }
     else
     {
         EvalError(te, "Argument must be a type or an expression!");
         return(null);
     }
 }
		public void Visit(TraitsExpression x)
		{
			
		}
Exemple #5
0
        IExpression TraitsExpression()
        {
            Expect(__traits);
            var ce = new TraitsExpression() { Location=t.Location};
            if(Expect(OpenParenthesis))
            {
                if (Expect (Identifier))
                    ce.Keyword = t.Value;
                else if (IsEOF)
                    ce.Keyword = DTokens.IncompleteId;

                var al = new List<TraitsArgument>();

                while (laKind == Comma)
                {
                    Step();

                    if (IsAssignExpression())
                        al.Add(new TraitsArgument(AssignExpression()));
                    else
                        al.Add(new TraitsArgument(Type()));
                }

                Expect (CloseParenthesis);

                if(al.Count != 0)
                    ce.Arguments = al.ToArray();
            }
            ce.EndLocation = t.EndLocation;
            return ce;
        }
 ISemantic E(TraitsExpression te)
 {
     // TODO: Return either bools, strings, array (pointers) to members or stuff
     return null;
 }
 ISemantic E(TraitsExpression te)
 {
     // TODO: Return either bools, strings, array (pointers) to members or stuff
     return(null);
 }
        /// <summary>
        /// Used when evaluating traits.
        /// Evaluates the first argument to <param name="t">t</param>,
        /// takes the second traits argument, tries to evaluate it to a string, and puts it + the first arg into an postfix_access expression
        /// </summary>
        internal static PostfixExpression_Access prepareMemberTraitExpression(ResolutionContext ctxt, TraitsExpression te, out AbstractType t, AbstractSymbolValueProvider vp = null)
        {
            if (te.Arguments != null && te.Arguments.Length == 2)
            {
                var tEx = te.Arguments[0];
                t = DResolver.StripMemberSymbols(ResolveTraitArgument(ctxt, tEx));

                if (t == null)
                {
                    ctxt.LogError(te, "First argument didn't resolve to a type");
                }
                else if (te.Arguments[1].AssignExpression != null)
                {
                    var litEx = te.Arguments[1].AssignExpression;
                    var v     = vp != null?Evaluation.EvaluateValue(litEx, vp) : Evaluation.EvaluateValue(litEx, ctxt);

                    if (v is ArrayValue && (v as ArrayValue).IsString)
                    {
                        var av = v as ArrayValue;

                        // Mock up a postfix_access expression to ensure static properties & ufcs methods are checked either
                        return(new PostfixExpression_Access
                        {
                            PostfixForeExpression = tEx.AssignExpression ?? new TypeDeclarationExpression(tEx.Type),
                            AccessExpression = new IdentifierExpression(av.StringValue)
                            {
                                Location = litEx.Location,
                                EndLocation = litEx.EndLocation
                            },
                            EndLocation = litEx.EndLocation
                        });
                    }
                    else
                    {
                        ctxt.LogError(litEx, "Second traits argument must evaluate to a string literal");
                    }
                }
                else
                {
                    ctxt.LogError(te, "Second traits argument must be an expression");
                }
            }

            t = null;
            return(null);
        }
 public override void Visit(TraitsExpression x)
 {
     if(x.Keyword == DTokens.IncompleteId)
     {
         prv = new TraitsExpressionCompletionProvider(cdgen);
         halt = true;
     }
     else
         base.Visit (x);
 }
Exemple #10
0
        IExpression TraitsExpression()
        {
            Expect(__traits);
            var ce = new TraitsExpression() { Location=t.Location};
            LastParsedObject = ce;
            Expect(OpenParenthesis);

            if(Expect(Identifier))
                ce.Keyword = t.Value;

            var al = new List<TraitsArgument>();

            while (laKind == Comma)
            {
                Step();
                if (IsAssignExpression())
                    al.Add(new TraitsArgument(){AssignExpression= AssignExpression()});
                else
                    al.Add(new TraitsArgument(){Type= Type()});
            }

            Expect(CloseParenthesis);
            ce.EndLocation = t.EndLocation;
            return ce;
        }
Exemple #11
0
		IExpression TraitsExpression(IBlockNode scope)
		{
			Expect(__traits);
			var ce = new TraitsExpression() { Location=t.Location};
			if(Expect(OpenParenthesis))
			{
				if (Expect (Identifier))
					ce.Keyword = t.Value;
				else if (IsEOF)
					ce.Keyword = DTokens.IncompleteId;

				var al = new List<TraitsArgument>();

				var weakTypeParsingBackup = AllowWeakTypeParsing;

				while (laKind == Comma)
				{
					Step();

					Lexer.PushLookAheadBackup ();

					AllowWeakTypeParsing = true;
					var td = Type (scope);
					AllowWeakTypeParsing = false;

					if (td != null && (laKind == Comma || laKind == CloseParenthesis || IsEOF)) {
						Lexer.PopLookAheadBackup ();
						al.Add (new TraitsArgument(td));
						continue;
					}

					Lexer.RestoreLookAheadBackup ();

					al.Add(new TraitsArgument(AssignExpression(scope)));
				}

				AllowWeakTypeParsing = weakTypeParsingBackup;

				Expect (CloseParenthesis);
				
				if(al.Count != 0)
					ce.Arguments = al.ToArray();
			}
			ce.EndLocation = t.EndLocation;
			return ce;
		}
		AbstractType E(TraitsArgument arg, TraitsExpression te)
		{
			if(arg.Type != null)
			{
				return TypeDeclarationResolver.ResolveSingle(arg.Type, ctxt);
			}
			else if(arg.AssignExpression != null)
			{
				return DResolver.StripAliasSymbol(EvaluateType(arg.AssignExpression, ctxt));
			}
			else
			{
				EvalError(te, "Argument must be a type or an expression!");
				return null;
			}
		}
		/// <summary>
		/// Used when evaluating traits.
		/// Evaluates the first argument to <param name="t">t</param>, 
		/// takes the second traits argument, tries to evaluate it to a string, and puts it + the first arg into an postfix_access expression
		/// </summary>
		PostfixExpression_Access prepareMemberTraitExpression(TraitsExpression te,out AbstractType t)
		{
			if(te.Arguments != null && te.Arguments.Length == 2)
			{
				var tEx = te.Arguments[0];
				t = DResolver.StripMemberSymbols(E(tEx,te));
				
				if(t == null)
					EvalError(te, "First argument didn't resolve to a type");
				else if(te.Arguments[1].AssignExpression != null)
				{
					var litEx = te.Arguments[1].AssignExpression;
					var eval_Backup = eval;
					eval = true;
					var v = E(litEx);
					eval = eval_Backup;
					
					if(v is ArrayValue && (v as ArrayValue).IsString)
					{
						var av = v as ArrayValue;
						
						// Mock up a postfix_access expression to ensure static properties & ufcs methods are checked either
						return new PostfixExpression_Access{ 
							PostfixForeExpression = tEx.AssignExpression ?? new TypeDeclarationExpression(tEx.Type),
							AccessExpression = new IdentifierExpression(av.StringValue) {
								Location = litEx.Location, 
								EndLocation = litEx.EndLocation},
							EndLocation = litEx.EndLocation
						};
					}
					else
						EvalError(te.Arguments[1].AssignExpression, "Second traits argument must evaluate to a string literal", v);
				}
				else
					EvalError(te, "Second traits argument must be an expression");
			}
			
			t = null;
			return null;
		}
		ISemantic E(TraitsExpression te)
		{
			switch(te.Keyword)
			{
				case "":
				case null:
					return null;
					
				case "hasMember":
					if(!eval)
						return new PrimitiveType(DTokens.Bool, 0);
					
					bool ret = false;
					var optionsBackup = ctxt.ContextIndependentOptions;
					ctxt.ContextIndependentOptions = ResolutionOptions.IgnoreAllProtectionAttributes;
					
					AbstractType t;
					var pfa = prepareMemberTraitExpression(te, out t);
					
					if(pfa != null && t != null)
					{
						ignoreErrors = true;
						eval = false;
						ret = E(pfa, t, false) != null;
						eval = true;
						ignoreErrors = false;
					}
					ctxt.ContextIndependentOptions = optionsBackup;
					return new PrimitiveValue(ret, te);
					
					
				case "identifier":
					if(!eval)
						return GetStringType();
					
					if(te.Arguments!=null && te.Arguments.Length == 1)
						return new ArrayValue(GetStringType(), te.Arguments[0].ToString());
					break;
					
					
				case "getMember":
					pfa = prepareMemberTraitExpression(te, out t);
					
					if(pfa == null ||t == null)
						break;
					
					var vs = E(pfa,t);
					if(vs == null || vs.Length == 0)
						return null;
					return vs[0];
					
					
				case "getOverloads":
					optionsBackup = ctxt.ContextIndependentOptions;
					ctxt.ContextIndependentOptions = ResolutionOptions.IgnoreAllProtectionAttributes;
					
					pfa = prepareMemberTraitExpression(te, out t);
					
					if(pfa != null  && t != null)
					{
						var evalBak = eval;
						eval = false;
						vs = E(pfa,t);
						eval = evalBak;
					}
					else
						vs = null;
					
					ctxt.ContextIndependentOptions = optionsBackup;
					
					return eval ? new TypeValue(new DTuple(te, vs)) as ISemantic : new DTuple(te, vs);
					
					
				case "getProtection":
					if(!eval)
						return GetStringType();
					
					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 = E(te.Arguments[0], te);
						
						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":
					if(!eval)
						return new PrimitiveType(DTokens.Bool);
					
					ret = false;
					
					if(te.Arguments == null || te.Arguments.Length < 2)
					{
						EvalError(te, "isSame требует для сравнения двух элементов");
					}
					else
					{
						t = E(te.Arguments[0], te);
						
						if(t != null)
						{
							var t2 = E(te.Arguments[1], te);
							
							if(t2 != null)
								ret = Resolver.ResultComparer.IsEqual(t,t2);
						}
					}
					
					return new PrimitiveValue(ret, te);
					
				case "compiles":
					if(!eval)
						return new PrimitiveType(DTokens.Bool);
					
					ret = false;
					
					if(te.Arguments != null){
						foreach(var arg in te.Arguments)
						{
							ret = E(arg, te) != null;
							
							if(!ret)
								break;
						}
					}
						
					return new PrimitiveValue(ret, te);
			}
			
			#region isXYZ-traits
			if(te.Keyword.StartsWith("is"))
			{
				if(eval)
				{
					var optionsBackup = ctxt.ContextIndependentOptions;
					ctxt.ContextIndependentOptions = ResolutionOptions.IgnoreAllProtectionAttributes;
					bool ret = false;
					
					if(te.Arguments != null)
					foreach(var arg in te.Arguments)
					{
						var t = E(arg,te);
						
						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.BasicTypes_Integral[pt.TypeToken] || 
										DTokens.BasicTypes_FloatingPoint[pt.TypeToken]);
									break;
								case "isFloating":
									pt = t as PrimitiveType;
									ret = pt != null && DTokens.BasicTypes_FloatingPoint[pt.TypeToken];
									break;
								case "isIntegral":
									pt = t as PrimitiveType;
									ret = pt != null && DTokens.BasicTypes_Integral[pt.TypeToken];
									break;
								case "isScalar":
									pt = t as PrimitiveType;
									ret = pt != null && DTokens.BasicTypes[pt.TypeToken];
									break;
								case "isUnsigned":
									pt = t as PrimitiveType;
									ret = pt != null && DTokens.BasicTypes_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
					return new PrimitiveType(DTokens.Bool, 0, te);
			}
			else
			{
				if(eval)
					EvalError(te, "Illegal trait token");
				return null;
			}
			#endregion
		}
        public AbstractType Visit(TraitsExpression te)
        {
            PostfixExpression_Access pfa;
            AbstractType             t;
            ResolutionOptions        optionsBackup;

            switch (te.Keyword)
            {
            case "":
            case null:
                return(null);

            case "identifier":
                return(GetStringType());

            case "getMember":
                pfa = prepareMemberTraitExpression(te, out t);

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

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


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

                pfa = prepareMemberTraitExpression(te, out t);

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

                ctxt.ContextIndependentOptions = optionsBackup;

                return(new DTuple(te, vs));


            case "getProtection":
                return(GetStringType());

            case "getVirtualFunctions":
                break;

            case "getVirtualMethods":
                break;

            case "parent":
                break;

            case "classInstanceSize":
                break;

            case "allMembers":
                break;

            case "derivedMembers":
                break;

            case "compiles":
                return(new PrimitiveType(DTokens.Bool));
            }

            if (te.Keyword.StartsWith("is") || te.Keyword.StartsWith("has"))
            {
                return(new PrimitiveType(DTokens.Bool));
            }

            return(null);
        }
Exemple #16
0
        IExpression TraitsExpression()
        {
            Expect(__traits);
            var ce = new TraitsExpression() { Location=t.Location};
            LastParsedObject = ce;
            if(Expect(OpenParenthesis))
            {
                if(Expect(Identifier))
                    ce.Keyword = t.Value;

                var al = new List<TraitsArgument>();

                while (laKind == Comma)
                {
                    Step();

                    if (IsAssignExpression())
                        al.Add(new TraitsArgument(AssignExpression()));
                    else
                        al.Add(new TraitsArgument(Type()));
                }

                if (Expect(CloseParenthesis))
                    TrackerVariables.ExpectingIdentifier = false;

                if(al.Count != 0)
                    ce.Arguments = al.ToArray();
            }
            ce.EndLocation = t.EndLocation;
            return ce;
        }
 PostfixExpression_Access prepareMemberTraitExpression(TraitsExpression te, out AbstractType t)
 {
     return(prepareMemberTraitExpression(ctxt, te, out t));
 }
Exemple #18
0
        ISemantic E(TraitsExpression te)
        {
            switch (te.Keyword)
            {
            case "":
            case null:
                return(null);

            case "hasMember":
                if (!eval)
                {
                    return(new PrimitiveType(DTokens.Bool, 0));
                }

                bool ret           = false;
                var  optionsBackup = ctxt.ContextIndependentOptions;
                ctxt.ContextIndependentOptions = ResolutionOptions.IgnoreAllProtectionAttributes;

                AbstractType t;
                var          pfa = prepareMemberTraitExpression(te, out t);

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


            case "identifier":
                if (!eval)
                {
                    return(GetStringType());
                }

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


            case "getMember":
                pfa = prepareMemberTraitExpression(te, out t);

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

                var vs = E(pfa, t);
                if (vs == null || vs.Length == 0)
                {
                    return(null);
                }
                return(vs[0]);


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

                pfa = prepareMemberTraitExpression(te, out t);

                if (pfa != null && t != null)
                {
                    var evalBak = eval;
                    eval = false;
                    vs   = E(pfa, t);
                    eval = evalBak;
                }
                else
                {
                    vs = null;
                }

                ctxt.ContextIndependentOptions = optionsBackup;

                return(eval ? new TypeValue(new DTuple(te, vs)) as ISemantic : new DTuple(te, vs));


            case "getProtection":
                if (!eval)
                {
                    return(GetStringType());
                }

                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 = E(te.Arguments[0], te);

                    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":
                if (!eval)
                {
                    return(new PrimitiveType(DTokens.Bool));
                }

                ret = false;

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

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

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

                return(new PrimitiveValue(ret, te));

            case "compiles":
                if (!eval)
                {
                    return(new PrimitiveType(DTokens.Bool));
                }

                ret = false;

                if (te.Arguments != null)
                {
                    foreach (var arg in te.Arguments)
                    {
                        ret = E(arg, te) != null;

                        if (!ret)
                        {
                            break;
                        }
                    }
                }

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

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

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

                            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.BasicTypes_Integral[pt.TypeToken] ||
                                        DTokens.BasicTypes_FloatingPoint[pt.TypeToken]);
                                    break;

                                case "isFloating":
                                    pt  = t as PrimitiveType;
                                    ret = pt != null && DTokens.BasicTypes_FloatingPoint[pt.TypeToken];
                                    break;

                                case "isIntegral":
                                    pt  = t as PrimitiveType;
                                    ret = pt != null && DTokens.BasicTypes_Integral[pt.TypeToken];
                                    break;

                                case "isScalar":
                                    pt  = t as PrimitiveType;
                                    ret = pt != null && DTokens.BasicTypes[pt.TypeToken];
                                    break;

                                case "isUnsigned":
                                    pt  = t as PrimitiveType;
                                    ret = pt != null && DTokens.BasicTypes_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
                {
                    return(new PrimitiveType(DTokens.Bool, 0, te));
                }
            }
            else
            {
                if (eval)
                {
                    EvalError(te, "Illegal trait token");
                }
                return(null);
            }
            #endregion
        }
 public void Visit(TraitsExpression x)
 {
 }
		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)
					{
						t.NonStaticAccess = true;
						ignoreErrors = true;
						var res = ExpressionTypeEvaluation.EvaluateType(pfa, ctxt, false);
						ret = res != null;
						ignoreErrors = false;
					}
					ctxt.ContextIndependentOptions = optionsBackup;
					return new PrimitiveValue(ret);
					
					
				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(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);
					
				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);
			}
			
			#region isXYZ-traits
			if(te.Keyword.StartsWith("is"))
			{
				var optionsBackup = ctxt.ContextIndependentOptions;
				ctxt.ContextIndependentOptions = ResolutionOptions.IgnoreAllProtectionAttributes;
				ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly;
				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);
			}
			else
			{
				EvalError(te, "Illegal trait token");
				return null;
			}
			#endregion
		}