public CFibre(CFibreScript Script, CFibreReg FunctionReg, int ArgCount, CFibreRegStore Data, CFibreRegStore Global, CFibreRegStore Local, List <CFibreVM.InteropFuncDelegate> InteropFuncs) { mScript = Script; mFramePtr = 0; mData = Data; mGlobal = Global; mLocal = Local; mInteropFuncs = InteropFuncs; mStores = new CFibreRegStore[] { Data, Global, Local }; mCallFrames = new Stack <CFibreCallFrame>(); if (FunctionReg == null) { mInstructionPtr = 0; mCallFrames.Push(new CFibreCallFrame(mInstructionPtr, 0, 0)); } else { if (FunctionReg.mID < -1) { int funcIndex = -FunctionReg.mID - 10; mInteropFuncs[funcIndex](this, 0); } else { mInstructionPtr = FunctionReg.mID; mCallFrames.Push(new CFibreCallFrame(mInstructionPtr, 0, ArgCount)); } } }
public bool GetBool(int Index, ref bool IsMatch) { CFibreReg reg = mLocal.mStore[Index + mFramePtr]; if (reg.mType == EFibreType.BOOL) { return(reg.mBool); } IsMatch = false; return(false); }
public int GetInt(int Index, ref bool IsMatch) { CFibreReg reg = mLocal.mStore[Index + mFramePtr]; if (reg.mType == EFibreType.NUMBER) { return((int)reg.mNumber); } IsMatch = false; return(0); }
public string GetString(int Index, ref bool IsMatch) { CFibreReg reg = mLocal.mStore[Index + mFramePtr]; if (reg.mType == EFibreType.STRING) { return(reg.mString); } IsMatch = false; return(""); }
private void _SetRegister(uint Register, CFibreReg Val) { int index = (int)(Register & 0x3FFFFFFF); int type = (int)(Register >> 30); CFibreRegStore stack = mStores[type]; if (type == 2) { stack.mStore[index + mFramePtr] = Val; } else { stack.mStore[index] = Val; } }
public CFibreReg WaitTime(CFibre Fibre, int ArgCount) { if (ArgCount == 1) { CTrigger trigger = new CTrigger(); trigger.mType = ETriggerType.TICK; trigger.mInfo = (int)Fibre.mLocal.mStore[Fibre.mFramePtr + 0].mNumber + _world.mGameTick; trigger.mCallbackFibre = Fibre; _triggers.Add(trigger); // TODO: Fix this cheap way to indicate that we need to suspend thread. CFibreReg reg = new CFibreReg(); reg.mType = EFibreType.COUNT; return(reg); } return(null); }
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); }
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); }
public void SetLocalRegister(int Index, CFibreReg Val) { mLocal.mStore[Index + mFramePtr] = Val; }