Пример #1
0
 // A complex identifier has the form Id, ComplexId.Id, or ComplexId!(ComplexId, ...)
 // where Id is a simple identifier and ComplexId is a complex identifier. Also, the
 // form X!Y!Z, i.e. #of(#of(...), ...) is not allowed. $Substitution is allowed.
 public static bool IsComplexId(LNode id, bool allowOf = true)
 {
     if (id.IsCall)
     {
         if (id.Name == S.Of)
         {
             if (allowOf)
             {
                 return((id.HasSimpleHead() || IsComplexId(id.Target, false)) && id.Args.All(a => IsComplexId(a)));
             }
             return(false);
         }
         else if (id.Calls(S.Dot, 2))
         {
             return(id.Args.Last.IsId && IsComplexId(id.Args[0]));
         }
         else if (id.Calls(S.Substitute, 1))
         {
             return(true);
         }
         else
         {
             return(false);
         }
     }
     else
     {
         return(id.IsId);
     }
 }
Пример #2
0
        static Symbol GetContractAttrMode(LNode attr, out LNode exceptionType)
        {
            var mode = attr.Name;

            exceptionType = null;
            if (!attr.HasSimpleHead())
            {
                var target = attr.Target;
                if (target.Calls(S.Of, 2) && target.Args[0].IsIdNamed(sy_ensuresOnThrow))
                {
                    exceptionType = target.Args[1];
                    mode          = sy_ensuresOnThrow;
                }
            }
            if (mode == __notnull)
            {
                mode = sy_notnull;
            }
            if (mode == sy_ensuresOnThrow || mode == sy_requires || mode == sy_notnull || mode == sy_assert ||
                mode == sy_ensures || mode == sy_ensuresAssert || mode == sy_ensuresFinally)
            {
                return(mode);
            }
            return(null);
        }
Пример #3
0
        /// <summary>Recursively applies macros in scope to <c>input</c>.</summary>
        /// <param name="maxExpansions">Maximum number of opportunities given
        /// to macros to transform a given subtree. The output of any macro is
        /// transformed again (as if by calling this method) with
        /// <c>maxExpansions = maxExpansions - 1</c> to encourage the
        /// expansion process to terminate eventually.</param>
        /// <returns>Returns a transformed tree or null if the macros did not
        /// change the syntax tree at any level, paired with a flag that is
        /// true if the remainder of the nodes in the current list of nodes
        /// should be dropped.</returns>
        LNode ApplyMacros(LNode input, int maxExpansions, bool isTargetNode)
        {
            if (maxExpansions <= 0)
            {
                return(null);
            }
            _s.StartNextNode(input, maxExpansions, isTargetNode);

            // Find macros...
            LNode target;

            if (input.HasSimpleHead())
            {
                GetApplicableMacros(_curScope.OpenNamespaces, input.Name, _s.FoundMacros);
            }
            else if ((target = input.Target).Calls(S.Dot, 2) && target.Args[1].IsId)
            {
                Symbol name = target.Args[1].Name, @namespace = NamespaceToSymbol(target.Args[0]);
                GetApplicableMacros(@namespace, name, _s.FoundMacros);
            }

            _ancestorStack.PushLast(input);
            try {
                if (_s.FoundMacros.Count != 0)
                {
                    return(ApplyMacrosFound(_s));
                }
                else
                {
                    return(ApplyMacrosToChildrenOf(input, maxExpansions));
                }
            } finally {
                _ancestorStack.PopLast(1);
            }
        }
Пример #4
0
            /// <summary>Applies macros in scope to <c>input</c>.</summary>
            /// <param name="maxExpansions">Maximum number of opportunities given
            /// to macros to transform a given subtree. The output of any macro is
            /// transformed again (as if by calling this method) with
            /// <c>maxExpansions = maxExpansions - 1</c> to encourage the
            /// expansion process to terminate eventually.</param>
            /// <returns>Returns a transformed tree or null if the macros did not
            /// change the syntax tree at any level.</returns>
            LNode ApplyMacros(LNode input, int maxExpansions)
            {
                if (maxExpansions <= 0)
                {
                    return(null);
                }
                // Find macros...
                _foundMacros.Clear();
                LNode target;

                if (input.HasSimpleHead())
                {
                    GetApplicableMacros(_curScope.OpenNamespaces, input.Name, _foundMacros);
                }
                else if ((target = input.Target).Calls(S.Dot, 2) && target.Args[1].IsId)
                {
                    Symbol name = target.Args[1].Name, @namespace = NamespaceToSymbol(target.Args[0]);
                    GetApplicableMacros(@namespace, name, _foundMacros);
                }


                if (_foundMacros.Count != 0)
                {
                    return(ApplyMacrosFound(input, maxExpansions));
                }
                else
                {
                    return(ApplyMacrosToChildren(input, maxExpansions));
                }
            }
Пример #5
0
        private bool HasSimpleTargetWithoutPAttrs(LNode node)
        {
            if (node.HasSimpleHead())
            {
                return(true);
            }
            var t = node.Target;

            return(!t.IsCall && !HasPAttrs(t));
        }
Пример #6
0
        public static LNode concat_id(LNode node, IMessageSink sink)
        {
            var args = node.Args;

            if (args.Count == 0)
            {
                return(null);
            }
            if (args.Slice(0, args.Count - 1).Any(n => n.IsCall))
            {
                return(Reject(sink, node, "All arguments to ##() or concat() must be identifiers or literals (except the last one)"));
            }

            RVList <LNode> attrs = node.Attrs;
            LNode          arg   = null;
            StringBuilder  sb    = new StringBuilder();

            for (int i = 0; i < args.Count; i++)
            {
                arg = args[i];
                attrs.AddRange(arg.Attrs);

                if (arg.IsLiteral)
                {
                    sb.Append(arg.Value ?? "null");
                }
                else if (arg.IsId)
                {
                    sb.Append(arg.Name);
                }
                else                   // call
                {
                    if (i + 1 != args.Count || !arg.HasSimpleHead())
                    {
                        return(Reject(sink, arg, "Expected simple identifier or literal"));
                    }
                    sb.Append(arg.Name);
                }
            }
            Symbol combined = GSymbol.Get(sb.ToString());
            LNode  result;

            if (arg.IsCall)
            {
                result = arg.WithTarget(combined);
            }
            else
            {
                result = LNode.Id(combined, node);
            }
            return(result.WithAttrs(attrs));
        }
Пример #7
0
        private void GetApplicableMacros(LNode curNode, List <MacroInfo> foundMacros)
        {
            LNode target;

            if (curNode.HasSimpleHead())
            {
                GetApplicableMacros(_curScope.OpenNamespaces, curNode.Name, foundMacros);
            }
            else if ((target = curNode.Target).Calls(S.Dot, 2) && target.Args[1].IsId)
            {
                Symbol name = target.Args[1].Name, @namespace = NamespaceToSymbol(target.Args[0]);
                GetApplicableMacros(@namespace, name, foundMacros);
            }
        }
Пример #8
0
        private static StringBuilder ConcatCore(LNode node, out LNodeList attrs, IMessageSink sink, bool allowLastToBeCall = false)
        {
            attrs = node.Attrs;
            var args = node.Args;

            if (args.Count == 0)
            {
                return(null);
            }

            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < args.Count; i++)
            {
                LNode arg = args[i];
                attrs.AddRange(arg.Attrs);

                if (arg.IsLiteral)
                {
                    if (!arg.TextValue.IsNull)
                    {
                        arg.TextValue.AppendTo(sb);
                    }
                    else
                    {
                        sb.Append(arg.Value ?? "null");
                    }
                }
                else if (arg.IsId)
                {
                    sb.Append(arg.Name);
                }
                else                     // call
                {
                    if (i + 1 != args.Count || !arg.HasSimpleHead())
                    {
                        Reject(sink, arg, "Expected simple identifier or literal");
                        return(null);
                    }
                    sb.Append(arg.Name);
                }
            }
            return(sb);
        }
Пример #9
0
            LNode ApplyMacrosToChildren(LNode node, int maxExpansions)
            {
                if (maxExpansions <= 0)
                {
                    return(null);
                }

                bool           changed = false;
                RVList <LNode> old;
                var            newAttrs = ApplyMacrosToList(old = node.Attrs, maxExpansions);

                if (newAttrs != old)
                {
                    node    = node.WithAttrs(newAttrs);
                    changed = true;
                }
                if (!node.HasSimpleHead())
                {
                    LNode target = node.Target, newTarget = ApplyMacros(target, maxExpansions);
                    if (newTarget != null)
                    {
                        if (newTarget.Calls(S.Splice, 1))
                        {
                            newTarget = newTarget.Args[0];
                        }
                        node    = node.WithTarget(newTarget);
                        changed = true;
                    }
                }
                var newArgs = ApplyMacrosToList(old = node.Args, maxExpansions);

                if (newArgs != old)
                {
                    node    = node.WithArgs(newArgs);
                    changed = true;
                }
                return(changed ? node : null);
            }
Пример #10
0
		// A complex identifier has the form Id, ComplexId.Id, or ComplexId!(ComplexId, ...)
		// where Id is a simple identifier and ComplexId is a complex identifier. Also, the
		// form X!Y!Z, i.e. #of(#of(...), ...) is not allowed. $Substitution is allowed.
		public static bool IsComplexId(LNode id, bool allowOf = true)
		{
			if (id.IsCall) {
				if (id.Name == S.Of) {
					if (allowOf)
						return (id.HasSimpleHead() || IsComplexId(id.Target, false)) && id.Args.All(a => IsComplexId(a));
					return false;
				} else if (id.Calls(S.Dot, 2)) {
					return id.Args.Last.IsId && IsComplexId(id.Args[0]);
				} else if (id.Calls(S.Substitute, 1)) {
					return true;
				} else
					return false;
			} else
				return id.IsId;
		}
Пример #11
0
		public static bool IsTargetDefinitionId(LNode id, bool allowDots)
		{
			return id.HasSimpleHead() || IsDefinitionId(id.Target, allowDots);
		}
Пример #12
0
 internal static bool HasSimpleHeadWPA(LNode self, Pedantics p)
 {
     return((p & Pedantics.IgnoreAttributesInOddPlaces) != 0 ? self.HasSimpleHead() : self.HasSimpleHeadWithoutPAttrs());
 }
Пример #13
0
 public static bool IsTargetDefinitionId(LNode id, bool allowDots)
 {
     return(id.HasSimpleHead() || IsDefinitionId(id.Target, allowDots));
 }
Пример #14
0
		internal static bool HasSimpleHeadWPA(LNode self, Pedantics p)
		{
			return (p & Pedantics.IgnoreWeirdAttributes) != 0 ? self.HasSimpleHead() : self.HasSimpleHeadWithoutPAttrs();
		}
Пример #15
0
        /// <summary>Recursively applies macros in scope to <c>input</c>.</summary>
        /// <param name="maxExpansions">Maximum number of opportunities given
        /// to macros to transform a given subtree. The output of any macro is
        /// transformed again (as if by calling this method) with
        /// <c>maxExpansions = maxExpansions - 1</c> to encourage the
        /// expansion process to terminate eventually.</param>
        /// <param name="nodeQueue">The act of processing child nodes (by calling
        /// ApplyMacrosToChildrenOf) invalidates most members of _s including
        /// _s.NodeQueue. But when ApplyMacrosToList calls this method it needs
        /// the node queue, so this method saves _s.NodeQueue in nodeQueue before
        /// doing something that will destroy _s.NodeQueue. It also sets
        /// _s.NodeQueue = nodeQueue when it starts.</param>
        /// <returns>Returns a transformed tree (or null if the macros did not
        /// change the syntax tree at any level).</returns>
        /// <remarks>EnqueueSplice is used if a #splice(...) is encountered.</remarks>
        LNode ApplyMacros(LNode input, int maxExpansions, bool isTargetNode, bool isSingleNode, ref DList <Pair <LNode, int> > nodeQueue)
        {
            _s.NodeQueue = nodeQueue;
            int   maxExpansionsBefore = maxExpansions;
            LNode resultNode          = null;

            for (LNode curNode = input; maxExpansions > 0; curNode = resultNode)
            {
                // If #splice, expand it
                if (!isSingleNode && curNode.Calls(S.Splice))
                {
                    if (curNode.ArgCount == 0)
                    {
                        return(curNode);                        // #splice()
                    }
                    curNode = resultNode = _s.EnqueueSplice(curNode.Args, maxExpansions, maxExpansionsBefore);
                    Debug.Assert(curNode != null);
                }

                _s.StartNextNode(curNode, maxExpansions, isTargetNode);
                GetApplicableMacros(curNode, _s.FoundMacros);
                if (_s.FoundMacros.Count == 0 && curNode.ArgCount == 0 &&
                    curNode.HasSimpleHead() && !curNode.HasAttrs)
                {
                    nodeQueue = _s.NodeQueue;
                    return(resultNode);                    // most common case: a boring leaf node
                }

                bool braces = curNode.Calls(S.Braces);
                if (braces)
                {
                    _scopes.Add(null);
                }

                MacroResult result;
                _ancestorStack.PushLast(curNode);
                try {
                    if (_s.FoundMacros.Count == 0)
                    {
                        nodeQueue = _s.NodeQueue;
                        return(ApplyMacrosToChildrenOf(curNode, maxExpansions) ?? resultNode);
                    }

                    // USER MACROS RUN HERE!
                    var result_ = ApplyMacrosFound(_s);
                    if (result_ == null)
                    {
                        // Macro(s) had no effect (not in this iteration, anyway),
                        // so move on to processing children.
                        nodeQueue = _s.NodeQueue;
                        return(_s.Preprocessed ?? ApplyMacrosToChildrenOf(curNode, maxExpansions) ?? resultNode);
                    }
                    result = result_.Value;
                } finally {
                    _ancestorStack.PopLast(1);
                    if (braces)
                    {
                        PopScope();
                    }
                }

                // Deal with result produced by the macro
                NodesReplaced++;
                Debug.Assert(result.NewNode != null);
                _s.DropRemainingNodesIfRequested();

                resultNode = result.NewNode;
                nodeQueue  = _s.NodeQueue;
                if ((result.Macro.Mode & MacroMode.ProcessChildrenAfter) != 0)
                {
                    return(ApplyMacrosToChildrenOf(resultNode, maxExpansions - 1) ?? resultNode);
                }
                else if ((result.Macro.Mode & (MacroMode.NoReprocessing | MacroMode.ProcessChildrenBefore)) != 0)
                {
                    return(resultNode);                    // we're done!
                }
                else if (resultNode == curNode)
                {
                    // node is unchanged, so reprocessing would produce the
                    // same result. Don't do that, just process children.
                    return(ApplyMacrosToChildrenOf(resultNode, maxExpansions - 1) ?? resultNode);
                }
                else
                {
                    // Avoid deepening the call stack like we used to do...
                    //   result2 = ApplyMacros(result.NewNode, s.MaxExpansions - 1, s.IsTarget);
                    //   if (result2 != null) result.DropRemainingNodesRequested |= _s.DropRemainingNodesRequested;
                    // instead, iterate, changing our own parameters.
                    maxExpansions--;
                    Debug.Assert(isTargetNode == _s.IsTarget);
                }
            }
            nodeQueue = _s.NodeQueue;
            return(resultNode);
        }