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); } }
public void TupleAssignmentTest() { var m = Module.FromDefinitions( "Threat ?attacker ?target: [set State = [threat ?attacker ?target]]", "Test: [Threat capitalist liv]"); var(_, state) = m.Call(State.Empty, "Test"); var tuple = state.Lookup(StateVariableName.Named("State")); Assert.IsTrue(tuple is object[] a && a.Length == 3 && a[0].Equals("threat") && a[1].Equals("capitalist") && a[2].Equals("liv")); }
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)); }
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); } }
/// <summary> /// Calls a task with the specified arguments and allows the user to provide their own continuation. /// The only (?) use case for this is when you want to forcibly generate multiple solutions /// </summary> internal static void GenerateSolutions(string taskName, object[] args, TextBuffer o, BindingEnvironment e, Step.Continuation k, MethodCallFrame predecessor) { new Call(StateVariableName.Named(taskName), args, null).Try(o, e, k, predecessor); }
public void VariableTest() { Assert.AreEqual(Module.Global["Write"], new VariableReference(StateVariableName.Named("Write")).Eval(EmptyEnvironment)); }