Esempio n. 1
0
        public static LNode unroll(LNode node, IMacroContext context)
        {
            LNode clause;

            // unroll (X, Y) \in ((X, Y), (Y, X)) {...}
            // unroll ((X, Y) in ((X, Y), (Y, X))) {...}
            if (node.ArgCount == 2 && ((clause = node.Args[0]).Calls(@in, 2) || clause.Calls(S.In, 2)))
            {
                LNode identifiers = clause.Args[0], cases = clause.Args[1];
                if (!cases.Calls(S.Tuple) && !cases.Calls(S.Braces) && !cases.Calls(S.Splice))
                {
                    cases = context.PreProcess(cases);
                    if (!cases.Calls(S.Tuple) && !cases.Calls(S.Braces) && !cases.Calls(S.Splice))
                    {
                        return(Reject(context, cases, "The right-hand side of 'in' should be a tuple or braced block."));
                    }
                }
                var result = unroll(identifiers, cases.Args, node.Args[1], context.Sink);
                if (result != null && node.HasPAttrs())
                {
                    context.Sink.Warning(result.Attrs[0], "'unroll' does not support attributes.");
                }
                return(result);
            }
            return(null);
        }
Esempio n. 2
0
 static LNode AutoStripBraces(LNode node)
 {
     if (node.Calls(S.Braces, 1) && !node.HasPAttrs())
     {
         return(node.Args[0]);
     }
     return(node);
 }
Esempio n. 3
0
 internal static LNode UnwrapBraces(LNode node)
 {
     if (node.Calls(S.Braces, 1) && !node.HasPAttrs())
     {
         return(node.Args[0]);
     }
     return(node);
 }
Esempio n. 4
0
 static bool AttributesMatch(LNode candidate, LNode pattern, ref MMap <Symbol, LNode> captures, out RVList <LNode> unmatchedAttrs)
 {
     if (pattern.HasPAttrs())
     {
         throw new NotImplementedException("TODO: attributes in patterns are not yet supported");
     }
     unmatchedAttrs = candidate.Attrs;
     return(true);
 }
        // e.g. given the method void f() {...}, prints "void f"
        //      for a cast operator #fn(Foo, #cast, #(...)) it prints "operator Foo" if requested
        private void PrintTypeAndName(bool isConstructor, bool isCastOperator = false, AttrStyle attrStyle = AttrStyle.IsDefinition, string eventKeywordOpt = null)
        {
            LNode retType = _n.Args[0], name = _n.Args[1];

            if (retType.HasPAttrs())
            {
                using (With(retType, StartStmt))
                    G.Verify(0 == PrintAttrs(AttrStyle.NoKeywordAttrs, null, "return"));
            }

            G.Verify(0 == PrintAttrs(attrStyle));

            var target = _n.Target;             // #fn or #prop

            PrintTrivia(target, trailingTrivia: false);
            PrintTrivia(target, trailingTrivia: true);

            if (eventKeywordOpt != null)
            {
                _out.Write(eventKeywordOpt, true);
            }

            if (_name == S.Delegate)
            {
                _out.Write("delegate ", true);
            }
            if (isCastOperator)
            {
                _out.Write("operator ", true);
                PrintType(retType, ContinueExpr, Ambiguity.AllowPointer);
            }
            else
            {
                if (!isConstructor)
                {
                    PrintType(retType, ContinueExpr, Ambiguity.AllowPointer | Ambiguity.NoParentheses);
                    if (_out.LastCharWritten != '\n')
                    {
                        _out.Space();
                    }
                }
                if (isConstructor && name.IsIdNamed(S.This))
                {
                    _out.Write("this", true);
                }
                else if (name.IsLiteral)                   // operator true/false
                {
                    _out.Write("operator ", true);
                    using (With(name, Precedence.MaxValue)) PrintLiteral();
                }
                else                     // Normal name
                {
                    PrintExpr(name, ContinueExpr, Ambiguity.InDefinitionName | Ambiguity.NoParentheses);
                }
            }
        }
Esempio n. 6
0
		public static LNode unroll(LNode var, LNode cases, LNode body, IMessageSink sink)
		{
			if (!cases.Calls(S.Tuple) && !cases.Calls(S.Braces))
				return Reject(sink, cases, "unroll: the right-hand side of 'in' should be a tuple");

			// Maps identifiers => replacements. The integer counts how many times replacement occurred.
			var replacements = InternalList<Triplet<Symbol, LNode, int>>.Empty;
			if (var.IsId && !var.HasPAttrs()) {
				replacements.Add(Pair.Create(var.Name, (LNode)LNode.Missing, 0));
			} else {
				var vars = var.Args;
				if ((var.Calls(S.Tuple) || var.Calls(S.Braces)) && vars.All(a => a.IsId && !a.HasPAttrs())) {
					replacements = new Triplet<Symbol, LNode, int>[vars.Count].AsInternalList();
					for (int i = 0; i < vars.Count; i++) {
						replacements.InternalArray[i].A = vars[i].Name;
						
						// Check for duplicate names
						for (int j = 0; j < i; j++)
							if (replacements[i].A == replacements[j].A && replacements[i].A.Name != "_")
								sink.Write(Severity.Error, vars[i], "unroll: duplicate name in the left-hand tuple"); // non-fatal
					}
				} else
					return Reject(sink, cases, "unroll: the left-hand side of 'in' should be a simple identifier or a tuple of simple identifiers.");
			}

			UnrollCtx ctx = new UnrollCtx { Replacements = replacements };
			WList<LNode> output = new WList<LNode>();
			int iteration = 0;
			foreach (LNode replacement in cases.Args)
			{
				iteration++;
				bool tuple = replacement.Calls(S.Tuple) || replacement.Calls(S.Braces);
				int count = tuple ? replacement.ArgCount : 1;
				if (replacements.Count != count)
				{
					sink.Write(Severity.Error, replacement, "unroll, iteration {0}: Expected {1} replacement items, got {2}", iteration, replacements.Count, count);
					if (count < replacements.Count)
						continue; // too few
				}
				for (int i = 0; i < replacements.Count; i++)
					replacements.InternalArray[i].B = tuple ? replacement.Args[i] : replacement;

				if (body.Calls(S.Braces)) {
					foreach (LNode stmt in body.Args)
						output.Add(ctx.Replace(stmt).Value);
				} else
					output.Add(ctx.Replace(body).Value);
			}

			foreach (var r in replacements)
				if (r.C == 0 && !r.A.Name.StartsWith("_"))
					sink.Write(Severity.Warning, var, "Replacement variable '{0}' was never used", r.A);
			
			return body.With(S.Splice, output.ToVList());
		}
Esempio n. 7
0
 static bool AttributesMatch(LNode candidate, LNode pattern, ref MMap <Symbol, LNode> captures, out LNodeList unmatchedAttrs)
 {
     if (pattern.HasPAttrs())
     {
         unmatchedAttrs = LNode.List();
         return(ListMatches(candidate.Attrs, pattern.Attrs, ref captures, ref unmatchedAttrs));
     }
     else
     {
         unmatchedAttrs = candidate.Attrs;
     }
     return(true);
 }
Esempio n. 8
0
		public static LNode unroll(LNode node, IMessageSink sink)
		{
			LNode clause;
			// unroll (X, Y) \in ((X, Y), (Y, X)) {...}
			// unroll ((X, Y) in ((X, Y), (Y, X))) {...}
			if (node.ArgCount == 2 && ((clause = node.Args[0]).Calls(@in, 2) || clause.Calls(S.In, 2)))
			{
				var result = unroll(clause.Args[0], clause.Args[1], node.Args[1], sink);
				if (result != null && node.HasPAttrs())
					sink.Write(Severity.Warning, result.Attrs[0], "'unroll' does not support attributes.");
				return result;
			}
			return null;
		}
Esempio n. 9
0
        // e.g. given the method void f() {...}, prints "void f"
        //      for a cast operator #fn(Foo, #cast, #(...)) it prints "operator Foo" if requested
        private LNode PrintTypeAndName(bool isConstructor, bool isCastOperator = false, AttrStyle attrStyle = AttrStyle.IsDefinition, string eventKeywordOpt = null)
        {
            LNode retType = _n.Args[0], name = _n.Args[1];
            var   ifClause = GetIfClause();

            if (retType.HasPAttrs())
            {
                using (With(retType))
                    G.Verify(0 == PrintAttrs(StartStmt, AttrStyle.NoKeywordAttrs, 0, null, "return"));
            }

            G.Verify(0 == PrintAttrs(StartStmt, attrStyle, 0, ifClause));

            if (eventKeywordOpt != null)
            {
                _out.Write(eventKeywordOpt, true);
            }

            if (_n.Name == S.Delegate)
            {
                _out.Write("delegate", true);
                _out.Space();
            }
            if (isCastOperator)
            {
                _out.Write("operator", true);
                _out.Space();
                PrintType(retType, ContinueExpr, Ambiguity.AllowPointer | Ambiguity.DropAttributes);
            }
            else
            {
                if (!isConstructor)
                {
                    PrintType(retType, ContinueExpr, Ambiguity.AllowPointer | Ambiguity.DropAttributes);
                    _out.Space();
                }
                if (isConstructor && name.IsIdNamed(S.This))
                {
                    _out.Write("this", true);
                }
                else
                {
                    PrintExpr(name, ContinueExpr, Ambiguity.InDefinitionName);
                }
            }
            return(ifClause);
        }
Esempio n. 10
0
        public static LNode unroll(LNode node, IMessageSink sink)
        {
            LNode clause;

            // unroll (X, Y) \in ((X, Y), (Y, X)) {...}
            // unroll ((X, Y) in ((X, Y), (Y, X))) {...}
            if (node.ArgCount == 2 && ((clause = node.Args[0]).Calls(@in, 2) || clause.Calls(S.In, 2)))
            {
                var result = unroll(clause.Args[0], clause.Args[1], node.Args[1], sink);
                if (result != null && node.HasPAttrs())
                {
                    sink.Write(Severity.Warning, result.Attrs[0], "'unroll' does not support attributes.");
                }
                return(result);
            }
            return(null);
        }
Esempio n. 11
0
        static LNode quote2(LNode node, IMessageSink sink, bool substitutions)
        {
            if (node.ArgCount != 1)
            {
                return(Reject(sink, node, "Expected a single parameter."));
            }
            LNode code = node.Args[0];

            if (code.Calls(S.Braces, 1) && !code.HasPAttrs())
            {
                return(QuoteOne(code.Args[0], substitutions));
            }
            else
            {
                return(QuoteOne(code, substitutions));
            }
        }
Esempio n. 12
0
		public static LNode unroll(LNode node, IMacroContext context)
		{
			LNode clause;
			// unroll (X, Y) \in ((X, Y), (Y, X)) {...}
			// unroll ((X, Y) in ((X, Y), (Y, X))) {...}
			if (node.ArgCount == 2 && ((clause = node.Args[0]).Calls(@in, 2) || clause.Calls(S.In, 2)))
			{
				LNode identifiers = clause.Args[0], cases = clause.Args[1];
				if (!cases.Calls(S.Tuple) && !cases.Calls(S.Braces) && !cases.Calls(S.Splice)) {
					cases = context.PreProcess(cases);
					if (!cases.Calls(S.Tuple) && !cases.Calls(S.Braces) && !cases.Calls(S.Splice))
						return Reject(context, cases, "The right-hand side of 'in' should be a tuple or braced block.");
				}
				var result = unroll(identifiers, cases.Args, node.Args[1], context.Sink);
				if (result != null && node.HasPAttrs())
					context.Sink.Warning(result.Attrs[0], "'unroll' does not support attributes.");
				return result;
			}
			return null;
		}
Esempio n. 13
0
		// These are validators for printing purposes: they check that each node 
		// that shouldn't have attributes, doesn't; if attributes are present in
		// strange places then we print with prefix notation instead to avoid 
		// losing them when round-tripping.

		internal static bool HasPAttrs(LNode node, Pedantics p) // for use in expression context
		{
			return (p & Pedantics.IgnoreWeirdAttributes) == 0 && node.HasPAttrs();
		}
Esempio n. 14
0
        public static LNode unroll(LNode var, VList <LNode> cases, LNode body, IMessageSink sink)
        {
            // Maps identifiers => replacements. The integer counts how many times replacement occurred.
            var replacements = InternalList <Triplet <Symbol, LNode, int> > .Empty;

            if (var.IsId && !var.HasPAttrs())
            {
                replacements.Add(Pair.Create(var.Name, (LNode)LNode.Missing, 0));
            }
            else
            {
                var vars = var.Args;
                if ((var.Calls(S.Tuple) || var.Calls(S.Braces)) && vars.All(a => a.IsId && !a.HasPAttrs()))
                {
                    replacements = new Triplet <Symbol, LNode, int> [vars.Count].AsInternalList();
                    for (int i = 0; i < vars.Count; i++)
                    {
                        replacements.InternalArray[i].A = vars[i].Name;

                        // Check for duplicate names
                        for (int j = 0; j < i; j++)
                        {
                            if (replacements[i].A == replacements[j].A && replacements[i].A.Name != "_")
                            {
                                sink.Error(vars[i], "Duplicate name in the left-hand tuple");                                 // non-fatal
                            }
                        }
                    }
                }
                else
                {
                    return(Reject(sink, var, "The left-hand side of 'in' should be a simple identifier or a tuple of simple identifiers."));
                }
            }

            UnrollCtx ctx = new UnrollCtx {
                Replacements = replacements
            };
            WList <LNode> output = new WList <LNode>();
            int iteration        = 0;
            foreach (LNode replacement in cases)
            {
                iteration++;
                bool tuple = replacement.Calls(S.Tuple) || replacement.Calls(S.Braces);
                int  count = tuple ? replacement.ArgCount : 1;
                if (replacements.Count != count)
                {
                    sink.Error(replacement, "iteration {0}: Expected {1} replacement items, got {2}", iteration, replacements.Count, count);
                    if (count < replacements.Count)
                    {
                        continue;                         // too few
                    }
                }
                for (int i = 0; i < replacements.Count; i++)
                {
                    replacements.InternalArray[i].B = tuple ? replacement.Args[i] : replacement;
                }

                if (body.Calls(S.Braces))
                {
                    foreach (LNode stmt in body.Args)
                    {
                        output.Add(ctx.Replace(stmt).Value);
                    }
                }
                else
                {
                    output.Add(ctx.Replace(body).Value);
                }
            }

            foreach (var r in replacements)
            {
                if (r.C == 0 && !r.A.Name.StartsWith("_"))
                {
                    sink.Write(Severity.Warning, var, "Replacement variable '{0}' was never used", r.A);
                }
            }

            return(body.With(S.Splice, output.ToVList()));
        }
Esempio n. 15
0
		static bool AttributesMatch(LNode candidate, LNode pattern, ref MMap<Symbol, LNode> captures, out RVList<LNode> unmatchedAttrs)
		{
			if (pattern.HasPAttrs())
				throw new NotImplementedException("TODO: attributes in patterns are not yet supported");
			unmatchedAttrs = candidate.Attrs;
			return true;
		}
Esempio n. 16
0
		static bool AttributesMatch(LNode candidate, LNode pattern, ref MMap<Symbol, LNode> captures, out VList<LNode> unmatchedAttrs)
		{
			if (pattern.HasPAttrs()) {
				unmatchedAttrs = LNode.List();
				return ListMatches(candidate.Attrs, pattern.Attrs, ref captures, ref unmatchedAttrs);
			} else {
				unmatchedAttrs = candidate.Attrs;
			}
			return true;
		}
Esempio n. 17
0
 internal static bool HasPAttrs(LNode node, Pedantics p)         // for use in expression context
 {
     return((p & Pedantics.IgnoreAttributesInOddPlaces) == 0 && node.HasPAttrs());
 }
Esempio n. 18
0
		static LNode AutoStripBraces(LNode node)
		{
			if (node.Calls(S.Braces, 1) && !node.HasPAttrs())
				return node.Args[0];
			return node;
		}
Esempio n. 19
0
        public static LNode unroll(LNode var, LNode cases, LNode body, IMessageSink sink)
        {
            if (!cases.Calls(S.Tuple) && !cases.Calls(S.Braces))
            {
                return(Reject(sink, cases, "static foreach: the right-hand side of 'in' should be a tuple"));
            }

            // Maps identifiers => replacements. The integer counts how many times replacement occurred.
            Triplet <Symbol, LNode, int>[] replacements = null;
            if (var.IsId && !var.HasPAttrs())
            {
                replacements = new Triplet <Symbol, LNode, int>[1] {
                    Pair.Create(var.Name, (LNode)LNode.Missing, 0)
                };
            }
            else
            {
                var vars = var.Args;
                if ((var.Calls(S.Tuple) || var.Calls(S.Braces)) && vars.All(a => a.IsId && !a.HasPAttrs()))
                {
                    replacements = new Triplet <Symbol, LNode, int> [vars.Count];
                    for (int i = 0; i < vars.Count; i++)
                    {
                        replacements[i].A = vars[i].Name;

                        // Check for duplicate names
                        for (int j = 0; j < i; j++)
                        {
                            if (replacements[i].A == replacements[j].A)
                            {
                                sink.Write(Severity.Error, vars[i], "unroll: duplicate name in the left-hand tuple");                                 // non-fatal
                            }
                        }
                    }
                }
                else
                {
                    return(Reject(sink, cases, "unroll: the left-hand side of 'in' should be a simple identifier or a tuple of simple identifiers."));
                }
            }

            ReplaceCtx ctx = new ReplaceCtx {
                Replacements = replacements
            };
            RWList <LNode> output = new RWList <LNode>();
            int iteration         = 0;
            foreach (LNode replacement in cases.Args)
            {
                iteration++;
                bool tuple = replacement.Calls(S.Tuple) || replacement.Calls(S.Braces);
                int  count = tuple ? replacement.ArgCount : 1;
                if (replacements.Length != count)
                {
                    sink.Write(Severity.Error, replacement, "unroll, iteration {0}: Expected {1} replacement items, got {2}", iteration, replacements.Length, count);
                    if (count < replacements.Length)
                    {
                        continue;                         // too few
                    }
                }
                for (int i = 0; i < replacements.Length; i++)
                {
                    replacements[i].B = tuple ? replacement.Args[i] : replacement;
                }

                if (body.Calls(S.Braces))
                {
                    foreach (LNode stmt in body.Args)
                    {
                        output.Add(ctx.Replace(stmt));
                    }
                }
                else
                {
                    output.Add(ctx.Replace(body));
                }
            }

            foreach (var r in replacements)
            {
                if (r.C == 0)
                {
                    sink.Write(Severity.Warning, r.B, "Replacement variable '{0}' was never used", r.A);
                }
            }

            return(body.With(S.Splice, output.ToRVList()));
        }