protected void OnLog(string sMsg) { DebugPrint?.Invoke(sMsg); }
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 OnDebugPrint(string s) { DebugPrint?.Invoke(this, s); }