SpiderScript - Moved header to directory, ready to remove from tree
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / exec_bytecode.c
index 50dfec4..9de7281 100644 (file)
@@ -105,6 +105,7 @@ tSpiderValue *Bytecode_int_GetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *tmp)
                        tmp = malloc(sizeof(tSpiderValue));
                        tmp->ReferenceCount = 1;
                } else {
+                       // Stops a stack value from having free() called on it
                        tmp->ReferenceCount = 2;
                }
                break;
@@ -222,7 +223,10 @@ void Bytecode_int_PrintStackValue(tBC_StackEnt *Ent)
                printf("Obj %p", Ent->Object);
                break;
        default:
-               printf("*%p", Ent->Reference);
+               if( Ent->Reference )
+                       printf("*%p (%i refs)", Ent->Reference, Ent->Reference->ReferenceCount);
+               else
+                       printf("NULL");
                break;
        }
 }
@@ -272,11 +276,14 @@ tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function *
                return NULL;
        }
        free(stack);
+       
        ret = Bytecode_int_GetSpiderValue(&val, &tmpsval);
        // Ensure it's a heap value
        if(ret == &tmpsval) {
                ret = malloc(sizeof(tSpiderValue));
                memcpy(ret, &tmpsval, sizeof(tSpiderValue));
+               // Set to 2 in _GetSpiderValue, so stack doesn't have free() called
+               ret->ReferenceCount = 1;
        }
 
        return ret;
@@ -311,10 +318,10 @@ int Bytecode_int_CallExternFunction(tSpiderScript *Script, tBC_Stack *Stack, tSp
        const char      *name = OP_STRING(op);
         int    arg_count = OP_INDX(op);
         int    i, ret = 0;
-       tSpiderNamespace        *ns = NULL;
        tSpiderValue    *args[arg_count];
        tSpiderValue    *rv;
-       tBC_StackEnt    val1;   
+       tBC_StackEnt    val1;
+       const char      *namespaces[] = {NULL}; // TODO: Default/imported namespaces
 
        DEBUG_F("CALL (general) %s %i args\n", name, arg_count);
        
@@ -326,31 +333,14 @@ int Bytecode_int_CallExternFunction(tSpiderScript *Script, tBC_Stack *Stack, tSp
                Bytecode_int_DerefStackValue(&val1);
        }
        
-       // Resolve namespace into pointer
-       if( op->Operation != BC_OP_CALLMETHOD ) {
-               const char *name_orig = name;
-               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(DefaultNS, name, &name);
-               }
-               if( !ns ) {
-                       AST_RuntimeError(NULL, "Namespace '%s' not found in '%s'", name, name_orig);
-                       return -1;
-               }
-       }
-       
        // Call the function etc.
        if( op->Operation == BC_OP_CALLFUNCTION )
        {
-               rv = SpiderScript_ExecuteFunction(Script, ns, name, arg_count, args);
+               rv = SpiderScript_ExecuteFunction(Script, name, namespaces, arg_count, args, &op->CacheEnt);
        }
        else if( op->Operation == BC_OP_CREATEOBJ )
        {
-               rv = SpiderScript_CreateObject(Script, ns, name, arg_count, args);
+               rv = SpiderScript_CreateObject(Script, name, namespaces, arg_count, args);
        }
        else if( op->Operation == BC_OP_CALLMETHOD )
        {
@@ -386,8 +376,18 @@ int Bytecode_int_CallExternFunction(tSpiderScript *Script, tBC_Stack *Stack, tSp
        PUT_STACKVAL(val1);
        // Deref return
        SpiderScript_DereferenceValue(rv);
-       
-       return ret;
+
+       #if 0
+       if(!rv) {
+               printf("%s returned NULL\n", name);
+       }
+       if( rv && rv != ERRPTR && rv->ReferenceCount != 1 ) {
+               printf("Return value from %s reference count fail (%i)\n",
+                       name, rv->ReferenceCount);
+       }
+       #endif  
+
+       return 0;
 }
 
 int Bytecode_int_LocalBinOp_Integer(int Operation, tBC_StackEnt *Val1, tBC_StackEnt *Val2)
@@ -410,7 +410,7 @@ int Bytecode_int_LocalBinOp_Integer(int Operation, tBC_StackEnt *Val1, tBC_Stack
        case BC_OP_BITOR:       Val1->Integer = Val1->Integer | Val2->Integer;  break;
        case BC_OP_BITXOR:      Val1->Integer = Val1->Integer ^ Val2->Integer;  break;
        case BC_OP_MODULO:      Val1->Integer = Val1->Integer % Val2->Integer;  break;
-       default:        AST_RuntimeError(NULL, "Invalid operation on datatype %i", Val1->Type); return -1;
+       default:        AST_RuntimeError(NULL, "Invalid operation on datatype Integer"); return -1;
        }
        return 0;
 }
@@ -419,11 +419,13 @@ int Bytecode_int_LocalBinOp_Real(int Operation, tBC_StackEnt *Val1, tBC_StackEnt
 {
        switch(Operation)
        {
+       // Real = Real OP Real
        case BC_OP_ADD:         Val1->Real = Val1->Real + Val2->Real;   return 0;
        case BC_OP_SUBTRACT:    Val1->Real = Val1->Real - Val2->Real;   return 0;
        case BC_OP_MULTIPLY:    Val1->Real = Val1->Real * Val2->Real;   return 0;
        case BC_OP_DIVIDE:      Val1->Real = Val1->Real / Val2->Real;   return 0;
 
+       // Bool/Integer = Real OP Real
        case BC_OP_EQUALS:              Val1->Integer = (Val1->Real == Val2->Real);     break;
        case BC_OP_NOTEQUALS:           Val1->Integer = (Val1->Real != Val2->Real);     break;
        case BC_OP_LESSTHAN:            Val1->Integer = (Val1->Real <  Val2->Real);     break;
@@ -431,7 +433,7 @@ int Bytecode_int_LocalBinOp_Real(int Operation, tBC_StackEnt *Val1, tBC_StackEnt
        case BC_OP_GREATERTHAN:         Val1->Integer = (Val1->Real >  Val2->Real);     break;
        case BC_OP_GREATERTHANOREQUAL:  Val1->Integer = (Val1->Real >= Val2->Real);     break;
        
-       default:        AST_RuntimeError(NULL, "Invalid operation on datatype %i", Val1->Type); return -1;
+       default:        AST_RuntimeError(NULL, "Invalid operation on datatype Real"); return -1;
        }
        Val1->Type = SS_DATATYPE_INTEGER;       // Becomes logical
        return 0;
@@ -494,7 +496,6 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t
                // Jumps
                case BC_OP_JUMP:
                        STATE_HDR();
-                       // NOTE: Evil, all jumps are off by -1, so fix that
                        jmp_target = Fcn->BCFcn->Labels[ OP_INDX(op) ]->Next;
                        DEBUG_F("JUMP #%i %p\n", OP_INDX(op), jmp_target);
                        nextop = jmp_target;
@@ -567,13 +568,101 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t
                                AST_RuntimeError(NULL, "Loading from invalid slot %i", slot);
                                return -1;
                        }
+                       // Remove whatever was in there before
                        DEBUG_F("[Deref "); PRINT_STACKVAL(local_vars[slot]); DEBUG_F("] ");
                        Bytecode_int_DerefStackValue( &local_vars[slot] );
+                       // Place new in
                        GET_STACKVAL(local_vars[slot]);
                        PRINT_STACKVAL(local_vars[slot]);
                        DEBUG_F("\n");
                        } break;
 
+               // Array index (get or set)
+               case BC_OP_INDEX:
+               case BC_OP_SETINDEX:
+                       STATE_HDR();
+                       GET_STACKVAL(val1);     // Index
+                       // TODO: Check that index is an integer
+                       if( val1.Type != SS_DATATYPE_INTEGER ) {
+                               nextop = NULL;
+                               break;
+                       }
+
+                       // Get array as raw spider value
+                       GET_STACKVAL(val2);     // Array
+                       pval1 = Bytecode_int_GetSpiderValue(&val2, &tmpVal1);
+                       Bytecode_int_DerefStackValue(&val2);
+
+                       if( op->Operation == BC_OP_SETINDEX ) {
+                               GET_STACKVAL(val2);
+                               pval2 = Bytecode_int_GetSpiderValue(&val2, NULL);
+                               Bytecode_int_DerefStackValue(&val2);
+                               
+                               DEBUG_F("SETINDEX %i ", val1.Integer); PRINT_STACKVAL(val2); DEBUG_F("\n");
+                       
+                               ret_val = AST_ExecuteNode_Index(Script, NULL, pval1, val1.Integer, pval2);
+                               if(ret_val == ERRPTR) { nextop = NULL; break; }
+                               SpiderScript_DereferenceValue(pval2);
+                       }
+                       else {
+                               DEBUG_F("INDEX %i ", val1.Integer);
+                               ret_val = AST_ExecuteNode_Index(Script, NULL, pval1, val1.Integer, ERRPTR);
+                               if(ret_val == ERRPTR) { nextop = NULL; break; }
+                               
+                               Bytecode_int_SetSpiderValue(&val1, ret_val);
+                               SpiderScript_DereferenceValue(ret_val);
+                               PUT_STACKVAL(val1);
+
+                               DEBUG_F("[Got "); PRINT_STACKVAL(val1); DEBUG_F("]\n");
+
+                       }
+                       // Dereference the array (or object, ...)
+                       if(pval1 != &tmpVal1)   SpiderScript_DereferenceValue(pval1);
+                       break;
+               
+               // Object element (get or set)
+               case BC_OP_ELEMENT:
+               case BC_OP_SETELEMENT:
+                       STATE_HDR();
+                       
+                       GET_STACKVAL(val1);
+                       // - Integers/Reals can't have elements :)
+                       if( val1.Type != ET_REFERENCE ) {
+                               nextop = NULL;
+                               break;
+                       }
+
+                       pval1 = Bytecode_int_GetSpiderValue(&val1, NULL);
+                       Bytecode_int_DerefStackValue(&val1);
+
+                       if( op->Operation == BC_OP_SETELEMENT ) {
+                               GET_STACKVAL(val2);
+                               pval2 = Bytecode_int_GetSpiderValue(&val2, &tmpVal2);
+                               Bytecode_int_DerefStackValue(&val2);
+                               
+                               DEBUG_F("SETELEMENT %s ", OP_STRING(op)); PRINT_STACKVAL(val2); DEBUG_F("\n");
+
+                               ret_val = AST_ExecuteNode_Element(Script, NULL, pval1, OP_STRING(op), pval2);
+                               if(ret_val == ERRPTR) { nextop = NULL; break; }
+                               
+                               if(pval2 != &tmpVal2)   SpiderScript_DereferenceValue(pval2);
+                       }
+                       else {
+                               DEBUG_F("ELEMENT %s ", OP_STRING(op));
+                               
+                               ret_val = AST_ExecuteNode_Element(Script, NULL, pval1, OP_STRING(op), ERRPTR);
+                               if(ret_val == ERRPTR) { nextop = NULL; break; }
+
+                               Bytecode_int_SetSpiderValue(&val2, ret_val);
+                               SpiderScript_DereferenceValue(ret_val);
+                               PUT_STACKVAL(val2);
+       
+                               DEBUG_F("[Got "); PRINT_STACKVAL(val2); DEBUG_F("]\n");
+                       }
+                       
+                       SpiderScript_DereferenceValue(pval1);
+                       break;
+
                // Constants:
                case BC_OP_LOADINT:
                        STATE_HDR();
@@ -596,6 +685,13 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t
                        val1.Reference = SpiderScript_CreateString(OP_INDX(op), OP_STRING(op));
                        PUT_STACKVAL(val1);
                        break;
+               case BC_OP_LOADNULL:
+                       STATE_HDR();
+                       DEBUG_F("LOADNULL\n");
+                       val1.Type = ET_REFERENCE;
+                       val1.Reference = NULL;
+                       PUT_STACKVAL(val1);
+                       break;
 
                case BC_OP_CAST:
                        STATE_HDR();
@@ -606,25 +702,26 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t
                                PUT_STACKVAL(val1);
                                break;
                        }
-                       switch(val2.Type * 100 + val1.Type )
-                       {
-                       case SS_DATATYPE_INTEGER*100 + SS_DATATYPE_REAL:
+                       if( val2.Type == SS_DATATYPE_INTEGER && val1.Type == SS_DATATYPE_REAL ) {
                                val2.Integer = val1.Real;
-                               PUT_STACKVAL(val2);
-                               break;
-                       case SS_DATATYPE_REAL*100 + SS_DATATYPE_INTEGER:
+                       }
+                       else if( val2.Type == SS_DATATYPE_REAL && val2.Type == SS_DATATYPE_INTEGER ) {
                                val2.Real = val1.Integer;
-                               PUT_STACKVAL(val2);
-                               break;
-                       default: {
+                       }
+                       else {
                                pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1);
                                pval2 = SpiderScript_CastValueTo(val2.Type, pval1);
-                               if(pval1 != &tmpVal1)   SpiderScript_DereferenceValue(pval1);
+                               
                                Bytecode_int_SetSpiderValue(&val2, pval2);
                                SpiderScript_DereferenceValue(pval2);
-                               PUT_STACKVAL(val2);
-                               } break;
+                               
+                               if(pval1 != &tmpVal1)   SpiderScript_DereferenceValue(pval1);
+                               Bytecode_int_DerefStackValue(&val1);
+//                             printf("CAST (%x->%x) - Original %i references remaining\n",
+//                                     pval1->Type, OP_INDX(op),
+//                                     pval1->ReferenceCount);
                        }
+                       PUT_STACKVAL(val2);
                        break;
 
                case BC_OP_DUPSTACK:
@@ -856,8 +953,13 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t
        {
                if( local_vars[i].Type != ET_NULL )
                {
+                       DEBUG_F("Var %i - ", i); 
+                       PRINT_STACKVAL(local_vars[i]);
                        Bytecode_int_DerefStackValue(&local_vars[i]);
+                       DEBUG_F("\n");
                }
+               else
+                       DEBUG_F("Var %i - empty\n", i);
        }
        
        // - Restore stack
@@ -873,7 +975,7 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t
                        n_rolled ++;
                }
                PUT_STACKVAL(val1);
-               DEBUG_F("Rolled back %i entried\n", n_rolled);
+               DEBUG_F("Rolled back %i entries\n", n_rolled);
        }
        
 

UCC git Repository :: git.ucc.asn.au