예제 #1
0
        AbstractType HandleAccessExpressions(PostfixExpression_Access acc, ResolutionContext ctxt)
        {
            AbstractType pfType = null;

            if (acc.PostfixForeExpression is PostfixExpression_Access)
            {
                pfType = HandleAccessExpressions((PostfixExpression_Access)acc.PostfixForeExpression, ctxt);
            }
            else
            {
                pfType = DResolver.StripAliasSymbol(Evaluation.EvaluateType(acc.PostfixForeExpression, ctxt));

                if (acc.PostfixForeExpression is IdentifierExpression ||
                    acc.PostfixForeExpression is TemplateInstanceExpression ||
                    acc.PostfixForeExpression is PostfixExpression_Access)
                {
                    HandleResult(acc.PostfixForeExpression, pfType);
                }
            }

            var accessedMembers = Evaluation.GetAccessedOverloads(acc, ctxt, pfType);

            ctxt.CheckForSingleResult(accessedMembers, acc);

            if (accessedMembers != null && accessedMembers.Length != 0)
            {
                HandleResult(acc, accessedMembers[0]);
                return(accessedMembers[0]);
            }

            return(null);
        }
예제 #2
0
        /// <summary>
        /// See <see cref="ResolveIdentifier"/>
        /// </summary>
        public static AbstractType ResolveSingle(string id, ResolutionContext ctxt, ISyntaxRegion idObject, bool ModuleScope = false)
        {
            var r = ResolveIdentifier(id, ctxt, idObject, ModuleScope);

            ctxt.CheckForSingleResult(r, idObject as ISyntaxRegion);

            return(r != null && r.Length != 0 ? r[0] : null);
        }
예제 #3
0
        /// <summary>
        /// See <see cref="Resolve"/>
        /// </summary>
        public static AbstractType ResolveSingle(IdentifierDeclaration id, ResolutionContext ctxt, AbstractType[] resultBases = null, bool filterForTemplateArgs = true)
        {
            var r = Resolve(id, ctxt, resultBases, filterForTemplateArgs);

            ctxt.CheckForSingleResult(r, id);

            return(r != null && r.Length != 0 ? r[0] : null);
        }
예제 #4
0
            public AbstractType Visit(DVariable variable)
            {
                AbstractType bt;

                if (CanResolveBase(variable))
                {
                    var bts = TypeDeclarationResolver.Resolve(variable.Type, ctxt);

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

                    // For auto variables, use the initializer to get its type
                    else if (variable.Initializer != null)
                    {
                        bt = DResolver.StripMemberSymbols(ExpressionTypeEvaluation.EvaluateType(variable.Initializer, ctxt));
                    }
                    else
                    {
                        bt = null;
                    }

                    // Check if inside an foreach statement header
                    if (bt == null && ctxt.ScopedStatement != null)
                    {
                        bt = GetForeachIteratorType(variable);
                    }

                    if (bt == null)
                    {
                        ctxt.CheckForSingleResult(bts, variable.Type as ISyntaxRegion ?? variable.Initializer);
                    }
                }
                else
                {
                    bt = null;
                }

                // Note: Also works for aliases! In this case, we simply try to resolve the aliased type, otherwise the variable's base type
                return(variable.IsAlias ?
                       new AliasedType(variable, bt, typeBase) :
                       new MemberSymbol(variable, bt, typeBase));
            }
예제 #5
0
        public static PointerType Resolve(PointerDecl pd, ResolutionContext ctxt)
        {
            var ptrBaseTypes = Resolve(pd.InnerDeclaration, ctxt);

            ctxt.CheckForSingleResult(ptrBaseTypes, pd);

            if (ptrBaseTypes == null || ptrBaseTypes.Length == 0)
            {
                return(null);
            }

            return(new PointerType(ptrBaseTypes[0], pd));
        }
예제 #6
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);
        }
예제 #7
0
        public static AbstractType Resolve(MemberFunctionAttributeDecl attrDecl, ResolutionContext ctxt)
        {
            if (attrDecl != null)
            {
                var ret = Resolve(attrDecl.InnerType, ctxt);

                ctxt.CheckForSingleResult(ret, attrDecl.InnerType);

                if (ret != null && ret.Length != 0 && ret[0] != null)
                {
                    ret[0].Modifier = attrDecl.Modifier;
                    return(ret[0]);
                }
            }
            return(null);
        }
예제 #8
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));
        }
예제 #9
0
        public AbstractType Visit(PostfixExpression_MethodCall call)
        {
            List <ISemantic> callArgs;
            ISymbolValue     delegValue;

            AbstractType[]             baseExpression;
            TemplateInstanceExpression tix;

            GetRawCallOverloads(ctxt, call, out baseExpression, out tix);

            var argTypeFilteredOverloads = Evaluation.EvalMethodCall(baseExpression, null, tix, ctxt, call, out callArgs, out delegValue, !ctxt.Options.HasFlag(ResolutionOptions.ReturnMethodReferencesOnly));

            // Check if one overload remains and return that one.
            ctxt.CheckForSingleResult(argTypeFilteredOverloads, call);
            return(argTypeFilteredOverloads != null && argTypeFilteredOverloads.Count != 0 ? argTypeFilteredOverloads[0] : null);
        }
예제 #10
0
        public static AbstractType GetMethodReturnType(DelegateType dg, ResolutionContext ctxt)
        {
            if (dg == null || ctxt == null)
            {
                return(null);
            }

            if (dg.IsFunctionLiteral)
            {
                return(GetMethodReturnType(((FunctionLiteral)dg.DeclarationOrExpressionBase).AnonymousMethod, ctxt));
            }
            else
            {
                var rt = ((DelegateDeclaration)dg.DeclarationOrExpressionBase).ReturnType;
                var r  = Resolve(rt, ctxt);

                ctxt.CheckForSingleResult(r, rt);

                return(r[0]);
            }
        }
예제 #11
0
        public static DelegateType Resolve(DelegateDeclaration dg, ResolutionContext ctxt)
        {
            var returnTypes = Resolve(dg.ReturnType, ctxt);

            ctxt.CheckForSingleResult(returnTypes, dg.ReturnType);

            if (returnTypes != null && returnTypes.Length != 0)
            {
                List <AbstractType> paramTypes = null;
                if (dg.Parameters != null &&
                    dg.Parameters.Count != 0)
                {
                    paramTypes = new List <AbstractType>();
                    foreach (var par in dg.Parameters)
                    {
                        paramTypes.Add(ResolveSingle(par.Type, ctxt));
                    }
                }
                return(new DelegateType(returnTypes[0], dg, paramTypes));
            }
            return(null);
        }
예제 #12
0
        public AbstractType Visit(UnaryExpression_Type x)
        {
            var uat = x as UnaryExpression_Type;

            if (uat.Type == null)
            {
                return(null);
            }

            var types = TypeDeclarationResolver.Resolve(uat.Type, ctxt);

            ctxt.CheckForSingleResult(types, uat.Type);

            if (types != null && types.Length != 0)
            {
                return(TypeDeclarationResolver.ResolveSingle(new IdentifierDeclaration(uat.AccessIdentifierHash)
                {
                    EndLocation = uat.EndLocation
                }, ctxt, types));
            }

            return(null);
        }
		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;
		}
		public static AbstractType Resolve(MemberFunctionAttributeDecl attrDecl, ResolutionContext ctxt)
		{
			if (attrDecl != null)
			{
				var ret = Resolve(attrDecl.InnerType, ctxt);

				ctxt.CheckForSingleResult(ret, attrDecl.InnerType);

				if (ret != null && ret.Length != 0 && ret[0] != null)
				{
					ret[0].Modifier = attrDecl.Modifier;
					return ret[0];
				}
			}
			return null;
		}
예제 #15
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);
        }
		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 DelegateType Resolve(DelegateDeclaration dg, ResolutionContext ctxt)
		{
			var returnTypes = Resolve(dg.ReturnType, ctxt);

			ctxt.CheckForSingleResult(returnTypes, dg.ReturnType);

			if (returnTypes != null && returnTypes.Length != 0)
			{
				List<AbstractType> paramTypes=null;
				if(dg.Parameters!=null && 
				   dg.Parameters.Count != 0)
				{	
					paramTypes = new List<AbstractType>();
					foreach(var par in dg.Parameters)
						paramTypes.Add(ResolveSingle(par.Type, ctxt));
				}
				return new DelegateType(returnTypes[0], dg, paramTypes);
			}
			return null;
		}
		public static PointerType Resolve(PointerDecl pd, ResolutionContext ctxt)
		{
			var ptrBaseTypes = Resolve(pd.InnerDeclaration, ctxt);

			ctxt.CheckForSingleResult(ptrBaseTypes, pd);

			if (ptrBaseTypes == null || ptrBaseTypes.Length == 0)
				return null;

			return new PointerType(ptrBaseTypes[0], pd);
		}
예제 #19
0
        public static AbstractType GetMethodReturnType(DMethod method, ResolutionContext ctxt)
        {
            if ((ctxt.Options & ResolutionOptions.DontResolveBaseTypes) == ResolutionOptions.DontResolveBaseTypes)
            {
                return(null);
            }

            /*
             * If a method's type equals null, assume that it's an 'auto' function..
             * 1) Search for a return statement
             * 2) Resolve the returned expression
             * 3) Use that one as the method's type
             */
            bool pushMethodScope = ctxt.ScopedBlock != method;

            if (method.Type != null)
            {
                if (pushMethodScope)
                {
                    ctxt.PushNewScope(method);
                }

                //FIXME: Is it legal to explicitly return a nested type?
                var returnType = TypeDeclarationResolver.Resolve(method.Type, ctxt);

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

                ctxt.CheckForSingleResult(returnType, method.Type);
                if (returnType != null && returnType.Length > 0)
                {
                    return(returnType[0]);
                }
            }
            else if (method.Body != null)
            {
                ReturnStatement returnStmt = null;
                var             list       = new List <IStatement> {
                    method.Body
                };
                var list2 = new List <IStatement>();

                bool foundMatch = false;
                while (!foundMatch && list.Count > 0)
                {
                    foreach (var stmt in list)
                    {
                        if (stmt is ReturnStatement)
                        {
                            returnStmt = stmt as ReturnStatement;

                            var te = returnStmt.ReturnExpression as TokenExpression;
                            if (te == null || te.Token != DTokens.Null)
                            {
                                foundMatch = true;
                                break;
                            }
                        }

                        var statementContainingStatement = stmt as StatementContainingStatement;
                        if (statementContainingStatement != null)
                        {
                            list2.AddRange(statementContainingStatement.SubStatements);
                        }
                    }

                    list  = list2;
                    list2 = new List <IStatement>();
                }

                if (returnStmt != null && returnStmt.ReturnExpression != null)
                {
                    if (pushMethodScope)
                    {
                        var dedTypes = ctxt.CurrentContext.DeducedTemplateParameters;
                        ctxt.PushNewScope(method, returnStmt);

                        if (dedTypes.Count != 0)
                        {
                            foreach (var kv in dedTypes)
                            {
                                ctxt.CurrentContext.DeducedTemplateParameters[kv.Key] = kv.Value;
                            }
                        }
                    }

                    var t = DResolver.StripMemberSymbols(ExpressionTypeEvaluation.EvaluateType(returnStmt.ReturnExpression, ctxt));

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

                    return(t);
                }

                return(new PrimitiveType(DTokens.Void));
            }

            return(null);
        }
		/// <summary>
		/// See <see cref="ResolveIdentifier"/>
		/// </summary>
		public static AbstractType ResolveSingle(string id, ResolutionContext ctxt, object idObject, bool ModuleScope = false)
		{
			var r = ResolveIdentifier(id, ctxt, idObject, ModuleScope);

			ctxt.CheckForSingleResult(r, idObject as ISyntaxRegion);

			return r != null && r.Length != 0 ? r[0] : null;
		}
예제 #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>
		/// The variable's or method's base type will be resolved (if auto type, the intializer's type will be taken).
		/// A class' base class will be searched.
		/// etc..
		/// </summary>
		public static AbstractType HandleNodeMatch(
			INode m,
			ResolutionContext ctxt,
			AbstractType resultBase = null,
			object typeBase = null)
		{
			AbstractType ret = null;

			// See https://github.com/aBothe/Mono-D/issues/161
			int stkC;

			if (stackCalls == null)
			{
				stackCalls = new Dictionary<INode, int>();
				stackCalls[m] = stkC = 1;
			}
			else if (stackCalls.TryGetValue(m, out stkC))
				stackCalls[m] = ++stkC;
			else
				stackCalls[m] = stkC = 1;
			/*
			 * Pushing a new scope is only required if current scope cannot be found in the handled node's hierarchy.
			 * Edit: No, it is required nearly every time because of nested type declarations - then, we do need the 
			 * current block scope.
			 */
			bool popAfterwards;
			{
				var newScope = m is IBlockNode ? (IBlockNode)m : m.Parent as IBlockNode;
				popAfterwards = ctxt.ScopedBlock != newScope && newScope != null;
				if (popAfterwards) {
					var options = ctxt.CurrentContext.ContextDependentOptions;
					var applyOptions = ctxt.ScopedBlockIsInNodeHierarchy (m);
					ctxt.PushNewScope (newScope);
					if (applyOptions)
						ctxt.CurrentContext.ContextDependentOptions = options;
				}
			}

			var canResolveBase = ((ctxt.Options & ResolutionOptions.DontResolveBaseTypes) != ResolutionOptions.DontResolveBaseTypes) && 
			                     stkC < 10 && (m.Type == null || m.Type.ToString(false) != m.Name);
			
			// To support resolving type parameters to concrete types if the context allows this, introduce all deduced parameters to the current context
			if (resultBase is DSymbol)
				ctxt.CurrentContext.IntroduceTemplateParameterTypes((DSymbol)resultBase);

			var importSymbolNode = m as ImportSymbolNode;
			var variable = m as DVariable;

			// Only import symbol aliases are allowed to search in the parse cache
			if (importSymbolNode != null)
				ret = HandleImportSymbolMatch (importSymbolNode,ctxt);
			else if (variable != null)
			{
				AbstractType bt = null;

				if (!(variable is EponymousTemplate)) {
					if (canResolveBase) {
						var bts = TypeDeclarationResolver.Resolve (variable.Type, ctxt);
						ctxt.CheckForSingleResult (bts, variable.Type);

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

					// For auto variables, use the initializer to get its type
					else if (variable.Initializer != null) {
							bt = DResolver.StripMemberSymbols (Evaluation.EvaluateType (variable.Initializer, ctxt));
						}

						// Check if inside an foreach statement header
						if (bt == null && ctxt.ScopedStatement != null)
							bt = GetForeachIteratorType (variable, ctxt);
					}

					// Note: Also works for aliases! In this case, we simply try to resolve the aliased type, otherwise the variable's base type
					ret = variable.IsAlias ?
					new AliasedType (variable, bt, typeBase as ISyntaxRegion) as MemberSymbol :
					new MemberSymbol (variable, bt, typeBase as ISyntaxRegion);
				} else
					ret = new EponymousTemplateType (variable as EponymousTemplate, GetInvisibleTypeParameters(variable, ctxt).AsReadOnly(), typeBase as ISyntaxRegion);
			}
			else if (m is DMethod)
			{
				ret = new MemberSymbol(m as DNode,canResolveBase ? GetMethodReturnType(m as DMethod, ctxt) : null, typeBase as ISyntaxRegion);
			}
			else if (m is DClassLike)
				ret = HandleClassLikeMatch (m as DClassLike, ctxt, typeBase, canResolveBase);
			else if (m is DModule)
			{
				var mod = (DModule)m;
				if (typeBase != null && typeBase.ToString() != mod.ModuleName)
				{
					var pack = ctxt.ParseCache.LookupPackage(typeBase.ToString()).FirstOrDefault();
					if (pack != null)
						ret = new PackageSymbol(pack, typeBase as ISyntaxRegion);
				}
				else
					ret = new ModuleSymbol(m as DModule, typeBase as ISyntaxRegion);
			}
			else if (m is DEnum)
				ret = new EnumType((DEnum)m, typeBase as ISyntaxRegion);
			else if (m is TemplateParameter.Node)
			{
				//ResolveResult[] templateParameterType = null;

				//TODO: Resolve the specialization type
				//var templateParameterType = TemplateInstanceHandler.ResolveTypeSpecialization(tmp, ctxt);
				ret = new TemplateParameterSymbol((m as TemplateParameter.Node).TemplateParameter, null, typeBase as ISyntaxRegion);
			}
			else if(m is NamedTemplateMixinNode)
			{
				var tmxNode = m as NamedTemplateMixinNode;
				ret = new MemberSymbol(tmxNode, canResolveBase ? ResolveSingle(tmxNode.Type, ctxt) : null, typeBase as ISyntaxRegion);
			}

			if (popAfterwards)
				ctxt.Pop();
			else if (resultBase is DSymbol)
				ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals((DSymbol)resultBase);

			if (stkC == 1)
				stackCalls.Remove(m);
			else
				stackCalls[m] = stkC-1;

			return ret;
		}
		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 GetMethodReturnType(DelegateType dg, ResolutionContext ctxt)
		{
			if (dg == null || ctxt == null)
				return null;

			if (dg.IsFunctionLiteral)
				return GetMethodReturnType(((FunctionLiteral)dg.DeclarationOrExpressionBase).AnonymousMethod, ctxt);
			else
			{
				var rt = ((DelegateDeclaration)dg.DeclarationOrExpressionBase).ReturnType;
				var r = Resolve(rt, ctxt);

				ctxt.CheckForSingleResult(r, rt);

				return r[0];
			}
		}
		AbstractType HandleAccessExpressions(PostfixExpression_Access acc, ResolutionContext ctxt)
		{
			AbstractType pfType = null;
			if (acc.PostfixForeExpression is PostfixExpression_Access)
				pfType = HandleAccessExpressions((PostfixExpression_Access)acc.PostfixForeExpression, ctxt);
			else
			{
				pfType = DResolver.StripAliasSymbol(Evaluation.EvaluateType(acc.PostfixForeExpression, ctxt));

				if (acc.PostfixForeExpression is IdentifierExpression ||
					acc.PostfixForeExpression is TemplateInstanceExpression ||
					acc.PostfixForeExpression is PostfixExpression_Access)
					HandleResult(acc.PostfixForeExpression, pfType);
			}
			
			var accessedMembers = Evaluation.GetAccessedOverloads(acc, ctxt, pfType);
			ctxt.CheckForSingleResult(accessedMembers, acc);

			if (accessedMembers != null && accessedMembers.Length != 0)
			{
				HandleResult(acc, accessedMembers[0]);
				return accessedMembers[0];
			}

			return null;
		}
예제 #26
0
        public static AbstractType ResolveSingle(ITypeDeclaration declaration, ResolutionContext ctxt)
        {
            if (declaration is IdentifierDeclaration)
            {
                return(ResolveSingle(declaration as IdentifierDeclaration, ctxt));
            }
            else if (declaration is TemplateInstanceExpression)
            {
                var a = ExpressionTypeEvaluation.GetOverloads(declaration as TemplateInstanceExpression, ctxt);
                ctxt.CheckForSingleResult(a, declaration);
                return(a != null && a.Length != 0 ? a[0] : null);
            }

            AbstractType t = null;

            if (declaration is DTokenDeclaration)
            {
                t = Resolve(declaration as DTokenDeclaration);
            }
            else if (declaration is TypeOfDeclaration)
            {
                t = Resolve(declaration as TypeOfDeclaration, ctxt);
            }
            else if (declaration is MemberFunctionAttributeDecl)
            {
                t = Resolve(declaration as MemberFunctionAttributeDecl, ctxt);
            }
            else if (declaration is ArrayDecl)
            {
                t = Resolve(declaration as ArrayDecl, ctxt);
            }
            else if (declaration is PointerDecl)
            {
                t = Resolve(declaration as PointerDecl, ctxt);
            }
            else if (declaration is DelegateDeclaration)
            {
                t = Resolve(declaration as DelegateDeclaration, ctxt);
            }

            //TODO: VarArgDeclaration
            else if (declaration is ITemplateParameterDeclaration)
            {
                var tpd = declaration as ITemplateParameterDeclaration;

                var templateParameter = tpd.TemplateParameter;

                //TODO: Is this correct handling?
                while (templateParameter is TemplateThisParameter)
                {
                    templateParameter = (templateParameter as TemplateThisParameter).FollowParameter;
                }

                if (tpd.TemplateParameter is TemplateValueParameter)
                {
                    // Return a member result -- it's a static variable
                }
                else
                {
                    // Return a type result?
                }
            }

            return(t);
        }
		public static AbstractType ResolveSingle(ITypeDeclaration declaration, ResolutionContext ctxt)
		{
			if (declaration is IdentifierDeclaration)
				return ResolveSingle(declaration as IdentifierDeclaration, ctxt);
			else if (declaration is TemplateInstanceExpression)
			{
				var a = Evaluation.GetOverloads(declaration as TemplateInstanceExpression, ctxt);
				ctxt.CheckForSingleResult(a, declaration);
				return a != null && a.Length != 0 ? a[0] : null;
			}

			AbstractType t = null;

			if (declaration is DTokenDeclaration)
				t = Resolve(declaration as DTokenDeclaration);
			else if (declaration is TypeOfDeclaration)
				t = Resolve(declaration as TypeOfDeclaration, ctxt);
			else if (declaration is MemberFunctionAttributeDecl)
				t = Resolve(declaration as MemberFunctionAttributeDecl, ctxt);
			else if (declaration is ArrayDecl)
				t = Resolve(declaration as ArrayDecl, ctxt);
			else if (declaration is PointerDecl)
				t = Resolve(declaration as PointerDecl, ctxt);
			else if (declaration is DelegateDeclaration)
				t = Resolve(declaration as DelegateDeclaration, ctxt);

			//TODO: VarArgDeclaration
			else if (declaration is ITemplateParameterDeclaration)
			{
				var tpd = declaration as ITemplateParameterDeclaration;

				var templateParameter = tpd.TemplateParameter;

				//TODO: Is this correct handling?
				while (templateParameter is TemplateThisParameter)
					templateParameter = (templateParameter as TemplateThisParameter).FollowParameter;

				if (tpd.TemplateParameter is TemplateValueParameter)
				{
					// Return a member result -- it's a static variable
				}
				else
				{
					// Return a type result?
				}
			}

			return t;
		}
		/// <summary>
		/// See <see cref="Resolve"/>
		/// </summary>
		public static AbstractType ResolveSingle(IdentifierDeclaration id, ResolutionContext ctxt, AbstractType[] resultBases = null, bool filterForTemplateArgs = true)
		{
			var r = Resolve(id, ctxt, resultBases, filterForTemplateArgs);

			ctxt.CheckForSingleResult(r, id);

			return r != null && r.Length != 0 ? r[0] : null;
		}
		public static AbstractType GetMethodReturnType(DMethod method, ResolutionContext ctxt)
		{
			if ((ctxt.Options & ResolutionOptions.DontResolveBaseTypes) == ResolutionOptions.DontResolveBaseTypes)
				return null;

			/*
			 * If a method's type equals null, assume that it's an 'auto' function..
			 * 1) Search for a return statement
			 * 2) Resolve the returned expression
			 * 3) Use that one as the method's type
			 */
			bool pushMethodScope = ctxt.ScopedBlock != method;

			if (method.Type != null)
			{
				if (pushMethodScope)
					ctxt.PushNewScope(method);

				//FIXME: Is it legal to explicitly return a nested type?
				var returnType = TypeDeclarationResolver.Resolve(method.Type, ctxt);

				if (pushMethodScope)
					ctxt.Pop();

				ctxt.CheckForSingleResult(returnType, method.Type);
				if(returnType != null && returnType.Length > 0)
					return returnType[0];
			}
			else if (method.Body != null)
			{
				ReturnStatement returnStmt = null;
				var list = new List<IStatement> { method.Body };
				var list2 = new List<IStatement>();

				bool foundMatch = false;
				while (!foundMatch && list.Count > 0)
				{
					foreach (var stmt in list)
					{
						if (stmt is ReturnStatement)
						{
							returnStmt = stmt as ReturnStatement;

							var te = returnStmt.ReturnExpression as TokenExpression;
							if (te == null || te.Token != DTokens.Null)
							{
								foundMatch = true;
								break;
							}
						}

						var statementContainingStatement = stmt as StatementContainingStatement;
						if (statementContainingStatement != null)
							list2.AddRange(statementContainingStatement.SubStatements);
					}

					list = list2;
					list2 = new List<IStatement>();
				}

				if (returnStmt != null && returnStmt.ReturnExpression != null)
				{
					if (pushMethodScope)
					{
						var dedTypes = ctxt.CurrentContext.DeducedTemplateParameters;
						ctxt.PushNewScope(method,returnStmt);

						if (dedTypes.Count != 0)
							foreach (var kv in dedTypes)
								ctxt.CurrentContext.DeducedTemplateParameters[kv.Key] = kv.Value;
					}

					var t =DResolver.StripMemberSymbols(Evaluation.EvaluateType(returnStmt.ReturnExpression, ctxt));

					if (pushMethodScope)
						ctxt.Pop();

					return t;
				}

				return new PrimitiveType (DTokens.Void);
			}

			return null;
		}
예제 #30
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;
        }
예제 #31
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);
        }
예제 #32
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));
        }
예제 #33
0
        /// <summary>
        /// The variable's or method's base type will be resolved (if auto type, the intializer's type will be taken).
        /// A class' base class will be searched.
        /// etc..
        /// </summary>
        public static AbstractType HandleNodeMatch(
            INode m,
            ResolutionContext ctxt,
            AbstractType resultBase = null,
            object typeBase         = null)
        {
            AbstractType ret = null;

            // See https://github.com/aBothe/Mono-D/issues/161
            int stkC;

            if (stackCalls == null)
            {
                stackCalls    = new Dictionary <INode, int>();
                stackCalls[m] = stkC = 1;
            }
            else if (stackCalls.TryGetValue(m, out stkC))
            {
                stackCalls[m] = ++stkC;
            }
            else
            {
                stackCalls[m] = stkC = 1;
            }

            /*
             * Pushing a new scope is only required if current scope cannot be found in the handled node's hierarchy.
             * Edit: No, it is required nearly every time because of nested type declarations - then, we do need the
             * current block scope.
             */
            bool popAfterwards;
            {
                var newScope = m is IBlockNode ? (IBlockNode)m : m.Parent as IBlockNode;
                popAfterwards = ctxt.ScopedBlock != newScope && newScope != null;
                if (popAfterwards)
                {
                    var options      = ctxt.CurrentContext.ContextDependentOptions;
                    var applyOptions = ctxt.ScopedBlockIsInNodeHierarchy(m);
                    ctxt.PushNewScope(newScope);
                    if (applyOptions)
                    {
                        ctxt.CurrentContext.ContextDependentOptions = options;
                    }
                }
            }

            var canResolveBase = ((ctxt.Options & ResolutionOptions.DontResolveBaseTypes) != ResolutionOptions.DontResolveBaseTypes) &&
                                 stkC < 10 && (m.Type == null || m.Type.ToString(false) != m.Name);

            // To support resolving type parameters to concrete types if the context allows this, introduce all deduced parameters to the current context
            if (resultBase is DSymbol)
            {
                ctxt.CurrentContext.IntroduceTemplateParameterTypes((DSymbol)resultBase);
            }

            var importSymbolNode = m as ImportSymbolNode;
            var variable         = m as DVariable;

            // Only import symbol aliases are allowed to search in the parse cache
            if (importSymbolNode != null)
            {
                ret = HandleImportSymbolMatch(importSymbolNode, ctxt);
            }
            else if (variable != null)
            {
                AbstractType bt = null;

                if (!(variable is EponymousTemplate))
                {
                    if (canResolveBase)
                    {
                        var bts = TypeDeclarationResolver.Resolve(variable.Type, ctxt);
                        ctxt.CheckForSingleResult(bts, variable.Type);

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

                        // For auto variables, use the initializer to get its type
                        else if (variable.Initializer != null)
                        {
                            bt = DResolver.StripMemberSymbols(Evaluation.EvaluateType(variable.Initializer, ctxt));
                        }

                        // Check if inside an foreach statement header
                        if (bt == null && ctxt.ScopedStatement != null)
                        {
                            bt = GetForeachIteratorType(variable, ctxt);
                        }
                    }

                    // Note: Also works for aliases! In this case, we simply try to resolve the aliased type, otherwise the variable's base type
                    ret = variable.IsAlias ?
                          new AliasedType(variable, bt, typeBase as ISyntaxRegion) as MemberSymbol :
                          new MemberSymbol(variable, bt, typeBase as ISyntaxRegion);
                }
                else
                {
                    ret = new EponymousTemplateType(variable as EponymousTemplate, GetInvisibleTypeParameters(variable, ctxt).AsReadOnly(), typeBase as ISyntaxRegion);
                }
            }
            else if (m is DMethod)
            {
                ret = new MemberSymbol(m as DNode, canResolveBase ? GetMethodReturnType(m as DMethod, ctxt) : null, typeBase as ISyntaxRegion);
            }
            else if (m is DClassLike)
            {
                ret = HandleClassLikeMatch(m as DClassLike, ctxt, typeBase, canResolveBase);
            }
            else if (m is DModule)
            {
                var mod = (DModule)m;
                if (typeBase != null && typeBase.ToString() != mod.ModuleName)
                {
                    var pack = ctxt.ParseCache.LookupPackage(typeBase.ToString()).FirstOrDefault();
                    if (pack != null)
                    {
                        ret = new PackageSymbol(pack, typeBase as ISyntaxRegion);
                    }
                }
                else
                {
                    ret = new ModuleSymbol(m as DModule, typeBase as ISyntaxRegion);
                }
            }
            else if (m is DEnum)
            {
                ret = new EnumType((DEnum)m, typeBase as ISyntaxRegion);
            }
            else if (m is TemplateParameter.Node)
            {
                //ResolveResult[] templateParameterType = null;

                //TODO: Resolve the specialization type
                //var templateParameterType = TemplateInstanceHandler.ResolveTypeSpecialization(tmp, ctxt);
                ret = new TemplateParameterSymbol((m as TemplateParameter.Node).TemplateParameter, null, typeBase as ISyntaxRegion);
            }
            else if (m is NamedTemplateMixinNode)
            {
                var tmxNode = m as NamedTemplateMixinNode;
                ret = new MemberSymbol(tmxNode, canResolveBase ? ResolveSingle(tmxNode.Type, ctxt) : null, typeBase as ISyntaxRegion);
            }

            if (popAfterwards)
            {
                ctxt.Pop();
            }
            else if (resultBase is DSymbol)
            {
                ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals((DSymbol)resultBase);
            }

            if (stkC == 1)
            {
                stackCalls.Remove(m);
            }
            else
            {
                stackCalls[m] = stkC - 1;
            }

            return(ret);
        }