public StdSimpleCallNode(Loyc.Syntax.Lexing.Token targetToken, LNodeList args, SourceRange range, NodeStyle style = NodeStyle.Default) : base(args, range, style) { _name = (Symbol)(targetToken.Value ?? GSymbol.Empty); _targetOffs = ClipUShort(targetToken.StartIndex - RAS.StartIndex); _targetLen = ClipUShort(targetToken.Length); }
static bool MatchThenParams(LNodeList cArgs, LNodeList pArgs, LNode paramsCap, ref MMap <Symbol, LNode> captures, ref LNodeList attrs) { // This helper function of MatchesPattern() is called when pArgs is followed // by a $(params capture). cArgs is the list of candidate.Args that have not // yet been matched; pArgs is the list of pattern.Args that have not yet been // matched, and paramsCap is the $(params capture) node that follows pArgs. captures = captures ?? new MMap <Symbol, LNode>(); int c = 0, p = 0; restart: for (; p < pArgs.Count; p++, c++) { if (IsParamsCapture(pArgs[p])) { if (!CaptureGroup(ref c, ref p, cArgs, pArgs, ref captures, ref attrs)) { return(false); } goto restart; } else { if (c >= cArgs.Count) { return(false); } if (!MatchesPatternNested(cArgs[c], pArgs[p], ref captures, ref attrs)) { return(false); } } } AddCapture(captures, paramsCap, new Slice_ <LNode>(cArgs, c)); return(true); }
protected internal override int GetHashCode(int recurse, int styleMask) { if (_hashCode != -1) { return(_hashCode); } LNodeList args = Args, attrs = Attrs; int hash = (args.Count << 3) + attrs.Count; if (recurse > 0) { var target = Target; if (target != null) { hash ^= target.GetHashCode(recurse - 1, styleMask); } for (int i = 0, c = System.Math.Min(attrs.Count, recurse << 2); i < c; i++) { hash = (hash * 4129) + attrs[i].GetHashCode(recurse - 1, styleMask); } for (int i = 0, c = System.Math.Min(args.Count, recurse << 2); i < c; i++) { hash = (hash * 1013) + args[i].GetHashCode(recurse - 1, styleMask); } } return(_hashCode = (hash += (int)Style & styleMask)); }
public DescendantsFrame(LNode node, NodeScanMode mode) { _node = node; _mode = mode; _children = LNodeList.Empty; _step = _index = 0; }
public StdSimpleCallNode(Symbol name, LNodeList args, SourceRange range, int targetStart, int targetEnd, NodeStyle style = NodeStyle.Default) : base(args, range, style) { _name = name ?? GSymbol.Empty; _targetOffs = ClipUShort(targetStart - RAS.StartIndex); _targetLen = ClipUShort(targetEnd - targetStart); }
/// <summary>Adds additional trailing trivia to an attribute list.</summary> public static LNodeList PlusTrailingTrivia(this LNodeList attrs, LNode trivia) { LNodeList oldTrivia; attrs = WithoutTrailingTrivia(attrs, out oldTrivia); return(attrs.Add(LNode.Call(S.TriviaTrailing, oldTrivia.Add(trivia)))); }
private static bool ListMatches(LNodeList candidates, LNodeList patterns, ref MMap <Symbol, LNode> captures, ref LNodeList unmatchedAttrs) { if (patterns.Count != candidates.Count && !patterns.Any(IsParamsCapture)) { return(false); } // Scan from the end of the list to the beginning (RVLists is good at this), // matching args one-by-one. Use MatchThenParams() in case of $(params capture). while (!patterns.IsEmpty) { LNode pArg = patterns.Pop(); if (IsParamsCapture(pArg)) { return(MatchThenParams(candidates, patterns, pArg, ref captures, ref unmatchedAttrs)); } if (candidates.IsEmpty) { return(false); } if (!MatchesPatternNested(candidates.Pop(), pArg, ref captures, ref unmatchedAttrs)) { return(false); } } return(true); }
public static IListSource <ILNode> GetTrailingTrivia(this ILNode node) { if (node is LNode) { LNodeList list = GetTrailingTrivia((LNode)node); if (list.IsEmpty) { return(EmptyList <ILNode> .Value); // avoid boxing in the common case } return(list); } else { VList <ILNode> list = VList <ILNode> .Empty; foreach (ILNode a in node.Attrs()) { if (a.Calls(S.TriviaTrailing)) { list.AddRange(a.Args()); } } if (list.IsEmpty) { return(EmptyList <ILNode> .Value); // avoid boxing in the common case } return(list); } }
public override LNode WithAttrs(LNodeList attrs) { if (attrs.Count == 0) { return(this); } return(new StdSimpleCallNodeWithAttrs(attrs, _name, _args, this)); }
public override LNode WithAttrs(LNodeList attrs) { if (attrs.Count == 0) { return(this); } return(new StdIdNodeWithAttrs(attrs, _name, this)); }
public override LNode WithAttrs(LNodeList attrs) { if (attrs.Count == 0) { return(this); } return(new StdComplexCallNodeWithAttrs(attrs, _target, _args, this)); }
/// <summary>Removes all existing trailing trivia from an attribute list and adds a new list of trailing trivia.</summary> /// <remarks>This method has a side-effect of recreating the %trailing /// node, if there is one, at the end of the attribute list. If <c>trivia</c> /// is empty then all calls to %trailing are removed.</remarks> public static LNodeList WithTrailingTrivia(this LNodeList attrs, LNodeList trivia) { var attrs2 = WithoutTrailingTrivia(attrs); if (trivia.IsEmpty) { return(attrs2); } return(attrs2.Add(LNode.Call(S.TriviaTrailing, trivia))); }
public sealed override LNode WithArgs(Func <LNode, Maybe <LNode> > selector) { LNodeList args = Args, newArgs = args.WhereSelect(selector); if (args == newArgs) { return(this); } return(WithArgs(newArgs)); }
public static LNode NodeNamed(this LNodeList self, Symbol name) { foreach (LNode node in self) { if (node.Name == name) { return(node); } } return(null); }
public static LNodeList WithSpliced(this LNodeList list, LNode node, Symbol listName = null) { if (node.Calls(listName ?? CodeSymbols.Splice)) { return(list.AddRange(node.Args)); } else { return(list.Add(node)); } }
public static LNodeList WithSpliced(this LNodeList list, int index, LNode node, Symbol listName = null) { if (node.Calls(listName ?? CodeSymbols.Splice)) { return(list.InsertRange(index, node.Args)); } else { return(list.Insert(index, node)); } }
/// <summary>Adds additional trailing trivia to an attribute list. Has no effect if <c>trivia</c> is empty.</summary> /// <remarks> /// Trailing trivia is represented by a call to <c>%trailing</c> in a node's /// attribute list; each argument to %trailing represents one piece of trivia. /// <para/> /// In the current design, this method has a side-effect of recreating the %trailing /// node at the end of the attribute list, and if there are multiple %trailing /// lists, consolidating them into a single list, but only if the specified <c>trivia</c> /// list is not empty.</remarks> public static LNodeList PlusTrailingTrivia(this LNodeList attrs, LNodeList trivia) { if (trivia.IsEmpty) { return(attrs); } LNodeList oldTrivia; attrs = WithoutTrailingTrivia(attrs, out oldTrivia); return(attrs.Add(LNode.Call(S.TriviaTrailing, oldTrivia.AddRange(trivia)))); }
public override CallNode WithArgs(LNodeList args) { if (args == _args) { return(this); } var copy = cov_Clone(); copy._args = args; NoNulls(args, nameof(Args)); return(copy); }
public static LNodeList WithoutNodeNamed(this LNodeList list, Symbol name, out LNode removedNode) { removedNode = null; for (int i = 0, c = list.Count; i < c; i++) { if (list[i].Name == name) { removedNode = list[i]; return(list.RemoveAt(i)); } } return(list); }
public static LNodeList GetTrivia(this LNodeList attrs) { var trivia = LNodeList.Empty; foreach (var a in attrs) { if (a.IsTrivia) { trivia.Add(a); } } return(trivia); }
/// <summary>Gets all trailing trivia attached to the specified node.</summary> /// <remarks>Trailing trivia is represented by a call to <c>%trailing</c> in /// a node's attribute list; each argument to %trailing represents one /// piece of trivia. If the attribute list has multiple calls to /// %trailing, this method combines those lists into a single list.</remarks> public static LNodeList GetTrailingTrivia(this LNodeList attrs) { var trivia = LNodeList.Empty; foreach (var a in attrs) { if (a.Calls(S.TriviaTrailing)) { trivia.AddRange(a.Args); } } return(trivia); }
public static LNodeList Without(this LNodeList list, LNode node) { int i = list.Count; foreach (var item in list.ToFVList()) { i--; if (item == node) { Debug.Assert(list[i] == node); return(list.RemoveAt(i)); } } return(list); }
public override LNode SelectMany(Func <LNode, IReadOnlyList <LNode> > selector, ReplaceOpt options = ReplaceOpt.ProcessAttrs) { var node = (options & ReplaceOpt.ProcessAttrs) != 0 ? WithAttrs(selector) : this; LNode target = node.Target, newTarget = LNode.List(selector(node.Target)).AsLNode(CodeSymbols.Splice); LNodeList newArgs = Args.SmartSelectMany(selector); if (newTarget != null && newTarget != target) { return(node.With(newTarget, newArgs)); } else { return(node.WithArgs(newArgs)); } }
public static LNodeList RecursiveReplace(this LNodeList self, Func <LNode, LNodeList?> matcher, LNode.ReplaceOpt options = LNode.ReplaceOpt.Default) { return(self.SmartSelectMany(n => { var choice = matcher(n); if (choice == null) { return n.RecursiveReplace(matcher, options); } else { return choice; } })); }
/// <summary>Converts a list of LNodes to a single LNode by using the list /// as the argument list in a call to the specified identifier, or, if the /// list contains a single item, by returning that single item.</summary> /// <param name="listIdentifier">Target of the node that is created if <c>list</c> /// does not contain exactly one item. Typical values include "'{}" and "#splice".</param> /// <remarks>This is the reverse of the operation performed by <see cref="AsList(LNode,Symbol)"/>.</remarks> public static LNode AsLNode(this LNodeList list, Symbol listIdentifier) { if (list.Count == 1) { return(list[0]); } else { var r = SourceRange.Synthetic; if (list.Count != 0) { r = list[0].Range; r = new SourceRange(r.Source, r.StartIndex, list.Last.Range.EndIndex - r.StartIndex); } return(LNode.Call(listIdentifier, list, r)); } }
public static int IndexWithName(this LNodeList self, Symbol name, int resultIfNotFound = -1) { int i = 0; foreach (LNode node in self) { if (node.Name == name) { return(i); } else { i++; } } return(resultIfNotFound); }
/// <summary>Gets a new list with any %trailing attributes removed. Trailing /// trivia inside those attributes are returned in an `out` parameter.</summary> public static LNodeList WithoutTrailingTrivia(this LNodeList attrs, out LNodeList trailingTrivia) { trailingTrivia = LNodeList.Empty; var attrs2 = attrs.SmartWhere(attr => !attr.Calls(S.TriviaTrailing)); if (attrs2 != attrs) { foreach (var attr in attrs) { if (attr.Calls(S.TriviaTrailing)) { trailingTrivia.AddRange(attr.Args); } } } return(attrs2); }
static bool CaptureGroup(ref int c, ref int p, LNodeList cArgs, LNodeList pArgs, ref MMap <Symbol, LNode> captures, ref LNodeList attrs) { Debug.Assert(IsParamsCapture(pArgs[p])); // The goal now is to find a sequence of nodes in cArgs that matches // the sequence pArgs[p+1 .. p+x] where x is the maximum value such // that none of the nodes in the sequence are $(params caps). int saved_p = p, saved_c = c; var savedCaptures = captures.AsImmutable(); var savedAttrs = attrs; int captureSize = 0; for (;; captureSize++) { for (p++, c += captureSize; ; c++, p++) { // If we run out of pArgs, great, we're done; if we run out // of cArgs, the match fails, unless all remaining pArgs are // $(params caps). if (p >= pArgs.Count || IsParamsCapture(pArgs[p])) { goto done_group; } else { if (c >= cArgs.Count) { return(false); } if (!MatchesPatternNested(cArgs[c], pArgs[p], ref captures, ref attrs)) { goto continue_group; } } } continue_group :; p = saved_p; c = saved_c; attrs = savedAttrs; captures = savedCaptures.AsMutable(); } done_group: AddCapture(captures, pArgs[saved_p], cArgs.Slice(saved_c, captureSize)); return(true); }
/// <summary>Prepends attributes to the first item in a list, except for /// trailing trivia (%trailing(...)), which is appended to the last item in /// the list. If the list is empty, the attributes are ignored.</summary> /// <returns>A modified version of the list with attributes added. If the /// attribute list is empty, the empty <c>list</c> is returned unchanged. /// </returns> public static LNodeList IncludingAttributes(this LNodeList list, LNodeList attributes) { if (attributes.IsEmpty || list.IsEmpty) { return(list); } attributes = attributes.WithoutTrailingTrivia(out LNodeList trailing); if (trailing.Count != 0) { if (attributes.Count != 0) { list[0] = list[0].PlusAttrsBefore(attributes); } list[list.Count - 1] = list.Last.PlusTrailingTrivia(trailing); } else { list[0] = list[0].PlusAttrsBefore(attributes); } return(list); }
public StdIdNodeWithAttrs(LNodeList attrs, Symbol name, SourceRange range, NodeStyle style = NodeStyle.Default) : base(name, range, style) { _attrs = attrs; NoNulls(attrs, "Attrs"); }