X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FLibraries%2Flibspiderscript.so_src%2Fexec_ast.c;h=d84b8f920672da729afcddf125310da4986f1b7e;hb=046980a1afd982af07dc97aaadb186e31eebb340;hp=22469798d124b28d5e5ed19f0f52af14bb256435;hpb=be6e3ccd05add9ad319a121661c20cb4769f58d7;p=tpg%2Facess2.git diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c index 22469798..d84b8f92 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c @@ -1,4 +1,7 @@ /* + * SpiderScript Library + * + * AST Execution */ #include #include @@ -508,7 +511,8 @@ tSpiderValue *SpiderScript_ExecuteFunction(tSpiderScript *Script, // Not found? if(!bFound) { - fprintf(stderr, "Undefined reference to function '%s'\n", Function); + fprintf(stderr, "Undefined reference to function '%s' (ns='%s')\n", + Function, Namespace->Name); return ERRPTR; } @@ -650,6 +654,9 @@ tSpiderValue *SpiderScript_CreateObject(tSpiderScript *Script, { class = NULL; // Just to allow the below code to be neat + //if( !Namespace ) + // Namespace = &Script->Variant->RootNamespace; + // Second: Scan current namespace if( !class && Namespace ) { @@ -745,10 +752,13 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) blockInfo.RetVal = NULL; blockInfo.BaseNamespace = Block->BaseNamespace; blockInfo.CurNamespace = NULL; + blockInfo.BreakTarget = NULL; blockInfo.Ident = giNextBlockIdent ++; ret = NULL; // Loop over all nodes, or until the return value is set - for(node = Node->Block.FirstChild; node && !blockInfo.RetVal; node = node->NextSibling ) + for(node = Node->Block.FirstChild; + node && !blockInfo.RetVal && !blockInfo.BreakTarget; + node = node->NextSibling ) { ret = AST_ExecuteNode(&blockInfo, node); if(ret == ERRPTR) break; // Error check @@ -767,6 +777,12 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) // Set parent's return value if needed if( blockInfo.RetVal ) Block->RetVal = blockInfo.RetVal; + if( blockInfo.BreakTarget ) { + Block->BreakTarget = blockInfo.BreakTarget; + Block->BreakType = blockInfo.BreakType; + } + + // TODO: Unset break if break type deontes a block break } break; @@ -784,12 +800,33 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) // Perform assignment operation if( Node->Assign.Operation != NODETYPE_NOP ) { - tSpiderValue *varVal = Variable_GetValue(Block, Node->Assign.Dest); - tSpiderValue *value; + tSpiderValue *varVal, *value; + + varVal = Variable_GetValue(Block, Node->Assign.Dest); + if(varVal == ERRPTR) return ERRPTR; + #if 0 + #else + if(varVal && varVal->ReferenceCount == 2) { + Object_Dereference(varVal); +// printf("pre: (%s) varVal->ReferenceCount = %i\n", +// Node->Assign.Dest->Variable.Name, +// varVal->ReferenceCount); + } + #endif value = AST_ExecuteNode_BinOp(Block, Node, Node->Assign.Operation, varVal, ret); if(value == ERRPTR) return ERRPTR; + if(ret) Object_Dereference(ret); + #if 0 if(varVal) Object_Dereference(varVal); + #else + if(varVal && varVal->ReferenceCount == 1) { + Object_Reference(varVal); +// printf("post: varVal->ReferenceCount = %i\n", varVal->ReferenceCount); + break; // If varVal was non-null, it has been updated by _BinOp + } + #endif + // Else, it was NULL, so has to be assigned ret = value; } @@ -843,6 +880,7 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) case NODETYPE_CREATEOBJECT: // Logical block (used to allocate `params`) { + tSpiderNamespace *ns = Block->CurNamespace; tSpiderValue *params[Node->FunctionCall.NumArgs]; i = 0; for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) @@ -856,14 +894,13 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) i ++; } - if( !Block->CurNamespace ) - Block->CurNamespace = Block->BaseNamespace; + if( !ns ) ns = Block->BaseNamespace; // Call the function if( Node->Type == NODETYPE_CREATEOBJECT ) { ret = SpiderScript_CreateObject(Block->Script, - Block->CurNamespace, + ns, Node->FunctionCall.Name, Node->FunctionCall.NumArgs, params ); @@ -887,7 +924,7 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) else { ret = SpiderScript_ExecuteFunction(Block->Script, - Block->CurNamespace, Node->FunctionCall.Name, + ns, Node->FunctionCall.Name, Node->FunctionCall.NumArgs, params ); } @@ -918,38 +955,59 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) // Loop case NODETYPE_LOOP: + // Initialise ret = AST_ExecuteNode(Block, Node->For.Init); if(ret == ERRPTR) break; - if( Node->For.bCheckAfter ) + + // Check initial condition + if( !Node->For.bCheckAfter ) { - do { - Object_Dereference(ret); - ret = AST_ExecuteNode(Block, Node->For.Code); - if(ret == ERRPTR) return ERRPTR; - Object_Dereference(ret); - ret = AST_ExecuteNode(Block, Node->For.Increment); - if(ret == ERRPTR) return ERRPTR; + Object_Dereference(ret); + + ret = AST_ExecuteNode(Block, Node->For.Condition); + if(ret == ERRPTR) return ERRPTR; + if(!SpiderScript_IsValueTrue(ret)) { Object_Dereference(ret); - ret = AST_ExecuteNode(Block, Node->For.Condition); - if(ret == ERRPTR) return ERRPTR; - } while( SpiderScript_IsValueTrue(ret) ); + ret = NULL; + break; + } } - else + + // Perform loop + for( ;; ) { Object_Dereference(ret); - ret = AST_ExecuteNode(Block, Node->For.Condition); + + // Code + ret = AST_ExecuteNode(Block, Node->For.Code); if(ret == ERRPTR) return ERRPTR; - while( SpiderScript_IsValueTrue(ret) ) { - Object_Dereference(ret); - ret = AST_ExecuteNode(Block, Node->For.Code); - if(ret == ERRPTR) return ERRPTR; - Object_Dereference(ret); - ret = AST_ExecuteNode(Block, Node->For.Increment); - if(ret == ERRPTR) return ERRPTR; - Object_Dereference(ret); - ret = AST_ExecuteNode(Block, Node->For.Condition); - if(ret == ERRPTR) return ERRPTR; + Object_Dereference(ret); + + if(Block->BreakTarget) + { + if( Block->BreakTarget[0] == '\0' || strcmp(Block->BreakTarget, Node->For.Tag) == 0 ) + { + // Ours + free((void*)Block->BreakTarget); Block->BreakTarget = NULL; + if( Block->BreakType == NODETYPE_CONTINUE ) { + // Continue, just keep going + } + else + break; + } + else + break; // Break out of this loop } + + // Increment + ret = AST_ExecuteNode(Block, Node->For.Increment); + if(ret == ERRPTR) return ERRPTR; + Object_Dereference(ret); + + // Check condition + ret = AST_ExecuteNode(Block, Node->For.Condition); + if(ret == ERRPTR) return ERRPTR; + if(!SpiderScript_IsValueTrue(ret)) break; } Object_Dereference(ret); ret = NULL; @@ -963,6 +1021,12 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) ret = NULL; // the `return` statement does not return a value break; + case NODETYPE_BREAK: + case NODETYPE_CONTINUE: + Block->BreakTarget = strdup(Node->Variable.Name); + Block->BreakType = Node->Type; + break; + // Define a variable case NODETYPE_DEFVAR: if( Node->DefVar.InitialValue ) { @@ -1303,6 +1367,10 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) // break; } _return: + // Reset namespace when no longer needed + if( Node->Type != NODETYPE_SCOPE ) + Block->CurNamespace = NULL; + #if TRACE_NODE_RETURNS if(ret && ret != ERRPTR) { AST_RuntimeError(Node, "Ret type of %p %i is %i", Node, Node->Type, ret->Type); @@ -1342,12 +1410,17 @@ tSpiderValue *AST_ExecuteNode_UniOp(tAST_BlockState *Block, tAST_Node *Node, int { // Integer Operations case SS_DATATYPE_INTEGER: + if( Value->ReferenceCount == 1 ) + Object_Reference(ret = Value); + else + ret = SpiderScript_CreateInteger(0); switch(Operation) { - case NODETYPE_NEGATE: ret = SpiderScript_CreateInteger( -Value->Integer ); break; - case NODETYPE_BWNOT: ret = SpiderScript_CreateInteger( ~Value->Integer ); break; + case NODETYPE_NEGATE: ret->Integer = -Value->Integer; break; + case NODETYPE_BWNOT: ret->Integer = ~Value->Integer; break; default: AST_RuntimeError(Node, "SpiderScript internal error: Exec,UniOP,Integer unknown op %i", Operation); + Object_Dereference(ret); ret = ERRPTR; break; } @@ -1443,6 +1516,11 @@ tSpiderValue *AST_ExecuteNode_BinOp(tAST_BlockState *Block, tAST_Node *Node, int case NODETYPE_ADD: // Concatenate ret = Object_StringConcat(Left, Right); break; + // TODO: Support python style 'i = %i' % i ? + // Might do it via a function call +// case NODETYPE_MODULUS: +// break; + default: AST_RuntimeError(Node, "SpiderScript internal error: Exec,BinOP,String unknown op %i", Operation); ret = ERRPTR; @@ -1451,23 +1529,28 @@ tSpiderValue *AST_ExecuteNode_BinOp(tAST_BlockState *Block, tAST_Node *Node, int break; // Integer Operations case SS_DATATYPE_INTEGER: + if( Left->ReferenceCount == 1 ) + Object_Reference(ret = Left); + else + ret = SpiderScript_CreateInteger(0); switch(Operation) { - case NODETYPE_ADD: ret = SpiderScript_CreateInteger( Left->Integer + Right->Integer ); break; - case NODETYPE_SUBTRACT: ret = SpiderScript_CreateInteger( Left->Integer - Right->Integer ); break; - case NODETYPE_MULTIPLY: ret = SpiderScript_CreateInteger( Left->Integer * Right->Integer ); break; - case NODETYPE_DIVIDE: ret = SpiderScript_CreateInteger( Left->Integer / Right->Integer ); break; - case NODETYPE_MODULO: ret = SpiderScript_CreateInteger( Left->Integer % Right->Integer ); break; - case NODETYPE_BWAND: ret = SpiderScript_CreateInteger( Left->Integer & Right->Integer ); break; - case NODETYPE_BWOR: ret = SpiderScript_CreateInteger( Left->Integer | Right->Integer ); break; - case NODETYPE_BWXOR: ret = SpiderScript_CreateInteger( Left->Integer ^ Right->Integer ); break; - case NODETYPE_BITSHIFTLEFT: ret = SpiderScript_CreateInteger( Left->Integer << Right->Integer ); break; - case NODETYPE_BITSHIFTRIGHT:ret = SpiderScript_CreateInteger( Left->Integer >> Right->Integer ); break; + case NODETYPE_ADD: ret->Integer = Left->Integer + Right->Integer; break; + case NODETYPE_SUBTRACT: ret->Integer = Left->Integer - Right->Integer; break; + case NODETYPE_MULTIPLY: ret->Integer = Left->Integer * Right->Integer; break; + case NODETYPE_DIVIDE: ret->Integer = Left->Integer / Right->Integer; break; + case NODETYPE_MODULO: ret->Integer = Left->Integer % Right->Integer; break; + case NODETYPE_BWAND: ret->Integer = Left->Integer & Right->Integer; break; + case NODETYPE_BWOR: ret->Integer = Left->Integer | Right->Integer; break; + case NODETYPE_BWXOR: ret->Integer = Left->Integer ^ Right->Integer; break; + case NODETYPE_BITSHIFTLEFT: ret->Integer = Left->Integer << Right->Integer; break; + case NODETYPE_BITSHIFTRIGHT:ret->Integer = Left->Integer >> Right->Integer; break; case NODETYPE_BITROTATELEFT: - ret = SpiderScript_CreateInteger( (Left->Integer << Right->Integer) | (Left->Integer >> (64-Right->Integer)) ); + ret->Integer = (Left->Integer << Right->Integer) | (Left->Integer >> (64-Right->Integer)); break; default: AST_RuntimeError(Node, "SpiderScript internal error: Exec,BinOP,Integer unknown op %i", Operation); + Object_Dereference(ret); ret = ERRPTR; break; } @@ -1475,14 +1558,19 @@ tSpiderValue *AST_ExecuteNode_BinOp(tAST_BlockState *Block, tAST_Node *Node, int // Real Numbers case SS_DATATYPE_REAL: + if( Left->ReferenceCount == 1 ) + Object_Reference(ret = Left); + else + ret = SpiderScript_CreateReal(0); switch(Operation) { - case NODETYPE_ADD: ret = SpiderScript_CreateReal( Left->Real + Right->Real ); break; - case NODETYPE_SUBTRACT: ret = SpiderScript_CreateReal( Left->Real - Right->Real ); break; - case NODETYPE_MULTIPLY: ret = SpiderScript_CreateReal( Left->Real * Right->Real ); break; - case NODETYPE_DIVIDE: ret = SpiderScript_CreateReal( Left->Real / Right->Real ); break; + case NODETYPE_ADD: ret->Real = Left->Real + Right->Real; break; + case NODETYPE_SUBTRACT: ret->Real = Left->Real - Right->Real; break; + case NODETYPE_MULTIPLY: ret->Real = Left->Real * Right->Real; break; + case NODETYPE_DIVIDE: ret->Real = Left->Real / Right->Real; break; default: AST_RuntimeError(Node, "SpiderScript internal error: Exec,BinOP,Real unknown op %i", Operation); + Object_Dereference(ret); ret = ERRPTR; break; } @@ -1593,7 +1681,9 @@ tAST_Variable *Variable_Lookup(tAST_BlockState *Block, tAST_Node *VarNode, int C */ int Variable_SetValue(tAST_BlockState *Block, tAST_Node *VarNode, tSpiderValue *Value) { - tAST_Variable *var = Variable_Lookup(Block, VarNode, Value->Type); + tAST_Variable *var; + + var = Variable_Lookup(Block, VarNode, (Value ? Value->Type : SS_DATATYPE_UNDEF)); if( !var ) return -1;