Exemple #1
0
 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);
 }
Exemple #2
0
        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);
        }
Exemple #3
0
        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));
        }
Exemple #4
0
 public DescendantsFrame(LNode node, NodeScanMode mode)
 {
     _node     = node;
     _mode     = mode;
     _children = LNodeList.Empty;
     _step     = _index = 0;
 }
Exemple #5
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);
 }
Exemple #6
0
        /// <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))));
        }
Exemple #7
0
        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);
        }
Exemple #8
0
 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);
     }
 }
Exemple #9
0
 public override LNode WithAttrs(LNodeList attrs)
 {
     if (attrs.Count == 0)
     {
         return(this);
     }
     return(new StdSimpleCallNodeWithAttrs(attrs, _name, _args, this));
 }
Exemple #10
0
 public override LNode WithAttrs(LNodeList attrs)
 {
     if (attrs.Count == 0)
     {
         return(this);
     }
     return(new StdIdNodeWithAttrs(attrs, _name, this));
 }
Exemple #11
0
 public override LNode WithAttrs(LNodeList attrs)
 {
     if (attrs.Count == 0)
     {
         return(this);
     }
     return(new StdComplexCallNodeWithAttrs(attrs, _target, _args, this));
 }
Exemple #12
0
        /// <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)));
        }
Exemple #13
0
        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));
        }
Exemple #14
0
 public static LNode NodeNamed(this LNodeList self, Symbol name)
 {
     foreach (LNode node in self)
     {
         if (node.Name == name)
         {
             return(node);
         }
     }
     return(null);
 }
Exemple #15
0
 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));
     }
 }
Exemple #16
0
 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));
     }
 }
Exemple #17
0
        /// <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))));
        }
Exemple #18
0
        public override CallNode WithArgs(LNodeList args)
        {
            if (args == _args)
            {
                return(this);
            }
            var copy = cov_Clone();

            copy._args = args;
            NoNulls(args, nameof(Args));
            return(copy);
        }
Exemple #19
0
 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);
 }
Exemple #20
0
        public static LNodeList GetTrivia(this LNodeList attrs)
        {
            var trivia = LNodeList.Empty;

            foreach (var a in attrs)
            {
                if (a.IsTrivia)
                {
                    trivia.Add(a);
                }
            }
            return(trivia);
        }
Exemple #21
0
        /// <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);
        }
Exemple #22
0
        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);
        }
Exemple #23
0
        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));
            }
        }
Exemple #24
0
 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;
         }
     }));
 }
Exemple #25
0
 /// <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));
     }
 }
Exemple #26
0
        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);
        }
Exemple #27
0
        /// <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);
        }
Exemple #28
0
        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);
        }
Exemple #29
0
 /// <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);
 }
Exemple #30
0
 public StdIdNodeWithAttrs(LNodeList attrs, Symbol name, SourceRange range, NodeStyle style = NodeStyle.Default)
     : base(name, range, style)
 {
     _attrs = attrs; NoNulls(attrs, "Attrs");
 }