SpiderScript - Fixes, SpiderWeb's print_test.sw works
authorJohn Hodge <[email protected]>
Wed, 21 Sep 2011 07:52:36 +0000 (15:52 +0800)
committerJohn Hodge <[email protected]>
Wed, 21 Sep 2011 07:52:36 +0000 (15:52 +0800)
Usermode/Libraries/libspiderscript.so_src/ast.h
Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c
Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c
Usermode/Libraries/libspiderscript.so_src/values.c

index 39ea294..8ee56d7 100644 (file)
@@ -80,7 +80,7 @@ struct sAST_Node
 {
        tAST_Node       *NextSibling;
        tAST_NodeType   Type;
-       
+
        const char      *File;
         int    Line;
        
index 7c1398e..58cc5f8 100644 (file)
@@ -79,11 +79,19 @@ tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn)
                return NULL;
        }
 
+       Bytecode_AppendConstInt(ret, 0);        // TODO: NULL
+       Bytecode_AppendReturn(ret);
        Fcn->BCFcn = ret;
 
        return ret;
 }
 
+// Indepotent operation
+#define CHECK_IF_NEEDED(b_warn) do { if(!bKeepValue) {\
+       if(b_warn)AST_RuntimeMessage(Node, "Bytecode", "Operation without saving");\
+       Bytecode_AppendDelete(Block->Handle);\
+} } while(0)
+
 /**
  * \brief Convert a node into bytecode
  * \param Block        Execution context
@@ -94,7 +102,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
        tAST_Node       *node;
         int    ret = 0;
         int    i, op = 0;
-        int    bAddedValue = 1;
+        int    bAddedValue = 1;        // Used to tell if the value needs to be deleted
        
        switch(Node->Type)
        {
@@ -119,7 +127,6 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                        }
                }
                Bytecode_AppendLeaveContext(Block->Handle);     // Leave this context
-               bAddedValue = 0;
                break;
        
        // Assignment
@@ -170,20 +177,25 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                        Bytecode_AppendDuplicate(Block->Handle);
                // Set the variable value
                ret = BC_Variable_SetValue( Block, Node->Assign.Dest );
-               bAddedValue = 0;
                break;
        
        // Post increment/decrement
        case NODETYPE_POSTINC:
        case NODETYPE_POSTDEC:
-               Bytecode_AppendConstInt(Block->Handle, 1);
-               
                // TODO: Support assigning to object attributes
                if( Node->UniOp.Value->Type != NODETYPE_VARIABLE ) {
                        AST_RuntimeError(Node, "LVALUE of assignment is not a variable");
                        return -1;
                }
 
+               // Save original value if requested
+               if(bKeepValue) {
+                       ret = BC_Variable_GetValue(Block, Node->UniOp.Value);
+                       if(ret) return ret;
+               }
+               
+               Bytecode_AppendConstInt(Block->Handle, 1);
+               
                ret = BC_Variable_GetValue(Block, Node->UniOp.Value);
                if(ret) return ret;
 
@@ -193,8 +205,10 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                        Bytecode_AppendBinOp(Block->Handle, BC_OP_ADD);
                if(ret) return ret;
 
+
                ret = BC_Variable_SetValue(Block, Node->UniOp.Value);
                if(ret) return ret;
+               // Doesn't push unless needed
                break;
        
        // Function Call
@@ -202,6 +216,13 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
        case NODETYPE_FUNCTIONCALL:
        case NODETYPE_CREATEOBJECT: {
                 int    nargs = 0;
+
+               // Put the object earlier on the stack to the arguments (for exec)
+               if( Node->Type == NODETYPE_METHODCALL ) {
+                       ret = AST_ConvertNode(Block, Node->FunctionCall.Object, 1);
+                       if(ret) return ret;
+               }               
+
                for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling)
                {
                        ret = AST_ConvertNode(Block, node, 1);
@@ -213,8 +234,6 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                if( Node->Type == NODETYPE_METHODCALL )
                {
                        // TODO: Sanity check stack top
-                       ret = AST_ConvertNode(Block, Node->FunctionCall.Object, 1);
-                       if(ret) return ret;
                        Bytecode_AppendMethodCall(Block->Handle, Node->FunctionCall.Name, nargs);
                }
                else
@@ -245,6 +264,8 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                                Bytecode_AppendFunctionCall(Block->Handle, manglename, nargs);
                        }
                }
+               CHECK_IF_NEEDED(0);     // Don't warn
+               // TODO: Implement warn_unused_ret
                } break;
        
        // Conditional
@@ -278,7 +299,6 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
 
                // End
                Bytecode_SetLabel(Block->Handle, if_end);
-               bAddedValue = 0;
                } break;
        
        // Loop
@@ -337,7 +357,6 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                Block->BreakTarget = saved_break;
                Block->ContinueTarget = saved_continue;
                Block->Tag = saved_tag;
-               bAddedValue = 0;
                } break;
        
        // Return
@@ -345,7 +364,6 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                ret = AST_ConvertNode(Block, Node->UniOp.Value, 1);
                if(ret) return ret;
                Bytecode_AppendReturn(Block->Handle);
-               bAddedValue = 0;
                break;
        
        case NODETYPE_BREAK:
@@ -360,7 +378,6 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                        Bytecode_AppendJump(Block->Handle, bi->BreakTarget);
                else
                        Bytecode_AppendJump(Block->Handle, bi->ContinueTarget);
-               bAddedValue = 0;
                } break;
        
        // Define a variable
@@ -374,7 +391,6 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                        if(ret) return ret;
                        Bytecode_AppendSaveVar(Block->Handle, Node->DefVar.Name);
                }
-               bAddedValue = 0;
                break;
        
        // Scope
@@ -387,11 +403,14 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                Block->CurNamespaceStack[i] = Node->Scope.Name;
                ret = AST_ConvertNode(Block, Node->Scope.Element, 2);
                Block->CurNamespaceStack[i] = NULL;
+               CHECK_IF_NEEDED(0);     // No warning?
+               // TODO: Will this collide with _CALLFUNCTION etc?
                break;
        
        // Variable
        case NODETYPE_VARIABLE:
                ret = BC_Variable_GetValue( Block, Node );
+               CHECK_IF_NEEDED(1);
                break;
        
        // Element of an Object
@@ -400,6 +419,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                if(ret) return ret;
 
                Bytecode_AppendElement(Block->Handle, Node->Scope.Name);
+               CHECK_IF_NEEDED(1);
                break;
 
        // Cast a value to another
@@ -407,6 +427,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                ret = AST_ConvertNode(Block, Node->Cast.Value, 1);
                if(ret) return ret;
                Bytecode_AppendCast(Block->Handle, Node->Cast.DataType);
+               CHECK_IF_NEEDED(1);
                break;
 
        // Index into an array
@@ -417,6 +438,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                if(ret) return ret;
                
                Bytecode_AppendIndex(Block->Handle);
+               CHECK_IF_NEEDED(1);
                break;
 
        // TODO: Implement runtime constants
@@ -429,12 +451,15 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
        // Constant Values
        case NODETYPE_STRING:
                Bytecode_AppendConstString(Block->Handle, Node->Constant.String.Data, Node->Constant.String.Length);
+               CHECK_IF_NEEDED(1);
                break;
        case NODETYPE_INTEGER:
                Bytecode_AppendConstInt(Block->Handle, Node->Constant.Integer);
+               CHECK_IF_NEEDED(1);
                break;
        case NODETYPE_REAL:
                Bytecode_AppendConstReal(Block->Handle, Node->Constant.Real);
+               CHECK_IF_NEEDED(1);
                break;
        
        // --- Operations ---
@@ -448,6 +473,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                ret = AST_ConvertNode(Block, Node->UniOp.Value, 1);
                if(ret) return ret;
                Bytecode_AppendUniOp(Block->Handle, op);
+               CHECK_IF_NEEDED(1);
                break;
 
        // Logic
@@ -478,6 +504,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
                if(ret) return ret;
        
                Bytecode_AppendBinOp(Block->Handle, op);
+               CHECK_IF_NEEDED(1);
                break;
        
        default:
@@ -495,9 +522,6 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue)
        }
        #endif
 
-       if( !bKeepValue && bAddedValue )
-               Bytecode_AppendDelete(Block->Handle);
-
        return ret;
 }
 
index 50e2f4f..9dabeff 100644 (file)
@@ -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:
@@ -410,9 +430,11 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t
                                AST_RuntimeError(NULL, "Loading from invalid slot %i", OP_INDX(op));
                                return -1;
                        }
+                       DEBUG_F("[Deref "); PRINT_STACKVAL(local_vars[OP_INDX(op)]); DEBUG_F("] ");
+                       Bytecode_int_DerefStackValue( &local_vars[OP_INDX(op)] );
+                       GET_STACKVAL(local_vars[OP_INDX(op)]);
                        PRINT_STACKVAL(local_vars[OP_INDX(op)]);
                        DEBUG_F("\n");
-                       GET_STACKVAL(local_vars[OP_INDX(op)]);
                        break;
 
                // Constants:
@@ -522,6 +544,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";
@@ -572,40 +620,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 +672,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 +741,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;
                }
index f05360d..12e1bf0 100644 (file)
@@ -32,13 +32,20 @@ void SpiderScript_DereferenceValue(tSpiderValue *Object)
 {
        if(!Object || Object == ERRPTR) return ;
        Object->ReferenceCount --;
+       if(Object->Type == SS_DATATYPE_OBJECT) {
+       }
        if( Object->ReferenceCount == 0 )
        {
                switch( (enum eSpiderScript_DataTypes) Object->Type )
                {
                case SS_DATATYPE_OBJECT:
-                       Object->Object->Type->Destructor( Object->Object );
+                       Object->Object->ReferenceCount --;
+                       if(Object->Object->ReferenceCount == 0) {
+                               Object->Object->Type->Destructor( Object->Object );
+                       }
+                       Object->Object = NULL;
                        break;
+
                case SS_DATATYPE_OPAQUE:
                        Object->Opaque.Destroy( Object->Opaque.Data );
                        break;
@@ -169,7 +176,7 @@ tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source)
        
        // Check if anything needs to be done
        if( Source->Type == Type ) {
-               SpiderScript_DereferenceValue(Source);
+               SpiderScript_ReferenceValue(Source);
                return Source;
        }
        

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