static LNode ProcessArgContractAttributes(LNode fn, int argsIndex, CodeContractRewriter rw, bool isLambda = false) { LNode fnArgs = fn.Args[argsIndex]; if (fnArgs.CallsMin(isLambda ? S.Tuple : S.AltList, 1)) { return(fn.WithArgChanged(argsIndex, fnArgs.WithArgs(arg => { if (arg.HasAttrs) { return arg.WithAttrs(rw.Process(arg.Attrs, GetVarName(arg))); } return arg; }))); } else if (isLambda) { var arg = fnArgs; // just one argument if (arg.HasAttrs) { fn = fn.WithArgChanged(argsIndex, arg.WithAttrs(rw.Process(arg.Attrs, GetVarName(arg)))); } } return(fn); }
LNode ConvertVarDeclToRunSequence(VList <LNode> attrs, LNode varType, LNode varName, LNode initValue) { initValue = BubbleUpBlocks(initValue); varType = varType ?? F.Missing; LNode @ref; attrs = attrs.WithoutNodeNamed(S.Ref, out @ref); var varName_apos = varName.PlusAttr(_trivia_isTmpVar); if (@ref != null) { varName_apos = varName_apos.PlusAttr(@ref); } { LNode resultValue; VList <LNode> stmts; if (initValue.CallsMin((Symbol)"#runSequence", 1) && (resultValue = initValue.Args[initValue.Args.Count - 1]) != null) { stmts = initValue.Args.WithoutLast(1); var newVarDecl = LNode.Call(LNode.List(attrs), CodeSymbols.Var, LNode.List(varType, LNode.Call(CodeSymbols.Assign, LNode.List(varName, resultValue)))); return(initValue.WithArgs(stmts.Add(newVarDecl).Add(varName_apos))); } else { var newVarDecl = LNode.Call(LNode.List(attrs), CodeSymbols.Var, LNode.List(varType, LNode.Call(CodeSymbols.Assign, LNode.List(varName, initValue)))); return(LNode.Call((Symbol)"#runSequence", LNode.List(newVarDecl, varName_apos))); } } }
/// <summary>Returns Basis if it's a method signature; otherwise constructs a default signature.</summary> public LNode GetMethodSignature() { if (Basis != null && Basis.Calls(S.Fn) && Basis.ArgCount.IsInRange(3, 4)) { var parts = Basis.Args; if (parts.Count == 4) { parts.RemoveAt(3); } if (IsRecognizer) { parts[0] = F.Bool; } parts[1] = F.Id(Name); // remove OneLiner style to avoid suppresing newlines in output for one-line rules return(Basis.WithArgs(parts).SetStyle(Basis.Style & ~NodeStyle.OneLiner)); } else { var method = F.Fn(IsRecognizer ? F.Bool : F.Void, F.Id(Name), F.List()); if (IsPrivate == true) { method = F.Attr(F.Id(S.Private), method); } else if (IsStartingRule | IsToken) { method = F.Attr(F.Id(S.Public), method); } return(method); } }
LNode EliminateBlockExprsInExecStmt(LNode stmt) { if (!stmt.IsCall) { return(stmt); } { LNode cond; VList <LNode> blocks; if (stmt.Calls(CodeSymbols.Braces)) { return(stmt.WithArgs(EliminateBlockExprs(stmt.Args, false))); } else if (stmt.CallsMin(CodeSymbols.If, 1) && (cond = stmt.Args[0]) != null) { blocks = new VList <LNode>(stmt.Args.Slice(1)); return(ProcessBlockCallStmt(stmt, 1)); } else if (stmt.HasSpecialName && stmt.ArgCount >= 1 && stmt.Args.Last.Calls(S.Braces)) { return(ProcessBlockCallStmt(stmt, stmt.ArgCount - 1)); } else { stmt = BubbleUpBlocks(stmt); if (stmt.CallsMin(__runSequence, 1)) { return(stmt.Args.AsLNode(S.Splice)); } } } return(stmt); }
/// <summary>Returns Basis if it's a method signature; otherwise constructs a default signature.</summary> public LNode GetMethodSignature() { if (Basis != null && Basis.Calls(S.Fn) && Basis.ArgCount.IsInRange(3, 4)) { var parts = Basis.Args; if (parts.Count == 4) { parts.RemoveAt(3); } if (IsRecognizer) { parts[0] = F.Bool; } parts[1] = F.Id(Name); return(Basis.WithArgs(parts)); } else { var method = F.Fn(IsRecognizer ? F.Bool : F.Void, F.Id(Name), F.List()); if (IsPrivate) { method = F.Attr(F.Id(S.Private), method); } else if (IsStartingRule | IsToken) { method = F.Attr(F.Id(S.Public), method); } return(method); } }
// Creates a temporary for an LValue (left side of `=`, or `ref` parameter) // e.g. f(x).Foo becomes f(x_N).Foo, and `var x_N = x` is added to `stmtSequence`, // where N is a unique integer for the temporary variable. LNode MaybeCreateTemporaryForLValue(LNode expr, ref VList <LNode> stmtSequence) { { LNode _, lhs; if (expr.Calls(CodeSymbols.Dot, 2) && (lhs = expr.Args[0]) != null || expr.CallsMin(CodeSymbols.Of, 1) && (lhs = expr.Args[0]) != null) { return(expr.WithArgChanged(0, MaybeCreateTemporaryForLValue(lhs, ref stmtSequence))); } else if ((_ = expr) != null && !_.IsCall) { return(expr); } else { var args = expr.Args.ToWList(); int i = 0; if (expr.CallsMin(S.IndexBracks, 1) || expr.CallsMin(S.NullIndexBracks, 1)) { // Consider foo[i]. We cannot always store `foo` in a temporary, as // this may change the code's behavior in case `foo` is a struct. i = 1; } for (; i < args.Count; i++) { if (!args[i].IsLiteral && !args[i].Attrs.Contains(_trivia_isTmpVar)) { LNode tmpVarName; stmtSequence.Add(TempVarDecl(Context, args[i], out tmpVarName)); args[i] = tmpVarName.PlusAttr(_trivia_isTmpVar); } } return(expr.WithArgs(args.ToVList())); } } }
protected virtual LNode MakeSuperExpr(LNode lhs, ref LNode primary, RVList <LNode> rhs) { if (primary == null) { return(lhs); // an error should have been printed already } if (lhs == primary) { if (primary.BaseStyle == NodeStyle.Operator) { primary = F.Call(primary, rhs); } else { primary = lhs.WithArgs(lhs.Args.AddRange(rhs)); } MarkSpecial(primary); return(primary); } else { Debug.Assert(lhs != null && lhs.IsCall && lhs.ArgCount > 0); Debug.Assert(lhs.BaseStyle != NodeStyle.Special); int c = lhs.ArgCount - 1; LNode ce = MakeSuperExpr(lhs.Args[c], ref primary, rhs); return(lhs.WithArgChanged(c, ce)); } }
public static LNode of(LNode node, IMessageSink sink) { LNode kind; if (node.ArgCount == 2 && (kind = node.Args[0]).IsId) { if (kind.IsIdNamed(_array)) { return(node.WithArgChanged(0, kind.WithName(S.Array))); } if (kind.IsIdNamed(_opt)) { return(node.WithArgChanged(0, kind.WithName(S.QuestionMark))); } if (kind.IsIdNamed(_ptr)) { return(node.WithArgChanged(0, kind.WithName(S._Pointer))); } } else if (node.ArgCount == 3 && (kind = node.Args[0]).IsIdNamed(_array) && node.Args[1].IsLiteral) { return(node.WithArgs(kind.WithName(S.GetArrayKeyword((int)node.Args[1].Value)), node.Args[2])); } return(null); }
public static LNode Try(LNode node, IMacroContext context) { var a = node.Args.ToWList(); for (int i = 1; i < a.Count; i++) { var clause = a[i]; if (clause.Calls(S.Catch) || clause.Calls(__except)) { if (clause.ArgCount == 1) { a[i] = clause.WithArgs(F.Missing, F.Missing, a[i].Args[0]); } else if (clause.ArgCount == 2) { if (clause.Args[0].Calls(__when, 2)) { a[i] = clause.WithArgs(clause[0][0], clause[0][1], clause[1]); } else { a[i] = clause.WithArgs(clause[0], F.Missing, clause[1]); } } } } if (a.ToLNodeList() != node.Args) { return(node.WithArgs(a.ToVList())); } return(null); }
public static LNode priorityTestPCB(LNode node, IMessageSink sink) { if (node.ArgCount == 2) { return(node.WithArgs(node[1], node[0])); } return(null); }
public static LNode Namespace(LNode node, IMacroContext context) { if (node.ArgCount == 2 && !node.Args.Last.Calls(S.Braces)) { context.DropRemainingNodes = true; return(node.WithArgs(node.Args.Add(F.Braces(context.RemainingNodes)))); } return(null); }
// Given Foo(x, y, a = 1, c = 2), extracts { a = 1, c = 2 } to a separate list private static LNodeList SeparateAttributeSetters(ref LNode attribute) { LNodeList setters = LNode.List(); while (attribute.Args.LastOrDefault()?.Calls(S.Assign) == true) { setters.Insert(0, attribute.Args.Last); attribute = attribute.WithArgs(attribute.Args.WithoutLast(1)); } return(setters); }
public static LNode @case(LNode node, IMessageSink sink) { if (node.ArgCount == 1) { return(node.WithTarget(S.Case)); } else if (node.ArgCount == 2 && node.Args[1].Calls(S.Braces)) { return(F.Call(S.Splice, new VList <LNode>(node.WithArgs(node.Args.First(1)), node.Args[1]))); } return(null); }
public static LNode runSequence(LNode node, IMacroContext context) { if (context.Parent.Calls(S.Braces)) { if (node.ArgCount == 1 && node.Args[0].Calls(S.Braces)) { return(node.WithArgs(node.Args[0].Args)); } return(node.WithTarget(S.Splice)); } return(Reject(context, node, "#useVarDeclExpressions is required to make #runSequence work")); }
LNode EliminateSequenceExpressionsInExecStmt(LNode stmt) { { LNode block, collection, cond, init, initValue, loopVar, name, tmp_11, tmp_12, tmp_13, type, varType; LNodeList attrs, incs, inits; if (stmt.Calls(CodeSymbols.Braces)) { return(stmt.WithArgs(EliminateSequenceExpressions(stmt.Args, false))); } else if ((attrs = stmt.Attrs).IsEmpty | true && stmt.Calls(CodeSymbols.Fixed, 2) && (init = stmt.Args[0]) != null && (block = stmt.Args[1]) != null) { init = EliminateSequenceExpressionsInExecStmt(init); block = EliminateSequenceExpressionsInChildStmt(block); if (UnwrapRunSequence(ref init, out var initSeq)) { return(LNode.Call(LNode.List(attrs), CodeSymbols.Braces, LNode.List().AddRange(initSeq.WithoutLast(1)).Add(LNode.Call(CodeSymbols.Fixed, LNode.List(initSeq.Last, block)))).SetStyle(NodeStyle.StatementBlock)); } else { return(stmt.WithArgs(init, block)); } }
LNode ESEInTryStmt(LNode stmt) { var args = stmt.Args.ToWList(); args[0] = EliminateSequenceExpressionsInChildStmt(args[0]); for (int i = 1; i < args.Count; i++) { var part = args[i]; if (part.Calls(S.Finally, 1) || part.Calls(S.Catch, 3)) { int lasti = part.ArgCount - 1; args[i] = part.WithArgChanged(lasti, EliminateSequenceExpressionsInChildStmt(part.Args[lasti])); } } return(stmt.WithArgs(args.ToVList())); }
public static LNode IfUnless(LNode node, IMacroContext context) { // #if(cond1, {...}, #elsif(cond2, {...}), #else({...})); // #unless(cond1, {...}, #else({...})); var args = node.Args; bool isUnless = node.Calls(__unless) && args.Count >= 2; if (isUnless) { node = node.WithArgChanged(0, F.Call(S.Not, args[0])); } if (args.Count >= 3) { LNode clause = args[2]; bool isElseIf = clause.Calls(__elsif) || clause.Calls(__elseif); if (clause.Calls(S.Else, 2) && clause[0].Calls("if", 1)) { // Although it's possible to accept "else if (foo)", "else if foo {...}" // would be parsed quite wrongly as "else (if foo {...})"! So issue a // warning to discourage the bad habit of writing "else if". context.Warning(clause[0].Target, "'else if' should be one word (elsif or elseif)"); isElseIf = true; clause = clause.WithArgChanged(0, clause[0][0]); } if (isElseIf) { var first3 = args.WithoutLast(args.Count - 3); // node: #if(cond1, {...}, #elsif(cond2, {...}), #elsif(cond3, {...}), #else({...})) // ^^^^^^^clause^^^^^^^ // ^^^^^^^^^^^^first3^^^^^^^^^^^^^^^^ // returns: #if(cond1, {...}, #if(cond2, {...}, #elsif(cond3, {...}), #else({...}))) LNode @else = clause.WithTarget(S.If); if (args.Count > 3) { @else = @else.WithArgs(@else.Args.AddRange(args.Slice(3))); } return(node.WithArgs(first3.WithoutLast(1).Add(@else))); } if (clause.Calls(S.Else, 1) && args.Count == 3) { return(node.WithArgChanged(2, clause[0])); } } return(isUnless ? node : null); }
/// <summary>Creates the default method definition wrapped around the body /// of the rule, which was generated by the caller. Returns <see cref="Basis"/> /// with the specified new method body. If Basis is null, a simple default /// method signature is used, e.g. <c>public void R() {...}</c> where R is /// the rule name.</summary> /// <param name="methodBody">The parsing code that was generated for this rule.</param> /// <returns>A method.</returns> public virtual LNode CreateRuleMethod(Rule rule, LNodeList methodBody) { LNode method = rule.GetMethodSignature(); var parts = method.Args.ToWList(); if (parts[0].IsIdNamed(S.Missing)) { parts[0] = F.Id(rule.Name); } Debug.Assert(parts.Count == 3); if (rule.IsRecognizer) { methodBody.Add(F.Call(S.Return, F.True)); } parts.Add(F.OnNewLine(F.Braces(methodBody))); return(method.WithArgs(parts.ToLNodeList())); }
/// <summary>Creates the default method definition to wrap around the body /// of the rule, which has already been generated. Returns <see cref="Basis"/> /// with the specified new method body. If Basis is null, a simple default /// method signature is used, e.g. <c>public void R() {...}</c> where R is /// the rule name.</summary> /// <param name="methodBody">The parsing code that was generated for this rule.</param> /// <returns>A method.</returns> public LNode CreateMethod(RVList <LNode> methodBody) { LNode method = GetMethodSignature(); var parts = method.Args.ToRWList(); if (parts[0].IsIdNamed(S.Missing)) { parts[0] = F.Id(Name); } Debug.Assert(parts.Count == 3); if (IsRecognizer) { methodBody.Add(F.Call(S.Return, F.True)); } parts.Add(F.Braces(methodBody)); return(method.WithArgs(parts.ToRVList())); }
LNode BubbleUpBlocks(LNode expr) { if (!expr.IsCall) { return(expr); } { LNode tmp_3 = null, value, varName, varType = null; VList <LNode> args, attrs; if (expr.Calls((Symbol)"#runSequence")) { args = expr.Args; if (args.Count == 1 && args[0].Calls(S.Braces)) { return(expr.WithArgs(args[0].Args)); } return(expr); } else if (expr.Calls(CodeSymbols.Braces)) { Context.Write(Severity.Error, expr, "A braced block is not supported directly within an expression. Did you mean to use `#runSequence {...}`?"); return(expr); } else if ((attrs = expr.Attrs).IsEmpty | true && attrs.NodeNamed(S.Out) != null && expr.Calls(CodeSymbols.Var, 2) && (varType = expr.Args[0]) != null && (varName = expr.Args[1]) != null && varName.IsId) { if (varType.IsIdNamed(S.Missing)) { Context.Write(Severity.Error, expr, "The data type of this variable declaration must be stated explicitly."); } return(LNode.Call((Symbol)"#runSequence", LNode.List(expr.WithoutAttrNamed(S.Out), varName))); } else if ((attrs = expr.Attrs).IsEmpty | true && expr.Calls(CodeSymbols.Var, 2) && (varType = expr.Args[0]) != null && (tmp_3 = expr.Args[1]) != null && tmp_3.Calls(CodeSymbols.Assign, 2) && (varName = tmp_3.Args[0]) != null && (value = tmp_3.Args[1]) != null || (attrs = expr.Attrs).IsEmpty | true && expr.Calls(CodeSymbols.ColonColon, 2) && (value = expr.Args[0]) != null && IsQuickBindLhs(value) && (varName = expr.Args[1]) != null && varName.IsId) { return(ConvertVarDeclToRunSequence(attrs, varType ?? F.Missing, varName, value)); } } if (expr.IsCall) { return(BubbleUp_GeneralCall(expr)); } else { return(expr); } }
LNode ESEInTryStmt(LNode stmt) { var args = stmt.Args.ToWList(); // Process `try` part args[0] = EliminateSequenceExpressionsInChildStmt(args[0]); // Process `catch` and `finally` clauses (`when` clause not supported) for (int i = 1; i < args.Count; i++) { var part = args[i]; if (part.Calls(S.Finally, 1) || part.Calls(S.Catch, 3)) { int lasti = part.ArgCount - 1; args[i] = part.WithArgChanged(lasti, EliminateSequenceExpressionsInChildStmt(part.Args[lasti])); } } return(stmt.WithArgs(args.ToVList())); }
Pair <VList <LNode>, LNode> BubbleUp_GeneralCall2(LNode expr) { var target = expr.Target; var args = expr.Args; var combinedSequence = LNode.List(); target = BubbleUpBlocks(target); if (target.CallsMin(__runSequence, 1)) { combinedSequence = target.Args.WithoutLast(1); expr = expr.WithTarget(target.Args.Last); } args = args.SmartSelect(arg => BubbleUpBlocks(arg)); int lastRunSeq = args.LastIndexWhere(a => a.CallsMin(__runSequence, 1)); if (lastRunSeq >= 0) { if (lastRunSeq > 0 && (args.Count == 2 && (target.IsIdNamed(S.And) || target.IsIdNamed(S.Or)) || args.Count == 3 && target.IsIdNamed(S.QuestionMark))) { Context.Write(Severity.Error, expr, "#useVarDeclExpressions is not designed to support sequences or variable declarations on the right-hand side of the `&&`, `||` or `?` operators. The generated code may be incorrect."); } var argsW = args.ToList(); for (int i = lastRunSeq - 1; i >= 0; i--) { if (!argsW[i].CallsMin(__runSequence, 1) && !argsW[i].IsLiteral) { LNode tmpVarName, tmpVarDecl = TempVarDecl(argsW[i], out tmpVarName); argsW[i] = LNode.Call((Symbol)"#runSequence", LNode.List(tmpVarDecl, tmpVarName)); } } for (int i = 0; i <= lastRunSeq; i++) { LNode arg = argsW[i]; if (arg.CallsMin(__runSequence, 1)) { combinedSequence.AddRange(arg.Args.WithoutLast(1)); argsW[i] = arg.Args.Last; } } expr = expr.WithArgs(LNode.List(argsW)); } return(Pair.Create(combinedSequence, expr)); }
LNode ApplyMacrosToChildrenOf(LNode node, int maxExpansions) { if (maxExpansions <= 0) { return(null); } bool changed = false; VList <LNode> old; var newAttrs = ApplyMacrosToList(old = node.Attrs, maxExpansions, true); _s.IsAttribute = false; if (newAttrs != old) { node = node.WithAttrs(newAttrs); changed = true; } LNode target = node.Target; if (target != null && target.Kind != LNodeKind.Literal) { DList <Pair <LNode, int> > _ = null; LNode newTarget = ApplyMacros(target, maxExpansions, true, true, ref _); 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, false); if (newArgs != old) { node = node.WithArgs(newArgs); changed = true; } return(changed ? node : null); }
/// <summary>See <see cref="IPGCodeGenHelper.CreateTryWrapperForRecognizer"/> for more information.</summary> public LNode CreateTryWrapperForRecognizer() { Debug.Assert(TryWrapperName != null); LNode method = GetMethodSignature(); LNode retType = method.Args[0], name = method.Args[1], args = method.Args[2]; RVList <LNode> forwardedArgs = ForwardedArgList(args); LNode lookahead = F.Id("lookaheadAmt"); Debug.Assert(args.Calls(S.List)); args = args.WithArgs(args.Args.Insert(0, F.Var(F.Int32, lookahead))); LNode body = F.Braces( F.Call(S.UsingStmt, F.Call(S.New, F.Call(SavePosition, F.@this, lookahead)), F.Call(S.Return, F.Call(name, forwardedArgs))) ); return(method.WithArgs(retType, TryWrapperName, args, body)); }
LNode ProcessBlockCallStmt(LNode stmt, int childStmtsStartAt) { List <LNode> childStmts = stmt.Slice(childStmtsStartAt).ToList(); LNode partialStmt = stmt.WithArgs(stmt.Args.First(childStmtsStartAt)); VList <LNode> advanceSequence; if (ProcessBlockCallStmt(ref partialStmt, out advanceSequence, childStmts)) { stmt = partialStmt.PlusArgs(childStmts); if (advanceSequence.Count != 0) { return(LNode.Call(CodeSymbols.Braces, LNode.List().AddRange(advanceSequence).Add(stmt)).SetStyle(NodeStyle.Statement)); } return(stmt); } else { return(stmt); } }
/// <summary>See <see cref="IPGCodeGenHelper.CreateTryWrapperForRecognizer"/> for more information.</summary> public LNode CreateTryWrapperForRecognizer(Rule rule) { Debug.Assert(rule.TryWrapperName != null); LNode method = rule.GetMethodSignature(); LNode retType = method.Args[0], name = method.Args[1], args = method.Args[2]; VList <LNode> forwardedArgs = ForwardedArgList(args); LNode lookahead = F.Id("lookaheadAmt"); Debug.Assert(args.Calls(S.AltList)); args = args.WithArgs(args.Args.Insert(0, F.Var(F.Int32, lookahead))); LNode savePosition = ApiType(F.Id(SavePosition)); LNode @this = InputSource ?? F.@this; LNode body = F.Braces( F.Call(S.UsingStmt, F.Call(S.New, F.Call(savePosition, @this, lookahead)), F.Call(S.Return, F.Call(name, forwardedArgs))) ); return(method.WithArgs(retType, rule.TryWrapperName, args, body)); }
public void PrependStmtsToGetterOrSetter(ref LNode braces, int getterIndex, LNode getter) { if (!PrependStmts.IsEmpty) { if (getter.ArgCount == 0) { Context.Write(Severity.Error, getter, "`{0}`: contracts cannot be applied to autoproperties. " + "A body is required, but you can use [field] on the property to add a body to `get` and `set` automatically.", getter); return; } else if (getter.ArgCount == 1) { var body = getter.Args[0]; if (!body.Calls(S.Braces)) { body = LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(body)))).SetStyle(NodeStyle.Statement); } body = body.WithArgs(body.Args.InsertRange(0, PrependStmts)); getter = getter.WithArgs(body); braces = braces.WithArgChanged(getterIndex, getter); } } }
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); }
public static LNode VarDecl(LNode node, IMacroContext context) { var a = node.Args; if (a.Count == 2) { LNode name = a[0], type = a[1], nameAssignment = name; if (type.Calls(S.Assign, 2)) { nameAssignment = type.WithArgs(name, type[1]); type = type[0]; } if (name.IsId) { return(node.With(S.Var, type, nameAssignment).SetBaseStyle(NodeStyle.Default)); } else { context.Write(Severity.Note, node, "Unrecognized variable declaration syntax"); return(null); } } return(null); }
public static LNode priorityTestPCB(LNode node, IMessageSink sink) { if (node.ArgCount == 2) return node.WithArgs(node[1], node[0]); return null; }
public static LNode @case(LNode node, IMessageSink sink) { if (node.ArgCount == 1) return node.WithTarget(S.Case); else if (node.ArgCount == 2 && node.Args[1].Calls(S.Braces)) return F.Call(S.Splice, new RVList<LNode>(node.WithArgs(node.Args.First(1)), node.Args[1])); return null; }
void FinishPrimaryExpr(ref LNode e) { TokenType la1; // Line 541: greedy( (TT.ColonColon|TT.Dot|TT.PtrArrow|TT.QuickBind) AtomOrTypeParamExpr / PrimaryExpr_NewStyleCast / TT.LParen TT.RParen | TT.LBrack TT.RBrack | TT.QuestionMark TT.LBrack TT.RBrack | TT.IncDec | &(TParams ~(TT.ContextualKeyword|TT.Id)) ((TT.LT|TT.Not) | TT.Dot TT.LBrack) => TParams | BracedBlockOrTokenLiteral )* for (;;) { switch (LA0) { case TT.Dot: { if (Try_FinishPrimaryExpr_Test0(0)) { switch (LA(1)) { case TT.At: case TT.Base: case TT.Checked: case TT.ContextualKeyword: case TT.Default: case TT.Delegate: case TT.Dot: case TT.Id: case TT.Is: case TT.LBrace: case TT.Literal: case TT.LParen: case TT.New: case TT.Operator: case TT.Sizeof: case TT.Substitute: case TT.This: case TT.TypeKeyword: case TT.Typeof: case TT.Unchecked: goto match1; case TT.LBrack: TParams(false, ref e); break; default: goto stop; } } else { switch (LA(1)) { case TT.At: case TT.Base: case TT.Checked: case TT.ContextualKeyword: case TT.Default: case TT.Delegate: case TT.Dot: case TT.Id: case TT.Is: case TT.LBrace: case TT.Literal: case TT.LParen: case TT.New: case TT.Operator: case TT.Sizeof: case TT.Substitute: case TT.This: case TT.TypeKeyword: case TT.Typeof: case TT.Unchecked: goto match1; default: goto stop; } } } break; case TT.ColonColon: case TT.PtrArrow: case TT.QuickBind: { switch (LA(1)) { case TT.At: case TT.Base: case TT.Checked: case TT.ContextualKeyword: case TT.Default: case TT.Delegate: case TT.Dot: case TT.Id: case TT.Is: case TT.LBrace: case TT.Literal: case TT.LParen: case TT.New: case TT.Operator: case TT.Sizeof: case TT.Substitute: case TT.This: case TT.TypeKeyword: case TT.Typeof: case TT.Unchecked: goto match1; default: goto stop; } } case TT.LParen: { if (Down(0) && Up(LA0 == TT.As || LA0 == TT.Using || LA0 == TT.PtrArrow)) { la1 = LA(1); if (la1 == TT.RParen) e = PrimaryExpr_NewStyleCast(e); else goto stop; } else { la1 = LA(1); if (la1 == TT.RParen) { var lp = MatchAny(); var rp = MatchAny(); // line 545 e = F.Call(e, ExprListInside(lp), e.Range.StartIndex, rp.EndIndex); } else goto stop; } } break; case TT.LBrack: { la1 = LA(1); if (la1 == TT.RBrack) { var lb = MatchAny(); var rb = MatchAny(); var list = new VList<LNode> { e }; e = F.Call(S.IndexBracks, AppendExprsInside(lb, list), e.Range.StartIndex, rb.EndIndex, lb.StartIndex, lb.EndIndex); } else goto stop; } break; case TT.QuestionMark: { la1 = LA(1); if (la1 == TT.LBrack) { var t = MatchAny(); var lb = MatchAny(); var rb = Match((int) TT.RBrack); // line 563 e = F.Call(S.NullIndexBracks, e, F.List(ExprListInside(lb)), e.Range.StartIndex, rb.EndIndex, t.StartIndex, lb.EndIndex); } else goto stop; } break; case TT.IncDec: { var t = MatchAny(); // line 565 e = F.Call(t.Value == S.PreInc ? S.PostInc : S.PostDec, e, e.Range.StartIndex, t.EndIndex, t.StartIndex, t.EndIndex); } break; case TT.LT: case TT.Not: { if (Try_FinishPrimaryExpr_Test0(0)) TParams(false, ref e); else goto stop; } break; case TT.At: case TT.LBrace: { la1 = LA(1); if (la1 == TT.LBrace || la1 == TT.LBrack || la1 == TT.RBrace) { var bb = BracedBlockOrTokenLiteral(); // line 569 if ((!e.IsCall || e.BaseStyle == NodeStyle.Operator)) { e = F.Call(e, bb, e.Range.StartIndex, bb.Range.EndIndex); } else { e = e.WithArgs(e.Args.Add(bb)).WithRange(e.Range.StartIndex, bb.Range.EndIndex); } } else goto stop; } break; default: goto stop; } continue; match1: { var op = MatchAny(); var rhs = AtomOrTypeParamExpr(); // line 542 e = F.Call((Symbol) op.Value, e, rhs, e.Range.StartIndex, rhs.Range.EndIndex, op.StartIndex, op.EndIndex, NodeStyle.Operator); } } stop:; }
public static LNode runSequence(LNode node, IMacroContext context) { if (context.Parent.Calls(S.Braces)) { if (node.ArgCount == 1 && node.Args[0].Calls(S.Braces)) return node.WithArgs(node.Args[0].Args); return node.WithTarget(S.Splice); } return Reject(context, node, "#useVarDeclExpressions is required to make #runSequence work"); }
private static bool DetectSetOrCreateMember(LNode arg, out Symbol relevantAttribute, out Symbol fieldName, out Symbol paramName, out LNode newArg, out LNode propOrFieldDecl) { relevantAttribute = null; fieldName = null; paramName = null; newArg = null; propOrFieldDecl = null; LNode _, type, name, defaultValue, propArgs; if (EcsValidators.IsPropertyDefinition(arg, out type, out name, out propArgs, out _, out defaultValue) && propArgs.ArgCount == 0) { // #property(Type, Name<T>, {...}) relevantAttribute = S.Property; fieldName = EcsNodePrinter.KeyNameComponentOf(name); paramName = ChooseArgName(fieldName); if (defaultValue != null) { // initializer is Args[4] newArg = LNode.Call(S.Var, LNode.List(type, F.Assign(paramName, defaultValue)), arg); propOrFieldDecl = arg.WithArgs(arg.Args.First(4)); } else { newArg = LNode.Call(S.Var, LNode.List(type, F.Id(paramName)), arg); propOrFieldDecl = arg; } DSOCM_DistributeAttributes(arg.Attrs, ref newArg, ref propOrFieldDecl); return true; } else if (IsVar(arg, out type, out paramName, out defaultValue)) { int a_i = 0; foreach (var attr in arg.Attrs) { if (attr.IsId) { var a = attr.Name; if (a == _set || FieldCreationAttributes.Contains(a)) { relevantAttribute = a; fieldName = paramName; paramName = ChooseArgName(fieldName); if (a == _set) { newArg = F.Var(type, paramName, defaultValue).WithAttrs(arg.Attrs.Without(attr)); } else { // in case of something like "[A] public params T arg = value", // assume that "= value" represents a default value, not a field // initializer. Most attributes stay on the argument. newArg = arg.WithArgChanged(1, defaultValue != null ? F.Assign(paramName, defaultValue) : F.Id(paramName)); propOrFieldDecl = LNode.Call(S.Var, LNode.List(type, F.Id(fieldName)), arg); DSOCM_DistributeAttributes(arg.Attrs, ref newArg, ref propOrFieldDecl); } break; } } a_i++; } return newArg != null; } return false; }
public static LNode SetOrCreateMember(LNode fn, IMessageSink sink) { // Expecting #fn(Type, Name, #(args), {body}) if (fn.ArgCount < 3 || !fn.Args[2].Calls(S.AltList)) return null; var args = fn.Args[2].Args; VList<LNode> propOrFieldDecls = VList<LNode>.Empty; Dictionary<Symbol, LNode> assignments = null; for (int i = 0; i < args.Count; i++) { var arg = args[i]; Symbol relevantAttribute, fieldName, paramName; LNode plainArg, propOrFieldDecl; if (DetectSetOrCreateMember(arg, out relevantAttribute, out fieldName, out paramName, out plainArg, out propOrFieldDecl)) { if (fn.ArgCount < 4) return Reject(sink, arg, Localize.Localized("'{0}': to set or create a field or property, the method must have a body in braces {{}}.", relevantAttribute)); args[i] = plainArg; assignments = assignments ?? new Dictionary<Symbol, LNode>(); assignments[fieldName] = F.Id(paramName); if (propOrFieldDecl != null) propOrFieldDecls.Add(propOrFieldDecl); } } if (assignments != null) // if this macro has been used... { var parts = fn.Args; parts[2] = parts[2].WithArgs(args); var body = parts[3]; // Ensure the method has a normal braced body if (!body.Calls(S.Braces)) { if (parts[0].IsIdNamed(S.Void)) body = F.Braces(body); else body = F.Braces(F.Call(S.Return, body)); } // In case one constructor calls another, we have to ensure that the // assignments are inserted _after_ that call, and if the constructor // call refers to properties or fields that will be set, we must remap // those references onto parameters, e.g. // this(public int X) { base(X); } => this(int x) { base(x); X = x; } var bodyStmts = body.Args; int indexAtWhichToDoAssignments = 0; if (fn.Calls(S.Constructor)) { LNode baseCall = bodyStmts[0, LNode.Missing]; if (baseCall.Calls(S.Base) || baseCall.Calls(S.This)) { bodyStmts[0] = baseCall.ReplaceRecursive(n => { LNode param; if (n.IsId && assignments.TryGetValue(n.Name, out param)) return param; return null; }); indexAtWhichToDoAssignments = 1; } } // Insert assignment statements parts[3] = body.WithArgs(bodyStmts.InsertRange(indexAtWhichToDoAssignments, assignments.Select(p => { if (p.Key == p.Value.Name) return F.Call(S.Assign, F.Dot(F.@this, F.Id(p.Key)), p.Value); else return F.Call(S.Assign, F.Id(p.Key), p.Value); }).ToList())); fn.Style &= ~NodeStyle.OneLiner; foreach (var p in parts) p.Style &= ~NodeStyle.OneLiner; // Return output code fn = fn.WithArgs(parts); if (propOrFieldDecls.IsEmpty) return fn; else { propOrFieldDecls.Add(fn); return F.Call(S.Splice, propOrFieldDecls); } } return null; }
public static LNode SetOrCreateMember(LNode fn, IMessageSink sink) { // Expecting #fn(Type, Name, #(args), {body}) if (fn.ArgCount < 3 || !fn.Args[2].Calls(S.AltList)) return null; var args = fn.Args[2].Args; LNode body = null; RVList<LNode> createStmts = RVList<LNode>.Empty; RVList<LNode> setStmts = RVList<LNode>.Empty; for (int i = 0; i < args.Count; i++) { var arg = args[i]; Symbol a = S.Property; Symbol fieldName = null; Symbol paramName = null; LNode plainArg = null; LNode createStmt = null; if (arg.Calls(S.Property)) { // #property(Type, Name<T>, {...}) var name = arg.Args[1]; fieldName = Ecs.EcsNodePrinter.KeyNameComponentOf(name); paramName = ChooseArgName(fieldName); plainArg = F.Var(arg.Args[0], paramName); createStmt = arg; } else { LNode type, defaultValue; if (IsVar(arg, out type, out paramName, out defaultValue)) { int a_i = 0; foreach (var attr in arg.Attrs) { if (attr.IsId) { a = attr.Name; if (a == _set || a == S.Public || a == S.Internal || a == S.Protected || a == S.Private || a == S.ProtectedIn || a == S.Static || a == S.Partial) { fieldName = paramName; paramName = ChooseArgName(fieldName); if (a == _set) { plainArg = F.Var(type, paramName, defaultValue).WithAttrs(arg.Attrs.RemoveAt(a_i)); } else { // in case of something like "[A] public params T arg = value", // assume that "= value" represents a default value, not a field // initializer, that [A] belongs on the field, except `params` // which stays on the argument. plainArg = F.Var(type, paramName, defaultValue); createStmt = arg; if (arg.Args[1].Calls(S.Assign, 2)) createStmt = arg.WithArgChanged(1, arg.Args[1].Args[0]); int i_params = arg.Attrs.IndexWithName(S.Params); if (i_params > -1) { plainArg = plainArg.PlusAttr(arg.Attrs[i_params]); createStmt = createStmt.WithAttrs(createStmt.Attrs.RemoveAt(i_params)); } } break; } } a_i++; } } } if (plainArg != null) { if (body == null) { if (fn.ArgCount < 4 || !fn.Args[3].Calls(S.Braces)) return Reject(sink, arg, Localize.From("'{0}': to set or create a field or property, the method must have a body in braces {{}}.", a)); body = fn.Args[3]; } args[i] = plainArg; LNode assignment; if (fieldName == paramName) assignment = F.Call(S.Assign, F.Dot(F.@this, F.Id(fieldName)), F.Id(paramName)); else assignment = F.Call(S.Assign, F.Id(fieldName), F.Id(paramName)); setStmts.Add(assignment); if (createStmt != null) createStmts.Add(createStmt); } } if (body != null) // if this macro has been used... { var parts = fn.Args; parts[2] = parts[2].WithArgs(args); parts[3] = body.WithArgs(body.Args.InsertRange(0, setStmts)); fn = fn.WithArgs(parts); if (createStmts.IsEmpty) return fn; else { createStmts.Add(fn); return F.Call(S.Splice, createStmts); } } return null; }
LNode ProcessBlockCallStmt(LNode stmt, int childStmtsStartAt) { List<LNode> childStmts = stmt.Args.Slice(childStmtsStartAt).ToList(); LNode partialStmt = stmt.WithArgs(stmt.Args.First(childStmtsStartAt)); VList<LNode> advanceSequence; if (ProcessBlockCallStmt2(ref partialStmt, out advanceSequence, childStmts)) { stmt = partialStmt.PlusArgs(childStmts); if (advanceSequence.Count != 0) return LNode.Call(CodeSymbols.Braces, LNode.List().AddRange(advanceSequence).Add(stmt)).SetStyle(NodeStyle.Statement); return stmt; // only the child statements changed } else return stmt; // no changes }
public LNode EliminateSequenceExpressions(LNode stmt, bool isDeclContext) { LNode retType, name, argList, bases, body, initValue; if (EcsValidators.SpaceDefinitionKind(stmt, out name, out bases, out body) != null) { // Space definition: class, struct, etc. return body == null ? stmt : stmt.WithArgChanged(2, EliminateSequenceExpressions(body, true)); } else if (EcsValidators.MethodDefinitionKind(stmt, out retType, out name, out argList, out body, true) != null) { // Method definition return body == null ? stmt : stmt.WithArgChanged(3, EliminateSequenceExpressionsInLambdaExpr(body, retType)); } else if (EcsValidators.IsPropertyDefinition(stmt, out retType, out name, out argList, out body, out initValue)) { // Property definition stmt = stmt.WithArgChanged(3, body.WithArgs(part => { if (part.ArgCount == 1 && part[0].Calls(S.Braces)) part = part.WithArgChanged(0, EliminateSequenceExpressions(part[0], false)); return part; })); if (initValue != null) { var initMethod = EliminateRunSeqFromInitializer(retType, name, ref initValue); if (initMethod != null) { stmt = stmt.WithArgChanged(4, initValue); return LNode.Call((Symbol) "#runSequence", LNode.List(stmt, initMethod)); } } return stmt; } else if (stmt.Calls(CodeSymbols.Braces)) { return stmt.WithArgs(EliminateSequenceExpressions(stmt.Args, isDeclContext)); } else if (!isDeclContext) { return EliminateSequenceExpressionsInExecStmt(stmt); } else if (stmt.CallsMin(S.Var, 2)) { // Eliminate blocks from field member var results = new List<LNode> { stmt }; var vars = stmt.Args; var varType = vars[0]; for (int i = 1; i < vars.Count; i++) { var @var = vars[i]; if (@var.Calls(CodeSymbols.Assign, 2) && (name = @var.Args[0]) != null && (initValue = @var.Args[1]) != null) { var initMethod = EliminateRunSeqFromInitializer(varType, name, ref initValue); if (initMethod != null) { results.Add(initMethod); vars[i] = vars[i].WithArgChanged(1, initValue); } } } if (results.Count > 1) { results[0] = stmt.WithArgs(vars); return LNode.List(results).AsLNode(__numrunSequence); } return stmt; } else return stmt; }
// Creates a temporary for an LValue (left side of `=`, or `ref` parameter) // e.g. f(x).Foo becomes f(x_N).Foo, and `var x_N = x` is added to `stmtSequence`, // where N is a unique integer for the temporary variable. LNode MaybeCreateTemporaryForLValue(LNode expr, ref VList<LNode> stmtSequence) { { LNode _, lhs; if (expr.Calls(CodeSymbols.Dot, 2) && (lhs = expr.Args[0]) != null || expr.CallsMin(CodeSymbols.Of, 1) && (lhs = expr.Args[0]) != null) return expr.WithArgChanged(0, MaybeCreateTemporaryForLValue(lhs, ref stmtSequence)); else if ((_ = expr) != null && !_.IsCall) return expr; else { var args = expr.Args.ToWList(); int i = 0; if (expr.CallsMin(S.IndexBracks, 1) || expr.CallsMin(S.NullIndexBracks, 1)) { // Consider foo[i]. We cannot always store `foo` in a temporary, as // this may change the code's behavior in case `foo` is a struct. i = 1; } for (; i < args.Count; i++) { if (!args[i].IsLiteral && !args[i].Attrs.Contains(_trivia_isTmpVar)) { LNode tmpVarName; stmtSequence.Add(TempVarDecl(Context, args[i], out tmpVarName)); args[i] = tmpVarName.PlusAttr(_trivia_isTmpVar); } } return expr.WithArgs(args.ToVList()); } } }
public LNode EliminateBlockExprs(LNode stmt, bool isDeclContext) { LNode retType, name, argList, bases, body, initValue; if (EcsValidators.SpaceDefinitionKind(stmt, out name, out bases, out body) != null) { return(body == null ? stmt : stmt.WithArgChanged(2, EliminateBlockExprs(body, true))); } else if (EcsValidators.MethodDefinitionKind(stmt, out retType, out name, out argList, out body, true) != null) { return(body == null ? stmt : stmt.WithArgChanged(3, EliminateBlockExprs(body, false))); } else if (EcsValidators.IsPropertyDefinition(stmt, out retType, out name, out argList, out body, out initValue)) { stmt = stmt.WithArgChanged(3, EliminateBlockExprs(body, false)); if (initValue != null) { var initMethod = EliminateRunSeqFromInitializer(retType, name, ref initValue); if (initMethod != null) { stmt = stmt.WithArgChanged(4, initValue); return(LNode.Call(CodeSymbols.Splice, LNode.List(stmt, initMethod))); } } return(stmt); } else if (!isDeclContext) { return(EliminateBlockExprsInExecStmt(stmt)); } else if (stmt.CallsMin(S.Var, 2)) { var results = new List <LNode> { stmt }; var vars = stmt.Args; var varType = vars[0]; for (int i = 1; i < vars.Count; i++) { { var tmp_1 = vars[i]; if (tmp_1.Calls(CodeSymbols.Assign, 2) && (name = tmp_1.Args[0]) != null && (initValue = tmp_1.Args[1]) != null) { var initMethod = EliminateRunSeqFromInitializer(varType, name, ref initValue); if (initMethod != null) { results.Add(initMethod); vars[i] = vars[i].WithArgChanged(1, initValue); } } } } if (results.Count > 1) { results[0] = stmt.WithArgs(vars); return(LNode.List(results).AsLNode(S.Splice)); } return(stmt); } else { return(stmt); } }
LNode EliminateSequenceExpressionsInExecStmt(LNode stmt) { { LNode block, collection, cond, init, initValue, loopVar, name, tmp_11, tmp_12, type; VList<LNode> attrs, incs, inits; if (stmt.Calls(CodeSymbols.Braces)) return stmt.WithArgs(EliminateSequenceExpressions(stmt.Args, false)); else if (stmt.CallsMin(CodeSymbols.If, 1) || stmt.Calls(CodeSymbols.UsingStmt, 2) || stmt.Calls(CodeSymbols.Lock, 2) || stmt.Calls(CodeSymbols.Switch, 2) && stmt.Args[1].Calls(CodeSymbols.Braces)) return ProcessBlockCallStmt(stmt, 1); else if ((attrs = stmt.Attrs).IsEmpty | true && stmt.Calls(CodeSymbols.Fixed, 2) && (init = stmt.Args[0]) != null && (block = stmt.Args[1]) != null) { init = EliminateSequenceExpressionsInExecStmt(init); block = EliminateSequenceExpressionsInChildStmt(block); if (init.CallsMin(__numrunSequence, 1)) { return LNode.Call(LNode.List(attrs), CodeSymbols.Braces, LNode.List().AddRange(init.Args.WithoutLast(1)).Add(LNode.Call(CodeSymbols.Fixed, LNode.List(init.Args.Last, block)))).SetStyle(NodeStyle.Statement); } else return stmt.WithArgChanged(1, block); } else if ((attrs = stmt.Attrs).IsEmpty | true && stmt.Calls(CodeSymbols.While, 2) && (cond = stmt.Args[0]) != null && (block = stmt.Args[1]) != null) { cond = BubbleUpBlocks(cond); block = EliminateSequenceExpressionsInChildStmt(block); if (cond.CallsMin(__numrunSequence, 1)) { return LNode.Call(LNode.List(attrs), CodeSymbols.For, LNode.List(LNode.Call(CodeSymbols.AltList), LNode.Missing, LNode.Call(CodeSymbols.AltList), LNode.Call(CodeSymbols.Braces, LNode.List().AddRange(cond.Args.WithoutLast(1)).Add(LNode.Call(CodeSymbols.If, LNode.List(cond.Args.Last, block, LNode.Call(CodeSymbols.Break))))).SetStyle(NodeStyle.Statement))); } else return stmt.WithArgChanged(1, block); } else if ((attrs = stmt.Attrs).IsEmpty | true && stmt.Calls(CodeSymbols.DoWhile, 2) && (block = stmt.Args[0]) != null && (cond = stmt.Args[1]) != null) { block = EliminateSequenceExpressionsInChildStmt(block); cond = BubbleUpBlocks(cond); if (cond.CallsMin(__numrunSequence, 1)) { var continue_N = F.Id(NextTempName(Context, "continue_")); var bodyStmts = block.AsList(S.Braces); bodyStmts.AddRange(cond.Args.WithoutLast(1)); bodyStmts.Add(LNode.Call(CodeSymbols.Assign, LNode.List(continue_N, cond.Args.Last)).SetStyle(NodeStyle.Operator)); return LNode.Call(LNode.List(attrs), CodeSymbols.For, LNode.List(LNode.Call(CodeSymbols.AltList, LNode.List(LNode.Call(CodeSymbols.Var, LNode.List(LNode.Id(CodeSymbols.Bool), LNode.Call(CodeSymbols.Assign, LNode.List(continue_N, LNode.Literal(true))))))), continue_N, LNode.Call(CodeSymbols.AltList), LNode.Call(CodeSymbols.Braces, LNode.List(bodyStmts)).SetStyle(NodeStyle.Statement))); } else return stmt.WithArgChanged(0, block); } else if ((attrs = stmt.Attrs).IsEmpty | true && stmt.Calls(CodeSymbols.For, 4) && stmt.Args[0].Calls(CodeSymbols.AltList) && (cond = stmt.Args[1]) != null && stmt.Args[2].Calls(CodeSymbols.AltList) && (block = stmt.Args[3]) != null) { inits = stmt.Args[0].Args; incs = stmt.Args[2].Args; return ESEInForLoop(stmt, attrs, inits, cond, incs, block); } else if ((attrs = stmt.Attrs).IsEmpty | true && stmt.Calls(CodeSymbols.ForEach, 3) && (tmp_11 = stmt.Args[0]) != null && tmp_11.Calls(CodeSymbols.Var, 2) && (type = tmp_11.Args[0]) != null && (loopVar = tmp_11.Args[1]) != null && (collection = stmt.Args[1]) != null && (block = stmt.Args[2]) != null) { block = EliminateSequenceExpressionsInChildStmt(block); collection = BubbleUpBlocks(collection); if (collection.CallsMin(__numrunSequence, 1)) { return LNode.Call(LNode.List(attrs), CodeSymbols.Braces, LNode.List().AddRange(collection.Args.WithoutLast(1)).Add(LNode.Call(CodeSymbols.ForEach, LNode.List(LNode.Call(CodeSymbols.Var, LNode.List(type, loopVar)), collection.Args.Last, block)))).SetStyle(NodeStyle.Statement); } else { return stmt.WithArgChanged(stmt.Args.Count - 1, block); } } else if ((attrs = stmt.Attrs).IsEmpty | true && stmt.Calls(CodeSymbols.Var, 2) && (type = stmt.Args[0]) != null && (tmp_12 = stmt.Args[1]) != null && tmp_12.Calls(CodeSymbols.Assign, 2) && (name = tmp_12.Args[0]) != null && (initValue = tmp_12.Args[1]) != null) { var initValue_apos = BubbleUpBlocks(initValue); if (initValue_apos != initValue) { { LNode last; VList<LNode> stmts; if (initValue_apos.CallsMin((Symbol) "#runSequence", 1) && (last = initValue_apos.Args[initValue_apos.Args.Count - 1]) != null) { stmts = initValue_apos.Args.WithoutLast(1); return LNode.Call((Symbol) "#runSequence", LNode.List().AddRange(stmts).Add(LNode.Call(LNode.List(attrs), CodeSymbols.Var, LNode.List(type, LNode.Call(CodeSymbols.Assign, LNode.List(name, last)))))); } else return LNode.Call(LNode.List(attrs), CodeSymbols.Var, LNode.List(type, LNode.Call(CodeSymbols.Assign, LNode.List(name, initValue_apos)))); } } } else if (stmt.CallsMin(S.Try, 2)) { return ESEInTryStmt(stmt); } else if (stmt.HasSpecialName && stmt.ArgCount >= 1 && stmt.Args.Last.Calls(S.Braces)) { return ProcessBlockCallStmt(stmt, stmt.ArgCount - 1); } else { // Ordinary expression statement return BubbleUpBlocks(stmt, stmtContext: true); } } return stmt; }
LNode ESEInTryStmt(LNode stmt) { var args = stmt.Args.ToWList(); // Process `try` part args[0] = EliminateSequenceExpressionsInChildStmt(args[0]); // Process `catch` and `finally` clauses (`when` clause not supported) for (int i = 1; i < args.Count; i++) { var part = args[i]; if (part.Calls(S.Finally, 1) || part.Calls(S.Catch, 3)) { int lasti = part.ArgCount - 1; args[i] = part.WithArgChanged(lasti, EliminateSequenceExpressionsInChildStmt(part.Args[lasti])); } } return stmt.WithArgs(args.ToVList()); }
public static LNode of(LNode node, IMessageSink sink) { LNode kind; if (node.ArgCount == 2 && (kind = node.Args[0]).IsId) { if (kind.IsIdNamed(_array)) return node.WithArgChanged(0, kind.WithName(S.Array)); if (kind.IsIdNamed(_opt)) return node.WithArgChanged(0, kind.WithName(S.QuestionMark)); if (kind.IsIdNamed(_ptr)) return node.WithArgChanged(0, kind.WithName(S._Pointer)); } else if (node.ArgCount == 3 && (kind = node.Args[0]).IsIdNamed(_array) && node.Args[1].IsLiteral) { return node.WithArgs(kind.WithName(S.GetArrayKeyword((int)node.Args[1].Value)), node.Args[2]); } return null; }
LNode ConvertVarDeclToRunSequence(VList<LNode> attrs, LNode varType, LNode varName, LNode initValue) { initValue = BubbleUpBlocks(initValue); varType = varType ?? F.Missing; LNode @ref; attrs = attrs.WithoutNodeNamed(S.Ref, out @ref); var varName_apos = varName.PlusAttr(_trivia_isTmpVar); if (@ref != null) varName_apos = varName_apos.PlusAttr(@ref); { LNode resultValue; VList<LNode> stmts; if (initValue.CallsMin((Symbol) "#runSequence", 1) && (resultValue = initValue.Args[initValue.Args.Count - 1]) != null) { stmts = initValue.Args.WithoutLast(1); var newVarDecl = LNode.Call(LNode.List(attrs), CodeSymbols.Var, LNode.List(varType, LNode.Call(CodeSymbols.Assign, LNode.List(varName, resultValue)))); return initValue.WithArgs(stmts.Add(newVarDecl).Add(varName_apos)); } else { var newVarDecl = LNode.Call(LNode.List(attrs), CodeSymbols.Var, LNode.List(varType, LNode.Call(CodeSymbols.Assign, LNode.List(varName, initValue)))); return LNode.Call((Symbol) "#runSequence", LNode.List(newVarDecl, varName_apos)); } } }
public static LNode Namespace(LNode node, IMacroContext context) { if (node.ArgCount == 2 && !node.Args.Last.Calls(S.Braces)) { context.DropRemainingNodes = true; return node.WithArgs(node.Args.Add(F.Braces(context.RemainingNodes))); } return null; }
// Bubbles up a call. The returned pair consists of // 1. A sequence of statements to run before the call // 2. The call with all (outer) #runSequences removed Pair<VList<LNode>, LNode> BubbleUp_GeneralCall2(LNode expr) { var target = expr.Target; var args = expr.Args; var combinedSequence = LNode.List(); // Bubbe up target target = BubbleUpBlocks(target); if (target.CallsMin(__numrunSequence, 1)) { combinedSequence = target.Args.WithoutLast(1); expr = expr.WithTarget(target.Args.Last); } // Bubble up each argument var isAssignment = EcsValidators.IsAssignmentOperator(expr.Name); if (isAssignment) { LNode lhs = BubbleUpBlocks(expr.Args[0]); LNode rhs = BubbleUpBlocks(expr.Args[1]); args = LNode.List(lhs, rhs); } else { // most common case args = args.SmartSelect(arg => BubbleUpBlocks(arg)); } int lastRunSeq = args.LastIndexWhere(a => a.CallsMin(__numrunSequence, 1)); if (lastRunSeq >= 0) { // last index of #runSequence that is not marked pure int lastRunSeqImpure = args.First(lastRunSeq + 1).LastIndexWhere(a => a.CallsMin(__numrunSequence, 1) && a.AttrNamed(_trivia_pure.Name) == null); if (lastRunSeq > 0 && (args.Count == 2 && (target.IsIdNamed(S.And) || target.IsIdNamed(S.Or)) || args.Count == 3 && target.IsIdNamed(S.QuestionMark))) { Context.Sink.Error(target, "#useSequenceExpressions is not designed to support sequences or variable declarations on the right-hand side of the `&&`, `||` or `?` operators. The generated code will be incorrect."); } var argsW = args.ToList(); for (int i = 0; i <= lastRunSeq; i++) { LNode arg = argsW[i]; if (!arg.IsLiteral) { if (arg.CallsMin(__numrunSequence, 1)) { combinedSequence.AddRange(arg.Args.WithoutLast(1)); argsW[i] = arg = arg.Args.Last; } if (i < lastRunSeqImpure) { if (i == 0 && (expr.CallsMin(S.IndexBracks, 1) || expr.CallsMin(S.NullIndexBracks, 1))) { // Consider foo[#runSequence(f(), i)]. In case this appears in // an lvalue context and `foo` is a struct, we cannot store `foo` in // a temporary, as this may silently change the code's behavior. // Better to take the risk of evaluating `foo` after `f()`. } else { if (isAssignment || arg.Attrs.Any(a => a.IsIdNamed(S.Ref) || a.IsIdNamed(S.Out))) argsW[i] = MaybeCreateTemporaryForLValue(arg, ref combinedSequence); else { // Create a temporary variable to hold this argument LNode tmpVarName, tmpVarDecl = TempVarDecl(Context, arg, out tmpVarName); combinedSequence.Add(tmpVarDecl); argsW[i] = tmpVarName.PlusAttr(_trivia_isTmpVar); } } } } } expr = expr.WithArgs(LNode.List(argsW)); } return Pair.Create(combinedSequence, expr); }
void WhereClausesOpt(ref LNode name) { TokenType la0; #line 1163 "EcsParserGrammar.les" var list = new BMultiMap<Symbol,LNode>(); #line default // Line 1164: (WhereClause)* for (;;) { la0 = LA0; if (la0 == TT.ContextualKeyword) list.Add(WhereClause()); else break; } #line 1165 "EcsParserGrammar.les" if ((list.Count != 0)) { if ((!name.CallsMin(S.Of, 2))) { Error("'{0}' is not generic and cannot use 'where' clauses.", name.ToString()); } else { var tparams = name.Args.ToRWList(); for (int i = 1; i < tparams.Count; i++) { var wheres = list[TParamSymbol(tparams[i])]; tparams[i] = tparams[i].PlusAttrs(wheres); wheres.Clear(); } name = name.WithArgs(tparams.ToRVList()); if ((list.Count > 0)) { Error(list[0].Value, "There is no type parameter named '{0}'", list[0].Key); } } } #line default }
public static LNode @case(LNode node, IMessageSink sink) { if (node.ArgCount >= 2 && node.Args.Last.Calls(S.Braces)) return F.Call(S.Splice, new VList<LNode>(node.WithArgs(node.Args.WithoutLast(1)), node.Args.Last)); if (node.ArgCount >= 1) return node.WithTarget(S.Case); return null; }