X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FLibraries%2Flibspiderscript.so_src%2Fexec_bytecode.c;h=e24011602906e24f1fdacbb2a8fa60092c028314;hb=239f2374299c1471a40b1087725b32f3f163d9b3;hp=b9384245647ae528faa8f4caa8dac9657194bd1a;hpb=1e45480331132c75898cbdd761ddd1fa48739e54;p=tpg%2Facess2.git diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c index b9384245..e2401160 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c @@ -2,32 +2,34 @@ * SpiderScript Library * by John Hodge (thePowersGang) * - * bytecode_makefile.c - * - Generate a bytecode file + * exec_bytecode.c + * - Execute bytecode */ #include -#include "bytecode_ops.h" +#include +#include "common.h" +#include "bytecode.h" +#include +#include "ast.h" -typedef sBC_StackEnt tBC_StackEnt; +typedef struct sBC_StackEnt tBC_StackEnt; +typedef struct sBC_Stack tBC_Stack; enum eBC_StackEntTypes { ET_NULL, // Start of the stack - ET_FUNCTION_START, // Start of the function - ET_INTEGER, // Integer / Boolean - ET_REAL, // Real number - ET_OBJECT, // Object + // SS_DATATYPE_* + ET_FUNCTION_START = NUM_SS_DATATYPES, ET_REFERENCE // Reference to a tSpiderValue }; struct sBC_StackEnt { - uint8_t EntType; - uint8_t _padding[3]; + uint8_t Type; union { uint64_t Integer; double Real; - tSpiderValue *Reference; + tSpiderValue *Reference; // Used for everything else tSpiderObject *Object; }; }; @@ -39,6 +41,10 @@ struct sBC_Stack tBC_StackEnt Entries[]; }; +// === PROTOTYPES === +tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args); + int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, tBC_Stack *Stack, int ArgCount); + // === CODE === int Bytecode_int_StackPop(tBC_Stack *Stack, tBC_StackEnt *Dest) { @@ -56,38 +62,189 @@ int Bytecode_int_StackPush(tBC_Stack *Stack, tBC_StackEnt *Src) return 0; } +int Bytecode_int_IsStackEntTrue(tBC_StackEnt *Ent) +{ + switch(Ent->Type) + { + case SS_DATATYPE_INTEGER: + return !!Ent->Integer; + case SS_DATATYPE_REAL: + return (-.5f < Ent->Real && Ent->Real < 0.5f); + case SS_DATATYPE_OBJECT: + return Ent->Object != NULL; + case ET_FUNCTION_START: + return -1; + default: + return SpiderScript_IsValueTrue(Ent->Reference); + } +} + +tSpiderValue *Bytecode_int_GetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *tmp) +{ + switch(Ent->Type) + { + case SS_DATATYPE_INTEGER: + tmp->Type = SS_DATATYPE_INTEGER; + tmp->ReferenceCount = 2; // Stops it being freed + tmp->Integer = Ent->Integer; + return tmp; + case SS_DATATYPE_REAL: + tmp->Type = SS_DATATYPE_REAL; + tmp->ReferenceCount = 2; // Stops it being freed + tmp->Real = Ent->Real; + return tmp; + case SS_DATATYPE_OBJECT: + tmp->Type = SS_DATATYPE_OBJECT; + tmp->ReferenceCount = 2; + tmp->Object = Ent->Object; + return tmp; + case ET_FUNCTION_START: + return NULL; + default: + return Ent->Reference; + } +} + +void Bytecode_int_SetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *Value) +{ + switch(Value->Type) + { + case SS_DATATYPE_INTEGER: + Ent->Type = SS_DATATYPE_INTEGER; + Ent->Integer = Value->Integer; + break; + case SS_DATATYPE_REAL: + Ent->Type = SS_DATATYPE_REAL; + Ent->Real = Value->Real; + break; + case SS_DATATYPE_OBJECT: + Ent->Type = SS_DATATYPE_OBJECT; + Ent->Object = Value->Object; + break; + default: + SpiderScript_ReferenceValue(Value); + Ent->Reference = Value; + break; + } +} + #define GET_STACKVAL(dst) if((ret = Bytecode_int_StackPop(Stack, &dst))) return ret; +#define OP_INDX(op_ptr) ((op_ptr)->Content.StringInt.Integer) +#define OP_STRING(op_ptr) ((op_ptr)->Content.StringInt.String) + +tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Args) +{ + const int stack_size = 100; + tSpiderValue *ret, tmpsval; + tBC_Stack *stack; + tBC_StackEnt val; + int i; + + stack = malloc(sizeof(tBC_Stack) + stack_size*sizeof(tBC_StackEnt)); + stack->EntrySpace = stack_size; + stack->EntryCount = 0; + + // Push arguments in order (so top is last arg) + for( i = 0; i < NArguments; i ++ ) + { + Bytecode_int_SetSpiderValue(&val, Args[i]); + Bytecode_int_StackPush(stack, &val); + } + + // Call + Bytecode_int_ExecuteFunction(Script, Fcn, stack, NArguments); + + // Get return value + Bytecode_int_StackPop(stack, &val); + ret = Bytecode_int_GetSpiderValue(&val, &tmpsval); + // Ensure it's a heap value + if(ret == &tmpsval) { + ret = malloc(sizeof(tSpiderValue)); + memcpy(ret, &tmpsval, sizeof(tSpiderValue)); + } + return ret; +} -int Bytecode_ExecuteFunction(tBC_Function *Fcn, tBC_Stack *Stack, int ArgCount); +/** + * \brief Execute a bytecode function with a stack + */ +int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, tBC_Stack *Stack, int ArgCount) { + int ret, ast_op, i; tBC_Op *op; tBC_StackEnt val1, val2; - tBC_StackEnt local_vars[Fcn->MaxVariableCount+Fcn->ArgumentCount]; + tBC_StackEnt local_vars[Fcn->BCFcn->MaxVariableCount]; // Includes arguments + tSpiderValue tmpVal1, tmpVal2; // temp storage + tSpiderValue *pval1, *pval2, *ret_val; // Pop off arguments + if( ArgCount > Fcn->ArgumentCount ) return -1; + for( i = Fcn->ArgumentCount; --i != ArgCount; ) + { + local_vars[i].Integer = 0; + local_vars[i].Type = Fcn->Arguments[i].Type; + } + for( ; i --; ) + { + GET_STACKVAL(local_vars[i]); + // TODO: Type checks / enforcing + } // Mark the start + memset(&val1, 0, sizeof(val1)); + val1.Type = ET_FUNCTION_START; + Bytecode_int_StackPush(Stack, &val1); // Execute! - op = Fcn->Operations; + op = Fcn->BCFcn->Operations; while(op) { tBC_Op *nextop = op->Next; - switch(op->Type) + ast_op = 0; + switch(op->Operation) { + // Jumps case BC_OP_JUMP: - nextop = Fcn->Labels[op->StringInt.Integer]; + nextop = Fcn->BCFcn->Labels[ OP_INDX(op) ]; break; case BC_OP_JUMPIF: GET_STACKVAL(val1); if( Bytecode_int_IsStackEntTrue(&val1) ) - nextop = Fcn->Labels[op->StringInt.Integer]; + nextop = Fcn->BCFcn->Labels[ OP_INDX(op) ]; break; case BC_OP_JUMPIFNOT: GET_STACKVAL(val1); if( !Bytecode_int_IsStackEntTrue(&val1) ) - nextop = Fcn->Labels[op->StringInt.Integer]; + nextop = Fcn->BCFcn->Labels[ OP_INDX(op) ]; + break; + + // Define variables + case BC_OP_DEFINEVAR: { + int type, slot; + type = OP_INDX(op) & 0xFFFF; + slot = OP_INDX(op) >> 16; + if(slot < 0 || slot >= sizeof(local_vars)/sizeof(local_vars[0])) return -1; + memset(&local_vars[slot], 0, sizeof(local_vars[0])); + local_vars[slot].Type = type; + } break; + + // Operations + case BC_OP_ADD: + ast_op = NODETYPE_ADD; + case BC_OP_SUBTRACT: + if(!ast_op) ast_op = NODETYPE_SUBTRACT; + + GET_STACKVAL(val2); + GET_STACKVAL(val1); + pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1); + pval2 = Bytecode_int_GetSpiderValue(&val2, &tmpVal2); + ret_val = AST_ExecuteNode_BinOp(Script, NULL, ast_op, pval1, pval2); + if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1); + if(pval2 != &tmpVal2) SpiderScript_DereferenceValue(pval2); + Bytecode_int_SetSpiderValue(&val1, ret_val); + if(ret_val != &tmpVal1) SpiderScript_DereferenceValue(ret_val); break; + default: // TODO: break; @@ -96,4 +253,12 @@ int Bytecode_ExecuteFunction(tBC_Function *Fcn, tBC_Stack *Stack, int ArgCount); } // Clean up + // - Delete local vars + + + // - Restore stack + + + return 0; } +