Ejemplo n.º 1
0
 /// <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;
 }
Ejemplo n.º 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);
    }
Ejemplo n.º 3
0
 //---------------------------------------------------------------BinaryOpIntrinsics
 public void CreateBinaryOpIntrinsic(BinaryOpKey key, BinaryOpDelegate intrinsic)
 {
     BinaryOpIntrinsics.TryAdd(key, intrinsic);
 }