From: John Hodge Date: Wed, 21 Sep 2011 07:52:36 +0000 (+0800) Subject: SpiderScript - Fixes, SpiderWeb's print_test.sw works X-Git-Tag: rel0.11~87 X-Git-Url: https://git.ucc.asn.au/?p=tpg%2Facess2.git;a=commitdiff_plain;h=a18890d3ecb360989383d727017a21c103fee865 SpiderScript - Fixes, SpiderWeb's print_test.sw works --- diff --git a/Usermode/Libraries/libspiderscript.so_src/ast.h b/Usermode/Libraries/libspiderscript.so_src/ast.h index 39ea2947..8ee56d77 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast.h +++ b/Usermode/Libraries/libspiderscript.so_src/ast.h @@ -80,7 +80,7 @@ struct sAST_Node { tAST_Node *NextSibling; tAST_NodeType Type; - + const char *File; int Line; diff --git a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c index 7c1398e8..58cc5f82 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c @@ -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; } diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c index 50e2f4f8..9dabeff6 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c @@ -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; } diff --git a/Usermode/Libraries/libspiderscript.so_src/values.c b/Usermode/Libraries/libspiderscript.so_src/values.c index f05360d4..12e1bf0d 100644 --- a/Usermode/Libraries/libspiderscript.so_src/values.c +++ b/Usermode/Libraries/libspiderscript.so_src/values.c @@ -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; }