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); }
static LNode AutoStripBraces(LNode node) { if (node.Calls(S.Braces, 1) && !node.HasPAttrs()) { return(node.Args[0]); } return(node); }
internal static LNode UnwrapBraces(LNode node) { if (node.Calls(S.Braces, 1) && !node.HasPAttrs()) { return(node.Args[0]); } return(node); }
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); } } }
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()); }
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); }
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; }
// 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); }
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); }
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)); } }
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; }
// 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(); }
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())); }
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; }
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; }
internal static bool HasPAttrs(LNode node, Pedantics p) // for use in expression context { return((p & Pedantics.IgnoreAttributesInOddPlaces) == 0 && node.HasPAttrs()); }
static LNode AutoStripBraces(LNode node) { if (node.Calls(S.Braces, 1) && !node.HasPAttrs()) return node.Args[0]; return node; }
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())); }