engine/source/scriptlib/Interpreter.c
/******************************************************************************
*  EvalInstruction -- This method evaluates a single byte-code instruction.
*  Parameters: none
*  Returns: S_OK
*           E_FAIL
******************************************************************************/
- This method evaluates a single byte-code instruction.
- This method evaluates a single byte - code instruction .
HRESULT Interpreter_EvalInstruction(Interpreter *pinterpreter)
{
    HRESULT hr = S_OK;
    Instruction *pInstruction;
    Instruction *currentCall;
    Instruction *returnEntry;
    if((pInstruction = *((Instruction **)pinterpreter->pCurrentInstruction)))
    {
        switch( pInstruction->OpCode )
        {
        case CONSTSTR:
        case CONSTDBL:
        case CONSTINT:
            break;
        case LOAD:
            ScriptVariant_Copy(pInstruction->theVal, pInstruction->theRef);
            break;
        case SAVE:
            ScriptVariant_Copy(pInstruction->theRef, pInstruction->theRef2);
            break;
        case INC:
            UNARYOP(ScriptVariant_Inc_Op);
            break;
        case DEC:
            UNARYOP(ScriptVariant_Dec_Op);
            break;
        case POS:
            UNARYOP(ScriptVariant_Pos);
            break;
        case NEG:
            UNARYOP(ScriptVariant_Neg);
            break;
        case NOT:
            UNARYOP(ScriptVariant_Boolean_Not);
            break;
        case MUL:
            BINARYOP(ScriptVariant_Mul);
            break;
        case DIV:
            BINARYOP(ScriptVariant_Div);
            break;
        case MOD:
            BINARYOP(ScriptVariant_Mod);
            break;
        case ADD:
            BINARYOP(ScriptVariant_Add);
            break;
        case SUB:
            BINARYOP(ScriptVariant_Sub);
            break;
        case SHL:
            BINARYOP(ScriptVariant_Shl);
            break;
        case SHR:
            BINARYOP(ScriptVariant_Shr);
            break;
        case GE:
            BINARYOP(ScriptVariant_Ge);
            break;
        case LE:
            BINARYOP(ScriptVariant_Le);
            break;
        case LT:
            BINARYOP(ScriptVariant_Lt);
            break;
        case GT:
            BINARYOP(ScriptVariant_Gt);
            break;
        case EQ:
            BINARYOP(ScriptVariant_Eq);
            break;
        case NE:
            BINARYOP(ScriptVariant_Ne);
            break;
        case OR:
            BINARYOP(ScriptVariant_Or);
            break;
        case AND:
            BINARYOP(ScriptVariant_And);
            break;
        case BIT_OR:
            BINARYOP(ScriptVariant_Bit_Or);
            break;
        case XOR:
            BINARYOP(ScriptVariant_Xor);
            break;
        case BIT_AND:
            BINARYOP(ScriptVariant_Bit_And);
            break;
        case DATA:
            break;
        case PARAM:
            currentCall = *(pinterpreter->pCurrentCall);
            if(List_GetSize(currentCall->theRefList) <= currentCall->theRefList->index)
            {
                ScriptVariant_Clear(pInstruction->theVal);
            }
            else
            {
                ScriptVariant_Copy(pInstruction->theVal, (ScriptVariant *)(currentCall->theRefList->solidlist[currentCall->theRefList->index]));
            }
            currentCall->theRefList->index++;
            break;
        case CALL:
            pInstruction->theRefList->index = 0;
            hr = Interpreter_Call(pinterpreter);
            break;
        case JUMPR:
            pinterpreter->pReturnEntry = pinterpreter->pCurrentInstruction;
            pinterpreter->pCurrentInstruction = pInstruction->ptheJumpTarget;
            break;
        case JUMP:
        case PJUMP:
            pinterpreter->pCurrentInstruction = pInstruction->ptheJumpTarget;
            break;
        case Branch_EQUAL:
            if(ScriptVariant_Eq(pInstruction->theRef, pInstruction->theRef2)->lVal)
            {
                pinterpreter->pCurrentInstruction = pInstruction->ptheJumpTarget;
            }
            break;
        case Branch_FALSE:
            if(!ScriptVariant_IsTrue(pInstruction->theRef))
            {
                pinterpreter->pCurrentInstruction = pInstruction->ptheJumpTarget;
            }
            break;
        case Branch_TRUE:
            if(ScriptVariant_IsTrue(pInstruction->theRef))
            {
                pinterpreter->pCurrentInstruction = pInstruction->ptheJumpTarget;
            }
            break;
        case RET:
            if(pinterpreter->pReturnEntry)
            {
                returnEntry = *(pinterpreter->pReturnEntry);
                if(returnEntry->theRef && pinterpreter->pCurrentCall)
                {
                    currentCall = *(pinterpreter->pCurrentCall);
                    ScriptVariant_Copy(currentCall->theVal, returnEntry->theRef);
                }
            }
            pinterpreter->pReturnEntry = NULL;
            pinterpreter->bCallCompleted = TRUE;
            break;
        case CHECKARG:
            break;
        case CLEAN:
            break;
        case ERR:
            hr = E_FAIL;
            break;
        case NOOP:
        case FUNCDECL:
            break;
        case PUSH:
            break;
        case POP:
            break;
        case IMMEDIATE:
        case DEFERRED:
            break;
        default:
            printf("\nUn-handled OpCode: %d\n", pInstruction->OpCode);
            hr = E_FAIL;
            break;
        }
        pinterpreter->pCurrentInstruction += pInstruction->step;
    }
    return hr;
}
HRESULT Interpreter_EvalInstruction ( Interpreter * pinterpreter ) { HRESULT hr = S_OK ; Instruction * pInstruction ; Instruction * currentCall ; Instruction * returnEntry ; if ( ( pInstruction = * ( ( Instruction * * ) pinterpreter -> pCurrentInstruction ) ) ) { switch ( pInstruction -> OpCode ) { case CONSTSTR : case CONSTDBL : case CONSTINT : break ; case LOAD : ScriptVariant_Copy ( pInstruction -> theVal , pInstruction -> theRef ) ; break ; case SAVE : ScriptVariant_Copy ( pInstruction -> theRef , pInstruction -> theRef2 ) ; break ; case INC : UNARYOP ( ScriptVariant_Inc_Op ) ; break ; case DEC : UNARYOP ( ScriptVariant_Dec_Op ) ; break ; case POS : UNARYOP ( ScriptVariant_Pos ) ; break ; case NEG : UNARYOP ( ScriptVariant_Neg ) ; break ; case NOT : UNARYOP ( ScriptVariant_Boolean_Not ) ; break ; case MUL : BINARYOP ( ScriptVariant_Mul ) ; break ; case DIV : BINARYOP ( ScriptVariant_Div ) ; break ; case MOD : BINARYOP ( ScriptVariant_Mod ) ; break ; case ADD : BINARYOP ( ScriptVariant_Add ) ; break ; case SUB : BINARYOP ( ScriptVariant_Sub ) ; break ; case SHL : BINARYOP ( ScriptVariant_Shl ) ; break ; case SHR : BINARYOP ( ScriptVariant_Shr ) ; break ; case GE : BINARYOP ( ScriptVariant_Ge ) ; break ; case LE : BINARYOP ( ScriptVariant_Le ) ; break ; case LT : BINARYOP ( ScriptVariant_Lt ) ; break ; case GT : BINARYOP ( ScriptVariant_Gt ) ; break ; case EQ : BINARYOP ( ScriptVariant_Eq ) ; break ; case NE : BINARYOP ( ScriptVariant_Ne ) ; break ; case OR : BINARYOP ( ScriptVariant_Or ) ; break ; case AND : BINARYOP ( ScriptVariant_And ) ; break ; case BIT_OR : BINARYOP ( ScriptVariant_Bit_Or ) ; break ; case XOR : BINARYOP ( ScriptVariant_Xor ) ; break ; case BIT_AND : BINARYOP ( ScriptVariant_Bit_And ) ; break ; case DATA : break ; case PARAM : currentCall = * ( pinterpreter -> pCurrentCall ) ; if ( List_GetSize ( currentCall -> theRefList ) <= currentCall -> theRefList -> index ) { ScriptVariant_Clear ( pInstruction -> theVal ) ; } else { ScriptVariant_Copy ( pInstruction -> theVal , ( ScriptVariant * ) ( currentCall -> theRefList -> solidlist [ currentCall -> theRefList -> index ] ) ) ; } currentCall -> theRefList -> index ++ ; break ; case CALL : pInstruction -> theRefList -> index = 0 ; hr = Interpreter_Call ( pinterpreter ) ; break ; case JUMPR : pinterpreter -> pReturnEntry = pinterpreter -> pCurrentInstruction ; pinterpreter -> pCurrentInstruction = pInstruction -> ptheJumpTarget ; break ; case JUMP : case PJUMP : pinterpreter -> pCurrentInstruction = pInstruction -> ptheJumpTarget ; break ; case Branch_EQUAL : if ( ScriptVariant_Eq ( pInstruction -> theRef , pInstruction -> theRef2 ) -> lVal ) { pinterpreter -> pCurrentInstruction = pInstruction -> ptheJumpTarget ; } break ; case Branch_FALSE : if ( ! ScriptVariant_IsTrue ( pInstruction -> theRef ) ) { pinterpreter -> pCurrentInstruction = pInstruction -> ptheJumpTarget ; } break ; case Branch_TRUE : if ( ScriptVariant_IsTrue ( pInstruction -> theRef ) ) { pinterpreter -> pCurrentInstruction = pInstruction -> ptheJumpTarget ; } break ; case RET : if ( pinterpreter -> pReturnEntry ) { returnEntry = * ( pinterpreter -> pReturnEntry ) ; if ( returnEntry -> theRef && pinterpreter -> pCurrentCall ) { currentCall = * ( pinterpreter -> pCurrentCall ) ; ScriptVariant_Copy ( currentCall -> theVal , returnEntry -> theRef ) ; } } pinterpreter -> pReturnEntry = NULL ; pinterpreter -> bCallCompleted = TRUE ; break ; case CHECKARG : break ; case CLEAN : break ; case ERR : hr = E_FAIL ; break ; case NOOP : case FUNCDECL : break ; case PUSH : break ; case POP : break ; case IMMEDIATE : case DEFERRED : break ; default : printf ( " \n \n " , pInstruction -> OpCode ) ; hr = E_FAIL ; break ; } pinterpreter -> pCurrentInstruction += pInstruction -> step ; } return hr ; }
EvalInstruction -- This method evaluates a single byte-code instruction.
EvalInstruction -- This method evaluates a single byte - code instruction .
//Retrieve the current instruction from the list //The OpCode will tell us what operation to perform. //Push a constant string //Push a constant double //Push a constant integer //Load a value into the data stack //Save a value from the data stack //use the UNARYOP macro to do an AutoIncrement //use the UNARYOP macro to do an AutoDecrement //use the UNARYOP macro to do a unary plus //use the UNARYOP macro to do a unary minus //use the UNARYOP macro to do a logical not //Use the BINARYOP macro to do a multipy //Use the BINARYOP macro to do a divide //Use the BINARYOP macro to do a mod //Use the BINARYOP macro to do an add //Use the BINARYOP macro to do a subtract //Use the BINARYOP macro to do a left shift //Use the BINARYOP macro to do a right shift //Use the BINARYOP macro to do a greater than- equal //Use the BINARYOP macro to do a less than- equal //Use the BINARYOP macro to do a less than //Use the BINARYOP macro to do a greater than //Use the BINARYOP macro to do an equality //Use the BINARYOP macro to do a not-equal //Use the BINARYOP macro to do a logical OR //Use the BINARYOP macro to do a logical AND //Use the BINARYOP macro to do a bitwise OR //Use the BINARYOP macro to do a bitwise XOR //Use the BINARYOP macro to do a bitwise AND //Create a new CSymbol and add it to the symbol table //again, we dont have to define anything if compiled //Create a new CSymbol from a value on the stack and add it to the //symbol table. //copy value from the cached parameter //assert(pinterpreter->pCurrentCall); //Call the specified method, and pass in a ScriptVariant* to receive the //return value.  If it's not NULL, then push it onto the data stack. //Reset the m_bCallCompleted flag back to false //pinterpreter->bCallCompleted = FALSE; // return //Jump to the specified label //Jump if the top two ScriptVariants are equal //Jump if the top ScriptVariant resolves to false //Jump if the top ScriptVariant resolves to true //Set the m_bCallCompleted flag to true so we know to stop evalutating //instructions //Make sure the argument count on the top of the stack matches the //number of arguments we have /*
            if(pinterpreter->pCurrentCall)
            {
            	currentCall = *(pinterpreter->pCurrentCall);
            	if(pInstruction->theVal->lVal != currentCall->theRef->lVal)
            	{
            		printf("Runtime error: argument count(%d) doesn't match, check your function call: %s.\n", (int)pInstruction->theVal->lVal, currentCall->Label);
            		hr = E_FAIL;
            	}
            }*/ //This instructs the interpreter to clean one value off the stack. //This OpCode denotes an error in the instruction list //This is a placeholder.  Don't do anything. //This instructs the interpreter to push a symbol scope. //This instructs the interpreter to pop a symbol scope //Ignore IMMEDIATE and DEFFERRED instructions, since they are only used //to mark immediate code. //If we hit the default, then we got an unrecognized instruction //Report an error //HandleRuntimeError( pInstruction, INVALID_INSTRUCTION, this ); //Increment the instruction list //return the result of this token evaluation