private static DataTree variableDataTree(Variable v) { string var_type = v.getTypeString(); string value = v.ToString(); string is_const = v.isConst().ToString(); string is_traced = v.isTraced().ToString(); return(new DataTree(v.getName(), null, new List <string> { "Name: " + v.getName(), "Type: " + var_type, "Value: " + value, "Const: " + is_const, "Traced: " + is_traced })); }
/// <summary> /// Call the function with input parameters (args) /// </summary> /// <param name="args"> The variables defining the new Main Context Stack</param> /// <returns> The return value of the function</returns> public Variable callFunction(Dictionary <string, Variable> args) { initialize(args); Debugging.assert(_in_function_scope); foreach (Instruction instruction in _instructions) { try { instruction.execute(); // return here (not continue, nor break) } catch (System.Reflection.TargetInvocationException out_exception) { if (!(out_exception.InnerException is AquilaControlFlowExceptions.ReturnValueException return_value_exception)) { throw; } Debugging.print("ReturnValueException was thrown"); string return_value_string = return_value_exception.getExprStr(); Expression return_value_expression = new Expression(return_value_string); Variable return_value = return_value_expression.evaluate(); if (_type != StringConstants.Types.AUTO_TYPE && _type != StringConstants.Types.NULL_TYPE) { Debugging.assert(return_value.getTypeString() == _type); } restore(); return(return_value); } } Debugging.print("no ReturnValueException thrown. returning NullVar"); if (_type != StringConstants.Types.AUTO_TYPE) { Debugging.assert(_type == StringConstants.Types.NULL_TYPE); } restore(); return(new NullVar()); }
private static DataTree variableDataTree(string variable) { if (!Global.variableExistsInCurrentScope(variable)) { return(new DataTree(variable, null, new List <string> { $"The variable \"{variable}\" does not exist in the current scope" })); } Variable v = Global.variableFromName(variable); string var_type = v.getTypeString(); string value = v.ToString(); string is_const = v.isConst().ToString(); string is_traced = v.isTraced().ToString(); return(new DataTree(variable, null, new List <string> { "Name: " + variable, "Type: " + var_type, "Value: " + value, "Const: " + is_const, "Traced: " + is_traced })); }
public override void execute() { setContext(); int context_integrity_check = Context.getStatusStackCount(); Debugging.print("Assignment: ", _var_name, " = ", _var_value.expr); // set the new value Variable variable; try { variable = Expression.parse(_var_name); } catch (AquilaExceptions.NameError) { // implicit declaration if (!Global.getSetting("implicit declaration in assignment")) { throw; } Debugging.print("Implicit declaration in Assignment!"); Declaration decl = new Declaration(line_index, _var_name.Substring(1), _var_value); // in the Assignment constructor: already check if _var_name != "" decl.execute(); // update things 'n stuff Global.onElementaryInstruction(); // reset Context // Smooth Context Context.resetUntilCountReached(context_integrity_check); Context.reset(); return; } // parsing new value Variable val = _var_value.evaluate(); Debugging.print("assigning " + _var_name + " with expr " + _var_value.expr + " with value " + val + " (2nd value assigned: " + val.assigned + ") and type: " + val.getTypeString()); // assert the new is not an unassigned (only declared) variable val.assertAssignment(); if (variable.hasSameParent(val)) { variable.setValue(val); } else { throw new AquilaExceptions.InvalidTypeError("You cannot change the type of your variables (" + variable.getTypeString() + " -> " + val.getTypeString() + "). This will never be supported because it would be considered bad style."); } // update things 'n stuff Global.onElementaryInstruction(); // reset Context // Smooth Context Context.resetUntilCountReached(context_integrity_check); Context.reset(); }
/// <summary> /// Process the input from the interpreter. /// If the input is one of the interactive-mode-only commands, the command should not /// be executed by the interpreter but will be executed by this function manually. /// </summary> /// <param name="input"> command line from the interactive-mode</param> /// <returns> should the command be executed ?</returns> internal static bool processInterpreterInput(string input) { switch (input) { case "help": { Global.stdoutWriteLine("All existing interactive-mode-only commands:"); // ReSharper disable once RedundantExplicitArrayCreation foreach (string command in new string[] { "help", "exit", "reset_env", "clear", // base interactive-mode "exec", "exec_info", // exec "debug", "trace_debug", "parse_debug", // debugging (enable/disable) "eval %expr", // expr "var %var_name", "vars", "$%var_name", // variables // ReSharper disable once StringLiteralTypo "funcs", "df_funcs", // functions "type", // ? "trace_info", "trace_uniq_stacks", "rewind %n %var_name", "peek_trace $%traced_value", // trace "get_context", "set_status", "set_info_null", "reset_context", // context "scope_info", // scope "show-settings", // settings }) { Global.stdoutWriteLine(" -> " + command); } return(false); } case "clear": if (!Global.getSetting("redirect debug stout & stderr")) { Console.Clear(); } return(false); case "vars": { Global.stdoutWriteLine("Global Variables:"); foreach (var pair in Global.getGlobalVariables()) { Global.stdoutWriteLine("\t" + pair.Key + " : " + pair.Value); } int i = 0; Global.stdoutWriteLine("Local Scope Variables:"); foreach (var dict in Global.getCurrentDictList()) { i++; foreach (var pair in dict) { Global.stdoutWrite(new string('\t', i)); Global.stdoutWrite(pair.Key + " : "); Global.stdoutWriteLine(pair.Value.ToString()); } } return(false); } // ReSharper disable once StringLiteralTypo case "funcs": { Global.stdoutWriteLine("User defined functions:"); foreach (var pair in Functions.user_functions) { Global.stdoutWriteLine(" * " + pair.Key + (pair.Value.isRec() ? " : [rec] " : " : ") + "(" + pair.Value.func_args.Count + ") -> " + pair.Value.getType()); } return(false); } case "df_funcs": Global.stdoutWriteLine("Default (predefined) functions:"); foreach (var pair in Functions.functions_dict) { MethodInfo method = pair.Value.GetMethodInfo(); Global.stdoutWriteLine(" * " + pair.Key + " [?] : (" + method.GetParameters().Length + ") -> " + method.ReturnType); } return(false); case "debug": Global.setSetting("debug", !Global.getSetting("debug")); return(false); case "trace_debug": Global.setSetting("trace debug", !Global.getSetting("trace debug")); return(false); case "parse_debug": Global.setSetting("parse debug", !Global.getSetting("parse debug")); return(false); case "trace_info": { Global.stdoutWriteLine("var tracers:"); foreach (VarTracer tracer in Global.var_tracers) { Global.stdoutWriteLine(" - var : " + (tracer.getTracedObject() as Variable).getName()); Global.stdoutWriteLine(" - stack : " + tracer.getStackCount()); Global.stdoutWriteLine(" - updated : " + tracer.last_stack_count); } Global.stdoutWriteLine("func tracers:"); foreach (FuncTracer tracer in Global.func_tracers) { Global.stdoutWriteLine(" - func : " + tracer.getTracedObject()); Global.stdoutWriteLine(" - stack : " + tracer.getStackCount()); } return(false); } case "trace_uniq_stacks": Global.var_tracers[0].printEventStack(); return(false); case "reset_env": Global.resetEnv(); Global.stdoutWriteLine(" [!] Global Environment reset"); return(false); case "get_context": { int status = Context.getStatus(); Context.StatusEnum status_quote = (Context.StatusEnum)status; object info = Context.getInfo(); bool blocked = Context.isFrozen(); bool enabled = Global.getSetting("fail on context assertions"); Global.stdoutWriteLine("status : " + status); Global.stdoutWriteLine("quote : " + status_quote); Global.stdoutWriteLine("info : " + info); Global.stdoutWriteLine("blocked : " + blocked); Global.stdoutWriteLine("asserts : " + enabled); return(false); } case "set_info_null": Context.setInfo(null); return(false); case "reset_context": Context.reset(); return(false); case "type": Global.stdoutWriteLine("type of NullVar: " + typeof(NullVar)); Global.stdoutWriteLine("type of Variable: " + typeof(Variable)); Global.stdoutWriteLine("type of Integer: " + typeof(Integer)); return(false); case "scope_info": Global.stdoutWriteLine("local scope depth: " + Global.getLocalScopeDepth()); Global.stdoutWriteLine("main scope depth: " + Global.getMainScopeDepth()); return(false); case "show-settings": foreach (var pair in Global.getSettings()) { Global.stdoutWriteLine($" - {pair.Key} : {pair.Value}"); } return(false); } if (input[0] == '$' && Global.variableExistsInCurrentScope(input.Substring(1))) { Global.stdoutWriteLine(Global.variableFromName(input.Substring(1)).ToString()); return(false); } if (input.StartsWith("set_status ")) { int status = int.Parse(input.Substring(11)); Context.setStatus((Context.StatusEnum)status); return(false); } if (input.StartsWith("eval ")) { Variable var_ = Expression.parse(input.Substring(5)); Global.stdoutWriteLine(var_.ToString()); return(false); } if (input.StartsWith("var ")) { string var_name = input.Substring(4); var_name = StringUtils.normalizeWhiteSpaces(var_name); if (var_name == "") { return(false); } Variable var_ = Global.variableFromName(var_name); Global.stdoutWriteLine("name : " + var_.getName()); Global.stdoutWriteLine("type : " + var_.getTypeString()); Global.stdoutWriteLine("const : " + var_.isConst()); Global.stdoutWriteLine("assigned : " + var_.assigned); Global.stdoutWriteLine("value : " + var_); Global.stdoutWriteLine("traced : " + var_.isTraced()); Global.stdoutWriteLine("^ mode : " + var_.trace_mode); if (var_ is NumericalValue value) { Global.stdoutWriteLine("*source : " + StringUtils.dynamic2Str(value.source_vars)); } return(false); } if (input.StartsWith("rewind")) { string[] splitted = input.Split(' '); if (splitted.Length == 3) { if (!int.TryParse(splitted[1], out int n)) { Global.stdoutWriteLine("cannot read n"); return(false); } string var_name = splitted[2]; Variable var_ = Expression.parse(var_name); if (!var_.isTraced()) { Global.stdoutWriteLine("Variable is not traced! Use the \"trace\" instruction to start tracing variables"); return(false); } var_.tracer.rewind(n); return(false); } Global.stdoutWriteLine("split count does not match 3"); return(false); } if (input.StartsWith("peek_trace")) { if (input.Length < 11) { return(false); } Variable var_ = Expression.parse(input.Substring(11)); if (!var_.isTraced()) { Global.stdoutWriteLine("Variable is not traced! Use the \"trace\" instruction to start tracing variables"); return(false); } Alteration alter = var_.tracer.peekEvent().alter; Global.stdoutWriteLine("name : " + alter.name); Global.stdoutWriteLine("variable : " + alter.affected.getName()); Global.stdoutWriteLine("main value : " + StringUtils.dynamic2Str(alter.main_value)); Global.stdoutWriteLine("num minor : " + alter.minor_values.Length); Global.stdoutWriteLine("minor values : " + StringUtils.dynamic2Str(alter.main_value)); Global.stdoutWriteLine("stack count : " + var_.tracer.getStackCount()); Global.stdoutWriteLine("updated : " + var_.tracer.last_stack_count); return(false); } if (input.StartsWith("#")) { Global.stdoutWriteLine("Handling macro parameter"); if (!input.Contains(' ')) { Parser.handleMacro(input.Substring(1), null); return(false); } int index = input.IndexOf(' '); // extract the key & value pair string value = input.Substring(index); input = input.Substring(1, index); // purge pair value = StringUtils.normalizeWhiteSpaces(value); input = StringUtils.normalizeWhiteSpaces(input); Parser.handleMacro(input, value); return(false); } return(true); }
/// <summary> /// Takes an arithmetical or logical expression and returns the corresponding variable /// <para/>Examples: /// <para/>* "5 + 6" : returns Integer (11) /// <para/>* "$l[5 * (1 - $i)]" : returns the elements at index 5*(1-i) in the list "l" /// <para/>* "$l" : returns the list variable l /// </summary> /// <param name="expr_string"> expression to parse</param> /// <returns> Variable object containing the value of the evaluated expression value (at time t)</returns> public static Variable parse(string expr_string) { /* Order of operations: * checking expression string integrity * raw dynamic list * clean redundant symbols * raw integer value * raw boolean value (not done yet) * raw float value (not done yet) * mathematical or logical operation * function call * variable access (e.g. $name or in list by index) */ // clean expression expr_string = StringUtils.normalizeWhiteSpaces(expr_string); Exception invalid_expr_exception = new AquilaExceptions.SyntaxExceptions.SyntaxError($"The sentence \"{expr_string}\" is not understood"); Debugging.print("input expression: " + expr_string); // matching parentheses & brackets Debugging.assert(StringUtils.checkMatchingDelimiters(expr_string, '(', ')'), new AquilaExceptions.SyntaxExceptions.UnclosedTagError("Unclosed parenthesis")); Debugging.assert(StringUtils.checkMatchingDelimiters(expr_string, '[', ']'), new AquilaExceptions.SyntaxExceptions.UnclosedTagError("Unclosed bracket")); expr_string = StringUtils.removeRedundantMatchingDelimiters(expr_string, '(', ')'); Debugging.print("dynamic list ?"); // dynamic list { DynamicList list = StringUtils.parseListExpression(expr_string); if (list != null) { return(list); } } // now that lists are over, check for redundant brackets expr_string = StringUtils.removeRedundantMatchingDelimiters(expr_string, '[', ']'); if (expr_string == null) { throw new AquilaExceptions.SyntaxExceptions.SyntaxError("Null Expression"); } Debugging.assert(expr_string != ""); //! NullValue here, instead of Exception Debugging.print("int ?"); // try evaluating expression as an integer if (int.TryParse(expr_string, out int int_value)) { return(new Integer(int_value, true)); } Debugging.print("bool ?"); // try evaluating expression as a boolean if (expr_string == "true") { return(new BooleanVar(true, true)); } if (expr_string == "false") { return(new BooleanVar(false, true)); } Debugging.print("float ?"); // try evaluating expression as float if (!expr_string.Contains(' ')) { if (float.TryParse(expr_string, out float float_value)) { Debugging.print("french/classic float"); return(new FloatVar(float_value, true)); } if (float.TryParse(expr_string.Replace('.', ','), out float_value)) { Debugging.print("normalized float"); return(new FloatVar(float_value, true)); } if (expr_string.EndsWith("f") && float.TryParse(expr_string.Substring(0, expr_string.Length - 1), out float_value)) { Debugging.print("f-float"); return(new FloatVar(float_value, true)); } if (expr_string.EndsWith("f") && float.TryParse(expr_string.Replace('.', ',').Substring(0, expr_string.Length - 1), out float_value)) { Debugging.print("f-float"); return(new FloatVar(float_value, true)); } } Debugging.print("checking for negative expression"); // special step: check for -(expr) if (expr_string.StartsWith("-")) { Debugging.print("evaluating expression without \"-\" sign"); string opposite_sign_expr = expr_string.Substring(1); // take away the "-" Variable opposite_sign_var = parse(opposite_sign_expr); Debugging.print("evaluated expression without the \"-\" symbol is of type ", opposite_sign_var.getTypeString(), " and value ", opposite_sign_var.getValue()); // ReSharper disable once ConvertIfStatementToSwitchExpression if (opposite_sign_var is Integer) { return(new Integer(-opposite_sign_var.getValue())); } if (opposite_sign_var is FloatVar) { return(new FloatVar(-opposite_sign_var.getValue())); } throw new AquilaExceptions.InvalidTypeError($"Cannot cast \"-\" on a {opposite_sign_var.getTypeString()} variable"); } Debugging.print("AL operations ?"); // mathematical and logical operations foreach (char op in Global.al_operations) { // ReSharper disable once PossibleNullReferenceException if (expr_string.Contains(op.ToString())) { string simplified = StringUtils.simplifyExpr(expr_string, new [] { op }); // only look for specific delimiter // more than one simplified expression ? if (simplified.Split(op).Length > 1) { Debugging.print("operation ", expr_string, " and op: ", op); List <string> splitted_str = StringUtils.splitStringKeepingStructureIntegrity(expr_string, op, Global.base_delimiters); // custom: logic operations laziness here (tmp) //! Variable variable = parse(splitted_str[0]); if (Global.getSetting("lazy logic") && variable is BooleanVar) { Debugging.print("lazy logic evaluation"); bool first = (variable as BooleanVar).getValue(); switch (op) { case '|': // when first: if (first) { return(new BooleanVar(true, true)); } break; case '&': // when !first: if (!first) { return(new BooleanVar(false, true)); } break; } } var splitted_var = new List <Variable> { variable }; splitted_var.AddRange(splitted_str.GetRange(1, splitted_str.Count - 1).Select(parse)); // reduce the list to a list of one element // e.g. expr1 + expr2 + expr3 => final_expr while (splitted_var.Count > 1) { // merge the two first expressions Variable expr1_var = splitted_var[0]; Variable expr2_var = splitted_var[1]; Variable result = applyOperator(expr1_var, expr2_var, op); // merge result of 0 and 1 splitted_var[0] = result; // remove 1 (part of it found in 0 now) splitted_var.RemoveAt(1); } return(splitted_var[0]); } } } Debugging.print("not (!) operator ?"); // '!' operator (only one to take one variable) if (expr_string.StartsWith("!")) { Debugging.assert(expr_string[1] == '('); Debugging.assert(expr_string[expr_string.Length - 1] == ')'); Variable expr = parse(expr_string.Substring(2, expr_string.Length - 3)); Debugging.assert(expr is BooleanVar); Debugging.print("base val b4 not operator is ", expr.getValue()); return(((BooleanVar)expr).not()); } Debugging.print("value function call ?"); // value function call if (expr_string.Contains("(")) { string function_name = expr_string.Split('(')[0]; // extract function name int func_call_length = function_name.Length; function_name = StringUtils.normalizeWhiteSpaces(function_name); Debugging.print("function name: ", function_name); Functions.assertFunctionExists(function_name); expr_string = expr_string.Substring(func_call_length); // remove function name expr_string = expr_string.Substring(1, expr_string.Length - 2); // remove parenthesis Debugging.print("expr_string for function call ", expr_string); var arg_list = new List <Expression>(); foreach (string arg_string in StringUtils.splitStringKeepingStructureIntegrity(expr_string, ',', Global.base_delimiters)) { string purged_arg_string = StringUtils.normalizeWhiteSpaces(arg_string); Expression arg_expr = new Expression(purged_arg_string); arg_list.Add(arg_expr); } if (arg_list.Count == 1 && arg_list[0].expr == "") { arg_list = new List <Expression>(); } Debugging.print("creating value function call with ", arg_list.Count, " parameters"); FunctionCall func_call = new FunctionCall(function_name, arg_list); return(func_call.callFunction()); } // function call without parenthesis -> no parameters either if (!expr_string.StartsWith(StringConstants.Other.VARIABLE_PREFIX) && !expr_string.Contains(' ')) { Debugging.print($"Call the function \"{expr_string}\" with no parameters"); var func_call = new FunctionCall(expr_string, new List <Expression>()); return(func_call.callFunction()); } Debugging.print("variable ?"); // variable access // since it is the last possibility for the parse call to return something, assert it is a variable Debugging.assert(expr_string.StartsWith(StringConstants.Other.VARIABLE_PREFIX), invalid_expr_exception); Debugging.print("list access ?"); // ReSharper disable once PossibleNullReferenceException if (expr_string.Contains("[")) { // brackets Debugging.assert(expr_string.EndsWith("]"), invalid_expr_exception); // cannot be "$l[0] + 5" bc AL_operations have already been processed int bracket_start_index = expr_string.IndexOf('['); Debugging.assert(bracket_start_index > 1, invalid_expr_exception); // "$[$i - 4]" is not valid // variable Expression var_name_expr = new Expression(expr_string.Substring(0, bracket_start_index)); Debugging.print("list name: " + var_name_expr.expr); // index list IEnumerable <string> index_list = StringUtils.getBracketsContent(expr_string.Substring(bracket_start_index)); string index_list_expr_string = index_list.Aggregate("", (current, s) => current + s + ", "); index_list_expr_string = "[" + index_list_expr_string.Substring(0, index_list_expr_string.Length - 2) + "]"; var index_list_expr = new Expression(index_list_expr_string); Debugging.print("index: " + index_list_expr.expr); // create a value function call (list_at call) object[] args = { var_name_expr, index_list_expr }; return(Functions.callFunctionByName("list_at", args)); } // only variable name, no brackets Debugging.print("var by name: ", expr_string); return(variableFromName(expr_string)); }
/// <summary> /// Applies an arithmetical or logical operation on two <see cref="Variable"/>s /// <para/>result = (variable1) op (variable2) /// </summary> /// <param name="v1"> var 1</param> /// <param name="v2"> var 2</param> /// <param name="op"> operator (e.g. '+', '-', '&')</param> /// <returns> result <see cref="Variable"/></returns> /// <exception cref="AquilaExceptions.InvalidTypeError"> Invalid type with this operator</exception> /// <exception cref="AquilaExceptions.SyntaxExceptions.SyntaxError"> Unknown operator char</exception> private static Variable applyOperator(Variable v1, Variable v2, char op) { int comparison; Debugging.print("applyOperator: ", v1.ToString(), " ", op, " ", v2.ToString(), " (", v1.getTypeString(), " ", op, " ", v2.getTypeString(), ")"); // Debugging.assert(v1.hasSameParent(v2)); // operations between same classes/subclasses if (!v1.hasSameParent(v2)) { if (v2.isConst()) { if (v2 is Integer) { Debugging.print("Converting int to float because of const status: ", v1.ToString()); Debugging.assert(v1 is FloatVar, new AquilaExceptions.InvalidTypeError($"The type \"{v1.getTypeString()}\" was not expected. \"{v1.getTypeString()}\" expected")); // if this is not a float, operation is not permitted ! v2 = new FloatVar((float)v2.getValue()); } } else { throw new AquilaExceptions.InvalidTypeError($"The type \"{v1.getTypeString()}\" was not expected"); } } switch (op) { // arithmetic case '+': if (v1 is NumericalValue) { return(((NumericalValue)v1).addition((NumericalValue)v2)); } else { throw new AquilaExceptions.InvalidTypeError($"Invalid type \"{v1.getTypeString()}\" with operator \"{op}\""); } case '-': if (v1 is NumericalValue) { return(((NumericalValue)v1).subtraction((NumericalValue)v2)); } else { throw new AquilaExceptions.InvalidTypeError($"Invalid type \"{v1.getTypeString()}\" with operator \"{op}\""); } case '/': if (v1 is NumericalValue) { return(((NumericalValue)v1).division((NumericalValue)v2)); } else { throw new AquilaExceptions.InvalidTypeError($"Invalid type \"{v1.getTypeString()}\" with operator \"{op}\""); } case '*': if (v1 is NumericalValue) { return(((NumericalValue)v1).mult((NumericalValue)v2)); } else { throw new AquilaExceptions.InvalidTypeError($"Invalid type \"{v1.getTypeString()}\" with operator \"{op}\""); } case '%': if (v1 is Integer) { return(((Integer)v1).modulo((Integer)v2)); } else { throw new AquilaExceptions.InvalidTypeError($"Invalid type \"{v1.getTypeString()}\" with operator \"{op}\""); } // logic case '<': Debugging.assert(v1 is Integer || v1 is FloatVar); comparison = v1 is Integer ? ((Integer)v1).compare(v2 as Integer) : ((FloatVar)v1).compare(v2 as FloatVar); return(new BooleanVar(comparison == -1)); case '>': Debugging.assert(v1 is Integer || v1 is FloatVar); comparison = v1 is Integer ? ((Integer)v1).compare(v2 as Integer) : ((FloatVar)v1).compare(v2 as FloatVar); return(new BooleanVar(comparison == 1)); case '{': Debugging.assert(v1 is Integer || v1 is FloatVar); comparison = v1 is Integer ? ((Integer)v1).compare(v2 as Integer) : ((FloatVar)v1).compare(v2 as FloatVar); return(new BooleanVar(comparison != 1)); case '}': Debugging.assert(v1 is Integer || v1 is FloatVar); comparison = v1 is Integer ? ((Integer)v1).compare(v2 as Integer) : ((FloatVar)v1).compare(v2 as FloatVar); return(new BooleanVar(comparison != -1)); case '~': Debugging.assert(v1 is Integer || v1 is FloatVar); comparison = v1 is Integer ? ((Integer)v1).compare(v2 as Integer) : ((FloatVar)v1).compare(v2 as FloatVar); return(new BooleanVar(comparison == 0)); case ':': Debugging.assert(v1 is Integer || v1 is FloatVar); comparison = v1 is Integer ? ((Integer)v1).compare(v2 as Integer) : ((FloatVar)v1).compare(v2 as FloatVar); return(new BooleanVar(comparison != 0)); case '|': Debugging.assert(v1 is BooleanVar); return(((BooleanVar)v1).or((BooleanVar)v2)); case '^': Debugging.assert(v1 is BooleanVar); return(((BooleanVar)v1).xor((BooleanVar)v2)); case '&': Debugging.assert(v1 is BooleanVar); return(((BooleanVar)v1).and((BooleanVar)v2)); default: throw new AquilaExceptions.SyntaxExceptions.SyntaxError("Unknown operand " + op); } }