From 2acaad7b0d455a6c7cb177e1a7ecc5f07f40c7bb Mon Sep 17 00:00:00 2001 From: John Hodge Date: Wed, 21 Sep 2011 12:20:02 +0800 Subject: [PATCH] SpiderScript - Bugfixing, most bytecode runs now --- .../libspiderscript.so_src/ast_to_bytecode.c | 29 ++++- .../libspiderscript.so_src/bytecode_gen.c | 4 +- .../libspiderscript.so_src/bytecode_gen.h | 1 + .../libspiderscript.so_src/bytecode_ops.h | 15 +-- .../libspiderscript.so_src/exec_bytecode.c | 117 +++++++++++++++--- 5 files changed, 136 insertions(+), 30 deletions(-) diff --git a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c index 6b7e038a..7c1398e8 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c @@ -94,11 +94,13 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) tAST_Node *node; int ret = 0; int i, op = 0; + int bAddedValue = 1; switch(Node->Type) { // No Operation case NODETYPE_NOP: + bAddedValue = 0; break; // Code block @@ -117,6 +119,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) } } Bytecode_AppendLeaveContext(Block->Handle); // Leave this context + bAddedValue = 0; break; // Assignment @@ -126,8 +129,6 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) AST_RuntimeError(Node, "LVALUE of assignment is not a variable"); return -1; } - ret = AST_ConvertNode(Block, Node->Assign.Value, 1); - if(ret) return ret; // Perform assignment operation if( Node->Assign.Operation != NODETYPE_NOP ) @@ -135,6 +136,8 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) ret = BC_Variable_GetValue(Block, Node->Assign.Dest); if(ret) return ret; + ret = AST_ConvertNode(Block, Node->Assign.Value, 1); + if(ret) return ret; switch(Node->Assign.Operation) { // General Binary Operations @@ -157,11 +160,17 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) printf("assign, op = %i\n", op); Bytecode_AppendBinOp(Block->Handle, op); } + else + { + ret = AST_ConvertNode(Block, Node->Assign.Value, 1); + if(ret) return ret; + } if( bKeepValue ) Bytecode_AppendDuplicate(Block->Handle); // Set the variable value ret = BC_Variable_SetValue( Block, Node->Assign.Dest ); + bAddedValue = 0; break; // Post increment/decrement @@ -269,6 +278,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) // End Bytecode_SetLabel(Block->Handle, if_end); + bAddedValue = 0; } break; // Loop @@ -327,6 +337,7 @@ 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 @@ -334,6 +345,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_AppendReturn(Block->Handle); + bAddedValue = 0; break; case NODETYPE_BREAK: @@ -348,6 +360,7 @@ 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 @@ -361,6 +374,7 @@ 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 @@ -466,10 +480,10 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) Bytecode_AppendBinOp(Block->Handle, op); break; - //default: - // ret = NULL; - // AST_RuntimeError(Node, "BUG - SpiderScript AST_ConvertNode Unimplemented %i", Node->Type); - // break; + default: + ret = -1; + AST_RuntimeError(Node, "BUG - SpiderScript AST_ConvertNode Unimplemented %i", Node->Type); + break; } #if TRACE_NODE_RETURNS @@ -481,6 +495,9 @@ 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/bytecode_gen.c b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c index 54835aea..b089b9ae 100644 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c +++ b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c @@ -395,6 +395,8 @@ void Bytecode_AppendCast(tBC_Function *Handle, int Type) DEF_BC_INT(BC_OP_CAST, Type) void Bytecode_AppendDuplicate(tBC_Function *Handle) DEF_BC_NONE(BC_OP_DUPSTACK); +void Bytecode_AppendDelete(tBC_Function *Handle) + DEF_BC_NONE(BC_OP_DELSTACK); // Does some bookeeping to allocate variable slots at compile time void Bytecode_AppendEnterContext(tBC_Function *Handle) @@ -414,7 +416,7 @@ void Bytecode_AppendLeaveContext(tBC_Function *Handle) Handle->CurContextDepth --; Handle->VariableCount = i; - DEF_BC_NONE(BC_OP_LEAVECONTEXT) + DEF_BC_NONE(BC_OP_LEAVECONTEXT); } //void Bytecode_AppendImportNamespace(tBC_Function *Handle, const char *Name); // DEF_BC_STRINT(BC_OP_IMPORTNS, Name, 0) diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h index 955049bf..0d901ebd 100644 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h +++ b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h @@ -67,6 +67,7 @@ extern void Bytecode_AppendBinOp(tBC_Function *Handle, int Operation); extern void Bytecode_AppendUniOp(tBC_Function *Handle, int Operation); extern void Bytecode_AppendCast(tBC_Function *Handlde, int Type); extern void Bytecode_AppendDuplicate(tBC_Function *Handlde); +extern void Bytecode_AppendDelete(tBC_Function *Handle); // - Context // TODO: Are contexts needed? Should variables be allocated like labels? extern void Bytecode_AppendEnterContext(tBC_Function *Handle); diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h b/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h index 1d15c595..59c58bea 100644 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h +++ b/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h @@ -24,38 +24,39 @@ enum eBC_Ops BC_OP_LOADSTR, BC_OP_DUPSTACK, // = 13 + BC_OP_DELSTACK, // BC_OP_CAST, // - BC_OP_ELEMENT, // = 15 + BC_OP_ELEMENT, // = 16 BC_OP_INDEX, - BC_OP_ENTERCONTEXT, // = 17 + BC_OP_ENTERCONTEXT, // = 18 BC_OP_LEAVECONTEXT, BC_OP_DEFINEVAR, // Operations - BC_OP_LOGICNOT, // 20 + BC_OP_LOGICNOT, // 21 BC_OP_LOGICAND, BC_OP_LOGICOR, BC_OP_LOGICXOR, - BC_OP_BITNOT, // 24 + BC_OP_BITNOT, // 25 BC_OP_BITAND, BC_OP_BITOR, BC_OP_BITXOR, - BC_OP_BITSHIFTLEFT, // 28 + BC_OP_BITSHIFTLEFT, // 29 BC_OP_BITSHIFTRIGHT, BC_OP_BITROTATELEFT, - BC_OP_NEG, // 31 + BC_OP_NEG, // 32 BC_OP_ADD, BC_OP_SUBTRACT, BC_OP_MULTIPLY, BC_OP_DIVIDE, BC_OP_MODULO, - BC_OP_EQUALS, // 37 + BC_OP_EQUALS, // 38 BC_OP_NOTEQUALS, BC_OP_LESSTHAN, BC_OP_LESSTHANOREQUAL, diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c index 1a74d4c2..50e2f4f8 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c @@ -12,9 +12,15 @@ #include #include #include "ast.h" +#include -//#define DEBUG_F(v...) printf(v) -#define DEBUG_F(v...) +#define TRACE 0 + +#if TRACE +# define DEBUG_F(v...) printf(v) +#else +# define DEBUG_F(v...) +#endif // === IMPORTS === extern void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); @@ -123,6 +129,7 @@ tSpiderValue *Bytecode_int_GetSpiderValue(tBC_StackEnt *Ent, tSpiderValue *tmp) AST_RuntimeError(NULL, "_GetSpiderValue on ET_FUNCTION_START"); return NULL; default: + SpiderScript_ReferenceValue(Ent->Reference); return Ent->Reference; } } @@ -169,13 +176,51 @@ void Bytecode_int_DerefStackValue(tBC_StackEnt *Ent) break; } } +void Bytecode_int_RefStackValue(tBC_StackEnt *Ent) +{ + switch(Ent->Type) + { + case SS_DATATYPE_INTEGER: + case SS_DATATYPE_REAL: + case SS_DATATYPE_OBJECT: + break; + default: + SpiderScript_ReferenceValue(Ent->Reference); + break; + } +} + +void Bytecode_int_PrintStackValue(tBC_StackEnt *Ent) +{ + switch(Ent->Type) + { + case SS_DATATYPE_INTEGER: + printf("0x%"PRIx64, Ent->Integer); + break; + case SS_DATATYPE_REAL: + printf("%lf", Ent->Real); + break; + case SS_DATATYPE_OBJECT: + printf("Obj %p", Ent->Object); + break; + default: + printf("*%p", Ent->Reference); + break; + } +} + +#if TRACE +# define PRINT_STACKVAL(val) Bytecode_int_PrintStackValue(&val) +#else +# define PRINT_STACKVAL(val) +#endif #define GET_STACKVAL(dst) if((ret = Bytecode_int_StackPop(Stack, &dst))) { \ AST_RuntimeError(NULL, "Stack pop failed, empty stack");\ return ret; \ } #define PUT_STACKVAL(src) if((ret = Bytecode_int_StackPush(Stack, &src))) { \ - AST_RuntimeError(NULL, "Stack pop failed, empty stack");\ + AST_RuntimeError(NULL, "Stack push failed, full stack");\ return ret; \ } #define OP_INDX(op_ptr) ((op_ptr)->Content.StringInt.Integer) @@ -255,6 +300,10 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t tSpiderValue tmpVal1, tmpVal2; // temp storage tSpiderValue *pval1, *pval2, *ret_val; tSpiderNamespace *default_namespace = &Script->Variant->RootNamespace; + + // Initialise local vars + for( i = 0; i < local_var_count; i ++ ) + local_vars[i].Type = ET_NULL; // Pop off arguments if( ArgCount > Fcn->ArgumentCount ) return -1; @@ -323,6 +372,10 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t } STATE_HDR(); DEBUG_F("DEFVAR %i of type %i\n", slot, type); + if( local_vars[slot].Type != ET_NULL ) { + Bytecode_int_DerefStackValue( &local_vars[slot] ); + local_vars[slot].Type = ET_NULL; + } memset(&local_vars[slot], 0, sizeof(local_vars[0])); local_vars[slot].Type = type; } break; @@ -341,21 +394,24 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t // Variables case BC_OP_LOADVAR: STATE_HDR(); - DEBUG_F("LOADVAR %i\n", OP_INDX(op)); + 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)); return -1; } + DEBUG_F("("); PRINT_STACKVAL(local_vars[OP_INDX(op)]); DEBUG_F(")\n"); PUT_STACKVAL(local_vars[OP_INDX(op)]); -// DUMP_STACKVAL(local_vars[OP_INDX(op)]); + Bytecode_int_RefStackValue( &local_vars[OP_INDX(op)] ); break; case BC_OP_SAVEVAR: STATE_HDR(); - DEBUG_F("SAVEVAR %i\n", OP_INDX(op)); + 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)); return -1; } + PRINT_STACKVAL(local_vars[OP_INDX(op)]); + DEBUG_F("\n"); GET_STACKVAL(local_vars[OP_INDX(op)]); break; @@ -398,7 +454,7 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t PUT_STACKVAL(val2); break; case SS_DATATYPE_REAL*100 + SS_DATATYPE_INTEGER: - val2.Integer = val1.Real; + val2.Real = val1.Integer; PUT_STACKVAL(val2); break; default: { @@ -414,10 +470,20 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t case BC_OP_DUPSTACK: STATE_HDR(); - DEBUG_F("DUPSTACK\n"); + DEBUG_F("DUPSTACK "); GET_STACKVAL(val1); + PRINT_STACKVAL(val1); + DEBUG_F("\n"); PUT_STACKVAL(val1); PUT_STACKVAL(val1); + Bytecode_int_RefStackValue(&val1); + break; + + // Discard the top item from the stack + case BC_OP_DELSTACK: + STATE_HDR(); + DEBUG_F("DELSTACK\n"); + GET_STACKVAL(val1); break; // Unary Operations @@ -439,6 +505,8 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t GET_STACKVAL(val1); pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1); + Bytecode_int_DerefStackValue(&val1); + ret_val = AST_ExecuteNode_UniOp(Script, NULL, ast_op, pval1); if(pval1 != &tmpVal1) SpiderScript_DereferenceValue(pval1); Bytecode_int_SetSpiderValue(&val1, ret_val); @@ -494,16 +562,19 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t STATE_HDR(); DEBUG_F("BINOP %i %s (bc %i)\n", ast_op, opstr, op->Operation); - GET_STACKVAL(val2); - GET_STACKVAL(val1); + GET_STACKVAL(val2); // Right + GET_STACKVAL(val1); // Left pval1 = Bytecode_int_GetSpiderValue(&val1, &tmpVal1); pval2 = Bytecode_int_GetSpiderValue(&val2, &tmpVal2); + Bytecode_int_DerefStackValue(&val1); + Bytecode_int_DerefStackValue(&val2); + 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); - Bytecode_int_StackPush(Stack, &val1); + PUT_STACKVAL(val1); break; // Functions etc @@ -539,6 +610,7 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t { GET_STACKVAL(val1); args[i] = Bytecode_int_GetSpiderValue(&val1, NULL); + Bytecode_int_DerefStackValue(&val1); } if( name[0] == BC_NS_SEPARATOR ) { @@ -585,14 +657,27 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t // Clean up // - Delete local vars - printf("TODO: Clean up local vars\n"); + for( i = 0; i < local_var_count; i ++ ) + { + if( local_vars[i].Type != ET_NULL ) + { + Bytecode_int_DerefStackValue(&local_vars[i]); + } + } // - Restore stack // printf("TODO: Roll back stack\n"); -// while( Stack->EntryCount && Stack->Entries[ --Stack->EntryCount ].Type != ET_FUNCTION_START ) -// { -// Bytecode_int_DerefStackValue( &Stack->Entries[Stack->EntryCount] ); -// } + if( Stack->Entries[Stack->EntryCount - 1].Type == ET_FUNCTION_START ) + Stack->EntryCount --; + else + { + GET_STACKVAL(val1); + while( Stack->EntryCount && Stack->Entries[ --Stack->EntryCount ].Type != ET_FUNCTION_START ) + { + Bytecode_int_DerefStackValue( &Stack->Entries[Stack->EntryCount] ); + } + PUT_STACKVAL(val1); + } return 0; -- 2.20.1