public virtual void run(VSMXObject globalVariables) { lock (this) { prefix = ""; pc = 0; exit = false; callStates = new Stack <VSMXCallState>(); pushCallState(VSMXNull.singleton, 0, false, true); this.globalVariables = globalVariables; VSMXBoolean.init(this); interpret(); callStates.Clear(); callState = null; prefix = ""; if (log.TraceEnabled) { log.trace(string.Format("Global variables after run(): {0}", globalVariables)); } } }
private void interpret(VSMXGroup code) { VSMXBaseObject o1, o2, o3, o, r; VSMXBaseObject[] arguments; float f1, f2, f; string s1, s2, s; int i1, i2, i; bool b; switch (code.Opcode) { case VSMXCode.VID_NOTHING: break; case VSMXCode.VID_OPERATOR_ASSIGN: o1 = stack.Pop().Value; o2 = stack.Pop(); if (o2 is VSMXReference) { if (log.TraceEnabled) { log.trace(string.Format("{0} = {1}", o2, o1)); } ((VSMXReference)o2).assign(o1); stack.Push(o1); } else { Console.WriteLine(string.Format("Line#{0:D} non-ref assignment {1}", pc - 1, code)); } break; case VSMXCode.VID_OPERATOR_ADD: o1 = stack.Pop().Value; o2 = stack.Pop().Value; if (o1 is VSMXString || o2 is VSMXString) { s1 = o1.StringValue; s2 = o2.StringValue; s = s2 + s1; stack.Push(new VSMXString(this, s)); } else { f1 = o1.FloatValue; f2 = o2.FloatValue; f = f2 + f1; stack.Push(new VSMXNumber(this, f)); } break; case VSMXCode.VID_OPERATOR_SUBTRACT: f1 = stack.Pop().FloatValue; f2 = stack.Pop().FloatValue; f = f2 - f1; stack.Push(new VSMXNumber(this, f)); break; case VSMXCode.VID_OPERATOR_MULTIPLY: f1 = stack.Pop().FloatValue; f2 = stack.Pop().FloatValue; f = f2 * f1; stack.Push(new VSMXNumber(this, f)); break; case VSMXCode.VID_OPERATOR_DIVIDE: f1 = stack.Pop().FloatValue; f2 = stack.Pop().FloatValue; f = f2 / f1; stack.Push(new VSMXNumber(this, f)); break; case VSMXCode.VID_OPERATOR_MOD: f1 = stack.Pop().FloatValue; f2 = stack.Pop().FloatValue; f = f2 % f1; stack.Push(new VSMXNumber(this, f)); break; case VSMXCode.VID_OPERATOR_POSITIVE: f1 = stack.Pop().FloatValue; f = f1; stack.Push(new VSMXNumber(this, f)); break; case VSMXCode.VID_OPERATOR_NEGATE: f1 = stack.Pop().FloatValue; f = -f1; stack.Push(new VSMXNumber(this, f)); break; case VSMXCode.VID_OPERATOR_NOT: b = stack.Pop().BooleanValue; b = !b; stack.Push(VSMXBoolean.getValue(b)); break; case VSMXCode.VID_P_INCREMENT: o = stack.Pop(); f = o.FloatValue; f += 1f; stack.Push(new VSMXNumber(this, f)); if (o is VSMXReference) { ((VSMXReference)o).assign(new VSMXNumber(this, f)); } else { Console.WriteLine(string.Format("Line#{0:D} non-ref increment {1}", pc - 1, code)); } break; case VSMXCode.VID_P_DECREMENT: o = stack.Pop(); f = o.FloatValue; f -= 1f; stack.Push(new VSMXNumber(this, f)); if (o is VSMXReference) { ((VSMXReference)o).assign(new VSMXNumber(this, f)); } else { Console.WriteLine(string.Format("Line#{0:D} non-ref increment {1}", pc - 1, code)); } break; case VSMXCode.VID_INCREMENT: o = stack.Pop(); f = o.FloatValue; stack.Push(new VSMXNumber(this, f)); if (o is VSMXReference) { ((VSMXReference)o).assign(new VSMXNumber(this, f + 1f)); } else { Console.WriteLine(string.Format("Line#{0:D} non-ref increment {1}", pc - 1, code)); } break; case VSMXCode.VID_DECREMENT: o = stack.Pop(); f = o.FloatValue; stack.Push(new VSMXNumber(this, f)); if (o is VSMXReference) { ((VSMXReference)o).assign(new VSMXNumber(this, f - 1f)); } else { Console.WriteLine(string.Format("Line#{0:D} non-ref decrement {1}", pc - 1, code)); } break; case VSMXCode.VID_OPERATOR_EQUAL: o1 = stack.Pop().Value; o2 = stack.Pop().Value; b = o1.Equals(o2); if (log.TraceEnabled) { //JAVA TO C# CONVERTER TODO TASK: The following line has a Java format specifier which cannot be directly translated to .NET: //ORIGINAL LINE: log.trace(String.format("%s == %s: %b", o1, o2, b)); log.trace(string.Format("%s == %s: %b", o1, o2, b)); } stack.Push(VSMXBoolean.getValue(b)); break; case VSMXCode.VID_OPERATOR_NOT_EQUAL: o1 = stack.Pop().Value; o2 = stack.Pop().Value; b = !o1.Equals(o2); if (log.TraceEnabled) { //JAVA TO C# CONVERTER TODO TASK: The following line has a Java format specifier which cannot be directly translated to .NET: //ORIGINAL LINE: log.trace(String.format("%s != %s: %b", o1, o2, b)); log.trace(string.Format("%s != %s: %b", o1, o2, b)); } stack.Push(VSMXBoolean.getValue(b)); break; case VSMXCode.VID_OPERATOR_IDENTITY: o1 = stack.Pop().Value; o2 = stack.Pop().Value; b = o1.identity(o2); stack.Push(VSMXBoolean.getValue(b)); break; case VSMXCode.VID_OPERATOR_NON_IDENTITY: o1 = stack.Pop().Value; o2 = stack.Pop().Value; b = !o1.identity(o2); stack.Push(VSMXBoolean.getValue(b)); break; case VSMXCode.VID_OPERATOR_LT: f1 = stack.Pop().FloatValue; f2 = stack.Pop().FloatValue; b = f2 < f1; stack.Push(VSMXBoolean.getValue(b)); break; case VSMXCode.VID_OPERATOR_LTE: f1 = stack.Pop().FloatValue; f2 = stack.Pop().FloatValue; b = f2 <= f1; stack.Push(VSMXBoolean.getValue(b)); break; case VSMXCode.VID_OPERATOR_GTE: f1 = stack.Pop().FloatValue; f2 = stack.Pop().FloatValue; b = f2 >= f1; stack.Push(VSMXBoolean.getValue(b)); break; case VSMXCode.VID_OPERATOR_GT: f1 = stack.Pop().FloatValue; f2 = stack.Pop().FloatValue; b = f2 > f1; stack.Push(VSMXBoolean.getValue(b)); break; case VSMXCode.VID_OPERATOR_INSTANCEOF: Console.WriteLine(string.Format("Line#{0:D} unimplemented {1}", pc - 1, code)); break; case VSMXCode.VID_OPERATOR_IN: Console.WriteLine(string.Format("Line#{0:D} unimplemented {1}", pc - 1, code)); break; case VSMXCode.VID_OPERATOR_TYPEOF: o = stack.Pop().Value; string typeOf = o.typeOf(); stack.Push(new VSMXString(this, typeOf)); break; case VSMXCode.VID_OPERATOR_B_AND: i1 = stack.Pop().IntValue; i2 = stack.Pop().IntValue; i = i1 & i2; stack.Push(new VSMXNumber(this, i)); break; case VSMXCode.VID_OPERATOR_B_XOR: i1 = stack.Pop().IntValue; i2 = stack.Pop().IntValue; i = i1 ^ i2; stack.Push(new VSMXNumber(this, i)); break; case VSMXCode.VID_OPERATOR_B_OR: i1 = stack.Pop().IntValue; i2 = stack.Pop().IntValue; i = i1 | i2; stack.Push(new VSMXNumber(this, i)); break; case VSMXCode.VID_OPERATOR_B_NOT: i1 = stack.Pop().IntValue; i = ~i1; stack.Push(new VSMXNumber(this, i)); break; case VSMXCode.VID_OPERATOR_LSHIFT: i1 = stack.Pop().IntValue; i2 = stack.Pop().IntValue; i = i2 << i1; stack.Push(new VSMXNumber(this, i)); break; case VSMXCode.VID_OPERATOR_RSHIFT: i1 = stack.Pop().IntValue; i2 = stack.Pop().IntValue; i = i2 >> i1; stack.Push(new VSMXNumber(this, i)); break; case VSMXCode.VID_OPERATOR_URSHIFT: i1 = stack.Pop().IntValue; i2 = stack.Pop().IntValue; i = (int)((uint)i2 >> i1); stack.Push(new VSMXNumber(this, i)); break; case VSMXCode.VID_STACK_COPY: o1 = stack.Peek(); stack.Push(o1); break; case VSMXCode.VID_STACK_SWAP: o1 = stack.Pop(); o2 = stack.Pop(); stack.Push(o1); stack.Push(o2); break; case VSMXCode.VID_END_STMT: stack.Clear(); break; case VSMXCode.VID_CONST_NULL: stack.Push(VSMXNull.singleton); break; case VSMXCode.VID_CONST_EMPTYARRAY: o = new VSMXArray(this); stack.Push(o); break; case VSMXCode.VID_CONST_BOOL: stack.Push(VSMXBoolean.getValue(code.value)); break; case VSMXCode.VID_CONST_INT: stack.Push(new VSMXNumber(this, code.value)); break; case VSMXCode.VID_CONST_FLOAT: stack.Push(new VSMXNumber(this, code.FloatValue)); break; case VSMXCode.VID_CONST_STRING: stack.Push(new VSMXString(this, mem.texts[code.value])); break; case VSMXCode.VID_CONST_OBJECT: break; case VSMXCode.VID_FUNCTION: stack.Push(new VSMXFunction(this, (code.id >> 8) & 0xFF, (code.id >> 24) & 0xFF, code.value)); break; case VSMXCode.VID_ARRAY: stack.Push(new VSMXArray(this)); break; case VSMXCode.VID_THIS: stack.Push(callState.ThisObject); break; case VSMXCode.VID_UNNAMED_VAR: stack.Push(new VSMXLocalVarReference(this, callState, code.value)); break; case VSMXCode.VID_VARIABLE: stack.Push(new VSMXReference(this, globalVariables, mem.names[code.value])); if (log.TraceEnabled) { log.trace(string.Format("{0} '{1}'", VSMXCode.VsmxDecOps[code.Opcode], mem.names[code.value])); } break; case VSMXCode.VID_PROPERTY: o = stack.Pop().Value; if (o is VSMXObject) { stack.Push(new VSMXReference(this, (VSMXObject)o, mem.properties[code.value])); if (log.TraceEnabled) { log.trace(string.Format("{0} '{1}': {2}", VSMXCode.VsmxDecOps[code.Opcode], mem.properties[code.value], stack.Peek())); } } else { stack.Push(o.getPropertyValue(mem.properties[code.value])); } break; case VSMXCode.VID_METHOD: o = stack.Pop().Value; stack.Push(new VSMXMethod(this, o, mem.properties[code.value])); if (log.TraceEnabled) { log.trace(string.Format("{0} '{1}'", VSMXCode.VsmxDecOps[code.Opcode], mem.properties[code.value])); } break; case VSMXCode.VID_SET_ATTR: o1 = stack.Pop().Value; o2 = stack.Pop(); o2.setPropertyValue(mem.properties[code.value], o1); if (log.TraceEnabled) { log.trace(string.Format("{0} {1}.{2} = {3}", VSMXCode.VsmxDecOps[code.Opcode], o2, mem.properties[code.value], o1)); } break; case VSMXCode.VID_UNSET: o1 = stack.Pop(); o1.deletePropertyValue(mem.properties[code.value]); break; case VSMXCode.VID_OBJ_ADD_ATTR: Console.WriteLine(string.Format("Line#{0:D} unimplemented {1}", pc - 1, code)); break; case VSMXCode.VID_ARRAY_INDEX: o1 = stack.Pop(); o2 = stack.Pop().Value; if (o2 is VSMXArray) { o = new VSMXReference(this, (VSMXObject)o2, o1.IntValue); if (log.TraceEnabled) { log.trace(string.Format("{0} VSMXArray {1}[{2:D}] = {3}", VSMXCode.VsmxDecOps[code.Opcode], o2, o1.IntValue, o)); } } else if (o2 is VSMXObject) { o = new VSMXReference(this, (VSMXObject)o2, o1.StringValue); if (log.TraceEnabled) { log.trace(string.Format("{0} VSMXObject {1}[{2}] = {3}", VSMXCode.VsmxDecOps[code.Opcode], o2, o1.StringValue, o)); } } else { o = o2.getPropertyValue(o1.StringValue); if (log.TraceEnabled) { log.trace(string.Format("{0} {1}[{2}] = {3}", VSMXCode.VsmxDecOps[code.Opcode], o2, o1.StringValue, o)); } } stack.Push(o); break; case VSMXCode.VID_ARRAY_INDEX_KEEP_OBJ: o1 = stack.Pop(); o2 = stack.Peek().Value; if (o2 is VSMXArray) { o = o2.getPropertyValue(o1.IntValue); } else { o = o2.getPropertyValue(o1.StringValue); } stack.Push(o); break; case VSMXCode.VID_ARRAY_INDEX_ASSIGN: o1 = stack.Pop().Value; o2 = stack.Pop(); o3 = stack.Pop().Value; if (o3 is VSMXArray) { o3.setPropertyValue(o2.IntValue, o1); } else { Console.WriteLine(string.Format("Line#{0:D} non-array index assignment {1}", pc - 1, code)); } break; case VSMXCode.VID_ARRAY_DELETE: o1 = stack.Pop(); o2 = stack.Pop().Value; if (o2 is VSMXArray) { o2.deletePropertyValue(o1.IntValue); } else { Console.WriteLine(string.Format("Line#{0:D} non-array delete {1}", pc - 1, code)); } break; case VSMXCode.VID_ARRAY_PUSH: o1 = stack.Pop().Value; o2 = stack.Pop().Value; if (o2 is VSMXArray) { int Length = ((VSMXArray)o2).Length; o2.setPropertyValue(Length, o1); stack.Push(o2); } else { Console.WriteLine(string.Format("Line#{0:D} non-array push {1}", pc - 1, code)); } break; case VSMXCode.VID_JUMP: pc = code.value; break; case VSMXCode.VID_JUMP_TRUE: o1 = stack.Pop(); b = o1.BooleanValue; if (b) { pc = code.value; } break; case VSMXCode.VID_JUMP_FALSE: o1 = stack.Pop(); b = !o1.BooleanValue; if (b) { pc = code.value; } break; case VSMXCode.VID_CALL_FUNC: arguments = popValues(code.value); o = stack.Pop().getValueWithArguments(code.value); if (o is VSMXFunction) { VSMXFunction function = (VSMXFunction)o; callFunction(function, VSMXNull.singleton, arguments, code.value, false); } else { stack.Push(VSMXNull.singleton); Console.WriteLine(string.Format("Line#{0:D} non-function call {1}", pc - 1, code)); } break; case VSMXCode.VID_CALL_METHOD: arguments = popValues(code.value); o = stack.Pop().getValueWithArguments(code.value); if (o is VSMXMethod) { VSMXMethod method = (VSMXMethod)o; VSMXFunction function = method.getFunction(code.value, arguments); if (function == null) { stack.Push(VSMXNull.singleton); Console.WriteLine(string.Format("Line#{0:D} non existing method {1}()", pc - 1, method.Name)); } else { callFunction(function, method.ThisObject, method.Arguments, method.NumberOfArguments, false); } } else if (o is VSMXFunction) { VSMXFunction function = (VSMXFunction)o; o = stack.Pop().Value; callFunction(function, o, arguments, code.value, false); } else { stack.Push(VSMXNull.singleton); Console.WriteLine(string.Format("Line#{0:D} non-method call {1}", pc - 1, code)); } break; case VSMXCode.VID_CALL_NEW: arguments = popValues(code.value); r = stack.Pop(); o = r.Value; if (o is VSMXArray) { if (code.value == 0) { stack.Push(new VSMXArray(this)); } else if (code.value == 1) { stack.Push(new VSMXArray(this, arguments[0].IntValue)); } else { Console.WriteLine(string.Format("Line#{0:D} wrong number of arguments for new Array {1}", pc - 1, code)); } } else if (o is VSMXFunction) { VSMXFunction function = (VSMXFunction)o; string className = null; if (r is VSMXReference) { className = ((VSMXReference)r).RefProperty; } VSMXObject thisObject = new VSMXObject(this, className); callFunction(function, thisObject, arguments, code.value, true); } else if (o is VSMXObject) { if (code.value == 0) { stack.Push(new VSMXObject(this, null)); } else { Console.WriteLine(string.Format("Line#{0:D} wrong number of arguments for new Object {1}", pc - 1, code)); } } else { stack.Push(new VSMXArray(this)); Console.WriteLine(string.Format("Line#{0:D} unimplemented {1}", pc - 1, code)); } break; case VSMXCode.VID_RETURN: o = stack.Pop().Value; if (callState.ReturnThis) { o = callState.ThisObject; } pc = callState.ReturnPc; if (callState.ExitAfterCall) { exit = true; } popCallState(); if (callState == null) { exit = true; } else { stack.Push(o); } break; case VSMXCode.VID_THROW: Console.WriteLine(string.Format("Line#{0:D} unimplemented {1}", pc - 1, code)); break; case VSMXCode.VID_TRY_BLOCK_IN: Console.WriteLine(string.Format("Line#{0:D} unimplemented {1}", pc - 1, code)); break; case VSMXCode.VID_TRY_BLOCK_OUT: Console.WriteLine(string.Format("Line#{0:D} unimplemented {1}", pc - 1, code)); break; case VSMXCode.VID_CATCH_FINALLY_BLOCK_IN: Console.WriteLine(string.Format("Line#{0:D} unimplemented {1}", pc - 1, code)); break; case VSMXCode.VID_CATCH_FINALLY_BLOCK_OUT: Console.WriteLine(string.Format("Line#{0:D} unimplemented {1}", pc - 1, code)); break; case VSMXCode.VID_END: exit = true; break; case VSMXCode.VID_DEBUG_FILE: //if (log.DebugEnabled) { Console.WriteLine(string.Format("debug file '{0}'", mem.texts[code.value])); } break; case VSMXCode.VID_DEBUG_LINE: //if (log.DebugEnabled) { Console.WriteLine(string.Format("debug line {0:D}", code.value)); } break; case VSMXCode.VID_MAKE_FLOAT_ARRAY: Console.WriteLine(string.Format("Line#{0:D} unimplemented {1}", pc - 1, code)); break; default: Console.WriteLine(string.Format("Line#{0:D} unimplemented {1}", pc - 1, code)); break; } }