Beispiel #1
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();
        }
Beispiel #2
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);
            }
        }