public override void execute() { setContext(); // get variable value Variable variable_value = _var_expr.evaluate(); // is the value assigned ? (only relevant if other variable) variable_value.assertAssignment(); Variable variable = Variable.fromRawValue(variable_value.getRawValue()); // keep track of source vars -> should do something generic for lots of attributes ... if (variable is NumericalValue) { ((NumericalValue)variable).source_vars = new Dictionary <string, NumericalValue>(((NumericalValue)variable_value).source_vars); } variable.setName(_var_name); // explicit typing if (_var_type != StringConstants.Types.AUTO_TYPE) { Debugging.print("checking variable explicit type"); Expression default_value = Global.default_values_by_var_type[_var_type]; Debugging.assert(variable_value.hasSameParent(default_value.evaluate())); // TypeException } // constant if (_constant) { if (variable_value.isConst()) { variable.setConst(); } else { throw new AquilaExceptions.InvalidVariableClassifierException( "The \"const\" cannot be used when assigning to a non-const value"); } } // actually declare it to its value if (_global) { Global.addGlobalVariable(_var_name, variable); } else { Global.getCurrentDict()[_var_name] = variable; // overwriting is mandatory Debugging.print("variable exists ", Global.variableExistsInCurrentScope(_var_name)); if (_assignment) { variable.assign(); // should not need this, but doing anyway } else { variable.assigned = false; } } Debugging.print("finished declaration with value assignment: ", variable.assigned); // automatic tracing ? if (_assignment && Global.getSetting("auto trace")) { Debugging.print("Tracing variable: \"auto trace\" setting set to true"); // Does NOT work by simply doing "variable.startTracing()", and idk why Tracing tracing_instr = new RawInstruction($"trace ${_var_name}", line_index).toInstr() as Tracing; //Tracing tracing_instr = new Tracing(line_index, new List<Expression>{_var_expr}); // <- does not work either :( tracing_instr.execute(); } // update things 'n stuff Global.onElementaryInstruction(); // reset Context Context.reset(); }
/// <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); } }