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()); }
/// <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); }