private void Interpret() { object[] operation; object akkumulator; object register; scopes = new Scopes(); scopes.PushScope(external); scopes.PushScope(); int startTime = Environment.TickCount; Cancel = false; running = true; pc = 0; bool accepted; // bool continues; object xPos; object defaultRenamed; object yPos; while ((pc < code.Count - 1) & running) { akkumulator = null; register = null; operation = (Object[])code[pc]; switch ((Opcodes)operation.GetValue(0)) { // Konstante allozieren case Opcodes.opAllocConst: { // Parameter: Name der Konstanten; Wert scopes.Allocate(operation.GetValue(1).ToString(), operation.GetValue(2).ToString(), Identifier.IdentifierTypes.idConst); break; } // Variable allozieren case Opcodes.opAllocVar: { // Parameter: Name der Variablen scopes.Allocate(operation.GetValue(1).ToString()); break; } // Wert auf den Stack schieben case Opcodes.opPushValue: { // Parameter: Wert scopes.Push(operation.GetValue(1)); break; } // Wert einer Variablen auf den Stack schieben case Opcodes.opPushVariable: { // Parameter: Variablenname string name; try { var tmp = operation.GetValue(1); if (tmp.GetType() == typeof(Identifier)) { name = ((Identifier)tmp).value.ToString(); } else { name = tmp.ToString(); } register = scopes.Retrieve(name); } catch (Exception) { // Variable nicht alloziert, also bei Host nachfragen accepted = false; Retrieve?.Invoke(operation.GetValue(1).ToString(), register.ToString(), accepted); if (!accepted) { // der Host weiss nichts von der Var. Implizit anlegen tun wir // sie aber nicht, da sie hier auf sie sofort lesend zugegriffen // würde running = false; ErrorObject.Raise((int)InterpreterError.runErrors.errUnknownVar, "Code.Run", "Unknown variable '" + operation.GetValue(1) + "'", 0, 0, 0); } } if (register == null) { running = false; ErrorObject.Raise((int)InterpreterError.runErrors.errUninitializedVar, "Code.Run", "Variable '" + operation.GetValue(1) + "' not hasn´t been assigned a Value yet", 0, 0, 0); } else { if (register.GetType() == typeof(Identifier)) { scopes.Push(((Identifier)register).value); } else { scopes.Push(register.ToString()); } } break; } // entfernt obersten Wert vom Stack case Opcodes.opPop: { scopes.PopScopes(); break; } // legt den n-ten Stackwert zuoberst auf den Stack case Opcodes.opPopWithIndex: { // Parameter: Index in den Stack (von oben an gezählt: 0..n) object result; register = scopes.Pop(Convert.ToInt32(operation.GetValue(1))); if (register is Identifier) { result = ((Identifier)register).value; } else { result = register; } scopes.Push(result); break; } // Wert auf dem Stack einer Variablen zuweisen case Opcodes.opAssign: { // Parameter: Variablenname // Stack: der zuzuweisende Wert object result; register = scopes.Pop(); if (register is Identifier) { result = ((Identifier)register).value; } else { result = register; } if (!scopes.Assign(operation.GetValue(1).ToString(), result)) { ; } { // Variable nicht alloziert, also Host anbieten accepted = false; Assign?.Invoke(operation.GetValue(1).ToString(), result.ToString(), ref accepted); if (!accepted) { // Host hat nicht mit Var am Hut, dann legen wir // sie eben selbst an scopes.Allocate(operation.GetValue(1).ToString(), result.ToString()); } } break; } case Opcodes.opAdd: case Opcodes.opSub: case Opcodes.opMultiplication: case Opcodes.opDivision: case Opcodes.opDiv: case Opcodes.opMod: case Opcodes.opPower: case Opcodes.opStringConcat: case Opcodes.opOr: case Opcodes.opAnd: case Opcodes.opEq: case Opcodes.opNotEq: case Opcodes.oplt: case Opcodes.opLEq: case Opcodes.opGt: case Opcodes.opGEq: BinaryMathOperators(operation, akkumulator, register); break; case Opcodes.opNegate: case Opcodes.opNot: case Opcodes.opFactorial: case Opcodes.opSin: case Opcodes.opCos: case Opcodes.opTan: case Opcodes.opATan: UnaryMathOperators(operation); break; case Opcodes.opDebugPrint: { string msg = string.Empty; register = scopes.PopScopes(); if (register != null) { msg = ((Identifier)register).value.ToString(); } DebugPrint?.Invoke(msg); break; } case Opcodes.opDebugClear: { DebugClear?.Invoke(); break; } case Opcodes.opDebugShow: { DebugShow?.Invoke(); break; } case Opcodes.opDebugHide: { DebugHide?.Invoke(); break; } case Opcodes.opMessage: { try { string msg = string.Empty; int type = 0; register = scopes.PopScopes(); // Message akkumulator = scopes.PopScopes().value; // Type if (register is Identifier) { if (register != null) { if (register.GetType() == typeof(Identifier)) { msg = ((Identifier)register).value.ToString(); } else { msg = register.ToString(); } } } if (akkumulator != null) { if (akkumulator.GetType() == typeof(Identifier)) { type = Convert.ToInt32(((Identifier)akkumulator).value); } else { type = Convert.ToInt32(akkumulator); } } Message?.Invoke(type, msg); } catch (Exception) { Message?.Invoke(-1, string.Empty); } break; } case Opcodes.opMsgbox: { if (!AllowUi) { running = false; ErrorObject.Raise((int)InterpreterError.runErrors.errNoUIallowed, "Code.Run", "MsgBox-Statement cannot be executed when no UI-elements are allowed", 0, 0, 0); } register = scopes.PopScopes().value; // Title akkumulator = scopes.PopScopes().value; // Buttons try { // TODO:InputBox // scopes.Push(MsgBox(scopes.Pop, (MsgBoxStyle)Akkumulator.ToString(), Register)); } catch (Exception ex) { running = false; ErrorObject.Raise((int)InterpreterError.runErrors.errMath, "Code.Run", "Error during MsgBox-call: " + ex.HResult + " (" + ex.Message + ")", 0, 0, 0); } break; } case Opcodes.opDoEvents: { break; } case Opcodes.opInputbox: { if (!AllowUi) { running = false; ErrorObject.Raise((int)InterpreterError.runErrors.errNoUIallowed, "Code.Run", "Inputbox-Statement cannot be executed when no UI-elements are allowed", 0, 0, 0); } yPos = scopes.PopScopes().value; xPos = scopes.PopScopes().value; defaultRenamed = scopes.PopScopes().value; register = scopes.PopScopes().value; akkumulator = scopes.PopScopes().value; try { // TODO:InputBox //string Anwert = Microsoft.VisualBasic.Interaction.InputBox(Akkumulator.ToString(), Register.ToString(), defaultRenamed.ToString(), Convert.ToInt32(xPos), Convert.ToInt32(yPos)); //scopes.Push(Anwert); } catch (Exception ex) { running = false; ErrorObject.Raise((int)InterpreterError.runErrors.errMath, "Code.Run", "Error during MsgBox-call: " + ex.HResult + " (" + ex.Message + ")", 0, 0, 0); } break; } case Opcodes.opJump: { pc = Convert.ToInt32(operation.GetValue(1)) - 1; break; } case Opcodes.opJumpTrue: { akkumulator = scopes.PopScopes().value; if (Convert.ToBoolean(akkumulator)) { pc = Convert.ToInt32(operation.GetValue(1)) - 1; } break; } case Opcodes.opJumpFalse: { akkumulator = scopes.PopScopes().value; if (!Convert.ToBoolean(akkumulator)) { pc = Convert.ToInt32(operation.GetValue(1)) - 1; } break; } case Opcodes.opJumpPop: { pc = Convert.ToInt32(scopes.PopScopes().value) - 1; break; } case Opcodes.opPushScope: { scopes.PushScope(); break; } case Opcodes.opPopScope: { scopes.PopScopes(); break; } case Opcodes.opCall: { scopes.Allocate("~RETURNADDR", (pc + 1).ToString(), Identifier.IdentifierTypes.idConst); pc = Convert.ToInt32(operation.GetValue(1)) - 1; break; } case Opcodes.opReturn: { pc = Convert.ToInt32(Convert.ToDouble(scopes.Retrieve("~RETURNADDR").value, CultureInfo.InvariantCulture) - 1); break; } } pc = pc + 1; // zum nächsten Befehl // wurde Interpretation unterbrochen? if (Cancel) { running = false; ErrorObject.Raise((int)InterpreterError.runErrors.errCancelled, "Code.Run", "Code execution aborted", 0, 0, 0); } // Timeout erreicht? var tickPassed = (Environment.TickCount - startTime); if (CodeTimeout > 0 && tickPassed >= CodeTimeout) { running = false; ErrorObject.Raise((int)InterpreterError.runErrors.errTimedOut, "Code.Run", "Timeout reached: code execution has been aborted", 0, 0, 0); } } running = false; }
private void BinaryMathOperators(object[] operation, object accumulator, object register) { register = scopes.PopScopes(); accumulator = scopes.PopScopes(); if (register != null && accumulator != null) { try { switch ((Opcodes)operation.GetValue(0)) { case Opcodes.opAdd: { double tmpAk = 0.0D; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToDouble(((Identifier)accumulator).value, CultureInfo.InvariantCulture); } else if (Helper.IsNumericDouble(accumulator)) { tmpAk = Convert.ToDouble(accumulator, CultureInfo.InvariantCulture); } double tmpReg = 0.0D; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToDouble(((Identifier)register).value, CultureInfo.InvariantCulture); } else if (Helper.IsNumericDouble(register)) { tmpReg = Convert.ToDouble(register, CultureInfo.InvariantCulture); } scopes.Push(tmpAk + tmpReg); break; } case Opcodes.opSub: { var tmpAk = 0.0D; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToDouble(((Identifier)accumulator).value, CultureInfo.InvariantCulture); } else if (Helper.IsNumericDouble(accumulator)) { tmpAk = Convert.ToDouble(accumulator, CultureInfo.InvariantCulture); } double tmpReg = 0.0D; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToDouble(((Identifier)register).value, CultureInfo.InvariantCulture); } else if (Helper.IsNumericDouble(register)) { tmpReg = Convert.ToDouble(register, CultureInfo.InvariantCulture); } scopes.Push(tmpAk - tmpReg); break; } case Opcodes.opMultiplication: { double tmpAk = 0.0D; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToDouble(((Identifier)accumulator).value, CultureInfo.InvariantCulture); } else if (Helper.IsNumericDouble(accumulator)) { tmpAk = Convert.ToDouble(accumulator, CultureInfo.InvariantCulture); } double tmpReg = 0.0D; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToDouble((((Identifier)register)).value, CultureInfo.InvariantCulture); } else if (Helper.IsNumericDouble(register)) { tmpReg = Convert.ToDouble(register, CultureInfo.InvariantCulture); } scopes.Push(Convert.ToDouble(tmpAk, CultureInfo.InvariantCulture) * Convert.ToDouble(tmpReg, CultureInfo.InvariantCulture)); break; } case Opcodes.opDivision: { double tmpAk = 0.0D; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToDouble(((Identifier)accumulator).value, CultureInfo.InvariantCulture); } else if (Helper.IsNumericDouble(accumulator)) { tmpAk = Convert.ToDouble(accumulator, CultureInfo.InvariantCulture); } double tmpReg = 0.0D; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToDouble(((Identifier)register).value, CultureInfo.InvariantCulture); } else if (Helper.IsNumericDouble(register)) { tmpReg = Convert.ToDouble(register, CultureInfo.InvariantCulture); } scopes.Push(Convert.ToDouble(tmpAk, CultureInfo.InvariantCulture) / Convert.ToDouble(tmpReg, CultureInfo.InvariantCulture)); break; } case Opcodes.opDiv: { double tmpAk = 0.0D; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToDouble(((Identifier)accumulator).value, CultureInfo.InvariantCulture); } else if (Helper.IsNumericDouble(accumulator)) { tmpAk = Convert.ToDouble(accumulator, CultureInfo.InvariantCulture); } double tmpReg = 0.0D; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToDouble(((Identifier)register).value, CultureInfo.InvariantCulture); } else if (Helper.IsNumericDouble(register)) { tmpReg = Convert.ToDouble(register, CultureInfo.InvariantCulture); } scopes.Push(Convert.ToInt32(tmpAk, CultureInfo.InvariantCulture) / Convert.ToInt32(tmpReg, CultureInfo.InvariantCulture)); break; } case Opcodes.opMod: { double tmpAk = 0.0D; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToDouble(((Identifier)accumulator).value, CultureInfo.InvariantCulture); } else if (Helper.IsNumericDouble(accumulator)) { tmpAk = Convert.ToDouble(accumulator, CultureInfo.InvariantCulture); } double tmpReg = 0.0D; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToDouble(((Identifier)register).value, CultureInfo.InvariantCulture); } else if (Helper.IsNumericDouble(register)) { tmpReg = Convert.ToDouble(register, CultureInfo.InvariantCulture); } scopes.Push(Convert.ToDouble(tmpAk, CultureInfo.InvariantCulture) % Convert.ToDouble(tmpReg, CultureInfo.InvariantCulture)); break; } case Opcodes.opPower: { double tmpAk = 0.0D; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToDouble(((Identifier)accumulator).value, CultureInfo.InvariantCulture); } else if (Helper.IsNumericDouble(accumulator)) { tmpAk = Convert.ToDouble(accumulator, CultureInfo.InvariantCulture); } double tmpReg = 0.0D; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToDouble(((Identifier)register).value, CultureInfo.InvariantCulture); } else if (Helper.IsNumericDouble(register)) { tmpReg = Convert.ToDouble(register, CultureInfo.InvariantCulture); } scopes.Push(Math.Pow(Convert.ToDouble(tmpAk, CultureInfo.InvariantCulture), Convert.ToDouble(tmpReg, CultureInfo.InvariantCulture))); break; } case Opcodes.opStringConcat: { string tmpAk; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToString(((Identifier)accumulator).value); } else { tmpAk = Convert.ToString(accumulator); } string tmpReg; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToString(((Identifier)register).value); } else { tmpReg = Convert.ToString(register); } scopes.Push(tmpAk + tmpReg); break; } case Opcodes.opOr: { int tmpAk = 0; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToInt32(((Identifier)accumulator).value); } else if (Helper.IsNumericInt(accumulator)) { tmpAk = Convert.ToInt32(accumulator); } int tmpReg = 0; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToInt32(((Identifier)register).value); } else if (Helper.IsNumericInt(register)) { tmpReg = Convert.ToInt32(register); } scopes.Push(tmpAk | tmpReg); break; } case Opcodes.opAnd: { int tmpAk = 0; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToInt32(((Identifier)accumulator).value); } else if (Helper.IsNumericInt(accumulator)) { tmpAk = Convert.ToInt32(accumulator); } int tmpReg = 0; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToInt32(((Identifier)register).value); } else if (Helper.IsNumericInt(register)) { tmpReg = Convert.ToInt32(register); } scopes.Push(tmpAk & tmpReg); break; } case Opcodes.opEq // = : { string tmpAk; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToString(((Identifier)accumulator).value); } else { tmpAk = Convert.ToString(accumulator); } string tmpReg; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToString(((Identifier)register).value); } else { tmpReg = Convert.ToString(register); } scopes.Push(tmpAk.Equals(tmpReg)); break; } case Opcodes.opNotEq // <> : { string tmpAk; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToString(((Identifier)accumulator).value); } else { tmpAk = Convert.ToString(accumulator); } string tmpReg = string.Empty; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToString(((Identifier)register).value); } else if (!Helper.IsNumericInt(register)) { tmpReg = Convert.ToString(register); } scopes.Push(!tmpAk.Equals(tmpReg)); break; } case Opcodes.oplt // < : { double tmpAk = 0.0D; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToInt32(((Identifier)accumulator).value); } else if (Helper.IsNumericInt(accumulator)) { tmpAk = Convert.ToInt32(accumulator); } double tmpReg = 0.0D; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToInt32(((Identifier)register).value); } else if (Helper.IsNumericInt(register)) { tmpReg = Convert.ToInt32(register); } scopes.Push(tmpAk < tmpReg); break; } case Opcodes.opLEq // <= : { double tmpAk = 0.0D; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToInt32(((Identifier)accumulator).value); } else if (Helper.IsNumericInt(accumulator)) { tmpAk = Convert.ToInt32(accumulator); } double tmpReg = 0.0D; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToInt32(((Identifier)register).value); } else if (Helper.IsNumericInt(register)) { tmpReg = Convert.ToInt32(register); } scopes.Push(tmpAk <= tmpReg); break; } case Opcodes.opGt // > : { double tmpAk = 0.0D; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToInt32(((Identifier)accumulator).value); } else if (Helper.IsNumericInt(accumulator)) { tmpAk = Convert.ToInt32(accumulator); } double tmpReg = 0; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToInt32(((Identifier)register).value); } else if (Helper.IsNumericInt(register)) { tmpReg = Convert.ToInt32(register); } scopes.Push(tmpAk > tmpReg); break; } case Opcodes.opGEq // >= : { double tmpAk = 0.0D; if (accumulator.GetType() == typeof(Identifier)) { tmpAk = Convert.ToInt32(((Identifier)accumulator).value); } else if (Helper.IsNumericInt(accumulator)) { tmpAk = Convert.ToInt32(accumulator); } double tmpReg = 0.0D; if (register.GetType() == typeof(Identifier)) { tmpReg = Convert.ToInt32(((Identifier)register).value); } else if (Helper.IsNumericInt(register)) { tmpReg = Convert.ToInt32(register); } scopes.Push(tmpAk >= tmpReg); break; } } } catch (Exception ex) { running = false; ErrorObject.Raise((int)InterpreterError.runErrors.errMath, "Code.Run", "Error during calculation (binary op " + operation.GetValue(0).ToString() + "): " + ex.HResult + "(" + ex.Message + ")", 0, 0, 0); } } }
private void UnaryMathOperators(object[] operation) { var akkumulator = scopes.PopScopes().value; try { switch ((Opcodes)operation.GetValue(0)) { case Opcodes.opNegate: { double number = Formathelper.FormatDoubleNumber(akkumulator.ToString()); scopes.Push(number * -1); break; } case Opcodes.opNot: { var tmp = Convert.ToBoolean(akkumulator); scopes.Push(!tmp); break; } case Opcodes.opFactorial: { scopes.Push(Factorial(Convert.ToInt32(akkumulator))); break; } case Opcodes.opSin: { double number = Formathelper.FormatDoubleNumber(akkumulator.ToString()); scopes.Push(Math.Sin(number)); break; } case Opcodes.opCos: { double number = Formathelper.FormatDoubleNumber(akkumulator.ToString()); scopes.Push(Math.Cos(number)); break; } case Opcodes.opTan: { double number = Formathelper.FormatDoubleNumber(akkumulator.ToString()); scopes.Push(Math.Tan(number)); break; } case Opcodes.opATan: { double number = Formathelper.FormatDoubleNumber(akkumulator.ToString()); scopes.Push(Math.Atan(number)); break; } } } catch (Exception ex) { running = false; ErrorObject.Raise((int)InterpreterError.runErrors.errMath, "Code.Run", "Error during calculation (unary op " + operation.GetValue(0).ToString() + "): " + ex.HResult + " (" + ex.Message + ")", 0, 0, 0); } }