예제 #1
0
    public void PrintState()
    {
        string output = "";

        output += "Thread:\r\n\t\tPC: " + mInstructionPtr + "\r\n\r\n";
        output += "\t\tFP: " + mFramePtr + "\r\n\r\n";
        output += "Local:\n\r";

        for (int i = 0; i < mLocal.mStore.Length; ++i)
        {
            CFibreReg val = mLocal.mStore[i];

            if (val == null)
            {
                break;
            }

            output += "L" + i + "\t";
            if (i < 100)
            {
                output += "\t";
            }
            output += val.mType + ", " + val.PrintVal() + "\n\r";
        }

        output += "\r\nCall Frames:\n\r";

        CFibreCallFrame[] callFrames = mCallFrames.ToArray();
        for (int i = 0; i < callFrames.Length; ++i)
        {
            CFibreCallFrame frame = callFrames[i];

            output += "F" + i + "\t";
            if (i < 100)
            {
                output += "\t";
            }
            output += frame.mNextInstruction + ", " + frame.mFramePtr + "\n\r";
        }

        File.WriteAllText(CGame.DataDirectory + "thread.txt", output);
    }
예제 #2
0
    public ERunResult Run()
    {
        while (mInstructionPtr != mScript.mProgram.Count)
        {
            // Fetch
            CFibreOpcode op = mScript.mProgram[mInstructionPtr++];

            // Decode & Execute
            switch (op.mOpcode)
            {
            case EFibreOpcodeType.NOP:
                break;

            case EFibreOpcodeType.MOV:
            {
                _SetRegister(op.mOperand[0], _GetRegister(op.mOperand[1]));
            } break;

            case EFibreOpcodeType.NOT:
            case EFibreOpcodeType.NEG:
            {
                CFibreReg        opL   = _GetRegister(op.mOperand[1]);
                BinaryOpDelegate opDel = _opTable[(int)op.mOpcode, (int)opL.mType, 0];

                if (opDel == null)
                {
                    throw new CFibreRuntimeException("Can't perform operator " + op.mOpcode + " on type " + opL.mType, this);
                }

                _SetRegister(op.mOperand[0], opDel(opL, null));
            }
            break;

            case EFibreOpcodeType.MUL:
            case EFibreOpcodeType.DIV:
            case EFibreOpcodeType.INC:
            case EFibreOpcodeType.DEC:
            case EFibreOpcodeType.MOD:

            case EFibreOpcodeType.EQL:
            case EFibreOpcodeType.NQL:
            case EFibreOpcodeType.LES:
            case EFibreOpcodeType.GRT:
            case EFibreOpcodeType.LQL:
            case EFibreOpcodeType.GQL:

            case EFibreOpcodeType.AND:
            case EFibreOpcodeType.LOR:
            {
                CFibreReg        opL   = _GetRegister(op.mOperand[1]);
                CFibreReg        opR   = _GetRegister(op.mOperand[2]);
                BinaryOpDelegate opDel = _opTable[(int)op.mOpcode, (int)opL.mType, (int)opR.mType];

                if (opDel == null)
                {
                    throw new CFibreRuntimeException("Can't perform operator " + op.mOpcode + " on types " + opL.mType + " and " + opR.mType, this);
                }

                _SetRegister(op.mOperand[0], opDel(opL, opR));
            }
            break;

            case EFibreOpcodeType.JMP:
            {
                mInstructionPtr = (int)op.mOperand[0];
            }
            break;

            case EFibreOpcodeType.J*Z:
            {
                CFibreReg opL = _GetRegister(op.mOperand[0]);

                if (opL.mType != EFibreType.BOOL)
                {
                    throw new CFibreRuntimeException("Comparison can only operate on a bool, got " + opL.mType, this);
                }

                if (opL.mBool == false)
                {
                    mInstructionPtr = (int)op.mOperand[1];
                }
            }
            break;

            case EFibreOpcodeType.JNZ:
            {
                CFibreReg opL = _GetRegister(op.mOperand[0]);

                if (opL.mType != EFibreType.BOOL)
                {
                    throw new CFibreRuntimeException("Comparison can only operate on a bool, got " + opL.mType, this);
                }

                if (opL.mBool == true)
                {
                    mInstructionPtr = (int)op.mOperand[1];
                }
            }
            break;

            case EFibreOpcodeType.CAL:
            {
                int       stackFrameStartIndex = (int)(op.mOperand[1] & 0x3FFFFFFF) + mFramePtr;
                int       argCount             = (int)op.mOperand[2];
                CFibreReg funcDef = _GetRegister(op.mOperand[0]);

                if (funcDef.mType != EFibreType.FUNCTION)
                {
                    throw new CFibreRuntimeException("Tried to call a function but got a " + funcDef.mType, this);
                }
                else
                {
                    // TODO: Push data about function so we can reference it in call stack for debugging.
                    mCallFrames.Push(new CFibreCallFrame(mInstructionPtr, stackFrameStartIndex, argCount));
                    mFramePtr = stackFrameStartIndex;

                    if (funcDef.mID < -1)
                    {
                        int       funcIndex   = -funcDef.mID - 10;
                        CFibreReg returnValue = mInteropFuncs[funcIndex](this, argCount);

                        if (returnValue != null && returnValue.mType != EFibreType.COUNT)
                        {
                            SetLocalRegister(0, returnValue);
                        }
                        else
                        {
                            SetLocalRegister(0, mData.mStore[2]);
                        }

                        CFibreCallFrame frame = mCallFrames.Pop();
                        mInstructionPtr = frame.mNextInstruction;

                        if (mCallFrames.Count == 0)
                        {
                            return(ERunResult.DONE);
                        }

                        mFramePtr = mCallFrames.Peek().mFramePtr;

                        if (returnValue != null && returnValue.mType == EFibreType.COUNT)
                        {
                            return(ERunResult.CONTINUE);
                        }
                    }
                    else
                    {
                        mInstructionPtr = funcDef.mID;
                    }
                }
            }
            break;

            case EFibreOpcodeType.FNC:
            {
                int argCount = (int)op.mOperand[0];

                // Push undefineds over missing args
                for (int i = mCallFrames.Peek().mPushedArgCount; i < argCount; ++i)
                {
                    SetLocalRegister(i, mData.mStore[2]);
                }
            }
            break;

            case EFibreOpcodeType.RET:
            {
                if (op.mOperand[0] == 0)
                {
                    SetLocalRegister(0, mData.mStore[2]);
                }

                CFibreCallFrame frame = mCallFrames.Pop();
                mInstructionPtr = frame.mNextInstruction;

                if (mCallFrames.Count == 0)
                {
                    return(ERunResult.DONE);
                }

                mFramePtr = mCallFrames.Peek().mFramePtr;
            }
            break;
            }
        }

        return(ERunResult.DONE);
    }