Exemple #1
0
        /// <summary>
        /// Remove a <see cref="Variable"/> and its references
        /// </summary>
        /// <param name="expr"> <see cref="Expression"/> resulting in a <see cref="Variable"/></param>
        /// <returns> <see cref="NullVar"/> (equivalent of null/void)</returns>
        private static NullVar deleteVarFunction(Expression expr)
        {
            // evaluate every expression
            Variable variable = expr.evaluate();
            string   var_name = variable.getName();

            // delete var
            Debugging.assert(Global.variableExistsInCurrentScope(var_name),
                             new AquilaExceptions.NameError($"Variable name \"{var_name}\" does not exist in the current Context"));
            // remove the Tracer if is traced
            if (variable.isTraced())
            {
                // remove from the usable variables
                Global.usable_variables.Remove(var_name);
                // Deletion Alteration
                var alter = new Alteration("delete_var", variable, null, new dynamic[] {});
                // Update the tracer with the death event
                variable.tracer.update(new Event(alter));
                // Remove the tracer
                Global.var_tracers.Remove(variable.tracer);
            }
            // remove from the dict
            Global.getCurrentDict().Remove(var_name);

            return(new NullVar());
        }
Exemple #2
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();
            }
        }
        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();
        }