예제 #1
0
        public static AbstractType[] HandleNodeMatches(
            IEnumerable <INode> matches,
            ResolutionContext ctxt,
            AbstractType resultBase       = null,
            ISyntaxRegion typeDeclaration = null)
        {
            // Abbreviate a foreach-loop + List alloc
            var ll = matches as IList <INode>;

            if (ll != null && ll.Count == 1)
            {
                return new[] { ll[0] == null ? null : HandleNodeMatch(ll[0], ctxt, resultBase, typeDeclaration) }
            }
            ;

            if (matches == null)
            {
                return(new AbstractType[0]);
            }

            var vis = new NodeMatchHandleVisitor {
                ctxt = ctxt, resultBase = resultBase, typeBase = typeDeclaration
            };
            var rl = new List <AbstractType>();

            foreach (var m in matches)
            {
                if (m == null)
                {
                    continue;
                }

                var res = HandleNodeMatch(m, ctxt, resultBase, typeDeclaration, vis);
                if (res != null)
                {
                    rl.Add(res);
                }
            }

            return(rl.ToArray());
        }
예제 #2
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);
        }