/// <summary> /// Resolves an operands value, if its indirectly points to another value. /// </summary> /// <param name="instruction">Instruction to get operand from.</param> /// <param name="index">Index of operand to get.</param> /// <returns>Resolved operand.</returns> private RuntimeValue ResolveOperand(RuntimeInstruction instruction, int index) { return ResolveValue(GetOperand(instruction, index)); }
/// <summary> /// Gets an operand at a given index from a given instruction. /// </summary> /// <param name="instruction">Instruction to get operand from.</param> /// <param name="index">Index of operand to get.</param> /// <returns>Operand at index of instruction's operand list.</returns> private RuntimeValue GetOperand(RuntimeInstruction instruction, int index) { return instruction.Operands[index]; }
/// <summary> /// Changes this scripts state to the given state. /// </summary> public void ChangeState(StateSymbol symbol) { _callStack.Clear(); _runtimeStack.Clear(); _inAtom = false; _lockInstruction = null; _previousInAtom = false; }
/// <summary> /// Runs this threads byte code. /// </summary> /// <param name="timeslice">Amount of time this thread is allowed to run for.</param> /// <returns>1 if the script has been forced to stop by a latency instruction, 2 if it has been forced to stop by a stack base marker or 3 if by an exit instruction.</returns> public int Run(int timeslice) { // Check that this thread is actually running. if (_isRunning == false) return 5; // Check the pause timer of this current thread. if (_isPaused == true) { if (_pauseTimer.DurationMillisecond <= _pauseLength) return 0; _isPaused = false; } // Check we are not at the end of this script, if we are then if (_instructionPointer >= _process.Instructions.Length) return 0; // If the debugger is running then we can't continue :S. if (_debugger != null && _debugger.RunScript == false) return 6; // Keep running until our timeslice runs out. int ticks = Environment.TickCount; // Don't use a high speed timer - To slow. //int secondsTimer = Environment.TickCount; //int instrCount = 0; //HighPreformanceTimer instructionTimer = new HighPreformanceTimer(); //float[] opCodeTimes = new float[Enum.GetNames(typeof(OpCode)).Length]; while (true) { #if !DEBUG try { #endif //instructionTimer.Restart(); // Checks if this script is still in its timeslice. if (timeslice != -1 && (Environment.TickCount - ticks) > timeslice && _priority != Priority.RealTime && _inAtom == false) return 0; // General exit stuff. else if (_process == null || _callStack.Count == 0 || _instructionPointer >= _process.Instructions.Length || _isPaused == true || _isRunning == false || _isWaiting == true) return 5; // Debugger else if (_debugger != null && _debugger.RunScript == false) return 6; // Retrieve's and execute's the next instruction in the list. int originalPointer = _instructionPointer; // Execute instruction and return result if neccessary. RuntimeValue op1, op2, stack1; RuntimeInstruction instruction = _process.Instructions[_instructionPointer]; //if (Environment.TickCount - secondsTimer > 10) //{ // secondsTimer = Environment.TickCount; //if (_process.Url == "media\\scripts\\LTTP 2.0.fs") // System.Console.WriteLine(_process.Url+":"+(instrCount * 100) + " instrs/ps"); // instrCount = 0; //} //else // instrCount++; // This was originally a seperate function but to speed it up a bit it has been inlined. #region Instruction Execution switch (instruction.OpCode) { case OpCode.NOP: break; #region POP case OpCode.POP_OBJECT: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.Object; stack1 = _runtimeStack.Pop(); SetObjectValue(op1, stack1.ObjectIndex); if (stack1.ObjectIndex != -1) SetObjectValue(stack1, -1); break; case OpCode.POP_BOOL: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.BooleanLiteral; op1.BooleanLiteral = _runtimeStack.Pop().BooleanLiteral; break; case OpCode.POP_BYTE: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.ByteLiteral; op1.ByteLiteral = _runtimeStack.Pop().ByteLiteral; break; case OpCode.POP_INT: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.IntegerLiteral; op1.IntegerLiteral = _runtimeStack.Pop().IntegerLiteral; break; case OpCode.POP_SHORT: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.ShortLiteral; op1.ShortLiteral = _runtimeStack.Pop().ShortLiteral; break; case OpCode.POP_FLOAT: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.FloatLiteral; op1.FloatLiteral = _runtimeStack.Pop().FloatLiteral; break; case OpCode.POP_STRING: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.StringLiteral; op1.StringLiteral = _runtimeStack.Pop().StringLiteral; break; case OpCode.POP_LONG: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.LongLiteral; op1.LongLiteral = _runtimeStack.Pop().LongLiteral; break; case OpCode.POP_DOUBLE: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.DoubleLiteral; op1.DoubleLiteral = _runtimeStack.Pop().DoubleLiteral; break; case OpCode.POP_MEMORY_INDEX: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.Invalid; op2 = _runtimeStack.Pop(); // op1.MemoryIndex = op2.MemoryIndex; op1.StackIndex = op2.StackIndex; SetMemoryIndexValue(op1, op2.MemoryIndex); if (op2.MemoryIndex != -1) SetMemoryIndexValue(op2, -1); break; case OpCode.POP_NULL: _runtimeStack.Pop(); // Pop value of stack, we are not actually // going to be using it so ignore it. if (ResolveOperand(instruction, 0).ObjectIndex != -1) SetObjectValue(ResolveOperand(instruction, 0), -1); else if (ResolveOperand(instruction, 0).MemoryIndex != -1) SetMemoryIndexValue(ResolveOperand(instruction, 0), -1); ResolveOperand(instruction, 0).Clear(); // Nullify value. break; case OpCode.POP_DESTROY: stack1 = _runtimeStack.Pop(); if (stack1.ObjectIndex != -1) SetObjectValue(stack1, -1); else if (stack1.MemoryIndex != -1) SetMemoryIndexValue(stack1, -1); _runtimeStack.Pop(); break; #endregion #region PUSH case OpCode.PUSH_OBJECT: SetObjectValue(_runtimeStack.PushEmpty(RuntimeValueType.Object), ResolveOperand(instruction, 0).ObjectIndex); break; case OpCode.PUSH_BOOL: _runtimeStack.PushEmpty(RuntimeValueType.BooleanLiteral).BooleanLiteral = ResolveOperand(instruction, 0).BooleanLiteral; break; case OpCode.PUSH_BYTE: _runtimeStack.PushEmpty(RuntimeValueType.ByteLiteral).ByteLiteral = ResolveOperand(instruction, 0).ByteLiteral; break; case OpCode.PUSH_INT: _runtimeStack.PushEmpty(RuntimeValueType.IntegerLiteral).IntegerLiteral = ResolveOperand(instruction, 0).IntegerLiteral; break; case OpCode.PUSH_SHORT: _runtimeStack.PushEmpty(RuntimeValueType.ShortLiteral).ShortLiteral = ResolveOperand(instruction, 0).ShortLiteral; break; case OpCode.PUSH_FLOAT: _runtimeStack.PushEmpty(RuntimeValueType.FloatLiteral).FloatLiteral = ResolveOperand(instruction, 0).FloatLiteral; break; case OpCode.PUSH_STRING: _runtimeStack.PushEmpty(RuntimeValueType.StringLiteral).StringLiteral = ResolveOperand(instruction, 0).StringLiteral; break; case OpCode.PUSH_LONG: _runtimeStack.PushEmpty(RuntimeValueType.LongLiteral).LongLiteral = ResolveOperand(instruction, 0).LongLiteral; break; case OpCode.PUSH_DOUBLE: _runtimeStack.PushEmpty(RuntimeValueType.DoubleLiteral).DoubleLiteral = ResolveOperand(instruction, 0).DoubleLiteral; break; case OpCode.PUSH_MEMORY_INDEX: op1 = ResolveOperand(instruction, 0); op2 = _runtimeStack.PushEmpty(RuntimeValueType.Invalid); //op2.MemoryIndex = op1.MemoryIndex; op2.StackIndex = op1.StackIndex; SetMemoryIndexValue(op2, op1.MemoryIndex); break; case OpCode.PUSH_NULL: _runtimeStack.PushEmpty(RuntimeValueType.Invalid).Clear(); break; #endregion #region CAST // Value casting op codes. case OpCode.CAST_NULL: if (ResolveOperand(instruction, 0).ObjectIndex != -1) SetObjectValue(ResolveOperand(instruction, 0), -1); else if (ResolveOperand(instruction, 0).MemoryIndex != -1) SetMemoryIndexValue(ResolveOperand(instruction, 0), -1); ResolveOperand(instruction, 0).Clear(); break; case OpCode.CAST_BOOL: op1 = ResolveOperand(instruction, 0); switch (op1.ValueType) { case RuntimeValueType.Object: op1.BooleanLiteral = op1.ObjectIndex == 0 ? false : true; SetObjectValue(op1, -1); break; case RuntimeValueType.ByteLiteral: op1.BooleanLiteral = op1.ByteLiteral == 0 ? false : true; break; case RuntimeValueType.DoubleLiteral: op1.BooleanLiteral = op1.DoubleLiteral == 0 ? false : true; break; case RuntimeValueType.FloatLiteral: op1.BooleanLiteral = op1.FloatLiteral == 0 ? false : true; break; case RuntimeValueType.IntegerLiteral: op1.BooleanLiteral = op1.IntegerLiteral == 0 ? false : true; break; case RuntimeValueType.LongLiteral: op1.BooleanLiteral = op1.LongLiteral == 0 ? false : true; break; case RuntimeValueType.ShortLiteral: op1.BooleanLiteral = op1.ShortLiteral == 0 ? false : true; break; case RuntimeValueType.StringLiteral: op1.BooleanLiteral = (op1.StringLiteral == "1" || op1.StringLiteral.ToLower() == "true" ? true : false); break; } op1.ValueType = RuntimeValueType.BooleanLiteral; break; case OpCode.CAST_BYTE: op1 = ResolveOperand(instruction, 0); switch (op1.ValueType) { case RuntimeValueType.Object: op1.ByteLiteral = (byte)op1.ObjectIndex; SetObjectValue(op1, -1); break; case RuntimeValueType.BooleanLiteral: op1.ByteLiteral = byte.Parse(op1.BooleanLiteral.ToString()); break; case RuntimeValueType.DoubleLiteral: op1.ByteLiteral = (byte)op1.DoubleLiteral; break; case RuntimeValueType.FloatLiteral: op1.ByteLiteral = (byte)op1.FloatLiteral; break; case RuntimeValueType.IntegerLiteral: op1.ByteLiteral = (byte)op1.IntegerLiteral; break; case RuntimeValueType.LongLiteral: op1.ByteLiteral = (byte)op1.LongLiteral; break; case RuntimeValueType.ShortLiteral: op1.ByteLiteral = (byte)op1.ShortLiteral; break; case RuntimeValueType.StringLiteral: op1.ByteLiteral = op1.StringLiteral == "" ? (byte)0 : (op1.StringLiteral.IndexOf('.') >= 0 ? (byte)float.Parse(op1.StringLiteral) : byte.Parse(op1.StringLiteral)); break; } op1.ValueType = RuntimeValueType.ByteLiteral; break; case OpCode.CAST_INT: op1 = ResolveOperand(instruction, 0); switch (op1.ValueType) { case RuntimeValueType.Object: op1.IntegerLiteral = (int)op1.ObjectIndex; SetObjectValue(op1, -1); break; case RuntimeValueType.BooleanLiteral: op1.IntegerLiteral = (op1.BooleanLiteral == true ? 1 : 0); break; case RuntimeValueType.ByteLiteral: op1.IntegerLiteral = (int)op1.ByteLiteral; break; case RuntimeValueType.DoubleLiteral: op1.IntegerLiteral = (int)op1.DoubleLiteral; break; case RuntimeValueType.FloatLiteral: op1.IntegerLiteral = (int)op1.FloatLiteral; break; case RuntimeValueType.LongLiteral: op1.IntegerLiteral = (int)op1.LongLiteral; break; case RuntimeValueType.ShortLiteral: op1.IntegerLiteral = (int)op1.ShortLiteral; break; case RuntimeValueType.StringLiteral: op1.IntegerLiteral = op1.StringLiteral == "" ? 0 : (op1.StringLiteral.IndexOf('.') >= 0 ? (int)float.Parse(op1.StringLiteral) : int.Parse(op1.StringLiteral)); break; } op1.ValueType = RuntimeValueType.IntegerLiteral; break; case OpCode.CAST_SHORT: op1 = ResolveOperand(instruction, 0); switch (op1.ValueType) { case RuntimeValueType.Object: op1.ShortLiteral = (short)op1.ObjectIndex; SetObjectValue(op1, -1); break; case RuntimeValueType.BooleanLiteral: op1.ShortLiteral = (short)(op1.BooleanLiteral == true ? 1 : 0); break; case RuntimeValueType.ByteLiteral: op1.ShortLiteral = (short)op1.ByteLiteral; break; case RuntimeValueType.DoubleLiteral: op1.ShortLiteral = (short)op1.DoubleLiteral; break; case RuntimeValueType.FloatLiteral: op1.ShortLiteral = (short)op1.FloatLiteral; break; case RuntimeValueType.IntegerLiteral: op1.ShortLiteral = (short)op1.IntegerLiteral; break; case RuntimeValueType.LongLiteral: op1.ShortLiteral = (short)op1.LongLiteral; break; case RuntimeValueType.StringLiteral: op1.ShortLiteral = op1.StringLiteral == "" ? (short)0 : (op1.StringLiteral.IndexOf('.') >= 0 ? (short)float.Parse(op1.StringLiteral) : short.Parse(op1.StringLiteral)); break; } op1.ValueType = RuntimeValueType.ShortLiteral; break; case OpCode.CAST_FLOAT: op1 = ResolveOperand(instruction, 0); switch (op1.ValueType) { case RuntimeValueType.FloatLiteral: op1.FloatLiteral = (float)op1.ObjectIndex; SetObjectValue(op1, -1); break; case RuntimeValueType.BooleanLiteral: op1.FloatLiteral = (op1.BooleanLiteral == true ? 1 : 0); break; case RuntimeValueType.ByteLiteral: op1.FloatLiteral = (float)op1.ByteLiteral; break; case RuntimeValueType.DoubleLiteral: op1.FloatLiteral = (float)op1.DoubleLiteral; break; case RuntimeValueType.IntegerLiteral: op1.FloatLiteral = (float)op1.IntegerLiteral; break; case RuntimeValueType.LongLiteral: op1.FloatLiteral = (float)op1.LongLiteral; break; case RuntimeValueType.ShortLiteral: op1.FloatLiteral = (float)op1.ShortLiteral; break; case RuntimeValueType.StringLiteral: op1.FloatLiteral = op1.StringLiteral == "" ? 0 : float.Parse(op1.StringLiteral); break; } op1.ValueType = RuntimeValueType.FloatLiteral; break; case OpCode.CAST_DOUBLE: op1 = ResolveOperand(instruction, 0); switch (op1.ValueType) { case RuntimeValueType.Object: op1.DoubleLiteral = (double)op1.ObjectIndex; SetObjectValue(op1, -1); break; case RuntimeValueType.BooleanLiteral: op1.DoubleLiteral = (op1.BooleanLiteral == true ? 1 : 0); break; case RuntimeValueType.ByteLiteral: op1.DoubleLiteral = (double)op1.ByteLiteral; break; case RuntimeValueType.FloatLiteral: op1.DoubleLiteral = (double)op1.FloatLiteral; break; case RuntimeValueType.IntegerLiteral: op1.DoubleLiteral = (double)op1.IntegerLiteral; break; case RuntimeValueType.LongLiteral: op1.DoubleLiteral = (double)op1.LongLiteral; break; case RuntimeValueType.ShortLiteral: op1.DoubleLiteral = (double)op1.ShortLiteral; break; case RuntimeValueType.StringLiteral: op1.DoubleLiteral = op1.StringLiteral == "" ? 0 : double.Parse(op1.StringLiteral); break; } op1.ValueType = RuntimeValueType.DoubleLiteral; break; case OpCode.CAST_LONG: op1 = ResolveOperand(instruction, 0); switch (op1.ValueType) { case RuntimeValueType.Object: op1.LongLiteral = (long)op1.ObjectIndex; SetObjectValue(op1, -1); break; case RuntimeValueType.BooleanLiteral: op1.LongLiteral = (op1.BooleanLiteral == true ? 1 : 0); break; case RuntimeValueType.ByteLiteral: op1.LongLiteral = (long)op1.ByteLiteral; break; case RuntimeValueType.DoubleLiteral: op1.LongLiteral = (long)op1.DoubleLiteral; break; case RuntimeValueType.FloatLiteral: op1.LongLiteral = (long)op1.FloatLiteral; break; case RuntimeValueType.IntegerLiteral: op1.LongLiteral = (long)op1.IntegerLiteral; break; case RuntimeValueType.ShortLiteral: op1.LongLiteral = (long)op1.ShortLiteral; break; case RuntimeValueType.StringLiteral: op1.LongLiteral = op1.StringLiteral == "" ? 0 : (op1.StringLiteral.IndexOf('.') >= 0 ? (long)float.Parse(op1.StringLiteral) : long.Parse(op1.StringLiteral)); break; } op1.ValueType = RuntimeValueType.LongLiteral; break; case OpCode.CAST_Object: op1 = ResolveOperand(instruction, 0); switch (op1.ValueType) { case RuntimeValueType.BooleanLiteral: SetObjectValue(op1, (op1.BooleanLiteral == true ? 1 : 0)); break; case RuntimeValueType.ByteLiteral: SetObjectValue(op1, op1.ByteLiteral); break; case RuntimeValueType.DoubleLiteral: SetObjectValue(op1, (int)op1.DoubleLiteral); break; case RuntimeValueType.FloatLiteral: SetObjectValue(op1, (int)op1.FloatLiteral); break; case RuntimeValueType.IntegerLiteral: SetObjectValue(op1, op1.IntegerLiteral); break; case RuntimeValueType.LongLiteral: SetObjectValue(op1, (int)op1.LongLiteral); break; case RuntimeValueType.ShortLiteral: SetObjectValue(op1, op1.ShortLiteral); break; case RuntimeValueType.StringLiteral: SetObjectValue(op1, (op1.StringLiteral != "" ? (op1.StringLiteral.IndexOf('.') >= 0 ? (int)float.Parse(op1.StringLiteral) : int.Parse(op1.StringLiteral)) : 0)); break; } op1.ValueType = RuntimeValueType.Object; break; case OpCode.CAST_STRING: op1 = ResolveOperand(instruction, 0); switch (op1.ValueType) { case RuntimeValueType.Object: op1.StringLiteral = op1.ObjectIndex.ToString(); SetObjectValue(op1, -1); break; case RuntimeValueType.BooleanLiteral: op1.StringLiteral = (op1.BooleanLiteral == true ? "1" : "0"); break; case RuntimeValueType.ByteLiteral: op1.StringLiteral = op1.ByteLiteral.ToString(); break; case RuntimeValueType.DoubleLiteral: op1.StringLiteral = op1.DoubleLiteral.ToString(); break; case RuntimeValueType.FloatLiteral: op1.StringLiteral = op1.FloatLiteral.ToString(); break; case RuntimeValueType.IntegerLiteral: op1.StringLiteral = op1.IntegerLiteral.ToString(); break; case RuntimeValueType.LongLiteral: op1.StringLiteral = op1.LongLiteral.ToString(); break; case RuntimeValueType.ShortLiteral: op1.StringLiteral = op1.ShortLiteral.ToString(); break; } op1.ValueType = RuntimeValueType.StringLiteral; break; #endregion #region MOV // Arithmetic op codes. case OpCode.MOV_BOOL: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.BooleanLiteral; op1.BooleanLiteral = ResolveOperand(instruction, 1).BooleanLiteral; break; case OpCode.MOV_BYTE: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.ByteLiteral; op1.ByteLiteral = ResolveOperand(instruction, 1).ByteLiteral; break; case OpCode.MOV_INT: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.IntegerLiteral; op1.IntegerLiteral = ResolveOperand(instruction, 1).IntegerLiteral; break; case OpCode.MOV_SHORT: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.ShortLiteral; op1.ShortLiteral = ResolveOperand(instruction, 1).ShortLiteral; break; case OpCode.MOV_FLOAT: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.FloatLiteral; op1.FloatLiteral = ResolveOperand(instruction, 1).FloatLiteral; break; case OpCode.MOV_DOUBLE: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.DoubleLiteral; op1.DoubleLiteral = ResolveOperand(instruction, 1).DoubleLiteral; break; case OpCode.MOV_LONG: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.LongLiteral; op1.LongLiteral = ResolveOperand(instruction, 1).LongLiteral; break; case OpCode.MOV_OBJECT: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.Object; SetObjectValue(op1, ResolveOperand(instruction, 1).ObjectIndex); break; case OpCode.MOV_NULL: if (ResolveOperand(instruction, 0).ObjectIndex != -1) SetObjectValue(ResolveOperand(instruction, 0), -1); else if (ResolveOperand(instruction, 0).MemoryIndex != -1) SetMemoryIndexValue(ResolveOperand(instruction, 0), -1); ResolveOperand(instruction, 0).Clear(); break; case OpCode.MOV_STRING: op1 = ResolveOperand(instruction, 0); op1.ValueType = RuntimeValueType.StringLiteral; op1.StringLiteral = ResolveOperand(instruction, 1).StringLiteral; break; case OpCode.MOV_MEMORY_INDEX: op1 = ResolveOperand(instruction, 0); op2 = ResolveOperand(instruction, 1); //op1.MemoryIndex = op2.MemoryIndex; op1.StackIndex = op2.StackIndex; SetMemoryIndexValue(op1, op2.MemoryIndex); break; #endregion #region MUL case OpCode.MUL_BYTE: ResolveOperand(instruction, 0).ByteLiteral *= ResolveOperand(instruction, 1).ByteLiteral; break; case OpCode.MUL_INT: ResolveOperand(instruction, 0).IntegerLiteral *= ResolveOperand(instruction, 1).IntegerLiteral; break; case OpCode.MUL_SHORT: ResolveOperand(instruction, 0).ShortLiteral *= ResolveOperand(instruction, 1).ShortLiteral; break; case OpCode.MUL_FLOAT: ResolveOperand(instruction, 0).FloatLiteral *= ResolveOperand(instruction, 1).FloatLiteral; break; case OpCode.MUL_DOUBLE: ResolveOperand(instruction, 0).DoubleLiteral *= ResolveOperand(instruction, 1).DoubleLiteral; break; case OpCode.MUL_LONG: ResolveOperand(instruction, 0).LongLiteral *= ResolveOperand(instruction, 1).LongLiteral; break; #endregion #region DIV case OpCode.DIV_BYTE: ResolveOperand(instruction, 0).ByteLiteral /= ResolveOperand(instruction, 1).ByteLiteral; break; case OpCode.DIV_INT: ResolveOperand(instruction, 0).IntegerLiteral /= ResolveOperand(instruction, 1).IntegerLiteral; break; case OpCode.DIV_SHORT: ResolveOperand(instruction, 0).ShortLiteral /= ResolveOperand(instruction, 1).ShortLiteral; break; case OpCode.DIV_FLOAT: ResolveOperand(instruction, 0).FloatLiteral /= ResolveOperand(instruction, 1).FloatLiteral; break; case OpCode.DIV_DOUBLE: ResolveOperand(instruction, 0).DoubleLiteral /= ResolveOperand(instruction, 1).DoubleLiteral; break; case OpCode.DIV_LONG: ResolveOperand(instruction, 0).LongLiteral /= ResolveOperand(instruction, 1).LongLiteral; break; #endregion #region ADD case OpCode.ADD_STRING: ResolveOperand(instruction, 0).StringLiteral += ResolveOperand(instruction, 1).StringLiteral; break; case OpCode.ADD_BYTE: ResolveOperand(instruction, 0).ByteLiteral += ResolveOperand(instruction, 1).ByteLiteral; break; case OpCode.ADD_INT: ResolveOperand(instruction, 0).IntegerLiteral += ResolveOperand(instruction, 1).IntegerLiteral; break; case OpCode.ADD_SHORT: ResolveOperand(instruction, 0).ShortLiteral += ResolveOperand(instruction, 1).ShortLiteral; break; case OpCode.ADD_FLOAT: ResolveOperand(instruction, 0).FloatLiteral += ResolveOperand(instruction, 1).FloatLiteral; break; case OpCode.ADD_DOUBLE: ResolveOperand(instruction, 0).DoubleLiteral += ResolveOperand(instruction, 1).DoubleLiteral; break; case OpCode.ADD_LONG: ResolveOperand(instruction, 0).LongLiteral += ResolveOperand(instruction, 1).LongLiteral; break; #endregion #region SUB case OpCode.SUB_BYTE: ResolveOperand(instruction, 0).ByteLiteral -= ResolveOperand(instruction, 1).ByteLiteral; break; case OpCode.SUB_INT: ResolveOperand(instruction, 0).IntegerLiteral -= ResolveOperand(instruction, 1).IntegerLiteral; break; case OpCode.SUB_SHORT: ResolveOperand(instruction, 0).ShortLiteral -= ResolveOperand(instruction, 1).ShortLiteral; break; case OpCode.SUB_FLOAT: ResolveOperand(instruction, 0).FloatLiteral -= ResolveOperand(instruction, 1).FloatLiteral; break; case OpCode.SUB_DOUBLE: ResolveOperand(instruction, 0).DoubleLiteral -= ResolveOperand(instruction, 1).DoubleLiteral; break; case OpCode.SUB_LONG: ResolveOperand(instruction, 0).LongLiteral -= ResolveOperand(instruction, 1).LongLiteral; break; #endregion #region INC case OpCode.INC_BYTE: ResolveOperand(instruction, 0).ByteLiteral++; break; case OpCode.INC_INT: ResolveOperand(instruction, 0).IntegerLiteral++; break; case OpCode.INC_SHORT: ResolveOperand(instruction, 0).ShortLiteral++; break; case OpCode.INC_FLOAT: ResolveOperand(instruction, 0).FloatLiteral++; break; case OpCode.INC_DOUBLE: ResolveOperand(instruction, 0).DoubleLiteral++; break; case OpCode.INC_LONG: ResolveOperand(instruction, 0).LongLiteral++; break; #endregion #region DEC case OpCode.DEC_BYTE: ResolveOperand(instruction, 0).ByteLiteral--; break; case OpCode.DEC_INT: ResolveOperand(instruction, 0).IntegerLiteral--; break; case OpCode.DEC_SHORT: ResolveOperand(instruction, 0).ShortLiteral--; break; case OpCode.DEC_FLOAT: ResolveOperand(instruction, 0).FloatLiteral--; break; case OpCode.DEC_DOUBLE: ResolveOperand(instruction, 0).DoubleLiteral--; break; case OpCode.DEC_LONG: ResolveOperand(instruction, 0).LongLiteral--; break; #endregion #region NEG case OpCode.NEG_BYTE: ResolveOperand(instruction, 0).ByteLiteral = (byte)(-(int)ResolveOperand(instruction, 0).ByteLiteral); break; case OpCode.NEG_INT: ResolveOperand(instruction, 0).IntegerLiteral = -ResolveOperand(instruction, 0).IntegerLiteral; break; case OpCode.NEG_SHORT: ResolveOperand(instruction, 0).ShortLiteral = (short)(-(int)ResolveOperand(instruction, 0).ShortLiteral); break; case OpCode.NEG_FLOAT: ResolveOperand(instruction, 0).FloatLiteral = -ResolveOperand(instruction, 0).FloatLiteral; break; case OpCode.NEG_DOUBLE: ResolveOperand(instruction, 0).DoubleLiteral = -ResolveOperand(instruction, 0).DoubleLiteral; break; case OpCode.NEG_LONG: ResolveOperand(instruction, 0).LongLiteral = -ResolveOperand(instruction, 0).LongLiteral; break; #endregion #region ABS case OpCode.ABS_BYTE: ResolveOperand(instruction, 0).ByteLiteral = (byte)(+(int)ResolveOperand(instruction, 0).ByteLiteral); break; case OpCode.ABS_INT: ResolveOperand(instruction, 0).IntegerLiteral = +ResolveOperand(instruction, 0).IntegerLiteral; break; case OpCode.ABS_SHORT: ResolveOperand(instruction, 0).ShortLiteral = (short)(-(int)ResolveOperand(instruction, 0).ShortLiteral); break; case OpCode.ABS_FLOAT: ResolveOperand(instruction, 0).FloatLiteral = +ResolveOperand(instruction, 0).FloatLiteral; break; case OpCode.ABS_DOUBLE: ResolveOperand(instruction, 0).DoubleLiteral = +ResolveOperand(instruction, 0).DoubleLiteral; break; case OpCode.ABS_LONG: ResolveOperand(instruction, 0).LongLiteral = +ResolveOperand(instruction, 0).LongLiteral; break; #endregion #region Bitwise Operations case OpCode.BIT_OR_INT: ResolveOperand(instruction, 0).IntegerLiteral |= ResolveOperand(instruction, 0).IntegerLiteral; break; case OpCode.BIT_AND_INT: ResolveOperand(instruction, 0).IntegerLiteral &= ResolveOperand(instruction, 0).IntegerLiteral; break; case OpCode.BIT_XOR_INT: ResolveOperand(instruction, 0).IntegerLiteral ^= ResolveOperand(instruction, 0).IntegerLiteral; break; case OpCode.BIT_NOT_INT: ResolveOperand(instruction, 0).IntegerLiteral = ~ResolveOperand(instruction, 0).IntegerLiteral; break; case OpCode.BIT_SHL_INT: ResolveOperand(instruction, 0).IntegerLiteral <<= ResolveOperand(instruction, 0).IntegerLiteral; break; case OpCode.BIT_SHR_INT: ResolveOperand(instruction, 0).IntegerLiteral >>= ResolveOperand(instruction, 0).IntegerLiteral; break; #endregion #region Misc Operations case OpCode.EXP_INT: ResolveOperand(instruction, 0).IntegerLiteral = (int)Math.Pow(ResolveOperand(instruction, 0).IntegerLiteral, ResolveOperand(instruction, 1).IntegerLiteral); break; case OpCode.MOD_INT: if (ResolveOperand(instruction, 0).IntegerLiteral != 0 && ResolveOperand(instruction, 1).IntegerLiteral != 0) ResolveOperand(instruction, 0).IntegerLiteral %= ResolveOperand(instruction, 1).IntegerLiteral; else ResolveOperand(instruction, 0).IntegerLiteral = 0; break; #endregion #region CMP // Flow of control op codes. case OpCode.CMP_NULL: op1 = ResolveOperand(instruction, 0); _registers[(int)Register.Compare].IntegerLiteral = (op1.IsNull() == true || ((op1.DataType.DataType == DataType.Object) && _process.ObjectHeap[op1.ObjectIndex] == null)) ? 1 : 0; break; case OpCode.CMP_Object: RuntimeObject obj1 = ResolveOperand(instruction, 0).ObjectIndex == -1 ? null : _process.ObjectHeap[ResolveOperand(instruction, 0).ObjectIndex]; RuntimeObject obj2 = ResolveOperand(instruction, 1).ObjectIndex == -1 ? null : _process.ObjectHeap[ResolveOperand(instruction, 1).ObjectIndex]; if (obj1 as NativeObject != null && obj2 as NativeObject != null) _registers[(int)Register.Compare].IntegerLiteral = (((NativeObject)obj1).Object == ((NativeObject)obj2).Object) ? 0 : 1; else if (obj1 as NativeObject == null && obj2 as NativeObject == null) _registers[(int)Register.Compare].IntegerLiteral = 0; else _registers[(int)Register.Compare].IntegerLiteral = Math.Sign(ResolveOperand(instruction, 0).ObjectIndex - ResolveOperand(instruction, 1).ObjectIndex); break; case OpCode.CMP_BOOL: _registers[(int)Register.Compare].IntegerLiteral = Math.Sign((ResolveOperand(instruction, 0).BooleanLiteral == true ? 1 : 0) - (ResolveOperand(instruction, 1).BooleanLiteral == true ? 1 : 0)); break; case OpCode.CMP_BYTE: _registers[(int)Register.Compare].IntegerLiteral = Math.Sign(ResolveOperand(instruction, 0).ByteLiteral - ResolveOperand(instruction, 1).ByteLiteral); break; case OpCode.CMP_INT: _registers[(int)Register.Compare].IntegerLiteral = Math.Sign(ResolveOperand(instruction, 0).IntegerLiteral - ResolveOperand(instruction, 1).IntegerLiteral); break; case OpCode.CMP_SHORT: _registers[(int)Register.Compare].IntegerLiteral = Math.Sign(ResolveOperand(instruction, 0).ShortLiteral - ResolveOperand(instruction, 1).ShortLiteral); break; case OpCode.CMP_FLOAT: _registers[(int)Register.Compare].IntegerLiteral = Math.Sign(ResolveOperand(instruction, 0).FloatLiteral - ResolveOperand(instruction, 1).FloatLiteral); break; case OpCode.CMP_STRING: _registers[(int)Register.Compare].IntegerLiteral = Math.Sign(ResolveOperand(instruction, 0).StringLiteral.CompareTo(ResolveOperand(instruction, 1).StringLiteral)); break; case OpCode.CMP_LONG: _registers[(int)Register.Compare].IntegerLiteral = Math.Sign(ResolveOperand(instruction, 0).LongLiteral - ResolveOperand(instruction, 1).LongLiteral); break; case OpCode.CMP_DOUBLE: _registers[(int)Register.Compare].IntegerLiteral = Math.Sign(ResolveOperand(instruction, 0).DoubleLiteral - ResolveOperand(instruction, 1).DoubleLiteral); break; case OpCode.CMP_MEMORY_INDEX: _registers[(int)Register.Compare].IntegerLiteral = Math.Sign(ResolveOperand(instruction, 0).MemoryIndex - ResolveOperand(instruction, 1).MemoryIndex); break; #endregion #region JMP case OpCode.JMP_EQ: if (_registers[(int)Register.Compare].IntegerLiteral == 0) _instructionPointer = ResolveOperand(instruction, 0).InstrIndex; break; case OpCode.JMP_L: if (_registers[(int)Register.Compare].IntegerLiteral == -1) _instructionPointer = ResolveOperand(instruction, 0).InstrIndex; break; case OpCode.JMP_G: if (_registers[(int)Register.Compare].IntegerLiteral == 1) _instructionPointer = ResolveOperand(instruction, 0).InstrIndex; break; case OpCode.JMP_LE: if (_registers[(int)Register.Compare].IntegerLiteral == -1 || _registers[(int)Register.Compare].IntegerLiteral == 0) _instructionPointer = ResolveOperand(instruction, 0).InstrIndex; break; case OpCode.JMP_GE: if (_registers[(int)Register.Compare].IntegerLiteral == 1 || _registers[(int)Register.Compare].IntegerLiteral == 0) _instructionPointer = ResolveOperand(instruction, 0).InstrIndex; break; case OpCode.JMP_NE: if (_registers[(int)Register.Compare].IntegerLiteral != 0) _instructionPointer = ResolveOperand(instruction, 0).InstrIndex; break; case OpCode.JMP: _instructionPointer = ResolveOperand(instruction, 0).InstrIndex; break; #endregion #region IS case OpCode.IS_EQ: stack1 = _runtimeStack.PushEmpty(RuntimeValueType.BooleanLiteral); stack1.BooleanLiteral = (_registers[(int)Register.Compare].IntegerLiteral == 0); break; case OpCode.IS_L: stack1 = _runtimeStack.PushEmpty(RuntimeValueType.BooleanLiteral); stack1.BooleanLiteral = (_registers[(int)Register.Compare].IntegerLiteral == -1); break; case OpCode.IS_G: stack1 = _runtimeStack.PushEmpty(RuntimeValueType.BooleanLiteral); stack1.BooleanLiteral = (_registers[(int)Register.Compare].IntegerLiteral == 1); break; case OpCode.IS_LE: stack1 = _runtimeStack.PushEmpty(RuntimeValueType.BooleanLiteral); stack1.BooleanLiteral = (_registers[(int)Register.Compare].IntegerLiteral == -1 || _registers[(int)Register.Compare].IntegerLiteral == 0); break; case OpCode.IS_GE: stack1 = _runtimeStack.PushEmpty(RuntimeValueType.BooleanLiteral); stack1.BooleanLiteral = (_registers[(int)Register.Compare].IntegerLiteral == 1 || _registers[(int)Register.Compare].IntegerLiteral == 0); break; case OpCode.IS_NE: stack1 = _runtimeStack.PushEmpty(RuntimeValueType.BooleanLiteral); stack1.BooleanLiteral = (_registers[(int)Register.Compare].IntegerLiteral != 0); break; #endregion #region Logical Operations case OpCode.LOGICAL_AND: stack1 = _runtimeStack.PushEmpty(RuntimeValueType.BooleanLiteral); stack1.BooleanLiteral = (ResolveOperand(instruction, 0).BooleanLiteral && ResolveOperand(instruction, 1).BooleanLiteral); break; case OpCode.LOGICAL_OR: stack1 = _runtimeStack.PushEmpty(RuntimeValueType.BooleanLiteral); stack1.BooleanLiteral = (ResolveOperand(instruction, 0).BooleanLiteral || ResolveOperand(instruction, 1).BooleanLiteral); break; case OpCode.LOGICAL_NOT: stack1 = _runtimeStack.PushEmpty(RuntimeValueType.BooleanLiteral); stack1.BooleanLiteral = !ResolveOperand(instruction, 0).BooleanLiteral; break; #endregion #region Stack Frame Manipulation case OpCode.CALL: // Increase instruction following this call so we don't // end up going round is circles when this call returns. _instructionPointer++; CallFunction(ResolveOperand(instruction, 0).Symbol as FunctionSymbol, false); break; case OpCode.RETURN: // Find the function index and throw corruption error if its not there. RuntimeValue functionValue = _runtimeStack.Pop(); if (functionValue.ValueType != RuntimeValueType.StackFrameIndex && functionValue.ValueType != RuntimeValueType.StackBaseMarker) { // Ahh hell, lets try and recover. #if DEBUG Error("Stack has been corrupted."); #else while (functionValue.ValueType != RuntimeValueType.StackFrameIndex && functionValue.ValueType != RuntimeValueType.StackBaseMarker) { if (_runtimeStack.TopIndex == 0) { Error("Stack has been corrupted."); break; } functionValue = _runtimeStack.Pop(); } #endif } // Find the parameter count and local data size. int parameterCount = 0, localDataSize = 0; if (functionValue.Symbol.Type == SymbolType.Function) { parameterCount = ((FunctionSymbol)functionValue.Symbol).ParameterCount; localDataSize = ((FunctionSymbol)functionValue.Symbol).LocalDataSize; } // Find the return value stack entry and throw corruption error if its not there. RuntimeValue returnAddressValue = _runtimeStack[_runtimeStack.TopIndex - (localDataSize + 1)]; if (returnAddressValue.ValueType != RuntimeValueType.ReturnAddress) Error("Stack has been corrupted."); // Reduce the reference count of any local varaibles. DataTypeValue[] parameterTypes = new DataTypeValue[((FunctionSymbol)functionValue.Symbol).ParameterCount]; for (int i = 0; i < ((FunctionSymbol)functionValue.Symbol).ParameterCount; i++) parameterTypes[(((FunctionSymbol)functionValue.Symbol).ParameterCount - 1) - i] = ((VariableSymbol)((FunctionSymbol)functionValue.Symbol).Symbols[i]).DataType; // Remove reference counts for parameters. //for (int i = 0; i < parameterCount; i++) //{ // RuntimeValue parameter = _runtimeStack[(_runtimeStack.TopIndex - (parameterCount + 1)) + i]; // if (parameterTypes[i].DataType == DataType.Object && parameter.ObjectIndex != -1 && _process.ObjectHeap[parameter.ObjectIndex] != null) // { // _process.ObjectHeap[parameter.ObjectIndex].ReferenceCount--; // DIE! // } //} // Remove reference counts for local variables. //foreach (Symbol symbol in functionValue.Symbol.Symbols) //{ // if (!(symbol is VariableSymbol) || ((VariableSymbol)symbol).VariableType != VariableType.Local) continue; // RuntimeValue local = GetRuntimeValueLocal(symbol.Identifier); // if (((VariableSymbol)symbol).DataType.DataType == DataType.Object && local.ObjectIndex != -1 && _process.ObjectHeap[local.ObjectIndex] != null) // _process.ObjectHeap[local.ObjectIndex].ReferenceCount--; // DIE! //} // Pop the functions stack frame. //_runtimeStack.PopFrame(parameterCount + localDataSize + 1); for (int i = 0; i < (parameterCount + localDataSize + 1); i++) { RuntimeValue stack = _runtimeStack.Pop(); if (stack.ObjectIndex != -1) SetObjectValue(stack, -1); else if (stack.MemoryIndex != -1) SetMemoryIndexValue(stack, -1); } // Restore the previous stack. _runtimeStack.FrameIndex = functionValue.InstrIndex; // Jump to the return address. _instructionPointer = returnAddressValue.InstrIndex; //if (_process.Url == "media\\scripts\\LTTP 2.0.fs" && _callStack.Peek().ToString().ToLower() == "onrender") //{ // System.Console.WriteLine("\n\n--- OnRender Statistics ---"); // for (int i = 0; i < opCodeTimes.Length; i++) // System.Console.WriteLine("Time spent on " + ((OpCode)i) + " = " + opCodeTimes[i] + " ms"); //} // Pop this function off the call stack. _callStack.Pop(); // If its a stack base marker make sure we exit the loop at the end. if (functionValue.ValueType == RuntimeValueType.StackBaseMarker) return 2; // Out of things to run? if (_callStack.Count == 0) return 5; break; #endregion #region Execution // Execution related op codes. case OpCode.EXIT: _isRunning = false; _instructionPointer++; return 3; case OpCode.PAUSE: _isPaused = true; _pauseLength = ResolveOperand(instruction, 0).IntegerLiteral; _pauseTimer.Restart(); _instructionPointer++; return 0; case OpCode.GOTO_STATE: _process.ChangeState(ResolveOperand(instruction, 0).Symbol as StateSymbol); break; //return 4; #endregion #region Memory Allocation case OpCode.ALLOCATE_HEAP_NULL: SetMemoryIndexValue(ResolveOperand(instruction, 1), _process.AllocateHeap(ResolveOperand(instruction, 0).IntegerLiteral, RuntimeValueType.Invalid, null)); break; case OpCode.ALLOCATE_HEAP_BOOL: SetMemoryIndexValue(ResolveOperand(instruction, 1), _process.AllocateHeap(ResolveOperand(instruction, 0).IntegerLiteral, RuntimeValueType.BooleanLiteral, null)); break; case OpCode.ALLOCATE_HEAP_BYTE: SetMemoryIndexValue(ResolveOperand(instruction, 1), _process.AllocateHeap(ResolveOperand(instruction, 0).IntegerLiteral, RuntimeValueType.ByteLiteral, null)); break; case OpCode.ALLOCATE_HEAP_INT: SetMemoryIndexValue(ResolveOperand(instruction, 1), _process.AllocateHeap(ResolveOperand(instruction, 0).IntegerLiteral, RuntimeValueType.IntegerLiteral, null)); break; case OpCode.ALLOCATE_HEAP_SHORT: SetMemoryIndexValue(ResolveOperand(instruction, 1), _process.AllocateHeap(ResolveOperand(instruction, 0).IntegerLiteral, RuntimeValueType.ShortLiteral, null)); break; case OpCode.ALLOCATE_HEAP_FLOAT: SetMemoryIndexValue(ResolveOperand(instruction, 1), _process.AllocateHeap(ResolveOperand(instruction, 0).IntegerLiteral, RuntimeValueType.FloatLiteral, null)); break; case OpCode.ALLOCATE_HEAP_DOUBLE: SetMemoryIndexValue(ResolveOperand(instruction, 1), _process.AllocateHeap(ResolveOperand(instruction, 0).IntegerLiteral, RuntimeValueType.DoubleLiteral, null)); break; case OpCode.ALLOCATE_HEAP_LONG: SetMemoryIndexValue(ResolveOperand(instruction, 1), _process.AllocateHeap(ResolveOperand(instruction, 0).IntegerLiteral, RuntimeValueType.LongLiteral, null)); break; case OpCode.ALLOCATE_HEAP_Object: SetMemoryIndexValue(ResolveOperand(instruction, 1), _process.AllocateHeap(ResolveOperand(instruction, 0).IntegerLiteral, RuntimeValueType.Object, null)); break; case OpCode.ALLOCATE_HEAP_STRING: SetMemoryIndexValue(ResolveOperand(instruction, 1), _process.AllocateHeap(ResolveOperand(instruction, 0).IntegerLiteral, RuntimeValueType.StringLiteral, null)); break; case OpCode.DEALLOCATE_HEAP: op1 = ResolveOperand(instruction, 0); _process.MemoryHeap[op1.MemoryIndex - 1].ReferenceCount = 0; break; #endregion #region Debug // Debug op codes. case OpCode.BREAKPOINT: if (_debugger == null) ShowDebugger(); else if (_debugger.NotifyOnBreakPoint == true) _debugger.NotifyOfBreakPoint(); break; // These are for the debugger. We can ignore them :P. case OpCode.ENTER_STATEMENT: if (_debugger != null && _debugger.NotifyOnEnter == true) _debugger.NotifyOfEntry(); break; case OpCode.EXIT_STATEMENT: if (_debugger != null && _debugger.NotifyOnExit == true) _debugger.NotifyOfExit(); break; #endregion #region Thread syncronization case OpCode.LOCK: if (instruction.Locked == true) return 1; // Return and don't increment instruction pointer. else { instruction.Locked = true; _lockInstruction = instruction; } break; case OpCode.UNLOCK: _lockInstruction.Locked = false; break; case OpCode.ENTER_ATOM: _previousInAtom = _inAtom; _inAtom = true; break; case OpCode.LEAVE_ATOM: _inAtom = _previousInAtom; break; #endregion #region Member Modification case OpCode.CALL_METHOD: // Object, Symbol { // Grab the object we are invoked a method off. RuntimeValue objValue = ResolveOperand(instruction, 0); if (objValue.ObjectIndex == -1) Error("Attempt to call method of null object."); RuntimeObject obj = _process.ObjectHeap[objValue.ObjectIndex]; // Grab the function. FunctionSymbol symbol = ResolveOperand(instruction, 1).Symbol as FunctionSymbol; // Clean out the return register and push this function onto the callstack. _callStack.Push(symbol); _registers[(int)Register.Return].Clear(); // Invoke the method. if (obj.InvokeMethod(this, symbol) == false) Error("An error occured while attempting to call a objects method '"+symbol.ToString()+"'. The method may not exist or may not be public."); // Pop of this functions parameters. for (int i = 0; i < symbol.ParameterCount; i++) _runtimeStack.Pop(); // Pop this value off the call stack. _callStack.Pop(); break; } case OpCode.SET_MEMBER: // Object, symbol, value { // Grab the object we are invoked a method off. RuntimeValue objValue = ResolveOperand(instruction, 0); if (objValue.ObjectIndex == -1) Error("Attempt to set member of null object."); RuntimeObject obj = _process.ObjectHeap[objValue.ObjectIndex]; // Grab the variable. VariableSymbol symbol = ResolveOperand(instruction, 1).Symbol as VariableSymbol; // Invoke the method. if (obj.SetMember(this, symbol, ResolveOperand(instruction, 2)) == false) Error("An error occured while attempting to set an objects member. The member may not exist or may not be public."); break; } case OpCode.SET_MEMBER_INDEXED: // Object, symbol, value, index { // Grab the object we are invoked a method off. RuntimeValue objValue = ResolveOperand(instruction, 0); if (objValue.ObjectIndex == -1) Error("Attempt to set member of null object."); RuntimeObject obj = _process.ObjectHeap[objValue.ObjectIndex]; // Grab the variable. VariableSymbol symbol = ResolveOperand(instruction, 1).Symbol as VariableSymbol; // Invoke the method. if (obj.SetMember(this, symbol, ResolveOperand(instruction, 2), ResolveOperand(instruction, 3)) == false) Error("An error occured while attempting to set an objects member. The member may not exist or may not be public."); break; } case OpCode.GET_MEMBER: // Object, symbol { // Grab the object we are invoked a method off. RuntimeValue objValue = ResolveOperand(instruction, 0); if (objValue.ObjectIndex == -1) Error("Attempt to set member of null object."); RuntimeObject obj = _process.ObjectHeap[objValue.ObjectIndex]; // Grab the variable. VariableSymbol symbol = ResolveOperand(instruction, 1).Symbol as VariableSymbol; // Clean out the return register. _registers[(int)Register.Return].Clear(); // Invoke the method. if (obj.SetMember(this, symbol, ResolveOperand(instruction, 2)) == false) Error("An error occured while attempting to get an objects member. The member may not exist or may not be public."); break; } case OpCode.GET_MEMBER_INDEXED: // Object, symbol, index { // Grab the object we are invoked a method off. RuntimeValue objValue = ResolveOperand(instruction, 0); if (objValue.ObjectIndex == -1) Error("Attempt to set member of null object."); RuntimeObject obj = _process.ObjectHeap[objValue.ObjectIndex]; // Grab the variable. VariableSymbol symbol = ResolveOperand(instruction, 1).Symbol as VariableSymbol; // Clean out the return register. _registers[(int)Register.Return].Clear(); // Invoke the method. if (obj.SetMember(this, symbol, ResolveOperand(instruction, 2), ResolveOperand(instruction, 3)) == false) Error("An error occured while attempting to get an objects member. The member may not exist or may not be public."); break; } #endregion // 'ello, 'ello. What goin' on 'ere then. default: Error("Virtual Machine encountered an invalid operation code ("+instruction.OpCode.ToString()+")."); break; } #endregion // Move onto next instruction if this instruction has not progressed the instruction pointer. if (_instructionPointer == originalPointer) _instructionPointer++; //opCodeTimes[(int)instruction.OpCode] += (float)instructionTimer.DurationMillisecond; //if (_process.Url == "media\\scripts\\LTTP 2.0.fs") // System.Console.WriteLine(instruction.OpCode.ToString() + " executed in " + instructionTimer.DurationMillisecond + "ms"); _instructionsExecuted++; #if !DEBUG } catch (Exception e) { Error(e.Message); } #endif } }
/// <summary> /// Loads the byte code from a given binary reader. /// </summary> /// <param name="reader">BinaryReader to load byte code from.</param> private void LoadByteCode(BinaryReader reader) { // Check the header is correct if (reader.ReadByte() == 'C' && reader.ReadByte() == 'R' && reader.ReadByte() == 'X') { // Read in header variables. _compileFlags = (CompileFlags)reader.ReadInt32(); _internalVariableIndex = reader.ReadInt32(); _memorySize = reader.ReadInt32(); int globalScopeIndex = reader.ReadInt32(); int memberScopeIndex = reader.ReadInt32(); _defaultEngineStateIndex = reader.ReadInt32(); _defaultEditorStateIndex = reader.ReadInt32(); // Create a new memory heap of the correct size if (_memorySize > _memoryHeap.Length) _memoryHeap = new RuntimeValue[_memorySize]; for (int i = 0; i < _memorySize; i++) _memoryHeap[i] = new RuntimeValue(RuntimeValueType.Invalid); // Set the 'special' globals to their appropriate values. _memoryHeap[0].ValueType = RuntimeValueType.Object; _memoryHeap[0].ObjectIndex = 0; int defineCount = reader.ReadInt32(); int symbolCount = reader.ReadInt32(); int instructionCount = reader.ReadInt32(); int debugFileCount = 0; if ((_compileFlags & CompileFlags.Debug) != 0) debugFileCount = reader.ReadInt32(); // Read in debug file list. string[] debugFiles = new string[debugFileCount]; if ((_compileFlags & CompileFlags.Debug) != 0) { for (int i = 0; i < debugFileCount; i++) debugFiles[i] = reader.ReadString(); } // Read in the define list. for (int i = 0; i < defineCount; i++) { string ident = reader.ReadString(); TokenID valueID = (TokenID)reader.ReadInt32(); string value = reader.ReadString(); Define define = new Define(ident, value, valueID); _defineList.Add(define); } // Read in symbol list. _symbolList = new Symbol[symbolCount]; for (int i = 0; i < symbolCount; i++) { // Read in general details about symbol. SymbolType type = (SymbolType)reader.ReadByte(); string identifier = reader.ReadString(); int scopeIndex = reader.ReadInt32(); Symbol scope = null; Symbol symbol = null; if (scopeIndex != -1) scope = (Symbol)_symbolList[scopeIndex]; // Read in specialized details about symbol. switch (type) { case SymbolType.JumpTarget: continue; // Ignore jump targets. case SymbolType.Namespace: NamespaceSymbol namespaceSymbol = new NamespaceSymbol(scope); symbol = namespaceSymbol; break; case SymbolType.Enumeration: EnumerationSymbol enumSymbol = new EnumerationSymbol(scope); symbol = enumSymbol; break; case SymbolType.String: StringSymbol stringSymbol = new StringSymbol(scope, identifier); symbol = stringSymbol; break; case SymbolType.Function: FunctionSymbol functionSymbol = new FunctionSymbol(identifier, scope); symbol = functionSymbol; functionSymbol.EntryPoint = reader.ReadInt32(); functionSymbol.LocalDataSize = reader.ReadInt16(); functionSymbol.IsEvent = reader.ReadBoolean(); functionSymbol.IsConsole = reader.ReadBoolean(); functionSymbol.IsExport = reader.ReadBoolean(); functionSymbol.IsImport = reader.ReadBoolean(); functionSymbol.IsThreadSpawner = reader.ReadBoolean(); functionSymbol.IsMember = reader.ReadBoolean(); functionSymbol.ParameterCount = reader.ReadByte(); bool isArray = reader.ReadBoolean(); bool isReference = reader.ReadBoolean(); functionSymbol.ReturnType = new DataTypeValue((DataType)reader.ReadByte(), isArray, isReference); functionSymbol.AccessModifier = (SymbolAccessModifier)reader.ReadByte(); break; case SymbolType.State: StateSymbol stateSymbol = new StateSymbol(scope); symbol = stateSymbol; stateSymbol.IsEngineDefault = reader.ReadBoolean(); stateSymbol.IsEditorDefault = reader.ReadBoolean(); break; case SymbolType.Variable: VariableSymbol variableSymbol = new VariableSymbol(scope); symbol = variableSymbol; variableSymbol.DataType = new DataTypeValue((DataType)reader.ReadByte(), false, false); variableSymbol.DataType.IsReference = reader.ReadBoolean(); variableSymbol.IsArray = reader.ReadBoolean(); variableSymbol.DataType.IsArray = variableSymbol.IsArray; variableSymbol.IsConstant = reader.ReadBoolean(); variableSymbol.MemoryIndex = reader.ReadInt32(); variableSymbol.StackIndex = reader.ReadInt32(); variableSymbol.VariableType = (VariableType)reader.ReadByte(); variableSymbol.IsProperty = reader.ReadBoolean(); variableSymbol.AccessModifier = (SymbolAccessModifier)reader.ReadByte(); variableSymbol.ConstToken = new Token(TokenID.TypeIdentifier, reader.ReadString(), 0, 0, ""); break; case SymbolType.MetaData: MetaDataSymbol metaDataSymbol = new MetaDataSymbol(scope, identifier, ""); symbol = metaDataSymbol; metaDataSymbol.Value = reader.ReadString(); break; } symbol.Identifier = identifier; symbol.Index = i; _symbolList[i] = symbol; } // Retrieve global scope. _globalScope = _symbolList[globalScopeIndex] as FunctionSymbol; _memberScope = _symbolList[memberScopeIndex] as FunctionSymbol; //_currentState = _symbolList[_defaultEngineStateIndex] as StateSymbol; // Force this to be declared in the engine / editor. // Read in instruction list. _instructionList = new RuntimeInstruction[instructionCount]; for (int i = 0; i < instructionCount; i++) { // Read in instruction details and create a new instruction. OpCode opCode = (OpCode)reader.ReadByte(); int operandCount = reader.ReadByte(); RuntimeInstruction instruction = new RuntimeInstruction(opCode); _instructionList[i] = instruction; if ((_compileFlags & CompileFlags.Debug) != 0) { int fileIndex = reader.ReadSByte(); if (fileIndex != -1) instruction.File = debugFiles[fileIndex]; instruction.Offset = reader.ReadInt16(); instruction.Line = reader.ReadInt16(); } // Read in each operand attached to this instruction for (int k = 0; k < operandCount; k++) { // Read in general details about this operand and create // a new runtime value instance. RuntimeValueType opType = (RuntimeValueType)reader.ReadInt32(); RuntimeValue operand = new RuntimeValue(opType); instruction.Operands[instruction.OperandCount] = operand; instruction.OperandCount++; // Read in specialized info about this operand. switch(opType) { case RuntimeValueType.BooleanLiteral: operand.BooleanLiteral = reader.ReadBoolean(); break; case RuntimeValueType.ByteLiteral: operand.ByteLiteral = reader.ReadByte(); break; case RuntimeValueType.DirectMemory: operand.MemoryIndex = reader.ReadInt32(); break; case RuntimeValueType.DirectMemoryIndexed: operand.MemoryIndex = reader.ReadInt32(); operand.OffsetRegister = (Register)reader.ReadByte(); break; case RuntimeValueType.DirectStack: operand.StackIndex = reader.ReadInt32(); break; case RuntimeValueType.DirectStackIndexed: operand.StackIndex = reader.ReadInt32(); operand.OffsetRegister = (Register)reader.ReadByte(); break; case RuntimeValueType.DoubleLiteral: operand.DoubleLiteral = reader.ReadDouble(); break; case RuntimeValueType.FloatLiteral: operand.FloatLiteral = reader.ReadSingle(); break; case RuntimeValueType.IndirectMemory: operand.Register = (Register)reader.ReadByte(); break; case RuntimeValueType.IndirectMemoryIndexed: operand.Register = (Register)reader.ReadByte(); operand.OffsetRegister = (Register)reader.ReadByte(); break; case RuntimeValueType.IndirectStack: operand.Register = (Register)reader.ReadByte(); break; case RuntimeValueType.IndirectStackIndexed: operand.Register = (Register)reader.ReadByte(); operand.OffsetRegister = (Register)reader.ReadByte(); break; case RuntimeValueType.InstrIndex: operand.InstrIndex = reader.ReadInt32(); break; case RuntimeValueType.IntegerLiteral: operand.IntegerLiteral = reader.ReadInt32(); break; case RuntimeValueType.LongLiteral: operand.LongLiteral = reader.ReadInt64(); break; case RuntimeValueType.Register: operand.Register = (Register)reader.ReadByte(); break; case RuntimeValueType.ShortLiteral: operand.ShortLiteral = reader.ReadInt16(); break; case RuntimeValueType.SymbolIndex: operand.SymbolIndex = reader.ReadInt32(); operand.Symbol = (Symbol)_symbolList[operand.SymbolIndex]; if (operand.Symbol is StringSymbol) { operand.StringLiteral = operand.Symbol.Identifier; operand.ValueType = RuntimeValueType.StringLiteral; } break; } } } // Fill the member-function hash table. foreach (Symbol symbol in GlobalScope.Symbols) if (symbol != null && symbol.Type == SymbolType.Function && ((FunctionSymbol)symbol).AccessModifier == SymbolAccessModifier.Public) _memberFunctionHashTable.Add(symbol.ToString().ToLower(), symbol); } else throw new Exception("Unable to load script byte code, header is invalid."); }