Example #1
0
            private LNode ApplyMacrosFound(LNode input, int maxExpansions)
            {
                // Implicit paramater: _foundMacros. _results and _messageHolder are
                // temporaries that are re-used between invocations of this method to
                // avoid stressing the garbage collector.
                var s = new ApplyMacroState {
                    foundMacros = _foundMacros, results = _results, messageHolder = _messageHolder
                };

                // if any of the macros use a priority flag, group by priority.
                if (_foundMacros.Count > 1)
                {
                    var p = s.foundMacros[0].Mode & MacroMode.PriorityMask;
                    for (int x = 1, c = s.foundMacros.Count; x < c; x++)
                    {
                        if ((s.foundMacros[x].Mode & MacroMode.PriorityMask) != p)
                        {
                            // need to make an independent list because _foundMacros may be cleared and re-used for descendant nodes
                            s.foundMacros = new List <MacroInfo>(s.foundMacros);
                            s.foundMacros.Sort();
                            for (int i = 0, j; i < c; i = j)
                            {
                                p = s.foundMacros[i].Mode & MacroMode.PriorityMask;
                                for (j = i + 1; j < c; j++)
                                {
                                    if ((s.foundMacros[j].Mode & MacroMode.PriorityMask) != p)
                                    {
                                        break;
                                    }
                                }
                                LNode result = ApplyMacrosFound2(input, maxExpansions, s.foundMacros.Slice(i, j - i), ref s);
                                if (result != null)
                                {
                                    return(result);
                                }
                            }
                            return(null);
                        }
                    }
                }
                return(ApplyMacrosFound2(input, maxExpansions, s.foundMacros.Slice(0), ref s));
            }
Example #2
0
            private LNode ApplyMacrosFound2(LNode input, int maxExpansions, ListSlice <MacroInfo> foundMacros, ref ApplyMacroState s)
            {
                s.results.Clear();
                s.messageHolder.List.Clear();

                int accepted = 0, acceptedIndex = -1;

                for (int i = 0; i < foundMacros.Count; i++)
                {
                    var macro      = foundMacros[i];
                    var macroInput = input;
                    if ((macro.Mode & MacroMode.ProcessChildrenBefore) != 0)
                    {
                        if (maxExpansions == 1)
                        {
                            continue;                             // avoid expanding both this macro and its children
                        }
                        if (s.preprocessed == null)
                        {
                            // _foundMacros, _results, and _messageHolder are re-used
                            // by callee for unrelated contexts, so make copies of the s.*
                            // variables which point to them.
                            s.foundMacros   = new List <MacroInfo>(s.foundMacros);
                            s.results       = new List <Result>(s.results);
                            s.messageHolder = s.messageHolder.Clone();
                            foundMacros     = new List <MacroInfo>(foundMacros).Slice(0);

                            s.preprocessed = ApplyMacrosToChildren(input, maxExpansions) ?? input;
                        }
                        macroInput = s.preprocessed;
                    }

                    LNode output = null;
                    int   mhi    = s.messageHolder.List.Count;
                    try {
                        output = macro.Macro(macroInput, s.messageHolder);
                        if (output != null)
                        {
                            accepted++; acceptedIndex = i;
                        }
                    } catch (ThreadAbortException e) {
                        _sink.Write(Severity.Error, input, "Macro-processing thread aborted in {0}", QualifiedName(macro.Macro.Method));
                        _sink.Write(Severity.Detail, input, e.StackTrace);
                        s.results.Add(new Result(macro, output, s.messageHolder.List.Slice(mhi, s.messageHolder.List.Count - mhi)));
                        PrintMessages(s.results, input, accepted, Severity.Error);
                        throw;
                    } catch (Exception e) {
                        s.messageHolder.Write(Severity.Error, input, "{0}: {1}", e.GetType().Name, e.Message);
                        s.messageHolder.Write(Severity.Detail, input, e.StackTrace);
                    }
                    s.results.Add(new Result(macro, output, s.messageHolder.List.Slice(mhi, s.messageHolder.List.Count - mhi)));
                }

                PrintMessages(s.results, input, accepted,
                              s.messageHolder.List.MaxOrDefault(msg => (int)msg.Severity).Severity);

                if (accepted >= 1)
                {
                    var result = s.results[acceptedIndex];

                    Debug.Assert(result.Node != null);
                    if ((result.Macro.Mode & MacroMode.ProcessChildrenBefore) != 0)
                    {
                        maxExpansions--;
                    }

                    if ((result.Macro.Mode & MacroMode.Normal) != 0)
                    {
                        if (result.Node == input)
                        {
                            return(ApplyMacrosToChildren(result.Node, maxExpansions - 1) ?? result.Node);
                        }
                        else
                        {
                            return(ApplyMacros(result.Node, maxExpansions - 1) ?? result.Node);
                        }
                    }
                    else if ((result.Macro.Mode & MacroMode.ProcessChildrenAfter) != 0)
                    {
                        return(ApplyMacrosToChildren(result.Node, maxExpansions - 1) ?? result.Node);
                    }
                    else
                    {
                        return(result.Node);
                    }
                }
                else
                {
                    // "{}" needs special treatment
                    if (input.Calls(S.Braces))
                    {
                        try {
                            return(s.preprocessed ?? ApplyMacrosToChildren(input, maxExpansions));
                        } finally {
                            PopScope();
                        }
                    }
                    return(s.preprocessed ?? ApplyMacrosToChildren(input, maxExpansions));
                }
            }