/// <summary> /// Creates a new BinaryOperator /// </summary> /// <param name="strOp">the string representation of the operator</param> /// <param name="precedence">the operator precedence. Lower precedence are processed first</param> /// <param name="doOp">the method that processes the operands</param> public BinaryOperator(string strOp, int precedence, BinaryOpDelegate doOp) { OperatorString = strOp.ToUpper(); Precedence = precedence; ExecuteOperator = doOp; }
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); }
//---------------------------------------------------------------BinaryOpIntrinsics public void CreateBinaryOpIntrinsic(BinaryOpKey key, BinaryOpDelegate intrinsic) { BinaryOpIntrinsics.TryAdd(key, intrinsic); }