Beispiel #1
0
        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
            }));
        }
Beispiel #2
0
        /// <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());
        }
Beispiel #3
0
        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
            }));
        }
Beispiel #4
0
        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();
        }
Beispiel #5
0
        /// <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);
        }
Beispiel #6
0
        /// <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));
        }
Beispiel #7
0
        /// <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);
            }
        }