/// <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.");
        }