Esempio n. 1
0
 /// <summary>
 /// unfreeze the status
 /// <para/>Exception will be raised if the context is not frozen
 /// </summary>
 public static void unfreeze()
 {
     if (Global.getSetting("flame mode"))
     {
         return;
     }
     Debugging.assert(_frozen);
     _frozen = false;
 }
Esempio n. 2
0
        /// <summary>
        /// Convert a list of <see cref="RawInstruction"/>s into a <see cref="Function"/>
        /// </summary>
        /// <param name="declaration_line"> First line, recursion, name, arguments</param>
        /// <param name="function_declaration"> The lines defining the function content</param>
        /// <returns> the corresponding <see cref="Function"/> object</returns>
        public static Function readFunction(string declaration_line, List <RawInstruction> function_declaration)
        {
            Debugging.assert(function_declaration.Count > 0); // >= 1
            bool resp = false;

            // function decl
            List <string> decl =
                StringUtils.splitStringKeepingStructureIntegrity(declaration_line, ' ', Global.base_delimiters);

            if (decl.Count == 4)
            {
                // function KEYWORD type name(args)
                Parser.print("special function. definition with count 4: " + decl[1]);
                Debugging.assert(decl[1] == "recursive"); // hardcoded.
                decl.RemoveAt(1);
                resp = true;                              // REPLACE WITH "rec-function", "end-rec-function"
            }
            Debugging.assert(decl.Count == 3);            // function type name(args)
            Debugging.assert(decl[0] == StringConstants.Keywords.FUNCTION_KEYWORD);
            // type
            string type_str = decl[1];

            // name
            Debugging.assert(decl[2].Contains("(") && decl[2].Contains(")"));
            int    name_sep_index = decl[2].IndexOf('(');
            string function_name  = decl[2].Substring(0, name_sep_index);

            Debugging.assert(StringUtils.validObjectName(function_name),
                             new AquilaExceptions.SyntaxExceptions.SyntaxError($"Invalid object name \"{function_name}\"")); // InvalidNamingException
            Debugging.assert(!functions_dict.ContainsKey(function_name),
                             new AquilaExceptions.FunctionNameError($"The function \"{function_name}\" is a predefined function. You cannot overwrite it"));
            // args
            string function_args_str = decl[2].Substring(name_sep_index + 1);

            function_args_str = function_args_str.Substring(0, function_args_str.Length - 1);
            Parser.print("name: " + function_name);
            Parser.print("args: " + StringUtils.dynamic2Str(function_args_str));
            List <string> function_args = function_args_str.Split(',').ToList();

            for (int i = 0; i < function_args.Count; i++)
            {
                function_args[i] = StringUtils.normalizeWhiteSpaces(function_args[i]);
            }

            if (function_args.Count == 1 && function_args[0] == "")
            {
                function_args.Clear();
            }

            Parser.print("args: " + StringUtils.dynamic2Str(function_args));

            // Instructions
            List <Instruction> instr_list = function_declaration.Select(raw_instruction => raw_instruction.toInstr()).ToList();

            return(new Function(function_name, type_str, function_args, instr_list, resp));
        }
Esempio n. 3
0
 /// <summary>
 /// Get the <see cref="Variable"/> from the current variable Dictionary.
 /// You an give the variable name with or without the "$" (<see cref="StringConstants.Other.VARIABLE_PREFIX"/>) prefix
 /// </summary>
 /// <param name="var_name"> The variable name (with or without the prefix)</param>
 /// <returns> the corresponding <see cref="Variable"/></returns>
 private static Variable variableFromName(string var_name)
 {
     if (var_name.StartsWith(StringConstants.Other.VARIABLE_PREFIX))
     {
         var_name = var_name.Substring(1);
     }
     Debugging.print("Variable access: ", var_name);
     //Interpreter.processInterpreterInput("vars");
     Debugging.assert(Global.variableExistsInCurrentScope(var_name),
                      new AquilaExceptions.NameError($"Variable name \"{var_name}\" does not exist in the current Context"));
     return(Global.variableFromName(var_name));
 }
Esempio n. 4
0
        /// <summary>
        /// Default function
        /// </summary>
        /// <para>
        /// Creates a copy of a <see cref="DynamicList"/>
        /// </para>
        /// <param name="list_expr"> the target <see cref="DynamicList"/></param>
        /// <returns> A new <see cref="DynamicList"/>. It's values are the same as the target list</returns>
        private static Variable copyListFunction(Expression list_expr)
        {
            // evaluate every expression
            Variable var_ = list_expr.evaluate();

            Debugging.assert(var_ is DynamicList); // TypeError
            DynamicList list = var_ as DynamicList;
            // copy list
            var raw = new List <dynamic>(list.getRawValue());

            return(Variable.fromRawValue(raw));
        }
Esempio n. 5
0
 /// <summary>
 /// Remove the last local context scope variable dict.
 /// This is called when exiting a nested instruction
 /// </summary>
 public static void resetLocalContextScope()
 {
     Debugging.print("exiting local scope (current): ", getLocalScopeDepth());
     Debugging.assert(getLocalScopeDepth() > 0);
     foreach (var pair in getCurrentDict().Where(pair => pair.Value.isTraced()))
     {
         pair.Value.tracer.update(new Event(new Alteration("delete_var", pair.Value,
                                                           pair.Value.getRawValue(), new dynamic[] {})));
     }
     removeVariableStackElement();
     Debugging.print("new local scope: " + getLocalScopeDepth());
 }
Esempio n. 6
0
        /// <summary>
        /// Removes the last added variable stack layer.
        /// This is called when exiting, for example, a function call
        /// </summary>
        public static void resetMainContextScope()
        {
            Debugging.print("exiting main scope depth (current): " + getMainScopeDepth());
            Debugging.assert(getMainScopeDepth() > 0); // cannot exit a function call or something in the main instruction loop
            foreach (var pair in _variable_stack.Peek().SelectMany(dictionary => dictionary.Where(pair => pair.Value.isTraced())))
            {
                pair.Value.tracer.update(new Event(new Alteration("delete_var", pair.Value,
                                                                  pair.Value.getRawValue(), Array.Empty <dynamic>())));
            }

            removeVariableStackLayer();
            Debugging.print("new main scope depth: " + getMainScopeDepth());
        }
Esempio n. 7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="name"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        private static Dictionary <string, Variable> args2Dict(string name, object[] args)
        {
            Dictionary <string, Variable> d = new Dictionary <string, Variable>();

            for (int i = 0; i < args.Length; i++)
            {
                Debugging.assert(args[i] is Expression);
                Variable v         = (args[i] as Expression).evaluate();
                string   func_name = user_functions[name].func_args[i];
                d.Add(func_name, v);
            }

            return(d);
        }
Esempio n. 8
0
        /// <summary>
        /// Append a value to the end of a list
        /// </summary>
        /// <param name="list_expr"> The list</param>
        /// <param name="value_expr"> The value</param>
        /// <returns> <see cref="NullVar"/> (equivalent of null/void)</returns>
        private static NullVar appendValue(Expression list_expr, Expression value_expr)
        {
            // extract list
            Variable list_var = list_expr.evaluate();

            Debugging.assert(list_var is DynamicList); // TypeError
            DynamicList list = list_var as DynamicList;
            // index
            Integer    index      = list.length();
            Expression index_expr = new Expression(index.getValue().ToString()); // this should definitely be ok

            // insert
            return(insertValueAt(list_expr, index_expr, value_expr));
        }
Esempio n. 9
0
        public override int compare(Variable other)
        {
            Debugging.assert(hasSameParent(other));
            dynamic other_value = other.getValue();

            trace("compare", new [] { other_value });
            if (numeric_value == other_value)
            {
                return(0);
            }
            if (numeric_value > other_value)
            {
                return(1);
            }
            return(-1);
        }
Esempio n. 10
0
        /// <summary>
        /// Delete the nth value of a list
        /// </summary>
        /// <param name="list_expr"> expression resulting in a <see cref="DynamicList"/> variable</param>
        /// <param name="index_expr"> expression resulting in a <see cref="Integer"/> variable</param>
        /// <returns> <see cref="NullVar"/> (equivalent of null/void)</returns>
        private static NullVar deleteValueAt(Expression list_expr, Expression index_expr)
        {
            // extract list
            Variable list_var = list_expr.evaluate();

            Debugging.assert(list_var is DynamicList); // TypeError
            DynamicList list = list_var as DynamicList;
            // extract index
            Variable index_var = index_expr.evaluate();

            Debugging.assert(index_var is Integer); // TypeError
            Integer index = index_var as Integer;

            // delete
            list.removeValue(index);
            return(new NullVar());
        }
Esempio n. 11
0
        /// <summary>
        /// Calculate the square root of a float
        /// </summary>
        /// <param name="expr"> The float</param>
        /// <returns> The sqrt of the input float</returns>
        private static Variable sqrtFunction(Expression expr)
        {
            Variable v = expr.evaluate();

            if (v is Integer)
            {
                int raw_int = v.getValue();
                // ReSharper disable once RedundantCast
                float raw_float = (float)raw_int;
                v = new FloatVar(raw_float);
            }
            Debugging.assert(v is FloatVar);
            double real      = (double)v.getValue();
            float  real_sqrt = (float)Math.Sqrt(real);

            return(new FloatVar(real_sqrt));
        }
Esempio n. 12
0
 internal static void testModeInstructionUpdate()
 {
     Debugging.assert(Global.getSetting("test mode"),
                      new AquilaExceptions.RuntimeError("Not in test mode"));
     // update instruction counter
     Global.test_values["instruction counter"]++;
     Debugging.print("- test run - Instruction count: ", Global.test_values["instruction counter"]);
     // still valid runtime ?
     if (Global.test_values["stopwatch"].ElapsedMilliseconds <= Global.test_values["max elapsed ms"] &&
         Global.test_values["instruction counter"] <= Global.test_values["max instruction counter"])
     {
         return;
     }
     // unfinished algorithm
     Global.test_values["unfinished run"] = true;
     throw new AquilaExceptions.RuntimeError("Test max run time exceeded");
 }
Esempio n. 13
0
        /// <summary>
        /// Add teh <see cref="Event"/> on top of the <see cref="Tracer.events"/> stack and
        /// process the make some assertions to detect abnormal behaviours
        /// </summary>
        /// <param name="event_"></param>
        public override void update(Event event_)
        {
            // blocked context ?
            if (Context.isFrozen() && !Global.getSetting("allow tracing in frozen context"))
            {
                return;
            }
            // checks
            Debugging.assert(event_.alter != null); // variable events can only hold Alterations, so checking for null

            // update
            events.Push(event_);
            printTrace("updated (value: " + StringUtils.dynamic2Str(peekValue()) + ")");

            // handle
            callUpdateHandler(event_.alter);
        }
Esempio n. 14
0
        public override int compare(Variable other)
        {
            Debugging.assert(hasSameParent(other));
            DynamicList other_list = (DynamicList)other;

            if (length().compare(other_list.length()) != 0)
            {
                return(length().compare(other_list.length()));
            }

            List <Variable> other_list_value = other.getValue();

            if (_list.Where((t, i) => other_list_value[i] != t).Any())
            {
                return(-1);
            }

            return(0);
        }
Esempio n. 15
0
        /// <summary>
        /// Insert the given value in the list at the given index
        /// </summary>
        /// <param name="list_expr"> The list</param>
        /// <param name="index_expr"> The index</param>
        /// <param name="value_expr"> The value</param>
        /// <returns> <see cref="NullVar"/> (equivalent of null/void)</returns>
        private static NullVar insertValueAt(Expression list_expr, Expression index_expr, Expression value_expr)
        {
            // extract list
            Variable list_var = list_expr.evaluate();

            Debugging.assert(list_var is DynamicList); // TypeError
            DynamicList list = list_var as DynamicList;
            // extract index
            Variable index_var = index_expr.evaluate();

            Debugging.assert(index_var is Integer);
            Integer index = index_var as Integer;
            // extract var
            Variable var_ = value_expr.evaluate();

            // insert
            list.insertValue(var_, index);
            return(new NullVar());
        }
Esempio n. 16
0
        public Declaration(int line_index, string var_name, Expression var_expr, string var_type = StringConstants.Types.AUTO_TYPE, bool assignment = true,
                           bool safe_mode = false,
                           bool overwrite = false,
                           bool constant  = false,
                           bool global    = false)
        {
            // mode: 0 -> new var (must not exist); 1 -> force overwrite (must exist); 2 -> safe overwrite (can exist)
            this.line_index = line_index;
            _var_name       = var_name;
            _var_expr       = var_expr;
            _var_type       = var_type;
            _assignment     = assignment;
            _constant       = constant;
            _global         = global;
            // check variable naming
            Debugging.assert(StringUtils.validObjectName(var_name),
                             new AquilaExceptions.SyntaxExceptions.SyntaxError($"Invalid object name \"{var_name}\""));
            // the declaration is not initiated in the right scope... cannot do this here
            bool var_exists = Global.variableExistsInCurrentScope(var_name);

            Debugging.print("new declaration: var_name = " + var_name +
                            ", var_expr = ", var_expr.expr,
                            ", var_type = ", var_type,
                            ", assignment = ", assignment,
                            ", mode = ", StringUtils.boolString(safe_mode, overwrite, _constant, _global),
                            ", exists = ", var_exists);
            // should not check overwriting modes if this is true
            if (Global.getSetting("implicit declaration in assignment"))
            {
                Debugging.print("implicit declaration in assignments, so skipping var existence checks (var exists: ", var_exists, ")");
                return;
            }

            if (safe_mode && var_exists)
            {
                Debugging.assert(!Global.variableFromName(var_name).isTraced());
            }
            if (overwrite)
            {
                Debugging.assert(var_exists);
            }
        }
Esempio n. 17
0
        /// <summary>
        /// Initialize the test run mode
        /// </summary>
        private static void initTestMode()
        {
            Debugging.assert(!Global.getSetting("test mode"),
                             new AquilaExceptions.RuntimeError("Already in test mode"));
            Global.setSetting("test mode", true);
            if (Global.test_values.Count != 0)
            {
                Global.test_values.Clear();
            }
            Stopwatch stopwatch = new Stopwatch();

            Global.test_values.Add("stopwatch", stopwatch);
            Global.test_values.Add("max elapsed ms", 10000); // n/1000 seconds
            Global.test_values.Add("instruction counter", 0);
            Global.test_values.Add("max instruction counter", 120);
            Global.test_values.Add("unfinished run", false);
            Global.test_values.Add("variable names", new List <string>());
            Global.test_values.Add("value variables", new List <string>());
            Global.test_values.Add("index variables", new List <string>());
            stopwatch.Start();
        }
Esempio n. 18
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());
        }
Esempio n. 19
0
        /// <summary>
        /// Set the value of the <see cref="_traced_var"/> (traced <see cref="Variable"/>) to be 'n' steps in the past ('n' <see cref="Alteration"/>s)
        /// </summary>
        /// <param name="n"> number of times to rewind the value of <see cref="_traced_var"/> once</param>
        public void rewind(int n = 1)
        {
            last_stack_count -= n;
            Debugging.assert(events.Count > 1); // 1 is for variable creation
            Debugging.assert(n < events.Count); // didn't rewind before creation of variable ?

            dynamic dyn_value;

            for (int i = 0; i < n; i++)
            {
                printTrace("rewind: ", i, "/", n);
                Event popped = events.Pop();
                printTrace("popped event: " + popped);
                dyn_value = popped.alter.main_value;
                printTrace("loop dyn_value: ", StringUtils.dynamic2Str(dyn_value));
            }

            Event new_ = peekEvent();

            printTrace("latest event after rewind: " + new_);
            dyn_value = peekValue();
            printTrace("final rewind value: " + StringUtils.dynamic2Str(dyn_value));
            _traced_var.forceSetValue(dyn_value);
        }
Esempio n. 20
0
        /// <summary>
        /// Process the <see cref="Event"/>
        /// </summary>
        /// <param name="event_"> <see cref="Event"/> that should be processed</param>
        public override void update(Event event_)
        {
            // blocked context ?
            if (Context.isFrozen() && !Global.getSetting("allow tracing in frozen context"))
            {
                printTrace("Context is blocked in function tracer update call. Normal behaviour ?");
                return;
            }
            // checks
            Debugging.assert(event_ != null);
            // extract
            events.Push(event_);

            printTrace("event stack size: " + events.Count);

            Alteration alter    = event_.alter;
            Variable   affected = alter.affected;

            Debugging.assert(affected != null);
            Debugging.assert(affected.isTraced());
            affected.tracer.update(new Event(new Alteration(traced_func, affected, event_.alter.main_value, event_.alter.minor_values)));  //! just push event_ !

            printTrace("updated all in function tracer update");
        }
Esempio n. 21
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));
        }
Esempio n. 22
0
        public Integer length() => assigned ? new Integer(_list.Count) : throw new AquilaExceptions.InvalidUsageException("Unassigned variable"); // AssignmentError

        public void validateIndex(Integer index)
        {
            assertAssignment();
            Debugging.assert(index.getValue() < _list.Count); // InvalidIndexException
        }
Esempio n. 23
0
        /// <summary>
        /// Get the value at the index in a list
        /// </summary>
        /// <param name="list_expr"> The list</param>
        /// <param name="index_list_expr"> The index</param>
        /// <returns></returns>
        private static Variable listAtFunction(Expression list_expr, Expression index_list_expr)
        {
            // extract list
            Variable list_var = list_expr.evaluate();

            Debugging.assert(list_var is DynamicList); // TypeError
            DynamicList list = list_var as DynamicList;
            // extract index
            Variable index_list_var = index_list_expr.evaluate();

            Debugging.assert(index_list_var is DynamicList); // TypeError
            DynamicList index_list = index_list_var as DynamicList;

            /*// test run ?
             * if (Global.getSetting("test mode"))
             * {
             *  // function to add to index dict
             *  void addToIndexList(string var_name)
             *  {
             *      if (var_name == "") return;
             *      var index_var_name_list = (List<string>) Global.test_values["index values"];
             *      // variable name already in index dict ?
             *      if (index_var_name_list.Contains(var_name)) return;
             *      // add to index dict
             *      index_var_name_list.Add(var_name);
             *  }
             * }*/
            // access at index
            Variable result = list.atIndexList(index_list);

            // trace list
            if (!list_var.isTraced())
            {
                return(result);
            }
            Tracer.printTrace("list_at last event: " + list_var.tracer.peekEvent());
            handleValueFunctionTracing("list_at", list,
                                       new dynamic[] { index_list.getValue() });
            // trace index
            //Tracer.printTrace("tmp list at ", index_list.toString());

            /*var index_list_var_value = index_list_var.getValue();
             * for (int i = 0; i < index_list_var_value.Count; i++)
             * {
             *  Variable index_var = index_list_var_value[i];
             *  var numeric_index = (NumericalValue) index_var;
             *  NumericalValue source = numeric_index.getTracedSource();
             *  if (source == null)
             *  {
             *      Tracer.printTrace("tmp index without source var");
             *      numeric_index.setName($"comp /{i}/");
             *      list.tracer.update(new Event(new Alteration("tmp_list_at", numeric_index,
             *          numeric_index.getValue(), new[] {list.getName(), index_list.getValue()},
             *          mode:"index")));
             *      continue;
             *  }
             *
             *  Tracer.printTrace("Traced source var: " + source.getName());
             *  numeric_index.setName($"comp /{i}/");
             *  list.tracer.update(new Event(new Alteration("tmp_list_at", numeric_index,
             *  numeric_index.getValue(), new[] {list.getName(), index_list.getValue()},
             *      mode:"index")));
             * }*/

            return(result);
        }
Esempio n. 24
0
 /// <summary>
 /// Does the function exists in the <see cref="functions_dict"/> or in the <see cref="user_functions"/> dict ?
 /// </summary>
 /// <param name="function_name"> Boolean value describing the function's existence</param>
 public static void assertFunctionExists(string function_name) =>
 Debugging.assert(functionExists(function_name),
                  new AquilaExceptions.FunctionNameError($"The function \"{function_name}\" does not exist"));
Esempio n. 25
0
        /// <summary>
        /// This function should be called at the end of every <see cref="Instruction.execute"/> call that is susceptible of
        /// changing the value of a <see cref="Variable"/>. It works in 3 steps:
        /// <para/>* Checks for any new assigned <see cref="Variable"/>s in the <see cref="Global._variable_stack"/> (if found: adds to the <see cref="Global.usable_variables"/>)
        /// <para/>* Update/Process all the awaiting <see cref="Event"/>s (<seealso cref="update"/>)
        /// <para/>* Check for any new <see cref="Event"/> which has not been processed by the <see cref="Global.tracer_update_handler_function"/>
        /// </summary>
        /// <param name="add_call_info"> stands for "additional calling information". If it has any value, it will be printed by the <see cref="Debugging.print"/> function for debugging</param>
        public static void updateTracers(string add_call_info = "")
        {
            if (Global.getSetting("test mode"))
            {
                return;
            }
            printTrace("updating tracers");
            // printTrace alter info about the call if needed
            if (add_call_info != "")
            {
                printTrace(add_call_info);
            }
            // check for new usable variables
            foreach (var pair in Global.getCurrentDict().Where(pair => !Global.usable_variables.Contains(pair.Key)))
            {
                printTrace("checking potential var ", pair.Value is NullVar ? StringConstants.Types.NULL_TYPE : pair.Value.getName());
                if (pair.Value is NullVar || !pair.Value.assigned)
                {
                    continue;
                }
                // new usable variable !
                printTrace("var ", pair.Value.getName(), " is usable (non-null & assigned)");
                Global.usable_variables.Add(pair.Key);
            }

            // checking tracers
            checkAllAwaitingEvents();

            // check tracer event stacks
            printTrace("checking variable tracers event stack counts");
            foreach (VarTracer tracer in Global.var_tracers)
            {
                // unread tracers updates
                while (tracer.last_stack_count != tracer.getStackCount())
                {
                    printTrace("stack count changed for ", tracer.getVar().getName(), " from ", tracer.last_stack_count, " to ", tracer.getStackCount());
                    //Global.stdoutWriteLine("call graphical function " + StringUtils.varList2String(tracer.getVar().getRawValue()) + " & call event: " + tracer.peekEvent().ToString());

                    // traced functions have already been processed. checking awaiting stacks
                    int diff = tracer.getStackCount() - tracer.last_stack_count;
                    Debugging.assert(diff > 0); // will run forever

                    tracer.last_stack_count++;  //! here
                }

                // awaiting tracer stacks
                while (tracer._awaiting_events.Count != 0)
                {
                    printTrace("awaiting stacks: ", tracer._awaiting_events.Count);
                    Alteration alter = tracer._awaiting_events.Peek().alter;
                    callUpdateHandler(alter);
                    tracer.update(tracer._awaiting_events.Pop());
                }
            }

            // update data_tree
            printTrace("Updating Global.data_tree");
            // ReSharper disable once InvertIf
            if (Global.getSetting("update data tree"))
            {
                Debugging.assert(Global.data_tree != null,
                                 new AquilaExceptions.RuntimeError("Tried to update data_tree, but it is null"));
                Global.data_tree = Global.data_tree.update();
            }
        }
Esempio n. 26
0
        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();
        }
Esempio n. 27
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);
            }
        }
Esempio n. 28
0
        /// <summary>
        /// Transforms a <see cref="RawInstruction"/> into an <see cref="Instruction"/>.
        /// <para/>The order of operations is:
        /// <para/>* variable declaration
        /// <para/>* variable modification
        /// <para/>* for loop
        /// <para/>* while loop
        /// <para/>* if statement
        /// <para/>* void function call
        /// </summary>
        /// <param name="line_index"> index of the line in the purged source code</param>
        /// <param name="raw_instr"> a <see cref="RawInstruction"/> to convert</param>
        /// <returns> the corresponding <see cref="Instruction"/></returns>
        /// <exception cref="AquilaExceptions.SyntaxExceptions.SyntaxError"> Invalid syntax</exception>
        private static Instruction rawInstr2Instr(int line_index, RawInstruction raw_instr)
        {
            /* Order of operations:
             * tracing
             * declaration
             * variable assignment
             * function definition
             * for loop
             * while loop
             * if statement
             * void function call
             */

            Parser.print($"from raw instr to instr: \"{raw_instr._instr}\" at line {line_index}");

            // split instruction
            List <string> instr = StringUtils.splitStringKeepingStructureIntegrity(raw_instr._instr, ' ', Global.base_delimiters);

            Parser.print("trace ?");
            // variable tracing
            if (instr[0] == StringConstants.Keywords.TRACE_KEYWORD)
            {
                if (Global.getSetting("auto trace"))
                {
                    Parser.print("\"trace\" instruction, but \"auto trace\" is set to true ?");
                }

                List <Expression> traced_vars = new List <Expression>();
                for (int i = 1; i < instr.Count; i++)
                {
                    traced_vars.Add(new Expression(instr[i]));
                }

                return(new Tracing(line_index, traced_vars));
            }

            Parser.print("decl ?");
            // variable declaration
            if (instr.Contains(StringConstants.Keywords.DECLARATION_KEYWORD))
            {
                // declaration modes
                bool safe_mode = false,
                     overwrite = false,
                     constant  = false,
                     global    = false;
                while (instr[0] != StringConstants.Keywords.DECLARATION_KEYWORD)
                {
                    switch (instr[0])
                    {
                    case StringConstants.Keywords.SAFE_DECLARATION_KEYWORD:
                        safe_mode = true;
                        Parser.print("safe mode !");
                        break;

                    case StringConstants.Keywords.OVERWRITE_DECLARATION_KEYWORD:
                        overwrite = true;
                        Parser.print("overwrite !");
                        break;

                    case StringConstants.Keywords.CONST_DECLARATION_KEYWORD:
                        constant = true;
                        Parser.print("const !");
                        break;

                    case StringConstants.Keywords.GLOBAL_DECLARATION_KEYWORD:
                        global = true;
                        Parser.print("global !");
                        break;

                    default:
                        throw new AquilaExceptions.UnknownKeywordError($"Unknown keyword in declaration: \"{instr[0]}\"");
                    }

                    instr.RemoveAt(0);
                }

                // remove the "decl"
                instr.RemoveAt(0);

                // define the type
                string type = StringConstants.Types.AUTO_TYPE;
                if (Global.type_list.Contains(instr[0]))
                {
                    type = instr[0];
                    instr.RemoveAt(0);
                    Debugging.assert(type != StringConstants.Types.NULL_TYPE,
                                     new AquilaExceptions.InvalidTypeError($"Cannot declare a variable with type: \"{StringConstants.Types.NULL_TYPE}\""));
                }

                Parser.print("instr: ", instr);

                Expression default_value;
                bool       valid_default_value;
                if (type != StringConstants.Types.AUTO_TYPE)
                {
                    default_value       = Global.default_values_by_var_type[type];
                    valid_default_value = true;
                }
                else
                {
                    default_value       = null;
                    valid_default_value = false;
                }
                var variable_declaration_buffer = new List <string>();
                var declarations = new List <Instruction>();

                foreach (string s in instr)
                {
                    Parser.print("Doing ", s, " with buffer ", StringUtils.dynamic2Str(variable_declaration_buffer));
                    // buffer should be "$var" "="
                    Parser.print(variable_declaration_buffer.Count);
                    if (variable_declaration_buffer.Count == 2)
                    {
                        Parser.print("adding with assignment", StringUtils.dynamic2Str(variable_declaration_buffer));
                        Debugging.assert(variable_declaration_buffer[1] == "=",
                                         new AquilaExceptions.SyntaxExceptions.SyntaxError($"Invalid declaration syntax at token: {s}"));
                        declarations.Add(new Declaration(line_index,
                                                         variable_declaration_buffer[0].Substring(1),
                                                         new Expression(s),
                                                         type,
                                                         true,
                                                         safe_mode,
                                                         overwrite,
                                                         constant,
                                                         global));
                        variable_declaration_buffer.Clear();
                        continue;
                    }
                    if (s.StartsWith(StringConstants.Other.VARIABLE_PREFIX))
                    {
                        if (variable_declaration_buffer.Any())
                        {
                            Debugging.assert(valid_default_value,
                                             new AquilaExceptions.InvalidTypeError($"Invalid variable type without assignment {StringConstants.Types.AUTO_TYPE}"));
                            // add the (empty) declaration
                            Parser.print("adding empty ", StringUtils.dynamic2Str(variable_declaration_buffer));
                            declarations.Add(new Declaration(line_index,
                                                             variable_declaration_buffer[0].Substring(1),
                                                             default_value,
                                                             type,
                                                             false,
                                                             safe_mode,
                                                             overwrite,
                                                             constant,
                                                             global));
                            // clear the buffer & restart
                            variable_declaration_buffer.Clear();
                            variable_declaration_buffer.Add(s);
                        }
                        else
                        {
                            // add variable to the buffer (start of buffer)
                            variable_declaration_buffer.Add(s);
                            Debugging.assert(variable_declaration_buffer.Count < 3,
                                             new AquilaExceptions.SyntaxExceptions.SyntaxError($"Invalid declaration syntax (buffer count > 3): {s}"));
                        }

                        continue;
                    }

                    // must be "="
                    Debugging.assert(s == "=",
                                     new AquilaExceptions.SyntaxExceptions.SyntaxError($"Cannot declare a value: {s}"));
                    variable_declaration_buffer.Add(s);
                }

                // trailing variable ?
                if (variable_declaration_buffer.Any())
                {
                    Parser.print("Trailing var decl buffer: ", variable_declaration_buffer);
                    Debugging.assert(variable_declaration_buffer.Count == 1,
                                     new AquilaExceptions.SyntaxExceptions.SyntaxError($"Invalid trailing declarations: {StringUtils.dynamic2Str(variable_declaration_buffer)}"));
                    declarations.Add(new Declaration(line_index, variable_declaration_buffer[0].Substring(1), default_value,
                                                     type, false, safe_mode, overwrite, constant, global));
                }

                return(new MultiInstruction(declarations.ToArray()));
            }

            Parser.print("assignment ?");
            // variable assignment
            if (instr.Count > 1 && instr[1].EndsWith("=") && (instr[0][0] == '$' || instr[0].Contains("(")))
            {
                Debugging.assert(instr.Count > 2); // syntax ?unfinished line?
                string var_designation = instr[0];
                string equal_sign      = instr[1];
                instr.RemoveAt(0); // remove "$name"
                instr.RemoveAt(0); // remove "{op?}="
                // reunite all on the right side of the "=" sign
                string assignment_string = StringUtils.reuniteBySymbol(instr);
                // custom operator in assignment
                if (equal_sign.Length != 1)
                {
                    Parser.print("Custom operator detected: ", equal_sign);
                    Debugging.assert(equal_sign.Length == 2);
                    assignment_string = $"{var_designation} {equal_sign[0]} ({assignment_string})";
                }
                // get the Expresion
                Expression assignment = new Expression(assignment_string);
                return(new Assignment(line_index, var_designation, assignment));
            }
            // increment || decrement
            if (instr.Count == 2 && (instr[1] == "++" || instr[1] == "--"))
            {
                Parser.print("Increment or Decrement detected");
                return(new Assignment(line_index, instr[0], new Expression($"{instr[0]} {instr[1][0]} 1")));
            }

            Parser.print("function definition ?");
            if (instr[0] == StringConstants.Keywords.FUNCTION_KEYWORD)
            {
                Debugging.assert(raw_instr._is_nested);                 // syntax???
                Debugging.assert(instr.Count == 3 || instr.Count == 4); // "function" "type" ("keyword"?) "name(args)"

                Function func = Functions.readFunction(raw_instr._instr, raw_instr._sub_instr_list);
                return(new FunctionDef(line_index, func));
            }

            Parser.print("for loop ?");
            // for loop
            if (instr[0] == StringConstants.Keywords.FOR_KEYWORD)
            {
                Debugging.assert(raw_instr._is_nested);                               // syntax???
                Debugging.assert(instr[1].StartsWith("(") && instr[1].EndsWith(")")); // syntax
                List <string> sub_instr =
                    StringUtils.splitStringKeepingStructureIntegrity(instr[1].Substring(1, instr[1].Length - 2), ';', Global.base_delimiters);
                sub_instr = StringUtils.normalizeWhiteSpacesInStrings(sub_instr);
                Parser.print(sub_instr);
                Debugging.assert(sub_instr.Count == 3); // syntax

                // start
                Instruction start = new RawInstruction(sub_instr[0], raw_instr._line_index).toInstr();

                // stop
                Expression condition = new Expression(sub_instr[1]);

                // step
                Instruction step = new RawInstruction(sub_instr[2], raw_instr._line_index).toInstr();

                // instr
                List <Instruction> loop_instructions = new List <Instruction>();
                int add_index = 0;
                foreach (RawInstruction loop_instr in raw_instr._sub_instr_list)
                {
                    loop_instructions.Add(rawInstr2Instr(line_index + ++add_index, loop_instr));
                }

                return(new ForLoop(line_index, start, condition, step, loop_instructions));
            }

            Parser.print("while loop ?");
            // while loop
            if (instr[0] == StringConstants.Keywords.WHILE_KEYWORD)
            {
                // syntax check
                Debugging.assert(instr.Count == 2); // syntax

                // condition expression
                Expression condition = new Expression(instr[1]);

                // instr
                List <Instruction> loop_instructions = new List <Instruction>();
                int add_index = 0;
                foreach (RawInstruction loop_instr in raw_instr._sub_instr_list)
                {
                    loop_instructions.Add(rawInstr2Instr(line_index + ++add_index, loop_instr));
                }

                return(new WhileLoop(line_index, condition, loop_instructions));
            }

            Parser.print("if statement ?");
            // if statement
            if (instr[0] == StringConstants.Keywords.IF_KEYWORD)
            {
                // syntax check
                Debugging.assert(instr.Count == 2); // syntax

                // condition expression
                Expression condition = new Expression(instr[1]);

                // instr
                List <Instruction> if_instructions   = new List <Instruction>();
                List <Instruction> else_instructions = new List <Instruction>();
                bool if_section = true;
                int  add_index  = 0;
                foreach (RawInstruction loop_instr in raw_instr._sub_instr_list)
                {
                    add_index++;
                    if (if_section)
                    {
                        if (loop_instr._instr == StringConstants.Keywords.ELSE_KEYWORD)
                        {
                            if_section = false;
                            continue;
                        }
                        if_instructions.Add(rawInstr2Instr(line_index + add_index, loop_instr));
                    }
                    else
                    {
                        else_instructions.Add(rawInstr2Instr(line_index + add_index, loop_instr));
                    }
                }

                return(new IfCondition(line_index, condition, if_instructions, else_instructions));
            }

            Parser.print("function call ?");
            // function call with spaces between function name and parenthesis
            if (instr.Count == 2 && instr[1].StartsWith("("))
            {
                Parser.print("function call with space between name and first parenthesis. Merging ", instr[0], " and ", instr[1]);
                instr[0] += instr[1];
                instr.RemoveAt(1);
            }
            // void function call (no return value, or return value not used)
            if (instr[0].Contains('('))
            {
                // syntax checks
                Debugging.assert(instr.Count == 1);                     // syntax
                Debugging.assert(instr[0][instr[0].Length - 1] == ')'); // syntax

                // function name
                string function_name = instr[0].Split('(')[0]; // extract function name
                if (Global.getSetting("check function existence before runtime"))
                {
                    Functions.assertFunctionExists(function_name);                                                               // assert function exists
                }
                Parser.print("expr_string for function call ", instr[0]);
                // extract args
                string exprs = instr[0].Substring(function_name.Length + 1); // + 1 : '('
                exprs = exprs.Substring(0, exprs.Length - 1);                // ')'
                List <string> arg_expr_str = StringUtils.splitStringKeepingStructureIntegrity(exprs, ',', Global.base_delimiters);

                // no args ?
                if (arg_expr_str.Count == 1 && StringUtils.normalizeWhiteSpaces(arg_expr_str[0]) == "")
                {
                    return(new VoidFunctionCall(line_index, function_name));
                }

                // ReSharper disable once SuggestVarOrType_Elsewhere
                object[] args = arg_expr_str.Select(x => (object)new Expression(x)).ToArray();

                return(new VoidFunctionCall(line_index, function_name, args));
            }

            // try using this as a function ?
            if (instr.Count == 1 && Functions.functionExists(instr[0]))
            {
                Parser.print($"Call the function \"{instr[0]}\" with no parameters");
                return(new VoidFunctionCall(line_index, instr[0]));
            }

            Parser.print("unrecognized line: \"", raw_instr._instr, "\"");
            throw new AquilaExceptions.SyntaxExceptions.SyntaxError($"Unknown syntax \"{raw_instr._instr}\"");
        }