private static void FromSetExpression(ChainBuilder chain, object[] expression, string sourceFile, int lineNumber) { if (expression.Length < 4 || !expression[2].Equals("=") || !(expression[1] is string name)) { throw new SyntaxError( $"A set command has the format [set name = value], which doesn't match the expression {Writer.TermToString(expression)}.", sourceFile, lineNumber); } if (DefinitionStream.IsGlobalVariableName(name)) { chain.AddStep(new AssignmentStep(StateVariableName.Named(name), FunctionalExpressionParser.FromTuple(chain.CanonicalizeArglist(expression), 3, sourceFile, lineNumber), null)); } else if (DefinitionStream.IsLocalVariableName(name)) { chain.AddStep(new AssignmentStep(chain.GetLocal(name), FunctionalExpressionParser.FromTuple(chain.CanonicalizeArglist(expression), 3, sourceFile, lineNumber), null)); } else { throw new SyntaxError( $"A set command can only update a variable; it can't update {expression[1]}", sourceFile, lineNumber); } }
internal static void FromCoolExpression(ChainBuilder chain, object[] expression, string sourceFile, int lineNumber) { if (expression.Length > 2) { throw new ArgumentCountException("cool", 1, expression.Skip(1).ToArray()); } var duration = 1; if (expression.Length == 2) { if (int.TryParse(expression[1] as string, out var d)) { duration = d; } else { throw new SyntaxError( $"Argument to cool must be an integer constant, but got {expression[1]}", sourceFile, lineNumber); } } chain.AddStep(new CoolStep(duration, null)); }
internal static void FromOnceExpression(ChainBuilder chain, object[] expression) { if (expression.Length != 1) { throw new ArgumentCountException("once", 0, expression.Skip(1).ToArray()); } chain.AddStep(new CoolStep(int.MaxValue, null)); }
public static void FromExpression(ChainBuilder chain, object[] expression, string sourceFile = null, int lineNumber = 0) { if (expression.Length != 3) { throw new ArgumentCountException("add", 2, expression.Skip(1).ToArray()); } if (!(expression[2] is string vName && DefinitionStream.IsGlobalVariableName(vName))) { throw new SyntaxError($"Invalid global variable name in add: {expression[2]}", sourceFile, lineNumber); } chain.AddStep(new AddStep(chain.Canonicalize(expression[1]), StateVariableName.Named(vName), null)); }
/// <summary> /// Given an array of tuples representing a Step expressions, make a step chain /// </summary> /// <param name="taskName">Name of the task to which this is an argument (for use in error messages)</param> /// <param name="body"></param> /// <returns></returns> /// <exception cref="ArgumentTypeException"></exception> public static Step ChainFromBody(string taskName, params object[] body) { var chain = new ChainBuilder(null, x => x, x => x); foreach (var step in body) { switch (step) { case "\n": break; case object[] invocation when invocation.Length > 0: var operation = invocation[0]; switch (operation) { case "add": AddStep.FromExpression(chain, invocation); break; case "removeNext": RemoveNextStep.FromExpression(chain, invocation); break; case "set": AssignmentStep.FromExpression(chain, invocation); break; default: // It's a call var arglist = new object[invocation.Length - 1]; Array.Copy(invocation, 1, arglist, 0, arglist.Length); chain.AddStep(new Call(operation, arglist, null)); break; } break; default: throw new ArgumentTypeException(taskName, typeof(Call), step, body); } } return(chain.FirstStep); }
private static void FromIncDecExpression(ChainBuilder chain, object[] expression, string sourceFile, int lineNumber) { if (expression.Length < 2 || !(expression[1] is string name)) { throw new SyntaxError( $"An inc or dec command has the format [inc name] or [inc name amount], which doesn't match the expression {Writer.TermToString(expression)}.", sourceFile, lineNumber); } var operation = expression[0].Equals("inc") ? "+" : "-"; var increment = (expression.Length == 2) ? new object[] { 1 } : expression.Skip(2).Prepend("(").Append(")"); var newValueExpression = new object[] { name, operation }.Concat(increment).ToArray(); if (DefinitionStream.IsGlobalVariableName(name)) { chain.AddStep(new AssignmentStep(StateVariableName.Named(name), FunctionalExpressionParser.FromTuple(chain.CanonicalizeArglist(newValueExpression), 0, sourceFile, lineNumber), null)); } else if (DefinitionStream.IsLocalVariableName(name)) { throw new SyntaxError( $"An inc or dec command cannot be used with the local variable {name} because local variables can only be set once.", sourceFile, lineNumber); } else { throw new SyntaxError( $"An inc or dec command can only update a variable; it can't update {expression[1]}", sourceFile, lineNumber); } }