Esempio n. 1
0
        static AbstractType HandleImportSymbolMatch(ImportSymbolNode importSymbolNode, ResolutionContext ctxt)
        {
            AbstractType ret = null;

            var modAlias = importSymbolNode is ModuleAliasNode;

            if (modAlias ? importSymbolNode.Type != null : importSymbolNode.Type.InnerDeclaration != null)
            {
                var mods = new List <DModule> ();
                var td   = modAlias ? importSymbolNode.Type : importSymbolNode.Type.InnerDeclaration;
                foreach (var mod in ctxt.ParseCache.LookupModuleName(td.ToString()))
                {
                    mods.Add(mod);
                }
                if (mods.Count == 0)
                {
                    ctxt.LogError(new NothingFoundError(importSymbolNode.Type));
                }
                else
                if (mods.Count > 1)
                {
                    var m__ = new List <ISemantic> ();
                    foreach (var mod in mods)
                    {
                        m__.Add(new ModuleSymbol(mod, importSymbolNode.Type));
                    }
                    ctxt.LogError(new AmbiguityError(importSymbolNode.Type, m__));
                }
                var bt = mods.Count != 0 ? (AbstractType) new ModuleSymbol(mods [0], td) : null;
                //TODO: Is this correct behaviour?
                if (!modAlias)
                {
                    var furtherId = ResolveFurtherTypeIdentifier(importSymbolNode.Type.ToString(false), new[] {
                        bt
                    }, ctxt, importSymbolNode.Type);
                    ctxt.CheckForSingleResult(furtherId, importSymbolNode.Type);
                    if (furtherId != null && furtherId.Length != 0)
                    {
                        bt = furtherId [0];
                    }
                    else
                    {
                        bt = null;
                    }
                }
                ret = new AliasedType(importSymbolNode, bt, importSymbolNode.Type);
            }
            return(ret);
        }
Esempio n. 2
0
        static AbstractType DeduceEponymousTemplate(EponymousTemplateType ept, ResolutionContext ctxt)
        {
            if (ept.Definition.Initializer == null &&
                ept.Definition.Type == null)
            {
                ctxt.LogError(ept.Definition, "Can't deduce type from empty initializer!");
                return(null);
            }

            // Introduce the deduced params to the current resolution context
            ctxt.CurrentContext.IntroduceTemplateParameterTypes(ept);

            // Get actual overloads
            AbstractType deducedType = null;
            var          def         = ept.Definition;

            deducedType = new MemberSymbol(def, def.Type != null ?
                                           TypeDeclarationResolver.ResolveSingle(def.Type, ctxt) :
                                           ExpressionTypeEvaluation.EvaluateType(def.Initializer, ctxt), null, ept.DeducedTypes); //ept; //ExpressionTypeEvaluation.EvaluateType (ept.Definition.Initializer, ctxt);

            deducedType.Tag = ept.Tag;                                                                                            // Currently requried for proper UFCS resolution - sustain ept's Tag

            // Undo context-related changes
            ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ept);

            return(deducedType);
        }
Esempio n. 3
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>
        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);
        }
Esempio n. 4
0
        /// <summary>
        /// Returns false if the item has already been set before and if the already set item is not equal to 'r'.
        /// Inserts 'r' into the target dictionary and returns true otherwise.
        /// </summary>
        bool Set(TemplateParameter p, ISemantic r, int nameHash)
        {
            if (p == null)
            {
                if (nameHash != 0 && TargetDictionary.ExpectedParameters != null)
                {
                    foreach (var tpar in TargetDictionary.ExpectedParameters)
                    {
                        if (tpar.NameHash == nameHash)
                        {
                            p = tpar;
                            break;
                        }
                    }
                }
            }

            if (p == null)
            {
                ctxt.LogError(null, "no fitting template parameter found!");
                return(false);
            }

            // void call(T)(T t) {}
            // call(myA) -- T is *not* myA but A, so only assign myA's type to T.
            if (p is TemplateTypeParameter)
            {
                var newR = Resolver.TypeResolution.DResolver.StripMemberSymbols(AbstractType.Get(r));
                if (newR != null)
                {
                    r = newR;
                }
            }

            TemplateParameterSymbol rl;

            if (!TargetDictionary.TryGetValue(p, out rl) || rl == null)
            {
                TargetDictionary[p] = new TemplateParameterSymbol(p, r);
                return(true);
            }
            else
            {
                if (ResultComparer.IsEqual(rl.Base, r))
                {
                    TargetDictionary[p] = new TemplateParameterSymbol(p, r);
                    return(true);
                }
                else if (rl == null)
                {
                    TargetDictionary[p] = new TemplateParameterSymbol(p, r);
                }

                // Error: Ambiguous assignment

                return(false);
            }
        }
Esempio n. 5
0
        static AbstractType HandleClassLikeMatch(DClassLike dc, ResolutionContext ctxt, object typeBase, bool canResolveBase)
        {
            AbstractType    ret;
            UserDefinedType udt = null;
            var             invisibleTypeParams = GetInvisibleTypeParameters(dc, ctxt);

            switch (dc.ClassType)
            {
            case DTokens.Struct:
                ret = new StructType(dc, typeBase as ISyntaxRegion, invisibleTypeParams);
                break;

            case DTokens.Union:
                ret = new UnionType(dc, typeBase as ISyntaxRegion, invisibleTypeParams);
                break;

            case DTokens.Class:
                udt = new ClassType(dc, typeBase as ISyntaxRegion, null, null, invisibleTypeParams);
                ret = null;
                break;

            case DTokens.Interface:
                udt = new InterfaceType(dc, typeBase as ISyntaxRegion, null, invisibleTypeParams);
                ret = null;
                break;

            case DTokens.Template:
                if (dc.ContainsAttribute(DTokens.Mixin))
                {
                    ret = new MixinTemplateType(dc, typeBase as ISyntaxRegion, invisibleTypeParams);
                }
                else
                {
                    ret = new TemplateType(dc, typeBase as ISyntaxRegion, invisibleTypeParams);
                }
                break;

            default:
                ret = null;
                ctxt.LogError(new ResolutionError(dc, "Unknown type (" + DTokens.GetTokenString(dc.ClassType) + ")"));
                break;
            }
            if (dc.ClassType == DTokens.Class || dc.ClassType == DTokens.Interface)
            {
                ret = canResolveBase ? DResolver.ResolveBaseClasses(udt, ctxt) : udt;
            }
            return(ret);
        }
Esempio n. 6
0
        AbstractType EvalForeExpression(PostfixExpression ex)
        {
            var foreExpr = ex.PostfixForeExpression != null?ex.PostfixForeExpression.Accept(this) : null;

            if (foreExpr == null)
            {
                ctxt.LogError(new NothingFoundError(ex.PostfixForeExpression));
            }

            return(foreExpr);
        }
Esempio n. 7
0
        public static AbstractType Resolve(ArrayDecl ad, ResolutionContext ctxt)
        {
            var valueTypes = Resolve(ad.ValueType, ctxt);

            ctxt.CheckForSingleResult(valueTypes, ad);

            AbstractType valueType        = null;
            AbstractType keyType          = null;
            int          fixedArrayLength = -1;

            if (valueTypes != null && valueTypes.Length != 0)
            {
                valueType = valueTypes[0];
            }

            ISymbolValue val;

            keyType = ResolveKey(ad, out fixedArrayLength, out val, ctxt);

            if (keyType == null || (keyType is PrimitiveType &&
                                    ((PrimitiveType)keyType).TypeToken == DTokens.Int))
            {
                if (fixedArrayLength >= 0)
                {
                    // D Magic: One might access tuple items directly in the pseudo array declaration - so stuff like Tup[0] i; becomes e.g. int i;
                    var dtup = DResolver.StripMemberSymbols(valueType) as DTuple;
                    if (dtup == null)
                    {
                        return(new ArrayType(valueType, fixedArrayLength, ad));
                    }

                    if (dtup.Items != null && fixedArrayLength < dtup.Items.Length)
                    {
                        return(AbstractType.Get(dtup.Items [fixedArrayLength]));
                    }
                    else
                    {
                        ctxt.LogError(ad, "TypeTuple only consists of " + (dtup.Items != null ? dtup.Items.Length : 0) + " items. Can't access item at index " + fixedArrayLength);
                        return(null);
                    }
                }
                return(new ArrayType(valueType, ad));
            }

            return(new AssocArrayType(valueType, keyType, ad));
        }
Esempio n. 8
0
        static AbstractType DeduceEponymousTemplate(EponymousTemplateType ept, ResolutionContext ctxt)
        {
            if (ept.Definition.Initializer == null)
            {
                ctxt.LogError(ept.Definition, "Can't deduce type from empty initializer!");
                return(null);
            }

            // Introduce the deduced params to the current resolution context
            ctxt.CurrentContext.IntroduceTemplateParameterTypes(ept);

            // Get actual overloads
            AbstractType deducedType = null;

            deducedType = new MemberSymbol(ept.Definition, Evaluation.EvaluateType(ept.Definition.Initializer, ctxt), null, ept.DeducedTypes);               //ept; //Evaluation.EvaluateType (ept.Definition.Initializer, ctxt);

            // Undo context-related changes
            ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ept);

            return(deducedType);
        }
Esempio n. 9
0
        AbstractType EvalForeExpression(PostfixExpression ex)
        {
            var foreExpr = ex.PostfixForeExpression != null?ex.PostfixForeExpression.Accept(this) : null;

            if (foreExpr is AliasedType)
            {
                foreExpr = DResolver.StripAliasSymbol(foreExpr);
            }

            if (foreExpr == null)
            {
                ctxt.LogError(new NothingFoundError(ex.PostfixForeExpression));
            }

            return(foreExpr);
        }
		static AbstractType HandleClassLikeMatch (DClassLike dc, ResolutionContext ctxt, object typeBase, bool canResolveBase)
		{
			AbstractType ret;
			UserDefinedType udt = null;
			var invisibleTypeParams = GetInvisibleTypeParameters (dc, ctxt);

			switch (dc.ClassType) {
				case DTokens.Struct:
					ret = new StructType (dc, typeBase as ISyntaxRegion, invisibleTypeParams);
					break;
				case DTokens.Union:
					ret = new UnionType (dc, typeBase as ISyntaxRegion, invisibleTypeParams);
					break;
				case DTokens.Class:
					udt = new ClassType (dc, typeBase as ISyntaxRegion, null, null, invisibleTypeParams);
					ret = null;
					break;
				case DTokens.Interface:
					udt = new InterfaceType (dc, typeBase as ISyntaxRegion, null, invisibleTypeParams);
					ret = null;
					break;
				case DTokens.Template:
					if (dc.ContainsAttribute (DTokens.Mixin))
						ret = new MixinTemplateType (dc, typeBase as ISyntaxRegion, invisibleTypeParams);
					else
						ret = new TemplateType (dc, typeBase as ISyntaxRegion, invisibleTypeParams);
					break;
				default:
					ret = null;
					ctxt.LogError (new ResolutionError (dc, "Unknown type (" + DTokens.GetTokenString (dc.ClassType) + ")"));
					break;
			}
			if (dc.ClassType == DTokens.Class || dc.ClassType == DTokens.Interface)
				ret = canResolveBase ? DResolver.ResolveBaseClasses (udt, ctxt) : udt;
			return ret;
		}
Esempio n. 11
0
        public static AbstractType ResolveKey(ArrayDecl ad, out int fixedArrayLength, out ISymbolValue keyVal, ResolutionContext ctxt)
        {
            keyVal           = null;
            fixedArrayLength = -1;
            AbstractType keyType = null;

            if (ad.KeyExpression != null)
            {
                //TODO: Template instance expressions?
                var id_x = ad.KeyExpression as IdentifierExpression;
                if (id_x != null && id_x.IsIdentifier)
                {
                    var id = new IdentifierDeclaration((string)id_x.Value)
                    {
                        Location    = id_x.Location,
                        EndLocation = id_x.EndLocation
                    };

                    keyType = TypeDeclarationResolver.ResolveSingle(id, ctxt);

                    if (keyType != null)
                    {
                        var tt = DResolver.StripAliasSymbol(keyType) as MemberSymbol;

                        if (tt == null ||
                            !(tt.Definition is DVariable) ||
                            ((DVariable)tt.Definition).Initializer == null)
                        {
                            return(keyType);
                        }
                    }
                }

                try
                {
                    keyVal = Evaluation.EvaluateValue(ad.KeyExpression, ctxt);

                    if (keyVal != null)
                    {
                        // Take the value's type as array key type
                        keyType = keyVal.RepresentedType;

                        // It should be mostly a number only that points out how large the final array should be
                        var pv = Evaluation.GetVariableContents(keyVal, new StandardValueProvider(ctxt)) as PrimitiveValue;
                        if (pv != null)
                        {
                            fixedArrayLength = System.Convert.ToInt32(pv.Value);

                            if (fixedArrayLength < 0)
                            {
                                ctxt.LogError(ad, "Invalid array size: Length value must be greater than 0");
                            }
                        }
                        //TODO Is there any other type of value allowed?
                    }
                }
                catch { }
            }
            else
            {
                var t = Resolve(ad.KeyType, ctxt);
                ctxt.CheckForSingleResult(t, ad.KeyType);

                if (t != null && t.Length != 0)
                {
                    return(t[0]);
                }
            }

            return(keyType);
        }
Esempio n. 12
0
        public static List <ISemantic> PreResolveTemplateArgs(TemplateInstanceExpression tix, ResolutionContext ctxt, out bool hasNonFinalArgument)
        {
            hasNonFinalArgument = false;
            // Resolve given argument expressions
            var templateArguments = new List <ISemantic>();

            if (tix != null && tix.Arguments != null)
            {
                foreach (var arg in tix.Arguments)
                {
                    if (arg is TypeDeclarationExpression)
                    {
                        var tde = (TypeDeclarationExpression)arg;

                        var res = TypeDeclarationResolver.Resolve(tde.Declaration, ctxt);

                        if (ctxt.CheckForSingleResult(res, tde.Declaration) || res != null)
                        {
                            var mr = res[0] as MemberSymbol;
                            if (mr != null && mr.Definition is DVariable)
                            {
                                var dv = (DVariable)mr.Definition;

                                if (dv.IsAlias || dv.Initializer == null)
                                {
                                    templateArguments.Add(mr);
                                    continue;
                                }

                                ISemantic eval = null;

                                try
                                {
                                    eval = new StandardValueProvider(ctxt)[dv];
                                }
                                catch (System.Exception ee)                                // Should be a non-const-expression error here only
                                {
                                    ctxt.LogError(dv.Initializer, ee.Message);
                                }

                                templateArguments.Add(eval == null ? (ISemantic)mr : eval);
                            }
                            else
                            {
                                if (!hasNonFinalArgument)
                                {
                                    hasNonFinalArgument = IsNonFinalArgument(res[0]);
                                }
                                templateArguments.Add(res[0]);
                            }
                        }
                    }
                    else
                    {
                        var v = Evaluation.EvaluateValue(arg, ctxt, true);
                        if (v is VariableValue)
                        {
                            var vv = v as VariableValue;
                            if (vv.Variable.IsConst && vv.Variable.Initializer != null)
                            {
                                v = Evaluation.EvaluateValue(vv, new StandardValueProvider(ctxt));
                            }
                        }
                        if (!hasNonFinalArgument)
                        {
                            hasNonFinalArgument = IsNonFinalArgument(v);
                        }
                        templateArguments.Add(v);
                    }
                }
            }

            return(templateArguments);
        }
        static AbstractType DeduceEponymousTemplate(EponymousTemplateType ept, ResolutionContext ctxt)
        {
            if (ept.Definition.Initializer == null &&
                ept.Definition.Type == null) {
                ctxt.LogError(ept.Definition, "Can't deduce type from empty initializer!");
                return null;
            }

            // Introduce the deduced params to the current resolution context
            ctxt.CurrentContext.IntroduceTemplateParameterTypes(ept);

            // Get actual overloads
            AbstractType deducedType = null;
            var def = ept.Definition;
            deducedType = new MemberSymbol(def, def.Type != null ?
                TypeDeclarationResolver.ResolveSingle(def.Type, ctxt) :
                ExpressionTypeEvaluation.EvaluateType(def.Initializer, ctxt), null, ept.DeducedTypes); //ept; //ExpressionTypeEvaluation.EvaluateType (ept.Definition.Initializer, ctxt);

            deducedType.Tag = ept.Tag; // Currently requried for proper UFCS resolution - sustain ept's Tag

            // Undo context-related changes
            ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ept);

            return deducedType;
        }
        public static List<ISemantic> PreResolveTemplateArgs(TemplateInstanceExpression tix, ResolutionContext ctxt, out bool hasNonFinalArgument)
        {
            hasNonFinalArgument = false;
            // Resolve given argument expressions
            var templateArguments = new List<ISemantic>();

            if (tix != null && tix.Arguments!=null)
                foreach (var arg in tix.Arguments)
                {
                    if (arg is TypeDeclarationExpression)
                    {
                        var tde = (TypeDeclarationExpression)arg;

                        var res = TypeDeclarationResolver.ResolveSingle(tde.Declaration, ctxt);

                        // Might be a simple symbol without any applied template arguments that is then passed to an template alias parameter
                        if (res == null && tde.Declaration is IdentifierDeclaration)
                            res = TypeDeclarationResolver.ResolveSingle(tde.Declaration as IdentifierDeclaration, ctxt, null, false);

                        var amb = res as AmbiguousType;
                        if (amb != null)
                        {
                            // Error
                            res = amb.Overloads[0];
                        }

                        var mr = res as MemberSymbol;
                        if (mr != null && mr.Definition is DVariable)
                        {
                            var dv = (DVariable)mr.Definition;

                            if (dv.IsAlias || dv.Initializer == null)
                            {
                                templateArguments.Add(mr);
                                continue;
                            }

                            ISemantic eval = null;

                            try
                            {
                                eval = new StandardValueProvider(ctxt)[dv];
                            }
                            catch(System.Exception ee) // Should be a non-const-expression error here only
                            {
                                ctxt.LogError(dv.Initializer, ee.Message);
                            }

                            templateArguments.Add(eval ?? (ISemantic)mr);
                        }
                        else{
                            if(!hasNonFinalArgument)
                                hasNonFinalArgument = IsNonFinalArgument(res);
                            templateArguments.Add(res);
                        }
                    }
                    else
                    {
                        ISemantic v = Evaluation.EvaluateValue(arg, ctxt, true);
                        if (v is VariableValue)
                        {
                            var vv = v as VariableValue;
                            if (vv.Variable.IsConst && vv.Variable.Initializer != null)
                                v = Evaluation.EvaluateValue(vv, new StandardValueProvider(ctxt));
                        }
                        if(!hasNonFinalArgument)
                            hasNonFinalArgument = IsNonFinalArgument(v);
                        v = DResolver.StripValueTypeWrappers(v);
                        templateArguments.Add(v);
                    }
                }

            return templateArguments;
        }
Esempio n. 15
0
        bool HandleAliasThisDeclarations(TemplateIntermediateType tit, MemberFilter vis)
        {
            bool pop;
            var  ch = tit.Definition [DVariable.AliasThisIdentifierHash];

            if (ch != null)
            {
                foreach (DVariable aliasDef in ch)
                {
                    if (MatchesCompilationConditions(aliasDef) ||
                        aliasDef.Type == null)
                    {
                        continue;
                    }

                    pop = ctxt.ScopedBlock != tit.Definition;
                    if (pop)
                    {
                        ctxt.PushNewScope(tit.Definition);
                    }

                    // Resolve the aliased symbol and expect it to be a member symbol(?).
                    //TODO: Check if other cases are allowed as well!
                    var aliasedSymbol = DResolver.StripAliasSymbol(TypeDeclarationResolver.ResolveSingle(aliasDef.Type, ctxt));
                    var aliasedMember = aliasedSymbol as MemberSymbol;

                    if (pop)
                    {
                        ctxt.Pop();
                    }

                    if (aliasedMember == null)
                    {
                        if (aliasedSymbol != null)
                        {
                            ctxt.LogError(aliasDef, "Aliased type from 'alias this' definition is expected to be a type instance, not " + aliasedSymbol.ToString() + "!");
                        }

                        continue;
                    }

                    /*
                     * The aliased member's type can be everything!
                     */
                    aliasedSymbol = aliasedMember.Base;

                    foreach (var statProp in StaticProperties.ListProperties(aliasedSymbol))
                    {
                        if (HandleItem(statProp))
                        {
                            return(true);
                        }
                    }

                    /** TODO: Visit ufcs recommendations and other things that
                     * become added in e.g. MemberCompletionProvider
                     */

                    var tit_ = aliasedSymbol as TemplateIntermediateType;
                    if (tit_ != null)
                    {
                        pop = !ctxt.ScopedBlockIsInNodeHierarchy(tit_.Definition);
                        if (pop)
                        {
                            ctxt.PushNewScope(tit_.Definition);
                        }
                        ctxt.CurrentContext.IntroduceTemplateParameterTypes(tit_);
                        var r = DeepScanClass(tit_, vis, true);
                        if (pop)
                        {
                            ctxt.Pop();
                        }
                        else
                        {
                            ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(tit_);
                        }
                        if (r)
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Esempio n. 16
0
        static AbstractType DeduceEponymousTemplate(EponymousTemplateType ept, ResolutionContext ctxt)
        {
            if (ept.Definition.Initializer == null) {
                ctxt.LogError (ept.Definition, "Can't deduce type from empty initializer!");
                return null;
            }

            // Introduce the deduced params to the current resolution context
            ctxt.CurrentContext.IntroduceTemplateParameterTypes(ept);

            // Get actual overloads
            AbstractType deducedType = null;

            deducedType = new MemberSymbol (ept.Definition, Evaluation.EvaluateType (ept.Definition.Initializer, ctxt), null, ept.DeducedTypes); //ept; //Evaluation.EvaluateType (ept.Definition.Initializer, ctxt);

            // Undo context-related changes
            ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ept);

            return deducedType;
        }
Esempio n. 17
0
            /// <summary>
            /// string[] s;
            ///
            /// foreach(i;s)
            /// {
            ///		// i is of type 'string'
            ///		writeln(i);
            /// }
            /// </summary>
            public AbstractType GetForeachIteratorType(DVariable i)
            {
                var r       = new List <AbstractType>();
                var curStmt = ctxt.ScopedStatement;

                bool init = true;

                // Walk up statement hierarchy -- note that foreach loops can be nested
                while (curStmt != null)
                {
                    if (init)
                    {
                        init = false;
                    }
                    else
                    {
                        curStmt = curStmt.Parent;
                    }

                    if (curStmt is ForeachStatement)
                    {
                        var fe = (ForeachStatement)curStmt;

                        if (fe.ForeachTypeList == null)
                        {
                            continue;
                        }

                        // If the searched variable is declared in the header
                        int iteratorIndex = -1;

                        for (int j = 0; j < fe.ForeachTypeList.Length; j++)
                        {
                            if (fe.ForeachTypeList[j] == i)
                            {
                                iteratorIndex = j;
                                break;
                            }
                        }

                        if (iteratorIndex == -1)
                        {
                            continue;
                        }

                        bool keyIsSearched = iteratorIndex == 0 && fe.ForeachTypeList.Length > 1;


                        // foreach(var k, var v; 0 .. 9)
                        if (keyIsSearched && fe.IsRangeStatement)
                        {
                            // -- it's static type int, of course(?)
                            return(new PrimitiveType(DTokens.Int));
                        }

                        var aggregateType = ExpressionTypeEvaluation.EvaluateType(fe.Aggregate, ctxt);

                        aggregateType = DResolver.StripMemberSymbols(aggregateType);

                        if (aggregateType == null)
                        {
                            return(null);
                        }

                        // The most common way to do a foreach
                        if (aggregateType is AssocArrayType)
                        {
                            var ar = (AssocArrayType)aggregateType;

                            return(keyIsSearched ? ar.KeyType : ar.ValueType);
                        }
                        else if (aggregateType is UserDefinedType)
                        {
                            var tr = (UserDefinedType)aggregateType;

                            if (keyIsSearched || !(tr.Definition is IBlockNode))
                            {
                                continue;
                            }

                            bool foundIterPropertyMatch = false;
                            #region Foreach over Structs and Classes with Ranges

                            // Enlist all 'back'/'front' members
                            var t_l = new List <AbstractType>();

                            foreach (var n in (IBlockNode)tr.Definition)
                            {
                                if (fe.IsReverse ? n.Name == "back" : n.Name == "front")
                                {
                                    t_l.Add(HandleNodeMatch(n, ctxt));
                                }
                            }

                            // Remove aliases
                            var iterPropertyTypes = DResolver.StripAliasSymbols(t_l);

                            foreach (var iterPropType in iterPropertyTypes)
                            {
                                if (iterPropType is MemberSymbol)
                                {
                                    foundIterPropertyMatch = true;

                                    var itp = (MemberSymbol)iterPropType;

                                    // Only take non-parameterized methods
                                    if (itp.Definition is DMethod && ((DMethod)itp.Definition).Parameters.Count != 0)
                                    {
                                        continue;
                                    }

                                    // Handle its base type [return type] as iterator type
                                    if (itp.Base != null)
                                    {
                                        r.Add(itp.Base);
                                    }

                                    foundIterPropertyMatch = true;
                                }
                            }

                            if (foundIterPropertyMatch)
                            {
                                continue;
                            }
                            #endregion

                            #region Foreach over Structs and Classes with opApply
                            t_l.Clear();
                            r.Clear();

                            foreach (var n in (IBlockNode)tr.Definition)
                            {
                                if (n is DMethod &&
                                    (fe.IsReverse ? n.Name == "opApplyReverse" : n.Name == "opApply"))
                                {
                                    t_l.Add(HandleNodeMatch(n, ctxt));
                                }
                            }

                            iterPropertyTypes = DResolver.StripAliasSymbols(t_l);

                            foreach (var iterPropertyType in iterPropertyTypes)
                            {
                                if (iterPropertyType is MemberSymbol)
                                {
                                    var mr = (MemberSymbol)iterPropertyType;
                                    var dm = mr.Definition as DMethod;

                                    if (dm == null || dm.Parameters.Count != 1)
                                    {
                                        continue;
                                    }

                                    var dg = dm.Parameters[0].Type as DelegateDeclaration;

                                    if (dg == null || dg.Parameters.Count != fe.ForeachTypeList.Length)
                                    {
                                        continue;
                                    }

                                    var paramType = Resolve(dg.Parameters[iteratorIndex].Type, ctxt);

                                    if (paramType != null && paramType.Length > 0)
                                    {
                                        r.Add(paramType[0]);
                                    }
                                }
                            }
                            #endregion
                        }

                        if (r.Count > 1)
                        {
                            ctxt.LogError(new ResolutionError(curStmt, "Ambigous iterator type"));
                        }

                        return(r.Count != 0 ? r[0] : null);
                    }
                }

                return(null);
            }
		static AbstractType HandleImportSymbolMatch (ImportSymbolNode importSymbolNode,ResolutionContext ctxt)
		{
			AbstractType ret = null;

			var modAlias = importSymbolNode is ModuleAliasNode;
			if (modAlias ? importSymbolNode.Type != null : importSymbolNode.Type.InnerDeclaration != null) {
				var mods = new List<DModule> ();
				var td = modAlias ? importSymbolNode.Type : importSymbolNode.Type.InnerDeclaration;
				foreach (var mod in ctxt.ParseCache.LookupModuleName (td.ToString ()))
					mods.Add (mod);
				if (mods.Count == 0)
					ctxt.LogError (new NothingFoundError (importSymbolNode.Type));
				else
					if (mods.Count > 1) {
						var m__ = new List<ISemantic> ();
						foreach (var mod in mods)
							m__.Add (new ModuleSymbol (mod, importSymbolNode.Type));
						ctxt.LogError (new AmbiguityError (importSymbolNode.Type, m__));
					}
				var bt = mods.Count != 0 ? (AbstractType)new ModuleSymbol (mods [0], td) : null;
				//TODO: Is this correct behaviour?
				if (!modAlias) {
					var furtherId = ResolveFurtherTypeIdentifier (importSymbolNode.Type.ToString (false), new[] {
						bt
					}, ctxt, importSymbolNode.Type);
					ctxt.CheckForSingleResult (furtherId, importSymbolNode.Type);
					if (furtherId != null && furtherId.Length != 0)
						bt = furtherId [0];
					else
						bt = null;
				}
				ret = new AliasedType (importSymbolNode, bt, importSymbolNode.Type);
			}
			return ret;
		}
		public static AbstractType Resolve(ArrayDecl ad, ResolutionContext ctxt)
		{
			var valueTypes = Resolve(ad.ValueType, ctxt);

			ctxt.CheckForSingleResult(valueTypes, ad);

			AbstractType valueType = null;
			AbstractType keyType = null;
			int fixedArrayLength = -1;

			if (valueTypes != null && valueTypes.Length != 0)
				valueType = valueTypes[0];

			ISymbolValue val;
			keyType = ResolveKey(ad, out fixedArrayLength, out val, ctxt);

			if (keyType == null || (keyType is PrimitiveType &&
			    ((PrimitiveType)keyType).TypeToken == DTokens.Int)) {

				if (fixedArrayLength >= 0) {
					// D Magic: One might access tuple items directly in the pseudo array declaration - so stuff like Tup[0] i; becomes e.g. int i;
					var dtup = DResolver.StripMemberSymbols (valueType) as DTuple;
					if (dtup == null)
						return new ArrayType (valueType, fixedArrayLength, ad);

					if (fixedArrayLength < dtup.Items.Length)
						return AbstractType.Get(dtup.Items [fixedArrayLength]);
					else {
						ctxt.LogError (ad, "TypeTuple only consists of " + dtup.Items.Length + " items. Can't access item at index " + fixedArrayLength);
						return null;
					}
				}
				return new ArrayType (valueType, ad);
			}

			return new AssocArrayType(valueType, keyType, ad);
		}
		public static AbstractType ResolveKey(ArrayDecl ad, out int fixedArrayLength, out ISymbolValue keyVal, ResolutionContext ctxt)
		{
			keyVal = null;
			fixedArrayLength = -1;
			AbstractType keyType = null;

			if (ad.KeyExpression != null)
			{
				//TODO: Template instance expressions?
				var id_x = ad.KeyExpression as IdentifierExpression;
				if (id_x != null && id_x.IsIdentifier)
				{
					var id = new IdentifierDeclaration((string)id_x.Value)
					{
						Location = id_x.Location,
						EndLocation = id_x.EndLocation
					};

					keyType = TypeDeclarationResolver.ResolveSingle(id, ctxt);

					if (keyType != null)
					{
						var tt = DResolver.StripAliasSymbol(keyType) as MemberSymbol;

						if (tt == null ||
							!(tt.Definition is DVariable) ||
							((DVariable)tt.Definition).Initializer == null)
							return keyType;
					}
				}

				try
				{
					keyVal = Evaluation.EvaluateValue(ad.KeyExpression, ctxt);

					if (keyVal != null)
					{
						// Take the value's type as array key type
						keyType = keyVal.RepresentedType;

						// It should be mostly a number only that points out how large the final array should be
						var pv = Evaluation.GetVariableContents(keyVal, new StandardValueProvider(ctxt)) as PrimitiveValue;
						if (pv != null)
						{
							fixedArrayLength = System.Convert.ToInt32(pv.Value);

							if (fixedArrayLength < 0)
								ctxt.LogError(ad, "Invalid array size: Length value must be greater than 0");
						}
						//TODO Is there any other type of value allowed?
					}
				}
				catch { }
			}
			else
			{
				var t = Resolve(ad.KeyType, ctxt);
				ctxt.CheckForSingleResult(t, ad.KeyType);

				if (t != null && t.Length != 0)
					return t[0];
			}

			return keyType;
		}
Esempio n. 21
0
        public static List<ISemantic> PreResolveTemplateArgs(TemplateInstanceExpression tix, ResolutionContext ctxt, out bool hasNonFinalArgument)
        {
            hasNonFinalArgument = false;
            // Resolve given argument expressions
            var templateArguments = new List<ISemantic>();

            if (tix != null && tix.Arguments!=null)
                foreach (var arg in tix.Arguments)
                {
                    if (arg is TypeDeclarationExpression)
                    {
                        var tde = (TypeDeclarationExpression)arg;

                        var res = TypeDeclarationResolver.Resolve(tde.Declaration, ctxt);

                        if (ctxt.CheckForSingleResult(res, tde.Declaration) || res != null)
                        {
                            var mr = res[0] as MemberSymbol;
                            if (mr != null && mr.Definition is DVariable)
                            {
                                var dv = (DVariable)mr.Definition;

                                if (dv.IsAlias || dv.Initializer == null)
                                {
                                    templateArguments.Add(mr);
                                    continue;
                                }

                                ISemantic eval = null;

                                try
                                {
                                    eval = new StandardValueProvider(ctxt)[dv];
                                }
                                catch(System.Exception ee) // Should be a non-const-expression error here only
                                {
                                    ctxt.LogError(dv.Initializer, ee.Message);
                                }

                                templateArguments.Add(eval==null ? (ISemantic)mr : eval);
                            }
                            else{
                                if(!hasNonFinalArgument)
                                    hasNonFinalArgument = IsNonFinalArgument(res[0]);
                                templateArguments.Add(res[0]);
                            }
                        }
                    }
                    else
                    {
                        var v = Evaluation.EvaluateValue(arg, ctxt, true);
                        if (v is VariableValue)
                        {
                            var vv = v as VariableValue;
                            if (vv.Variable.IsConst && vv.Variable.Initializer != null)
                                v = Evaluation.EvaluateValue(vv, new StandardValueProvider(ctxt));
                        }
                        if(!hasNonFinalArgument)
                            hasNonFinalArgument = IsNonFinalArgument(v);
                        templateArguments.Add(v);
                    }
                }

            return templateArguments;
        }
		/// <summary>
		/// string[] s;
		/// 
		/// foreach(i;s)
		/// {
		///		// i is of type 'string'
		///		writeln(i);
		/// }
		/// </summary>
		public static AbstractType GetForeachIteratorType(DVariable i, ResolutionContext ctxt)
		{
			var r = new List<AbstractType>();
			var curStmt = ctxt.ScopedStatement;

			bool init = true;
			// Walk up statement hierarchy -- note that foreach loops can be nested
			while (curStmt != null)
			{
				if (init)
					init = false;
				else
					curStmt = curStmt.Parent;

				if (curStmt is ForeachStatement)
				{
					var fe = (ForeachStatement)curStmt;

					if (fe.ForeachTypeList == null)
						continue;

					// If the searched variable is declared in the header
					int iteratorIndex = -1;

					for (int j = 0; j < fe.ForeachTypeList.Length; j++)
						if (fe.ForeachTypeList[j] == i)
						{
							iteratorIndex = j;
							break;
						}

					if (iteratorIndex == -1)
						continue;

					bool keyIsSearched = iteratorIndex == 0 && fe.ForeachTypeList.Length > 1;


					// foreach(var k, var v; 0 .. 9)
					if (keyIsSearched && fe.IsRangeStatement)
					{
						// -- it's static type int, of course(?)
						return new PrimitiveType(DTokens.Int);
					}

					var aggregateType = Evaluation.EvaluateType(fe.Aggregate, ctxt);

					aggregateType = DResolver.StripMemberSymbols(aggregateType);

					if (aggregateType == null)
						return null;

					// The most common way to do a foreach
					if (aggregateType is AssocArrayType)
					{
						var ar = (AssocArrayType)aggregateType;

						return keyIsSearched ? ar.KeyType : ar.ValueType;
					}
					else if (aggregateType is UserDefinedType)
					{
						var tr = (UserDefinedType)aggregateType;

						if (keyIsSearched || !(tr.Definition is IBlockNode))
							continue;

						bool foundIterPropertyMatch = false;
						#region Foreach over Structs and Classes with Ranges

						// Enlist all 'back'/'front' members
						var t_l = new List<AbstractType>();

						foreach (var n in (IBlockNode)tr.Definition)
							if (fe.IsReverse ? n.Name == "back" : n.Name == "front")
								t_l.Add(HandleNodeMatch(n, ctxt));

						// Remove aliases
						var iterPropertyTypes = DResolver.StripAliasSymbols(t_l);

						foreach (var iterPropType in iterPropertyTypes)
							if (iterPropType is MemberSymbol)
							{
								foundIterPropertyMatch = true;

								var itp = (MemberSymbol)iterPropType;

								// Only take non-parameterized methods
								if (itp.Definition is DMethod && ((DMethod)itp.Definition).Parameters.Count != 0)
									continue;

								// Handle its base type [return type] as iterator type
								if (itp.Base != null)
									r.Add(itp.Base);

								foundIterPropertyMatch = true;
							}

						if (foundIterPropertyMatch)
							continue;
						#endregion

						#region Foreach over Structs and Classes with opApply
						t_l.Clear();
						r.Clear();

						foreach (var n in (IBlockNode)tr.Definition)
							if (n is DMethod &&
								(fe.IsReverse ? n.Name == "opApplyReverse" : n.Name == "opApply"))
								t_l.Add(HandleNodeMatch(n, ctxt));

						iterPropertyTypes = DResolver.StripAliasSymbols(t_l);

						foreach (var iterPropertyType in iterPropertyTypes)
							if (iterPropertyType is MemberSymbol)
							{
								var mr = (MemberSymbol)iterPropertyType;
								var dm = mr.Definition as DMethod;

								if (dm == null || dm.Parameters.Count != 1)
									continue;

								var dg = dm.Parameters[0].Type as DelegateDeclaration;

								if (dg == null || dg.Parameters.Count != fe.ForeachTypeList.Length)
									continue;

								var paramType = Resolve(dg.Parameters[iteratorIndex].Type, ctxt);

								if (paramType != null && paramType.Length > 0)
									r.Add(paramType[0]);
							}
						#endregion
					}

					if (r.Count > 1)
						ctxt.LogError(new ResolutionError(curStmt, "Ambigous iterator type"));

					return r.Count != 0 ? r[0] : null;
				}
			}

			return null;
		}
Esempio n. 23
0
        /// <summary>
        /// Takes the class passed via the tr, and resolves its base class and/or implemented interfaces.
        /// Also usable for enums.
        ///
        /// Never returns null. Instead, the original 'tr' object will be returned if no base class was resolved.
        /// Will clone 'tr', whereas the new object will contain the base class.
        /// </summary>
        public static UserDefinedType ResolveBaseClasses(UserDefinedType tr, ResolutionContext ctxt, bool ResolveFirstBaseIdOnly = false)
        {
            if (bcStack > 8)
            {
                bcStack--;
                return(tr);
            }

            if (tr is EnumType)
            {
                var et = tr as EnumType;

                AbstractType bt = null;

                if (et.Definition.Type == null)
                {
                    bt = new PrimitiveType(DTokens.Int);
                }
                else
                {
                    if (tr.Definition.Parent is IBlockNode)
                    {
                        ctxt.PushNewScope((IBlockNode)tr.Definition.Parent);
                    }

                    var bts = TypeDeclarationResolver.Resolve(et.Definition.Type, ctxt);

                    if (tr.Definition.Parent is IBlockNode)
                    {
                        ctxt.Pop();
                    }

                    ctxt.CheckForSingleResult(bts, et.Definition.Type);

                    if (bts != null && bts.Length != 0)
                    {
                        bt = bts[0];
                    }
                }

                return(new EnumType(et.Definition, bt, et.DeclarationOrExpressionBase));
            }

            var dc = tr.Definition as DClassLike;

            // Return immediately if searching base classes of the Object class
            if (dc == null || ((dc.BaseClasses == null || dc.BaseClasses.Count < 1) && dc.Name == "Object"))
            {
                return(tr);
            }

            // If no base class(es) specified, and if it's no interface that is handled, return the global Object reference
            // -- and do not throw any error message, it's ok
            if (dc.BaseClasses == null || dc.BaseClasses.Count < 1)
            {
                if (tr is ClassType)                // Only Classes can inherit from non-interfaces
                {
                    return(new ClassType(dc, tr.DeclarationOrExpressionBase, ctxt.ParseCache.ObjectClassResult));
                }
                return(tr);
            }

            #region Base class & interface resolution
            TemplateIntermediateType baseClass = null;
            var interfaces = new List <InterfaceType>();

            if (!(tr is ClassType || tr is InterfaceType))
            {
                if (dc.BaseClasses.Count != 0)
                {
                    ctxt.LogError(dc, "Only classes and interfaces may inherit from other classes/interfaces");
                }
                return(tr);
            }

            for (int i = 0; i < (ResolveFirstBaseIdOnly ? 1 : dc.BaseClasses.Count); i++)
            {
                var type = dc.BaseClasses[i];

                // If there's an explicit 'Object' inheritance, also return the pre-resolved object class
                if (type is IdentifierDeclaration && ((IdentifierDeclaration)type).Id == "Object")
                {
                    if (baseClass != null)
                    {
                        ctxt.LogError(new ResolutionError(dc, "Class must not have two base classes"));
                        continue;
                    }
                    else if (i != 0)
                    {
                        ctxt.LogError(new ResolutionError(dc, "The base class name must preceed base interfaces"));
                        continue;
                    }

                    baseClass = ctxt.ParseCache.ObjectClassResult;
                    continue;
                }

                if (type == null || type.ToString(false) == dc.Name || dc.NodeRoot == dc)
                {
                    ctxt.LogError(new ResolutionError(dc, "A class cannot inherit from itself"));
                    continue;
                }

                ctxt.PushNewScope(dc.Parent as IBlockNode);

                bcStack++;

                var res = DResolver.StripAliasSymbols(TypeDeclarationResolver.Resolve(type, ctxt));

                ctxt.CheckForSingleResult(res, type);

                if (res != null && res.Length != 0)
                {
                    var r = res[0];
                    if (r is ClassType || r is TemplateType)
                    {
                        if (tr is InterfaceType)
                        {
                            ctxt.LogError(new ResolutionError(type, "An interface cannot inherit from non-interfaces"));
                        }
                        else if (i == 0)
                        {
                            baseClass = (TemplateIntermediateType)r;
                        }
                        else
                        {
                            ctxt.LogError(new ResolutionError(dc, "The base " + (r is ClassType ?  "class" : "template") + " name must preceed base interfaces"));
                        }
                    }
                    else if (r is InterfaceType)
                    {
                        interfaces.Add((InterfaceType)r);
                    }
                    else
                    {
                        ctxt.LogError(new ResolutionError(type, "Resolved class is neither a class nor an interface"));
                        continue;
                    }
                }

                bcStack--;

                ctxt.Pop();
            }
            #endregion

            if (baseClass == null && interfaces.Count == 0)
            {
                return(tr);
            }

            if (tr is ClassType)
            {
                return(new ClassType(dc, tr.DeclarationOrExpressionBase, baseClass, interfaces.Count == 0 ? null : interfaces.ToArray(), tr.DeducedTypes));
            }
            else if (tr is InterfaceType)
            {
                return(new InterfaceType(dc, tr.DeclarationOrExpressionBase, interfaces.Count == 0 ? null : interfaces.ToArray(), tr.DeducedTypes));
            }

            // Method should end here
            return(tr);
        }
Esempio n. 24
0
        /// <summary>
        /// Takes the class passed via the tr, and resolves its base class and/or implemented interfaces.
        /// Also usable for enums.
        ///
        /// Never returns null. Instead, the original 'tr' object will be returned if no base class was resolved.
        /// Will clone 'tr', whereas the new object will contain the base class.
        /// </summary>
        public static TemplateIntermediateType ResolveClassOrInterface(DClassLike dc, ResolutionContext ctxt, ISyntaxRegion instanceDeclaration, bool ResolveFirstBaseIdOnly = false, IEnumerable <TemplateParameterSymbol> extraDeducedTemplateParams = null)
        {
            if (parsedClassInstanceDecls == null)
            {
                parsedClassInstanceDecls = new List <ISyntaxRegion> ();
            }

            switch (dc.ClassType)
            {
            case DTokens.Class:
            case DTokens.Interface:
                break;

            default:
                if (dc.BaseClasses.Count != 0)
                {
                    ctxt.LogError(dc, "Only classes and interfaces may inherit from other classes/interfaces");
                }
                return(null);
            }

            bool isClass = dc.ClassType == DTokens.Class;

            if (bcStack > 6 || (instanceDeclaration != null && parsedClassInstanceDecls.Contains(instanceDeclaration)))
            {
                return(isClass ? new ClassType(dc, instanceDeclaration, null) as TemplateIntermediateType : new InterfaceType(dc, instanceDeclaration));
            }

            if (instanceDeclaration != null)
            {
                parsedClassInstanceDecls.Add(instanceDeclaration);
            }
            bcStack++;

            var deducedTypes = new DeducedTypeDictionary(dc);
            var tix          = instanceDeclaration as TemplateInstanceExpression;

            if (tix != null && (ctxt.Options & ResolutionOptions.NoTemplateParameterDeduction) == 0)
            {
                bool hasUndeterminedArgs;
                var  givenTemplateArguments = TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt, out hasUndeterminedArgs);

                if (!TemplateInstanceHandler.DeduceParams(givenTemplateArguments, false, ctxt, null, dc, deducedTypes))
                {
                    parsedClassInstanceDecls.Remove(instanceDeclaration);
                    bcStack--;
                    return(null);
                }
            }

            if (extraDeducedTemplateParams != null)
            {
                foreach (var tps in extraDeducedTemplateParams)
                {
                    deducedTypes[tps.Parameter] = tps;
                }
            }


            if (dc.BaseClasses == null || dc.BaseClasses.Count < 1)
            {
                parsedClassInstanceDecls.Remove(instanceDeclaration);
                bcStack--;

                // The Object class has no further base class;
                // Normal class instances have the object as base class;
                // Interfaces must not have any default base class/interface
                return(isClass ? new ClassType(dc, instanceDeclaration, dc.NameHash != ObjectNameHash ? ctxt.ParseCache.ObjectClassResult : null, null, deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null) :
                       new InterfaceType(dc, instanceDeclaration, null, deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null) as TemplateIntermediateType);
            }


            #region Base class & interface resolution
            AbstractType[] res;
            var            pop = ctxt.ScopedBlock != dc.Parent;
            if (pop)
            {
                ctxt.PushNewScope(dc.Parent as IBlockNode);
            }

            foreach (var kv in deducedTypes)
            {
                ctxt.CurrentContext.DeducedTemplateParameters[kv.Key] = kv.Value;
            }

            TemplateIntermediateType baseClass = null;
            var interfaces = new List <InterfaceType>();
            try
            {
                for (int i = 0; i < (ResolveFirstBaseIdOnly ? 1 : dc.BaseClasses.Count); i++)
                {
                    var type = dc.BaseClasses[i];

                    // If there's an explicit 'Object' inheritance, also return the pre-resolved object class
                    if (type is IdentifierDeclaration &&
                        (type as IdentifierDeclaration).IdHash == ObjectNameHash)
                    {
                        if (baseClass != null)
                        {
                            ctxt.LogError(new ResolutionError(dc, "Class must not have two base classes"));
                            continue;
                        }
                        else if (i != 0)
                        {
                            ctxt.LogError(new ResolutionError(dc, "The base class name must preceed base interfaces"));
                            continue;
                        }

                        baseClass = ctxt.ParseCache.ObjectClassResult;
                        continue;
                    }

                    if (type == null || (type is IdentifierDeclaration && (type as IdentifierDeclaration).IdHash == dc.NameHash) || dc.NodeRoot == dc)
                    {
                        ctxt.LogError(new ResolutionError(dc, "A class cannot inherit from itself"));
                        continue;
                    }

                    res = DResolver.StripAliasSymbols(TypeDeclarationResolver.Resolve(type, ctxt));

                    ctxt.CheckForSingleResult(res, type);

                    if (res != null && res.Length != 0)
                    {
                        var r = res[0];
                        if (r is ClassType || r is TemplateType)
                        {
                            if (!isClass)
                            {
                                ctxt.LogError(new ResolutionError(type, "An interface cannot inherit from non-interfaces"));
                            }
                            else if (i == 0)
                            {
                                baseClass = r as TemplateIntermediateType;
                            }
                            else
                            {
                                ctxt.LogError(new ResolutionError(dc, "The base " + (r is ClassType ?  "class" : "template") + " name must preceed base interfaces"));
                            }
                        }
                        else if (r is InterfaceType)
                        {
                            interfaces.Add(r as InterfaceType);

                            if (isClass && dc.NameHash != ObjectNameHash && baseClass == null)
                            {
                                baseClass = ctxt.ParseCache.ObjectClassResult;
                            }
                        }
                        else
                        {
                            ctxt.LogError(new ResolutionError(type, "Resolved class is neither a class nor an interface"));
                            continue;
                        }
                    }
                }
            }
            finally
            {
                bcStack--;
                parsedClassInstanceDecls.Remove(instanceDeclaration);
            }

            if (pop)
            {
                ctxt.Pop();
            }
            else
            {
                foreach (var kv in deducedTypes)                 // May be backup old tps?
                {
                    ctxt.CurrentContext.DeducedTemplateParameters.Remove(kv.Key);
                }
            }

            #endregion

            if (isClass)
            {
                return(new ClassType(dc, instanceDeclaration, baseClass, interfaces.Count == 0 ? null : interfaces.ToArray(), deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null));
            }

            return(new InterfaceType(dc, instanceDeclaration, interfaces.Count == 0 ? null : interfaces.ToArray(), deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null));
        }
        /// <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);
        }
Esempio n. 26
0
        public static List <ISemantic> PreResolveTemplateArgs(TemplateInstanceExpression tix, ResolutionContext ctxt)
        {
            // Resolve given argument expressions
            var templateArguments = new List <ISemantic>();

            if (tix != null && tix.Arguments != null)
            {
                foreach (var arg in tix.Arguments)
                {
                    if (arg is TypeDeclarationExpression)
                    {
                        var tde = (TypeDeclarationExpression)arg;

                        var res = TypeDeclarationResolver.ResolveSingle(tde.Declaration, ctxt);

                        // Might be a simple symbol without any applied template arguments that is then passed to an template alias parameter
                        if (res == null && tde.Declaration is IdentifierDeclaration)
                        {
                            res = TypeDeclarationResolver.ResolveSingle(tde.Declaration as IdentifierDeclaration, ctxt, null, false);
                        }

                        var amb = res as AmbiguousType;
                        if (amb != null)
                        {
                            // Error
                            res = amb.Overloads[0];
                        }

                        var mr = res as MemberSymbol;
                        if (mr != null && mr.Definition is DVariable)
                        {
                            var dv = (DVariable)mr.Definition;

                            if (dv.IsAlias || dv.Initializer == null)
                            {
                                templateArguments.Add(mr);
                                continue;
                            }

                            ISemantic eval = null;

                            try
                            {
                                eval = new StandardValueProvider(ctxt)[dv];
                            }
                            catch (System.Exception ee)                            // Should be a non-const-expression error here only
                            {
                                ctxt.LogError(dv.Initializer, ee.Message);
                            }

                            templateArguments.Add(eval ?? (ISemantic)mr);
                        }
                        else
                        {
                            templateArguments.Add(res);
                        }
                    }
                    else
                    {
                        ISemantic v = Evaluation.EvaluateValue(arg, ctxt, true);
                        if (v is VariableValue)
                        {
                            var vv = v as VariableValue;
                            if (vv.Variable.IsConst && vv.Variable.Initializer != null)
                            {
                                v = Evaluation.EvaluateValue(vv, new StandardValueProvider(ctxt));
                            }
                        }

                        v = DResolver.StripValueTypeWrappers(v);
                        templateArguments.Add(v);
                    }
                }
            }

            return(templateArguments);
        }