コード例 #1
0
        LNode Process(ref RVList <LNode> list, LNode single, bool asRoot, bool resetOpenNamespaces, bool areAttributesOrIsTarget)
        {
            if (single == null && list.Count == 0)
            {
                return(null);                // no-op requested
            }
            var oldS         = _s;
            var oldAncestors = _ancestorStack;
            var oldMP        = MacroProcessor._current;

            MacroProcessor._current = _parent;
            bool newScope = false;

            try {
                bool reentrant = _reentrancyCounter++ != 0;
                if (!reentrant)
                {
                    asRoot = true;
                }
                Debug.Assert(reentrant || _scopes.Count == 0);
                Debug.Assert(reentrant || _ancestorStack == null);

                if (asRoot)
                {
                    _ancestorStack = new DList <LNode>();
                }
                _s = new CurNodeState();
                if (asRoot || resetOpenNamespaces)
                {
                    var namespaces = !reentrant || resetOpenNamespaces?_parent.PreOpenedNamespaces.Clone() : _curScope.OpenNamespaces.Clone();

                    var properties = asRoot ? new MMap <object, object>() : _curScope.ScopedProperties;
                    newScope  = true;
                    _curScope = new Scope(namespaces, properties, this, true);
                    _scopes.Add(_curScope);
                }
                int maxExpansions = asRoot ? MaxExpansions : _s.MaxExpansions - 1;
                if (single != null)
                {
                    return(ApplyMacros(single, maxExpansions, areAttributesOrIsTarget));
                }
                else
                {
                    int   oldStackCount = _ancestorStack.Count;
                    LNode splice        = null;
                    if (asRoot)
                    {
                        splice = list.AsLNode(S.Splice);
                        _ancestorStack.PushLast(splice);
                    }
                    list = ApplyMacrosToList(list, maxExpansions, areAttributesOrIsTarget);
                    _ancestorStack.PopLast();
                    Debug.Assert(_ancestorStack.Count == oldStackCount);
                    return(splice);
                }
            } finally {
                _reentrancyCounter--;
                MacroProcessor._current = oldMP;
                _ancestorStack          = oldAncestors;
                _s = oldS;
                if (newScope)
                {
                    PopScope();
                }
            }
        }
コード例 #2
0
        public static LNode on_return(LNode node, IMacroContext context)
        {
            LNode firstArg, rest, on_handler = ValidateOnStmt(node, context, out rest, out firstArg);

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

            // Get/construct the declaration of the var to return, and get its name
            LNode varDecl = firstArg, varName = firstArg;
            bool  varAssigned = false;

            if (firstArg == null)
            {
                varName = F.Id(__result__);
                varDecl = F.Var(F._Missing, varName);
            }
            else
            {
                if (varDecl.Calls(S.Var, 2))
                {
                    if (varAssigned = (varName = varDecl.Args[1]).Calls(S.Assign, 2))
                    {
                        varName = varName.Args[0];
                    }
                }
                else if (varName.IsId)
                {
                    varDecl = node.With(S.Var, F._Missing, varName);
                }
                else
                {
                    return(Reject(context, firstArg, "The first parameter to on_return must be a simple identifier (the name of a variable to return) or a variable declaration (for a variable to be returned)."));
                }
            }
            var retExpr = F.Call(S.Substitute, F.Id(__retexpr__));

            Pair <LNode, LNode>[] patterns = new Pair <LNode, LNode>[2] {
                // return; => { <on_handler> return; }
                new Pair <LNode, LNode>(F.Call(S.Return), varAssigned
                                                ? on_handler.WithArgs(new RVList <LNode>(varDecl)
                                                                      .AddRange(on_handler.Args)
                                                                      .Add(F.Call(S.Return, varName)))
                                                : on_handler.PlusArg(F.Call(S.Return))),
                // return exp; => { <varDecl = $exp> <on_handler> return <varName>; }
                new Pair <LNode, LNode>(F.Call(S.Return, retExpr),
                                        on_handler.WithArgs(new RVList <LNode>(
                                                                varDecl.WithArgChanged(1, F.Call(S.Assign, varName, retExpr)))
                                                            .AddRange(on_handler.Args)
                                                            .Add(F.Call(S.Return, varName))))
            };
            int            replacementCount = 0;
            RVList <LNode> output           = StandardMacros.Replace(rest.Args, patterns, out replacementCount);

            if (replacementCount == 0)
            {
                context.Write(Severity.Warning, node, "'on_return': no 'return' statements were found below this line, so this macro had no effect.");
            }
            return(output.AsLNode(S.Splice));
        }