Пример #1
0
            /// <summary>
            /// Add 'superior' template parameters to the current symbol because
            /// the parameters might be re-used in the nested class.
            /// </summary>
            List <TemplateParameterSymbol> GetInvisibleTypeParameters(DNode n)
            {
                var invisibleTypeParams = new List <TemplateParameterSymbol>();

                var tStk = new Stack <ContextFrame>();

                do
                {
                    var curCtxt = ctxt.Pop();
                    tStk.Push(curCtxt);
                    foreach (var kv in curCtxt.DeducedTemplateParameters)
                    {
                        if (!n.ContainsTemplateParameter(kv.Value.Parameter))
                        {
                            invisibleTypeParams.Add(kv.Value);
                        }
                    }
                }while (ctxt.PrevContextIsInSameHierarchy);
                while (tStk.Count != 0)
                {
                    ctxt.Push(tStk.Pop());
                }

                return(invisibleTypeParams);
            }
Пример #2
0
        public static Dictionary<int, Dictionary<ISyntaxRegion, byte>> Scan(DModule ast, ResolutionContext ctxt)
        {
            if (ast == null)
                return new Dictionary<int, Dictionary<ISyntaxRegion,byte>>();

            var typeRefFinder = new TypeReferenceFinder(ctxt);

            ContextFrame backupFrame = null;

            if(ctxt.ScopedBlock == ast)
                backupFrame = ctxt.Pop ();
            /*
            if (ctxt.CurrentContext == null)
            {
                ctxt.Push(backupFrame);
                backupFrame = null;
            }*/

            //typeRefFinder.ast = ast;
            // Enum all identifiers
            ast.Accept (typeRefFinder);

            if (backupFrame != null)
                ctxt.Push (backupFrame);

            // Crawl through all remaining expressions by evaluating their types and check if they're actual type references.
            /*typeRefFinder.queueCount = typeRefFinder.q.Count;
            typeRefFinder.ResolveAllIdentifiers();
            */
            return typeRefFinder.Matches;
        }
Пример #3
0
        /// <summary>
        /// Resolves an identifier and returns the definition + its base type.
        /// Does not deduce any template parameters or nor filters out unfitting template specifications!
        /// </summary>
        public static AbstractType[] ResolveIdentifier(int idHash, ResolutionContext ctxt, object idObject, bool ModuleScope = false)
        {
            var loc = idObject is ISyntaxRegion ? ((ISyntaxRegion)idObject).Location : CodeLocation.Empty;

            if (ModuleScope)
            {
                ctxt.PushNewScope(ctxt.ScopedBlock.NodeRoot as DModule);
            }

            // If there are symbols that must be preferred, take them instead of scanning the ast
            else
            {
                TemplateParameterSymbol dedTemplateParam;
                if (ctxt.GetTemplateParam(idHash, out dedTemplateParam))
                {
                    return new[] { dedTemplateParam }
                }
                ;
            }

            var res = NameScan.SearchAndResolve(ctxt, loc, idHash, idObject);

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

            return /*res.Count == 0 ? null :*/ (res.ToArray());
        }
Пример #4
0
        static AbstractType[] TryGetImplicitProperty(TemplateType template, ResolutionContext ctxt)
        {
            // Prepare a new context
            bool pop = !ctxt.ScopedBlockIsInNodeHierarchy(template.Definition);

            if (pop)
            {
                ctxt.PushNewScope(template.Definition);
            }

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

            // Get actual overloads
            var matchingChild = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(template.NameHash, new[] { template }, ctxt);

            // Undo context-related changes
            if (pop)
            {
                ctxt.Pop();
            }
            else
            {
                ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(template);
            }

            return(matchingChild);
        }
Пример #5
0
		static string GetMixinContent(MixinStatement mx, ResolutionContext ctxt, bool takeStmtCache ,out ISyntaxRegion cachedContent)
		{
			cachedContent = null;
			
			if(!CheckAndPushAnalysisStack(mx))
				return null;
			
			bool pop;
			if(pop = (ctxt.ScopedBlock != mx.ParentNode && mx.ParentNode != null))
				ctxt.PushNewScope(mx.ParentNode as IBlockNode, mx);
			
			bool hadCachedItem;
			if(takeStmtCache)
			{
				BlockStatement stmt;
				hadCachedItem = mixinStmtCache.TryGet(ctxt, mx, out stmt);
				cachedContent = stmt;
			}
			else
			{
				DModule mod;
				hadCachedItem = mixinDeclCache.TryGet(ctxt, mx, out mod);
				cachedContent = mod;
			}
			
			if(hadCachedItem)
			{
				stmtsBeingAnalysed.Remove(mx);
				if(pop)
					ctxt.Pop();
				return null;
			}
			
			var x = mx.MixinExpression;
			ISemantic v = null;
			try // 'try' because there is always a risk of e.g. not having something implemented or having an evaluation exception...
			{
				// Evaluate the mixin expression
				v = Evaluation.EvaluateValue(x, ctxt);
			}
			catch{}
			
			stmtsBeingAnalysed.Remove(mx);
			if(pop) 
				ctxt.Pop();
			
			// Ensure it's a string literal
			var av = v as ArrayValue;
			if(av != null && av.IsString)
				return av.StringValue;
			
			if(takeStmtCache)
				mixinStmtCache.Add(ctxt, mx, null);
			else
				mixinDeclCache.Add(ctxt, mx, null);
			return null;
		}
Пример #6
0
		public static MemberSymbol[] TryResolveUFCS(
			ISemantic firstArgument, 
			PostfixExpression_Access acc, 
			ResolutionContext ctxt)
		{
			if (ctxt == null)
				return null;
			
			int name=0;

			if (acc.AccessExpression is IdentifierExpression)
				name = ((IdentifierExpression)acc.AccessExpression).ValueStringHash;
			else if (acc.AccessExpression is TemplateInstanceExpression)
				name = ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdHash;
			else
				return null;

			var methodMatches = new List<MemberSymbol>();
			if(ctxt.ParseCache!=null)
				foreach (var pc in ctxt.ParseCache)
				{
					var tempResults=pc.UfcsCache.FindFitting(ctxt, acc.Location, firstArgument, name);

					if (tempResults != null)
						foreach (var m in tempResults)
						{
							ctxt.PushNewScope(m);

							if (m.TemplateParameters != null && m.TemplateParameters.Length != 0)
							{
								var ov = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(
									new[] { new MemberSymbol(m, null, acc) }, 
									new[] { firstArgument }, true, ctxt);

								if (ov == null || ov.Length == 0)
									continue;

								var ms = (DSymbol)ov[0];
								ctxt.CurrentContext.IntroduceTemplateParameterTypes(ms);
							}
							
							var mr = TypeDeclarationResolver.HandleNodeMatch(m, ctxt, null, acc) as MemberSymbol;
							if (mr!=null)
							{
								mr.FirstArgument = firstArgument;
								mr.DeducedTypes = ctxt.CurrentContext.DeducedTemplateParameters.ToReadonly();
								mr.IsUFCSResult = true;
								methodMatches.Add(mr);
							}
							ctxt.Pop();
						}
				}

			return methodMatches.Count == 0 ? null : methodMatches.ToArray();
		}
Пример #7
0
        public override void VisitAbstractStmt(AbstractStatement stmt)
        {
            var  back = ctxt.ScopedStatement;
            bool pop  = false;

            if (back != stmt)
            {
                var parentNode = stmt.ParentNode;
                if (parentNode != null && ctxt.ScopedBlock != parentNode)
                {
                    ctxt.PushNewScope(stmt.ParentNode as IBlockNode, stmt);
                    pop = true;
                }
                else if (ctxt.ScopedBlock != null)
                {
                    ctxt.CurrentContext.Set(stmt);
                }
                else
                {
                    back = stmt;
                }
                OnScopedStatementChanged(stmt);
            }
            base.VisitAbstractStmt(stmt);
            if (back != stmt)
            {
                if (!pop)
                {
                    ctxt.CurrentContext.Set(back);
                }
                else
                {
                    ctxt.Pop();
                }
            }
        }
Пример #8
0
        /// <summary>
        /// Resolves an identifier and returns the definition + its base type.
        /// Does not deduce any template parameters or nor filters out unfitting template specifications!
        /// </summary>
        public static AbstractType[] ResolveIdentifier(int idHash, ResolutionContext ctxt, ISyntaxRegion idObject, bool ModuleScope = false)
        {
            var loc = idObject is ISyntaxRegion ? ((ISyntaxRegion)idObject).Location : CodeLocation.Empty;

            if (ModuleScope)
            {
                ctxt.PushNewScope(ctxt.ScopedBlock.NodeRoot as DModule);
            }

            // If there are symbols that must be preferred, take them instead of scanning the ast
            else
            {
                TemplateParameterSymbol dedTemplateParam;
                if (ctxt.GetTemplateParam(idHash, out dedTemplateParam))
                {
                    return new[] { dedTemplateParam }
                }
                ;
            }

            var res = NameScan.SearchAndResolve(ctxt, loc, idHash, idObject);

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

            if (res.Count != 0)
            {
                return /*res.Count == 0 ? null :*/ (res.ToArray());
            }

            // Support some very basic static typing if no phobos is given atm
            if (idHash == Evaluation.stringTypeHash)
            {
                res.Add(Evaluation.GetStringType(ctxt));
            }
            else if (idHash == Evaluation.wstringTypeHash)
            {
                res.Add(Evaluation.GetStringType(ctxt, LiteralSubformat.Utf16));
            }
            else if (idHash == Evaluation.dstringTypeHash)
            {
                res.Add(Evaluation.GetStringType(ctxt, LiteralSubformat.Utf32));
            }

            return(res.ToArray());
        }
Пример #9
0
        static AbstractType[] TryGetImplicitProperty(TemplateType template, ResolutionContext ctxt)
        {
            // Prepare a new context
            bool pop = !ctxt.ScopedBlockIsInNodeHierarchy(template.Definition);

            if (pop)
            {
                ctxt.PushNewScope(template.Definition);
            }

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

            // Get actual overloads
            var matchingChild = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(template.NameHash, new[] { template }, ctxt);

            if (matchingChild != null)             // Currently requried for proper UFCS resolution - sustain template's Tag
            {
                foreach (var ch in matchingChild)
                {
                    var ds = ch as DSymbol;

                    if (ds != null)
                    {
                        var newDeducedTypes = new DeducedTypeDictionary(ds);
                        foreach (var tps in template.DeducedTypes)
                        {
                            newDeducedTypes[tps.Parameter] = tps;
                        }
                        ds.DeducedTypes = newDeducedTypes.ToReadonly();
                    }
                    ch.Tag = template.Tag;
                }
            }

            // Undo context-related changes
            if (pop)
            {
                ctxt.Pop();
            }
            else
            {
                ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(template);
            }

            return(matchingChild);
        }
Пример #10
0
        /// <summary>
        /// http://dlang.org/operatoroverloading.html#Dispatch
        /// Check for the existence of an opDispatch overload.
        /// Important: Because static opDispatches are allowed as well, do check whether we can access non-static overloads from non-instance expressions or such
        /// </summary>
        public static IEnumerable <AbstractType> TryResolveFurtherIdViaOpDispatch(ResolutionContext ctxt, int nextIdentifierHash, UserDefinedType b)
        {
            // The usual SO prevention
            if (nextIdentifierHash == opDispatchId || b == null)
            {
                yield break;
            }

            var pop = ctxt.ScopedBlock != b.Definition;

            if (pop)
            {
                // Mainly required for not resolving opDispatch's return type, as this will be performed later on in higher levels
                var opt = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.PushNewScope(b.Definition as IBlockNode);
                ctxt.CurrentContext.IntroduceTemplateParameterTypes(b);
                ctxt.CurrentContext.ContextDependentOptions = opt;
            }

            // Look for opDispatch-Members inside b's Definition
            var overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(opDispatchId, new[] { b }, ctxt);

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

            if (overloads == null || overloads.Length < 0)
            {
                yield break;
            }

            var av = new ArrayValue(Evaluation.GetStringType(ctxt), Strings.TryGet(nextIdentifierHash));

            foreach (DSymbol o in overloads)
            {
                var dn = o.Definition;
                if (dn.TemplateParameters != null && dn.TemplateParameters.Length > 0 &&
                    dn.TemplateParameters[0] is TemplateValueParameter)
                {
                    //TODO: Test parameter types for being a string value
                    o.DeducedTypes = new System.Collections.ObjectModel.ReadOnlyCollection <TemplateParameterSymbol> (
                        new[] { new TemplateParameterSymbol(dn.TemplateParameters[0], av) });
                    yield return(o);
                }
            }
        }
        internal override IAnalysisSet Resolve(AnalysisUnit unit, ResolutionContext context)
        {
            if (context.Cache.TryGetValue(this, out var res))
            {
                return(res);
            }

            if (!Push())
            {
                return(AnalysisSet.Empty);
            }

            try {
                if (!context.Push())
                {
                    return(AnalysisSet.Empty);
                }
                try {
                    res = ResolveOnce(unit, context, out var allowCache);
                    bool changed = !Equals(res);
                    while (changed && context.ResolveFully)
                    {
                        res = res.Resolve(unit, context, out changed);
                    }
                    if (context.ResolveFully)
                    {
                        res.Split <LazyValueInfo>(out _, out res);
                    }
                    if (allowCache)
                    {
                        context.Cache[this] = res;
                    }
                    return(res);
                } finally {
                    context.Pop();
                }
            } finally {
                Pop();
            }
        }
Пример #12
0
        public static Dictionary <int, Dictionary <ISyntaxRegion, byte> > Scan(DModule ast, ResolutionContext ctxt)
        {
            if (ast == null)
            {
                return(new Dictionary <int, Dictionary <ISyntaxRegion, byte> >());
            }

            var typeRefFinder = new TypeReferenceFinder(ctxt);

            ContextFrame backupFrame = null;

            if (ctxt.ScopedBlock == ast)
            {
                backupFrame = ctxt.Pop();
            }

            /*
             * if (ctxt.CurrentContext == null)
             * {
             *      ctxt.Push(backupFrame);
             *      backupFrame = null;
             * }*/

            //typeRefFinder.ast = ast;
            // Enum all identifiers
            ast.Accept(typeRefFinder);

            if (backupFrame != null)
            {
                ctxt.Push(backupFrame);
            }

            // Crawl through all remaining expressions by evaluating their types and check if they're actual type references.

            /*typeRefFinder.queueCount = typeRefFinder.q.Count;
             * typeRefFinder.ResolveAllIdentifiers();
             */
            return(typeRefFinder.Matches);
        }
		/// <summary>
		/// Resolves an identifier and returns the definition + its base type.
		/// Does not deduce any template parameters or nor filters out unfitting template specifications!
		/// </summary>
		public static AbstractType[] ResolveIdentifier(int idHash, ResolutionContext ctxt, object idObject, bool ModuleScope = false)
		{
			var loc = idObject is ISyntaxRegion ? ((ISyntaxRegion)idObject).Location : CodeLocation.Empty;

			if (ModuleScope)
				ctxt.PushNewScope(ctxt.ScopedBlock.NodeRoot as DModule);

			// If there are symbols that must be preferred, take them instead of scanning the ast
			else
			{
				TemplateParameterSymbol dedTemplateParam;
				if (ctxt.GetTemplateParam(idHash, out dedTemplateParam))
					return new[] { dedTemplateParam };
			}

			var res = NameScan.SearchAndResolve(ctxt, loc, idHash, idObject);

			if (ModuleScope)
				ctxt.Pop();

			return /*res.Count == 0 ? null :*/ res.ToArray();
		}
Пример #14
0
        /// <summary>
        /// </summary>
        /// <param name="ast">Сканируемое синтаксическое дерево</param>
        /// <param name="symbol">Не может быть символом-пасынком АСТ</param>
        /// <param name="ctxt">Контекст, необходимый для поиска символов</param>
        /// <returns></returns>
        public static IEnumerable <ISyntaxRegion> Scan(DModule ast, INode symbol, ResolutionContext ctxt, bool includeDefinition = true)
        {
            if (ast == null || symbol == null || ctxt == null)
            {
                return(null);
            }

            ctxt.PushNewScope(ast);

            var f = new ReferencesFinder(symbol, ast, ctxt);

            ast.Accept(f);

            ctxt.Pop();

            var nodeRoot = symbol.NodeRoot as DModule;

            if (includeDefinition && nodeRoot != null && nodeRoot.FileName == ast.FileName)
            {
                var dc = symbol.Parent as DClassLike;
                if (dc != null && dc.ClassType == DSharp.Parser.DTokens.Template &&
                    dc.NameHash == symbol.NameHash)
                {
                    f.l.Insert(0, new IdentifierDeclaration(dc.NameHash)
                    {
                        Location    = dc.NameLocation,
                        EndLocation = new CodeLocation(dc.NameLocation.Column + dc.Name.Length, dc.NameLocation.Line)
                    });
                }

                f.l.Insert(0, new IdentifierDeclaration(symbol.NameHash)
                {
                    Location    = symbol.NameLocation,
                    EndLocation = new CodeLocation(symbol.NameLocation.Column + symbol.Name.Length, symbol.NameLocation.Line)
                });
            }

            return(f.l);
        }
Пример #15
0
        /// <summary>
        /// http://dlang.org/operatoroverloading.html#Dispatch
        /// Check for the existence of an opDispatch overload.
        /// Important: Because static opDispatches are allowed as well, do check whether we can access non-static overloads from non-instance expressions or such
        /// </summary>
        public static IEnumerable<AbstractType> TryResolveFurtherIdViaOpDispatch(ResolutionContext ctxt, int nextIdentifierHash, UserDefinedType b)
        {
            // The usual SO prevention
            if (nextIdentifierHash == opDispatchId || b == null)
                yield break;

            var pop = ctxt.ScopedBlock != b.Definition;
            if (pop) {
                // Mainly required for not resolving opDispatch's return type, as this will be performed later on in higher levels
                var opt = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.PushNewScope (b.Definition as IBlockNode);
                ctxt.CurrentContext.IntroduceTemplateParameterTypes (b);
                ctxt.CurrentContext.ContextDependentOptions = opt;
            }

            // Look for opDispatch-Members inside b's Definition
            var overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier (opDispatchId, new[]{b}, ctxt);

            if(pop)
                ctxt.Pop ();

            if (overloads == null || overloads.Length < 0)
                yield break;

            var av = new ArrayValue (Evaluation.GetStringType(ctxt), Strings.TryGet(nextIdentifierHash));

            foreach (DSymbol o in overloads) {
                var dn = o.Definition;
                if (dn.TemplateParameters != null && dn.TemplateParameters.Length > 0 &&
                    dn.TemplateParameters[0] is TemplateValueParameter)
                {
                    //TODO: Test parameter types for being a string value
                    o.DeducedTypes = new System.Collections.ObjectModel.ReadOnlyCollection<TemplateParameterSymbol> (
                        new[]{ new TemplateParameterSymbol(dn.TemplateParameters[0], av) } );
                    yield return o;
                }
            }
        }
Пример #16
0
        bool IsMoreSpecialized(ITypeDeclaration Spec, TemplateParameter t2, Dictionary <TemplateParameter, ISemantic> t1_DummyParamList)
        {
            // Make a type out of t1's specialization
            var pop = ctxt.ScopedBlock != null;

            if (pop)
            {
                ctxt.PushNewScope(ctxt.ScopedBlock.Parent as IBlockNode);
            }
            var frame = ctxt.CurrentContext;

            // Make the T in e.g. T[] a virtual type so T will be replaced by it
            // T** will be X** then - so a theoretically valid type instead of a template param
            var dummyType = new ClassType(new DClassLike {
                Name = "X"
            }, null, null);

            foreach (var kv in t1_DummyParamList)
            {
                frame.DeducedTemplateParameters[kv.Key] = new TemplateParameterSymbol(t2, dummyType);
            }

            var t1_TypeResults = Resolver.TypeResolution.TypeDeclarationResolver.Resolve(Spec, ctxt);

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

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

            // Now try to fit the virtual Type t2 into t1 - and return true if it's possible
            return(new TemplateParameterDeduction(new DeducedTypeDictionary(), ctxt).Handle(t2, t1_TypeResults[0]));
        }
Пример #17
0
        /*
         * public bool WaitForFinish(int millisecondsToWait = -1)
         * {
         *      if(millisecondsToWait < 0)
         *              return completedEvent.WaitOne();
         *      return completedEvent.WaitOne(millisecondsToWait);
         * }*/

        public void CacheModuleMethods(DModule ast, ResolutionContext ctxt)
        {
            foreach (var m in ast)
            {
                if (m is DMethod)
                {
                    var dm = (DMethod)m;

                    if (dm.Parameters == null || dm.NameHash == 0 || dm.Parameters.Count == 0 || dm.Parameters[0].Type == null)
                    {
                        continue;
                    }

                    ctxt.PushNewScope(dm);
                    var firstArg_result = TypeDeclarationResolver.Resolve(dm.Parameters[0].Type, ctxt);
                    ctxt.Pop();

                    if (firstArg_result != null && firstArg_result.Length != 0)
                    {
                        CachedMethods[dm] = firstArg_result[0];
                    }
                }
            }
        }
Пример #18
0
		/// <summary>
		/// </summary>
		/// <param name="ast">The syntax tree to scan</param>
		/// <param name="symbol">Might not be a child symbol of ast</param>
		/// <param name="ctxt">The context required to search for symbols</param>
		/// <returns></returns>
		public static IEnumerable<ISyntaxRegion> Scan(DModule ast, INode symbol, ResolutionContext ctxt, bool includeDefinition = true)
		{
			if (ast == null || symbol == null || ctxt == null)
				return null;

			ctxt.PushNewScope(ast);

			var f = new ReferencesFinder(symbol, ast, ctxt);

			ast.Accept (f);

			ctxt.Pop();

			var nodeRoot = symbol.NodeRoot as DModule;
			if (includeDefinition && nodeRoot != null && nodeRoot.FileName == ast.FileName)
			{
				var dc = symbol.Parent as DClassLike;
				if (dc != null && dc.ClassType == DSharp.Parser.DTokens.Template &&
					dc.NameHash == symbol.NameHash)
				{
					f.l.Insert(0, new IdentifierDeclaration(dc.NameHash)
						{
							Location = dc.NameLocation,
							EndLocation = new CodeLocation(dc.NameLocation.Column + dc.Name.Length, dc.NameLocation.Line)
						});
				}

				f.l.Insert(0, new IdentifierDeclaration(symbol.NameHash)
					{
						Location = symbol.NameLocation,
						EndLocation = new CodeLocation(symbol.NameLocation.Column + symbol.Name.Length,	symbol.NameLocation.Line)
					});
			}

			return f.l;
		}
        static void HandleDMethodOverload(ResolutionContext ctxt, bool eval, ISymbolValue baseValue, List <ISemantic> callArguments, bool returnBaseTypeOnly, bool hasNonFinalArgs, List <AbstractType> argTypeFilteredOverloads, ref bool hasHandledUfcsResultBefore, MemberSymbol ms)
        {
            var dm = ms.Definition as DMethod;

            if (dm == null)
            {
                return;
            }

            ISemantic firstUfcsArg;
            bool      isUfcs = UFCSResolver.IsUfcsResult(ms, out firstUfcsArg);

            // In the case of an ufcs, insert the first argument into the CallArguments list
            if (isUfcs && !hasHandledUfcsResultBefore)
            {
                callArguments.Insert(0, eval ? baseValue as ISemantic : firstUfcsArg);
                hasHandledUfcsResultBefore = true;
            }
            else if (!isUfcs && hasHandledUfcsResultBefore)             // In the rare case of having a ufcs result occuring _after_ a normal member result, remove the initial arg again
            {
                callArguments.RemoveAt(0);
                hasHandledUfcsResultBefore = false;
            }

            if (dm.Parameters.Count == 0 && callArguments.Count > 0)
            {
                return;
            }

            var deducedTypeDict        = new DeducedTypeDictionary(ms);
            var templateParamDeduction = new TemplateParameterDeduction(deducedTypeDict, ctxt);

            var pop = ctxt.ScopedBlock != dm;

            if (pop)
            {
                ctxt.PushNewScope(dm);
                ctxt.CurrentContext.DeducedTemplateParameters = deducedTypeDict;
            }

            bool add        = true;
            int  currentArg = 0;

            if (dm.Parameters.Count > 0 || callArguments.Count > 0)
            {
                for (int i = 0; i < dm.Parameters.Count; i++)
                {
                    var paramType = dm.Parameters[i].Type;

                    if (!pop)
                    {
                        ctxt.CurrentContext.IntroduceTemplateParameterTypes(ms);
                    }

                    // Handle the usage of tuples: Tuples may only be used as as-is, so not as an array, pointer or in a modified way..
                    if (paramType is IdentifierDeclaration &&
                        TryHandleMethodArgumentTuple(ctxt, ref add, callArguments, dm, deducedTypeDict, i, ref currentArg))
                    {
                        continue;
                    }
                    else if (currentArg < callArguments.Count)
                    {
                        if (!(add = templateParamDeduction.HandleDecl(null, paramType, callArguments[currentArg++])))
                        {
                            break;
                        }
                    }
                    else
                    {
                        // If there are more parameters than arguments given, check if the param has default values
                        add = !(dm.Parameters[i] is DVariable) || (dm.Parameters[i] as DVariable).Initializer != null;

                        // Assume that all further method parameters do have default values - and don't check further parameters
                        break;
                    }
                }
            }

            if (!add)
            {
                if (pop)
                {
                    ctxt.Pop();
                }
                else
                {
                    ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ms);
                }
                return;
            }

            // If type params were unassigned, try to take the defaults
            if (dm.TemplateParameters != null)
            {
                foreach (var tpar in dm.TemplateParameters)
                {
                    if (deducedTypeDict[tpar] == null && !templateParamDeduction.Handle(tpar, null))
                    {
                        if (!hasNonFinalArgs)
                        {
                            if (pop)
                            {
                                ctxt.Pop();
                            }
                            else
                            {
                                ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ms);
                            }
                            return;
                        }

                        deducedTypeDict[tpar] = new TemplateParameterSymbol(tpar, null);
                    }
                }
            }

            if (deducedTypeDict.AllParamatersSatisfied || hasNonFinalArgs)
            {
                ms.DeducedTypes = deducedTypeDict.ToReadonly();
                if (!pop)
                {
                    ctxt.CurrentContext.IntroduceTemplateParameterTypes(ms);
                }

                var bt = TypeDeclarationResolver.GetMethodReturnType(dm, ctxt) ?? ms.Base;

                if (pop)
                {
                    ctxt.Pop();
                }
                else
                {
                    ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ms);
                }

                if (eval || !returnBaseTypeOnly)
                {
                    argTypeFilteredOverloads.Add(new MemberSymbol(dm, bt, ms.DeclarationOrExpressionBase, ms.DeducedTypes)
                    {
                        Tag = ms.Tag
                    });
                }
                else
                {
                    argTypeFilteredOverloads.Add(bt);
                }
            }
        }
Пример #20
0
        /// <summary>
        /// Used for searching further identifier list parts.
        ///
        /// a.b -- nextIdentifier would be 'b' whereas <param name="resultBases">resultBases</param> contained the resolution result for 'a'
        /// </summary>
        public static AbstractType[] ResolveFurtherTypeIdentifier(int nextIdentifierHash,
                                                                  IEnumerable <AbstractType> resultBases,
                                                                  ResolutionContext ctxt,
                                                                  ISyntaxRegion typeIdObject = null)
        {
            MemberSymbol statProp;

            if ((resultBases = DResolver.StripMemberSymbols(resultBases)) == null)
            {
                return(null);
            }

            var r = new List <AbstractType>();

            foreach (var b in resultBases)
            {
                if (b is UserDefinedType)
                {
                    var udt = b as UserDefinedType;
                    var bn  = udt.Definition as IBlockNode;

                    bool pop = b is MixinTemplateType;
                    if (pop)
                    {
                        ctxt.PushNewScope(bn);
                    }
                    ctxt.CurrentContext.IntroduceTemplateParameterTypes(udt);

                    r.AddRange(SingleNodeNameScan.SearchChildrenAndResolve(ctxt, udt, nextIdentifierHash, typeIdObject));

                    List <TemplateParameterSymbol> dedTypes = null;
                    foreach (var t in r)
                    {
                        var ds = t as DSymbol;
                        if (ds != null && ds.DeducedTypes == null)
                        {
                            if (dedTypes == null)
                            {
                                dedTypes = ctxt.DeducedTypesInHierarchy;
                            }

                            ds.DeducedTypes = new System.Collections.ObjectModel.ReadOnlyCollection <TemplateParameterSymbol>(dedTypes);
                        }
                    }

                    statProp = StaticProperties.TryEvalPropertyType(ctxt, b, nextIdentifierHash);
                    if (statProp != null)
                    {
                        r.Add(statProp);
                    }

                    // go the opDispatch way if possible - http://dlang.org/operatoroverloading.html#Dispatch
                    if (r.Count == 0 && nextIdentifierHash != OpDispatchResolution.opDispatchId)
                    {
                        r.AddRange(OpDispatchResolution.TryResolveFurtherIdViaOpDispatch(ctxt, nextIdentifierHash, udt));
                    }

                    if (r.Count == 0)
                    {
                        r.AddRange(UFCSResolver.TryResolveUFCS(b, nextIdentifierHash, !pop && typeIdObject != null ? typeIdObject.Location : ctxt.ScopedBlock.BlockStartLocation, ctxt, typeIdObject));
                    }

                    if (pop)
                    {
                        ctxt.Pop();
                    }
                    else
                    {
                        ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(udt);
                    }
                }
                else if (b is PackageSymbol)
                {
                    var pack = (b as PackageSymbol).Package;

                    var accessedModule = pack.GetModule(nextIdentifierHash);
                    if (accessedModule != null)
                    {
                        r.Add(new ModuleSymbol(accessedModule as DModule, typeIdObject as ISyntaxRegion, b as PackageSymbol));
                    }
                    else if ((pack = pack.GetPackage(nextIdentifierHash)) != null)
                    {
                        r.Add(new PackageSymbol(pack, typeIdObject as ISyntaxRegion));
                    }
                }
                else if (b is ModuleSymbol)
                {
                    r.AddRange(SingleNodeNameScan.SearchChildrenAndResolve(ctxt, b as ModuleSymbol, nextIdentifierHash, typeIdObject));
                }
                else
                {
                    statProp = StaticProperties.TryEvalPropertyType(ctxt, b, nextIdentifierHash);
                    if (statProp != null)
                    {
                        r.Add(statProp);
                    }

                    if (r.Count == 0)                    // Only if there hasn't been a result yet?
                    {
                        r.AddRange(UFCSResolver.TryResolveUFCS(b, nextIdentifierHash, typeIdObject != null ? typeIdObject.Location : ctxt.ScopedBlock.BlockStartLocation, ctxt, typeIdObject));
                    }
                }
            }

            return(r.Count == 0 ? null : r.ToArray());
        }
Пример #21
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);
        }
		/// <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;
		}
		/// <summary>
		/// Used for searching further identifier list parts.
		/// 
		/// a.b -- nextIdentifier would be 'b' whereas <param name="resultBases">resultBases</param> contained the resolution result for 'a'
		/// </summary>
		public static AbstractType[] ResolveFurtherTypeIdentifier(int nextIdentifierHash,
			IEnumerable<AbstractType> resultBases,
			ResolutionContext ctxt,
			object typeIdObject = null)
		{
			MemberSymbol statProp;
			if ((resultBases = DResolver.StripMemberSymbols(resultBases)) == null)
				return null;

			var r = new List<AbstractType>();

			foreach(var b in resultBases)
			{
				if (b is UserDefinedType)
				{
					var udt = b as UserDefinedType;
					var bn = udt.Definition as IBlockNode;
					
					bool pop = !(b is MixinTemplateType);
					if(!pop)
						ctxt.PushNewScope(bn);
					ctxt.CurrentContext.IntroduceTemplateParameterTypes(udt);

					r.AddRange(SingleNodeNameScan.SearchChildrenAndResolve(ctxt, bn, nextIdentifierHash, typeIdObject));

					List<TemplateParameterSymbol> dedTypes = null;
					foreach (var t in r)
					{
						var ds = t as DSymbol;
						if (ds != null && ds.DeducedTypes == null)
						{
							if (dedTypes == null)
								dedTypes = ctxt.DeducedTypesInHierarchy;

							ds.DeducedTypes = new System.Collections.ObjectModel.ReadOnlyCollection<TemplateParameterSymbol>(dedTypes);
						}
					}

					statProp = StaticProperties.TryEvalPropertyType(ctxt, b, nextIdentifierHash);
					if (statProp != null)
						r.Add(statProp);

					ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(udt);
					if(!pop)
						ctxt.Pop();
				}
				else if (b is PackageSymbol)
				{
					var pack = (b as PackageSymbol).Package;

					var accessedModule = pack.GetModule(nextIdentifierHash);
					if (accessedModule != null)
						r.Add(new ModuleSymbol(accessedModule as DModule, typeIdObject as ISyntaxRegion, b as PackageSymbol));
					else if ((pack = pack.GetPackage(nextIdentifierHash)) != null)
						r.Add(new PackageSymbol(pack, typeIdObject as ISyntaxRegion));
				}
				else if (b is ModuleSymbol)
					r.AddRange(SingleNodeNameScan.SearchChildrenAndResolve(ctxt, (b as ModuleSymbol).Definition, nextIdentifierHash, typeIdObject));
				else
				{
					statProp = StaticProperties.TryEvalPropertyType(ctxt, b, nextIdentifierHash);
					if (statProp != null)
						r.Add(statProp);
				}
				// TODO: Search for UFCS symbols
			}

			return r.Count == 0 ? null : r.ToArray();
		}
Пример #24
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);
        }
Пример #25
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));
        }
Пример #26
0
		/*
		public bool WaitForFinish(int millisecondsToWait = -1)
		{
			if(millisecondsToWait < 0)
				return completedEvent.WaitOne();
			return completedEvent.WaitOne(millisecondsToWait);
		}*/

		public void CacheModuleMethods(DModule ast, ResolutionContext ctxt)
		{
			foreach (var m in ast)
				if (m is DMethod)
				{
					var dm = (DMethod)m;

					if (dm.Parameters == null || dm.NameHash == 0 || dm.Parameters.Count == 0 || dm.Parameters[0].Type == null)
						continue;

					ctxt.PushNewScope(dm);
					var firstArg_result = TypeDeclarationResolver.Resolve(dm.Parameters[0].Type, ctxt);
					ctxt.Pop();

					if (firstArg_result != null && firstArg_result.Length != 0)
						CachedMethods[dm] = firstArg_result[0];
				}
		}
Пример #27
0
        static AbstractType[] TryGetImplicitProperty(TemplateType template, ResolutionContext ctxt)
        {
            // Prepare a new context
            bool pop = !ctxt.ScopedBlockIsInNodeHierarchy(template.Definition);
            if (pop)
                ctxt.PushNewScope(template.Definition);

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

            // Get actual overloads
            var matchingChild = TypeDeclarationResolver.ResolveFurtherTypeIdentifier( template.NameHash, new[]{ template }, ctxt);

            // Undo context-related changes
            if (pop)
                ctxt.Pop();
            else
                ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(template);

            return matchingChild;
        }
Пример #28
0
        public static MemberSymbol[] TryResolveUFCS(
            ISemantic firstArgument,
            PostfixExpression_Access acc,
            ResolutionContext ctxt)
        {
            if (ctxt == null)
            {
                return(null);
            }

            int name = 0;

            if (acc.AccessExpression is IdentifierExpression)
            {
                name = ((IdentifierExpression)acc.AccessExpression).ValueStringHash;
            }
            else if (acc.AccessExpression is TemplateInstanceExpression)
            {
                name = ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdHash;
            }
            else
            {
                return(null);
            }

            var methodMatches = new List <MemberSymbol>();

            if (ctxt.ParseCache != null)
            {
                foreach (var pc in ctxt.ParseCache)
                {
                    var tempResults = pc.UfcsCache.FindFitting(ctxt, acc.Location, firstArgument, name);

                    if (tempResults != null)
                    {
                        foreach (var m in tempResults)
                        {
                            ctxt.PushNewScope(m);

                            if (m.TemplateParameters != null && m.TemplateParameters.Length != 0)
                            {
                                var ov = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(
                                    new[] { new MemberSymbol(m, null, acc) },
                                    new[] { firstArgument }, true, ctxt);

                                if (ov == null || ov.Length == 0)
                                {
                                    continue;
                                }

                                var ms = (DSymbol)ov[0];
                                ctxt.CurrentContext.IntroduceTemplateParameterTypes(ms);
                            }

                            var mr = TypeDeclarationResolver.HandleNodeMatch(m, ctxt, null, acc) as MemberSymbol;
                            if (mr != null)
                            {
                                mr.FirstArgument = firstArgument;
                                mr.DeducedTypes  = ctxt.CurrentContext.DeducedTemplateParameters.ToReadonly();
                                mr.IsUFCSResult  = true;
                                methodMatches.Add(mr);
                            }
                            ctxt.Pop();
                        }
                    }
                }
            }

            return(methodMatches.Count == 0 ? null : methodMatches.ToArray());
        }
Пример #29
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);
        }
		/// <summary>
		/// Add 'superior' template parameters to the current symbol because 
		/// the parameters might be re-used in the nested class.
		/// </summary>
		static List<TemplateParameterSymbol> GetInvisibleTypeParameters(DNode n,ResolutionContext ctxt)
		{
			var invisibleTypeParams = new List<TemplateParameterSymbol> ();

			var tStk = new Stack<ContextFrame> ();
			do {
				var curCtxt = ctxt.Pop ();
				tStk.Push (curCtxt);
				foreach (var kv in curCtxt.DeducedTemplateParameters)
					if (!n.ContainsTemplateParameter (kv.Value.Parameter))
						invisibleTypeParams.Add (kv.Value);
			}
			while (ctxt.PrevContextIsInSameHierarchy);
			while (tStk.Count != 0)
				ctxt.Push (tStk.Pop ());

			return invisibleTypeParams;
		}
Пример #31
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,
            ISyntaxRegion typeBase     = null,
            NodeMatchHandleVisitor vis = null)
        {
            // See https://github.com/aBothe/Mono-D/issues/161
            int stkC;

            if (stackCalls == null)
            {
                stackCalls    = new Dictionary <INode, int>();
                stackCalls[m] = 1;
            }
            else
            {
                stackCalls[m] = stackCalls.TryGetValue(m, out stkC) ? ++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;
                    }
                }
            }

            // 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 ret = m.Accept(vis ?? new NodeMatchHandleVisitor {
                ctxt = ctxt, resultBase = resultBase, typeBase = typeBase
            });

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

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

            return(ret);
        }
		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;
		}
Пример #33
0
        /// <summary>
        /// Used for searching further identifier list parts.
        ///
        /// a.b -- nextIdentifier would be 'b' whereas <param name="resultBases">resultBases</param> contained the resolution result for 'a'
        /// </summary>
        public static AbstractType[] ResolveFurtherTypeIdentifier(int nextIdentifierHash,
                                                                  IEnumerable <AbstractType> resultBases,
                                                                  ResolutionContext ctxt,
                                                                  object typeIdObject = null)
        {
            MemberSymbol statProp;

            if ((resultBases = DResolver.StripMemberSymbols(resultBases)) == null)
            {
                return(null);
            }

            var r = new List <AbstractType>();

            foreach (var b in resultBases)
            {
                if (b is UserDefinedType)
                {
                    var udt = b as UserDefinedType;
                    var bn  = udt.Definition as IBlockNode;

                    bool pop = !(b is MixinTemplateType);
                    if (!pop)
                    {
                        ctxt.PushNewScope(bn);
                    }
                    ctxt.CurrentContext.IntroduceTemplateParameterTypes(udt);

                    r.AddRange(SingleNodeNameScan.SearchChildrenAndResolve(ctxt, bn, nextIdentifierHash, typeIdObject));

                    List <TemplateParameterSymbol> dedTypes = null;
                    foreach (var t in r)
                    {
                        var ds = t as DSymbol;
                        if (ds != null && ds.DeducedTypes == null)
                        {
                            if (dedTypes == null)
                            {
                                dedTypes = ctxt.DeducedTypesInHierarchy;
                            }

                            ds.DeducedTypes = new System.Collections.ObjectModel.ReadOnlyCollection <TemplateParameterSymbol>(dedTypes);
                        }
                    }

                    statProp = StaticProperties.TryEvalPropertyType(ctxt, b, nextIdentifierHash);
                    if (statProp != null)
                    {
                        r.Add(statProp);
                    }

                    ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(udt);
                    if (!pop)
                    {
                        ctxt.Pop();
                    }
                }
                else if (b is PackageSymbol)
                {
                    var pack = (b as PackageSymbol).Package;

                    var accessedModule = pack.GetModule(nextIdentifierHash);
                    if (accessedModule != null)
                    {
                        r.Add(new ModuleSymbol(accessedModule as DModule, typeIdObject as ISyntaxRegion, b as PackageSymbol));
                    }
                    else if ((pack = pack.GetPackage(nextIdentifierHash)) != null)
                    {
                        r.Add(new PackageSymbol(pack, typeIdObject as ISyntaxRegion));
                    }
                }
                else if (b is ModuleSymbol)
                {
                    r.AddRange(SingleNodeNameScan.SearchChildrenAndResolve(ctxt, (b as ModuleSymbol).Definition, nextIdentifierHash, typeIdObject));
                }
                else
                {
                    statProp = StaticProperties.TryEvalPropertyType(ctxt, b, nextIdentifierHash);
                    if (statProp != null)
                    {
                        r.Add(statProp);
                    }
                }
                // TODO: Search for UFCS symbols
            }

            return(r.Count == 0 ? null : r.ToArray());
        }
Пример #34
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);
        }