X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FLibraries%2Flibspiderscript.so_src%2Fexec_bytecode.c;h=4673bd286759a989061c401a7bff103e79b27143;hb=2f9415b7b804073b0365781ad4f05a7306b6c890;hp=50e2f4f888a57f2c053b12a2ffe8f52370edb76b;hpb=2acaad7b0d455a6c7cb177e1a7ecc5f07f40c7bb;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 50e2f4f8..4673bd28 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c @@ -41,8 +41,8 @@ struct sBC_StackEnt { uint8_t Type; union { - uint64_t Integer; - double Real; + int64_t Integer; + double Real; tSpiderValue *Reference; // Used for everything else tSpiderObject *Object; tSpiderNamespace *Namespace; @@ -154,6 +154,7 @@ void Bytecode_int_SetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *Value) case SS_DATATYPE_OBJECT: Ent->Type = SS_DATATYPE_OBJECT; Ent->Object = Value->Object; + Ent->Object->ReferenceCount ++; break; default: SpiderScript_ReferenceValue(Value); @@ -169,10 +170,21 @@ void Bytecode_int_DerefStackValue(tBC_StackEnt *Ent) { case SS_DATATYPE_INTEGER: case SS_DATATYPE_REAL: + break; case SS_DATATYPE_OBJECT: + if(Ent->Object) { + Ent->Object->ReferenceCount --; + if(Ent->Object->ReferenceCount == 0) { + Ent->Object->Type->Destructor( Ent->Object ); + } +// printf("Object %p derefed (obj refcount = %i)\n", Ent->Object, Ent->Object->ReferenceCount); + } + Ent->Object = NULL; break; default: - SpiderScript_DereferenceValue(Ent->Reference); + if(Ent->Reference) + SpiderScript_DereferenceValue(Ent->Reference); + Ent->Reference = NULL; break; } } @@ -182,10 +194,16 @@ void Bytecode_int_RefStackValue(tBC_StackEnt *Ent) { case SS_DATATYPE_INTEGER: case SS_DATATYPE_REAL: + break; case SS_DATATYPE_OBJECT: + if(Ent->Object) { + Ent->Object->ReferenceCount ++; +// printf("Object %p referenced (count = %i)\n", Ent->Object, Ent->Object->ReferenceCount); + } break; default: - SpiderScript_ReferenceValue(Ent->Reference); + if(Ent->Reference) + SpiderScript_ReferenceValue(Ent->Reference); break; } } @@ -335,6 +353,8 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t switch(op->Operation) { case BC_OP_NOP: + STATE_HDR(); + DEBUG_F("NOP\n"); break; // Jumps case BC_OP_JUMP: @@ -392,28 +412,32 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t break; // Variables - case BC_OP_LOADVAR: + case BC_OP_LOADVAR: { + int slot = OP_INDX(op); STATE_HDR(); - DEBUG_F("LOADVAR %i ", OP_INDX(op)); - if( OP_INDX(op) < 0 || OP_INDX(op) >= local_var_count ) { - AST_RuntimeError(NULL, "Loading from invalid slot %i", OP_INDX(op)); + DEBUG_F("LOADVAR %i ", slot); + if( slot < 0 || slot >= local_var_count ) { + AST_RuntimeError(NULL, "Loading from invalid slot %i", slot); return -1; } - DEBUG_F("("); PRINT_STACKVAL(local_vars[OP_INDX(op)]); DEBUG_F(")\n"); - PUT_STACKVAL(local_vars[OP_INDX(op)]); - Bytecode_int_RefStackValue( &local_vars[OP_INDX(op)] ); - break; - case BC_OP_SAVEVAR: + DEBUG_F("("); PRINT_STACKVAL(local_vars[slot]); DEBUG_F(")\n"); + PUT_STACKVAL(local_vars[slot]); + Bytecode_int_RefStackValue( &local_vars[slot] ); + } break; + case BC_OP_SAVEVAR: { + int slot = OP_INDX(op); STATE_HDR(); - DEBUG_F("SAVEVAR %i = ", OP_INDX(op)); - if( OP_INDX(op) < 0 || OP_INDX(op) >= local_var_count ) { - AST_RuntimeError(NULL, "Loading from invalid slot %i", OP_INDX(op)); + DEBUG_F("SAVEVAR %i = ", slot); + if( slot < 0 || slot >= local_var_count ) { + AST_RuntimeError(NULL, "Loading from invalid slot %i", slot); return -1; } - PRINT_STACKVAL(local_vars[OP_INDX(op)]); + DEBUG_F("[Deref "); PRINT_STACKVAL(local_vars[slot]); DEBUG_F("] "); + Bytecode_int_DerefStackValue( &local_vars[slot] ); + GET_STACKVAL(local_vars[slot]); + PRINT_STACKVAL(local_vars[slot]); DEBUG_F("\n"); - GET_STACKVAL(local_vars[OP_INDX(op)]); - break; + } break; // Constants: case BC_OP_LOADINT: @@ -522,6 +546,32 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t if(!ast_op) ast_op = NODETYPE_LOGICALOR, opstr = "LOGICOR"; case BC_OP_LOGICXOR: if(!ast_op) ast_op = NODETYPE_LOGICALXOR, opstr = "LOGICXOR"; + + STATE_HDR(); + DEBUG_F("%s\n", opstr); + + GET_STACKVAL(val1); + GET_STACKVAL(val2); + + switch(op->Operation) + { + case BC_OP_LOGICAND: + i = Bytecode_int_IsStackEntTrue(&val1) && Bytecode_int_IsStackEntTrue(&val2); + break; + case BC_OP_LOGICOR: + i = Bytecode_int_IsStackEntTrue(&val1) || Bytecode_int_IsStackEntTrue(&val2); + break; + case BC_OP_LOGICXOR: + i = Bytecode_int_IsStackEntTrue(&val1) ^ Bytecode_int_IsStackEntTrue(&val2); + break; + } + Bytecode_int_DerefStackValue(&val1); + Bytecode_int_DerefStackValue(&val2); + + val1.Type = SS_DATATYPE_INTEGER; + val1.Integer = i; + Bytecode_int_StackPush(Stack, &val1); + break; case BC_OP_BITAND: if(!ast_op) ast_op = NODETYPE_BWAND, opstr = "BITAND"; @@ -564,6 +614,32 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t GET_STACKVAL(val2); // Right GET_STACKVAL(val1); // Left + + #define PERFORM_NUM_OP(_type, _field) if(val1.Type == _type && val1.Type == val2.Type) { \ + switch(op->Operation) { \ + case BC_OP_ADD: val1._field = val1._field + val2._field; break; \ + case BC_OP_SUBTRACT: val1._field = val1._field - val2._field; break; \ + case BC_OP_MULTIPLY: val1._field = val1._field * val2._field; break; \ + case BC_OP_DIVIDE: val1._field = val1._field / val2._field; break; \ + case BC_OP_EQUALS: val1._field = val1._field == val2._field; break; \ + case BC_OP_LESSTHAN: val1._field = val1._field < val2._field; break; \ + case BC_OP_LESSTHANOREQUAL: val1._field = val1._field <= val2._field; break; \ + case BC_OP_GREATERTHAN: val1._field = val1._field > val2._field; break; \ + case BC_OP_GREATERTHANOREQUAL: val1._field = val1._field >= val2._field; break; \ + \ + case BC_OP_BITAND: val1._field = (int64_t)val1._field & (int64_t)val2._field; break; \ + case BC_OP_BITOR: val1._field = (int64_t)val1._field | (int64_t)val2._field; break; \ + case BC_OP_BITXOR: val1._field = (int64_t)val1._field ^ (int64_t)val2._field; break; \ + case BC_OP_MODULO: val1._field = (int64_t)val1._field % (int64_t)val2._field; break; \ + default: AST_RuntimeError(NULL, "Invalid operation on datatype %i", _type); nextop = NULL; break;\ + }\ + PUT_STACKVAL(val1);\ + break;\ + } + + PERFORM_NUM_OP(SS_DATATYPE_INTEGER, Integer); + PERFORM_NUM_OP(SS_DATATYPE_REAL, Real); + pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1); pval2 = Bytecode_int_GetSpiderValue(&val2, &tmpVal2); Bytecode_int_DerefStackValue(&val1); @@ -572,40 +648,51 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t ret_val = AST_ExecuteNode_BinOp(Script, NULL, ast_op, pval1, pval2); if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1); if(pval2 != &tmpVal2) SpiderScript_DereferenceValue(pval2); + + if(ret_val == ERRPTR) { + AST_RuntimeError(NULL, "_BinOp returned ERRPTR"); + nextop = NULL; + break; + } Bytecode_int_SetSpiderValue(&val1, ret_val); if(ret_val != &tmpVal1) SpiderScript_DereferenceValue(ret_val); PUT_STACKVAL(val1); break; // Functions etc - case BC_OP_CALLFUNCTION: { - tScript_Function *fcn; + case BC_OP_CREATEOBJ: + case BC_OP_CALLFUNCTION: + case BC_OP_CALLMETHOD: { + tScript_Function *fcn = NULL; const char *name = OP_STRING(op); int arg_count = OP_INDX(op); STATE_HDR(); DEBUG_F("CALL FUNCTION %s %i args\n", name, arg_count); - // Check current script functions (for fast call) - for(fcn = Script->Functions; fcn; fcn = fcn->Next) + if( op->Operation == BC_OP_CALLFUNCTION ) { - if(strcmp(name, fcn->Name) == 0) { + // Check current script functions (for fast call) + for(fcn = Script->Functions; fcn; fcn = fcn->Next) + { + if(strcmp(name, fcn->Name) == 0) { + break; + } + } + if(fcn && fcn->BCFcn) + { + DEBUG_F(" - Fast call\n"); + Bytecode_int_ExecuteFunction(Script, fcn, Stack, arg_count); break; } } - if(fcn && fcn->BCFcn) - { - DEBUG_F(" - Fast call\n"); - Bytecode_int_ExecuteFunction(Script, fcn, Stack, arg_count); - break; - } // Slower call { tSpiderNamespace *ns = NULL; tSpiderValue *args[arg_count]; tSpiderValue *rv; -// for( i = 0; i < arg_count; i ++ ) + // Read arguments for( i = arg_count; i --; ) { GET_STACKVAL(val1); @@ -613,16 +700,50 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t Bytecode_int_DerefStackValue(&val1); } - if( name[0] == BC_NS_SEPARATOR ) { - name ++; - ns = Bytecode_int_ResolveNamespace(&Script->Variant->RootNamespace, name, &name); - } - else { - // TODO: Support multiple default namespaces - ns = Bytecode_int_ResolveNamespace(default_namespace, name, &name); + // Resolve namespace into pointer + if( op->Operation != BC_OP_CALLMETHOD ) { + if( name[0] == BC_NS_SEPARATOR ) { + name ++; + ns = Bytecode_int_ResolveNamespace(&Script->Variant->RootNamespace, name, &name); + } + else { + // TODO: Support multiple default namespaces + ns = Bytecode_int_ResolveNamespace(default_namespace, name, &name); + } } - rv = SpiderScript_ExecuteFunction(Script, ns, name, arg_count, args); + // Call the function etc. + if( op->Operation == BC_OP_CALLFUNCTION ) + { + rv = SpiderScript_ExecuteFunction(Script, ns, name, arg_count, args); + } + else if( op->Operation == BC_OP_CREATEOBJ ) + { + rv = SpiderScript_CreateObject(Script, ns, name, arg_count, args); + } + else if( op->Operation == BC_OP_CALLMETHOD ) + { + tSpiderObject *obj; + GET_STACKVAL(val1); + + if(val1.Type == SS_DATATYPE_OBJECT) + obj = val1.Object; + else if(val1.Type == ET_REFERENCE && val1.Reference->Type == SS_DATATYPE_OBJECT) + obj = val1.Reference->Object; + else { + // Error + AST_RuntimeError(NULL, "OP_CALLMETHOD on non object"); + nextop = NULL; + break; + } + rv = SpiderScript_ExecuteMethod(Script, obj, name, arg_count, args); + Bytecode_int_DerefStackValue(&val1); + } + else + { + AST_RuntimeError(NULL, "BUG - Unknown operation for CALL/CREATEOBJ (%i)", op->Operation); + rv = ERRPTR; + } if(rv == ERRPTR) { AST_RuntimeError(NULL, "SpiderScript_ExecuteFunction returned ERRPTR"); nextop = NULL; @@ -648,7 +769,7 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t default: // TODO: STATE_HDR(); - printf("Unknown operation %i\n", op->Operation); + AST_RuntimeError(NULL, "Unknown operation %i\n", op->Operation); nextop = NULL; break; }