X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FLibraries%2Flibspiderscript.so_src%2Fexec_ast.c;h=33dbea45cb496660ef04f8a3b9c8d5ec7869cdb5;hb=7681237dd0061c95dd4b22ca1b5c8c3c8b8fae2e;hp=0421686f95cf94e6866b70f056b5559f37a0dd6c;hpb=86f49ede5038704ac4f12eab9794e9a8110a4985;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 0421686f..33dbea45 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c @@ -8,16 +8,17 @@ // === PROTOTYPES === void Object_Dereference(tSpiderValue *Object); void Object_Reference(tSpiderValue *Object); -tSpiderValue *Object_CreateInteger(uint64_t Value); -tSpiderValue *Object_CreateReal(double Value); -tSpiderValue *Object_CreateString(int Length, const char *Data); -tSpiderValue *Object_CastTo(int Type, tSpiderValue *Source); - int Object_IsTrue(tSpiderValue *Value); +tSpiderValue *SpiderScript_CreateInteger(uint64_t Value); +tSpiderValue *SpiderScript_CreateReal(double Value); +tSpiderValue *SpiderScript_CreateString(int Length, const char *Data); +tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source); + int SpiderScript_IsValueTrue(tSpiderValue *Value); +char *SpiderScript_DumpValue(tSpiderValue *Value); tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node); tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name); -void Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value); + int Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value); tSpiderValue *Variable_GetValue(tAST_BlockState *Block, const char *Name); void Variable_Destroy(tAST_Variable *Variable); @@ -28,6 +29,7 @@ void Variable_Destroy(tAST_Variable *Variable); void Object_Dereference(tSpiderValue *Object) { if(!Object) return ; + if(Object == ERRPTR) return ; Object->ReferenceCount --; if( Object->ReferenceCount == 0 ) { switch( (enum eSpiderScript_DataTypes) Object->Type ) @@ -54,7 +56,7 @@ void Object_Reference(tSpiderValue *Object) /** * \brief Create an integer object */ -tSpiderValue *Object_CreateInteger(uint64_t Value) +tSpiderValue *SpiderScript_CreateInteger(uint64_t Value) { tSpiderValue *ret = malloc( sizeof(tSpiderValue) ); ret->Type = SS_DATATYPE_INTEGER; @@ -66,7 +68,7 @@ tSpiderValue *Object_CreateInteger(uint64_t Value) /** * \brief Create an real number object */ -tSpiderValue *Object_CreateReal(double Value) +tSpiderValue *SpiderScript_CreateReal(double Value) { tSpiderValue *ret = malloc( sizeof(tSpiderValue) ); ret->Type = SS_DATATYPE_REAL; @@ -78,7 +80,7 @@ tSpiderValue *Object_CreateReal(double Value) /** * \brief Create an string object */ -tSpiderValue *Object_CreateString(int Length, const char *Data) +tSpiderValue *SpiderScript_CreateString(int Length, const char *Data) { tSpiderValue *ret = malloc( sizeof(tSpiderValue) + Length + 1 ); ret->Type = SS_DATATYPE_STRING; @@ -119,9 +121,13 @@ tSpiderValue *Object_StringConcat(tSpiderValue *Str1, tSpiderValue *Str2) * \brief Type Destination type * \brief Source Input data */ -tSpiderValue *Object_CastTo(int Type, tSpiderValue *Source) +tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source) { tSpiderValue *ret = ERRPTR; + int len = 0; + + if( !Source ) return NULL; + // Check if anything needs to be done if( Source->Type == Type ) { Object_Reference(Source); @@ -131,10 +137,9 @@ tSpiderValue *Object_CastTo(int Type, tSpiderValue *Source) switch( (enum eSpiderScript_DataTypes)Type ) { case SS_DATATYPE_UNDEF: - case SS_DATATYPE_NULL: case SS_DATATYPE_ARRAY: case SS_DATATYPE_OPAQUE: - fprintf(stderr, "Object_CastTo - Invalid cast to %i\n", Type); + fprintf(stderr, "SpiderScript_CastValueTo - Invalid cast to %i\n", Type); return ERRPTR; case SS_DATATYPE_INTEGER: @@ -147,12 +152,36 @@ tSpiderValue *Object_CastTo(int Type, tSpiderValue *Source) case SS_DATATYPE_STRING: ret->Integer = atoi(Source->String.Data); break; case SS_DATATYPE_REAL: ret->Integer = Source->Real; break; default: - fprintf(stderr, "Object_CastTo - Invalid cast from %i\n", Source->Type); + fprintf(stderr, "SpiderScript_CastValueTo - Invalid cast from %i\n", Source->Type); + free(ret); + ret = ERRPTR; + break; + } + break; + + case SS_DATATYPE_STRING: + switch(Source->Type) + { + case SS_DATATYPE_INTEGER: len = snprintf(NULL, 0, "%li", Source->Integer); break; + case SS_DATATYPE_REAL: snprintf(NULL, 0, "%f", Source->Real); break; + default: break; + } + ret = malloc(sizeof(tSpiderValue) + len + 1); + ret->Type = SS_DATATYPE_STRING; + ret->ReferenceCount = 1; + ret->String.Length = len; + switch(Source->Type) + { + case SS_DATATYPE_INTEGER: sprintf(ret->String.Data, "%li", Source->Integer); break; + case SS_DATATYPE_REAL: sprintf(ret->String.Data, "%f", Source->Real); break; + default: + fprintf(stderr, "SpiderScript_CastValueTo - Invalid cast from %i\n", Source->Type); free(ret); ret = ERRPTR; break; } break; + default: fprintf(stderr, "BUG REPORT: Unimplemented cast target\n"); break; @@ -164,12 +193,14 @@ tSpiderValue *Object_CastTo(int Type, tSpiderValue *Source) /** * \brief Condenses a value down to a boolean */ -int Object_IsTrue(tSpiderValue *Value) +int SpiderScript_IsValueTrue(tSpiderValue *Value) { + if( Value == ERRPTR ) return 0; + if( Value == NULL ) return 0; + switch( (enum eSpiderScript_DataTypes)Value->Type ) { case SS_DATATYPE_UNDEF: - case SS_DATATYPE_NULL: return 0; case SS_DATATYPE_INTEGER: @@ -190,12 +221,66 @@ int Object_IsTrue(tSpiderValue *Value) case SS_DATATYPE_ARRAY: return Value->Array.Length > 0; default: - fprintf(stderr, "Spiderscript internal error: Unknown type %i in Object_IsTrue\n", Value->Type); + fprintf(stderr, "Spiderscript internal error: Unknown type %i in SpiderScript_IsValueTrue\n", Value->Type); return 0; } return 0; } +/** + * \brief Dump a value into a string + * \return Heap string + */ +char *SpiderScript_DumpValue(tSpiderValue *Value) +{ + char *ret; + if( Value == ERRPTR ) + return strdup("ERRPTR"); + if( Value == NULL ) + return strdup("null"); + + switch( (enum eSpiderScript_DataTypes)Value->Type ) + { + case SS_DATATYPE_UNDEF: return strdup("undefined"); + + case SS_DATATYPE_INTEGER: + ret = malloc( sizeof(Value->Integer)*2 + 3 ); + sprintf(ret, "0x%lx", Value->Integer); + return ret; + + case SS_DATATYPE_REAL: + ret = malloc( sprintf(NULL, "%f", Value->Real) + 1 ); + sprintf(ret, "%f", Value->Real); + return ret; + + case SS_DATATYPE_STRING: + ret = malloc( Value->String.Length + 3 ); + ret[0] = '"'; + strcpy(ret+1, Value->String.Data); + ret[Value->String.Length+1] = '"'; + ret[Value->String.Length+2] = '\0'; + return ret; + + case SS_DATATYPE_OBJECT: + ret = malloc( sprintf(NULL, "{%s *%p}", Value->Object->Type->Name, Value->Object) + 1 ); + sprintf(ret, "{%s *%p}", Value->Object->Type->Name, Value->Object); + return ret; + + case SS_DATATYPE_OPAQUE: + ret = malloc( sprintf(NULL, "*%p", Value->Opaque.Data) + 1 ); + sprintf(ret, "*%p", Value->Opaque.Data); + return ret; + + case SS_DATATYPE_ARRAY: + return strdup("Array"); + + default: + fprintf(stderr, "Spiderscript internal error: Unknown type %i in Object_Dump\n", Value->Type); + return NULL; + } + +} + /** * \brief Execute an AST node and return its value */ @@ -216,23 +301,18 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) { tAST_BlockState blockInfo; blockInfo.FirstVar = NULL; + blockInfo.RetVal = NULL; blockInfo.Parent = Block; blockInfo.Script = Block->Script; ret = NULL; - for(node = Node->Block.FirstChild; node; node = node->NextSibling ) + for(node = Node->Block.FirstChild; node && !blockInfo.RetVal; node = node->NextSibling ) { - if(node->Type == NODETYPE_RETURN) { - ret = AST_ExecuteNode(&blockInfo, node); + tmpobj = AST_ExecuteNode(&blockInfo, node); + if(tmpobj == ERRPTR) { // Error check + ret = ERRPTR; break ; } - else { - tmpobj = AST_ExecuteNode(&blockInfo, node); - if(tmpobj == ERRPTR) { // Error check - ret = ERRPTR; - break ; - } - if(tmpobj) Object_Dereference(tmpobj); // Free unused value - } + if(tmpobj) Object_Dereference(tmpobj); // Free unused value } // Clean up variables while(blockInfo.FirstVar) @@ -241,6 +321,9 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) Variable_Destroy( blockInfo.FirstVar ); blockInfo.FirstVar = nextVar; } + + if( blockInfo.RetVal ) + Block->RetVal = blockInfo.RetVal; } break; @@ -253,7 +336,13 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) } ret = AST_ExecuteNode(Block, Node->Assign.Value); if(ret != ERRPTR) - Variable_SetValue( Block, Node->Assign.Dest->Variable.Name, ret ); + { + if( Variable_SetValue( Block, Node->Assign.Dest->Variable.Name, ret ) ) { + Object_Dereference( ret ); + fprintf(stderr, "on line %i\n", Node->Line); + return ERRPTR; + } + } break; // Function Call @@ -289,9 +378,46 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) } break; - // Return's special handling happens elsewhere + // Conditional + case NODETYPE_IF: + ret = AST_ExecuteNode(Block, Node->If.Condition); + if( SpiderScript_IsValueTrue(ret) ) { + AST_ExecuteNode(Block, Node->If.True); + } + else { + AST_ExecuteNode(Block, Node->If.False); + } + Object_Dereference(ret); + break; + + // Loop + case NODETYPE_LOOP: + ret = AST_ExecuteNode(Block, Node->For.Init); + if( Node->For.bCheckAfter ) { + do { + Object_Dereference(ret); + ret = AST_ExecuteNode(Block, Node->For.Code); + Object_Dereference(ret); + ret = AST_ExecuteNode(Block, Node->For.Condition); + } while( SpiderScript_IsValueTrue(ret) ); + } + else { + Object_Dereference(ret); + ret = AST_ExecuteNode(Block, Node->For.Condition); + while( SpiderScript_IsValueTrue(ret) ) { + Object_Dereference(ret); + ret = AST_ExecuteNode(Block, Node->For.Code); + Object_Dereference(ret); + ret = AST_ExecuteNode(Block, Node->For.Condition); + } + Object_Dereference(ret); + } + break; + + // Return case NODETYPE_RETURN: ret = AST_ExecuteNode(Block, Node->UniOp.Value); + Block->RetVal = ret; // Return value set break; // Define a variable @@ -308,7 +434,7 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) // Cast a value to another case NODETYPE_CAST: - ret = Object_CastTo( + ret = SpiderScript_CastValueTo( Node->Cast.DataType, AST_ExecuteNode(Block, Node->Cast.Value) ); @@ -326,9 +452,9 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) ret = ERRPTR; break; // Constant Values - case NODETYPE_STRING: ret = Object_CreateString( Node->String.Length, Node->String.Data ); break; - case NODETYPE_INTEGER: ret = Object_CreateInteger( Node->Integer ); break; - case NODETYPE_REAL: ret = Object_CreateReal( Node->Real ); break; + case NODETYPE_STRING: ret = SpiderScript_CreateString( Node->String.Length, Node->String.Data ); break; + case NODETYPE_INTEGER: ret = SpiderScript_CreateInteger( Node->Integer ); break; + case NODETYPE_REAL: ret = SpiderScript_CreateReal( Node->Real ); break; // --- Operations --- // Boolean Operations @@ -346,13 +472,13 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) switch( Node->Type ) { case NODETYPE_LOGICALAND: - ret = Object_CreateInteger( Object_IsTrue(op1) && Object_IsTrue(op2) ); + ret = SpiderScript_CreateInteger( SpiderScript_IsValueTrue(op1) && SpiderScript_IsValueTrue(op2) ); break; case NODETYPE_LOGICALOR: - ret = Object_CreateInteger( Object_IsTrue(op1) || Object_IsTrue(op2) ); + ret = SpiderScript_CreateInteger( SpiderScript_IsValueTrue(op1) || SpiderScript_IsValueTrue(op2) ); break; case NODETYPE_LOGICALXOR: - ret = Object_CreateInteger( Object_IsTrue(op1) ^ Object_IsTrue(op2) ); + ret = SpiderScript_CreateInteger( SpiderScript_IsValueTrue(op1) ^ SpiderScript_IsValueTrue(op2) ); break; default: break; } @@ -374,22 +500,13 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) return ERRPTR; } - // No conversion done for NULL - // TODO: Determine if this will ever be needed - if( op1->Type == SS_DATATYPE_NULL ) - { - // NULLs always typecheck - ret = Object_CreateInteger(op2->Type == SS_DATATYPE_NULL); - break; - } - // Convert types if( op1->Type != op2->Type ) { // If dynamically typed, convert op2 to op1's type if(Block->Script->Variant->bDyamicTyped) { tmpobj = op2; - op2 = Object_CastTo(op1->Type, op2); + op2 = SpiderScript_CastValueTo(op1->Type, op2); Object_Dereference(tmpobj); if(op2 == ERRPTR) { Object_Dereference(op1); @@ -398,7 +515,8 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) } // If statically typed, this should never happen, but catch it anyway else { - fprintf(stderr, "PARSER ERROR: Statically typed implicit cast\n"); + fprintf(stderr, "PARSER ERROR: Statically typed implicit cast (line %i)\n", + Node->Line); ret = ERRPTR; break; } @@ -406,8 +524,6 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) // Do operation switch(op1->Type) { - // - NULL - case SS_DATATYPE_NULL: break; // - String Compare (does a strcmp, well memcmp) case SS_DATATYPE_STRING: // Call memcmp to do most of the work @@ -442,9 +558,9 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) // Create return switch(Node->Type) { - case NODETYPE_EQUALS: ret = Object_CreateInteger(cmp == 0); break; - case NODETYPE_LESSTHAN: ret = Object_CreateInteger(cmp < 0); break; - case NODETYPE_GREATERTHAN: ret = Object_CreateInteger(cmp > 0); break; + case NODETYPE_EQUALS: ret = SpiderScript_CreateInteger(cmp == 0); break; + case NODETYPE_LESSTHAN: ret = SpiderScript_CreateInteger(cmp < 0); break; + case NODETYPE_GREATERTHAN: ret = SpiderScript_CreateInteger(cmp > 0); break; default: fprintf(stderr, "SpiderScript internal error: Exec,CmpOp unknown op %i", Node->Type); ret = ERRPTR; @@ -479,7 +595,7 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) if(Block->Script->Variant->bDyamicTyped) { tmpobj = op2; - op2 = Object_CastTo(op1->Type, op2); + op2 = SpiderScript_CastValueTo(op1->Type, op2); Object_Dereference(tmpobj); if(op2 == ERRPTR) { Object_Dereference(op1); @@ -488,16 +604,24 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) } // If statically typed, this should never happen, but catch it anyway else { - fprintf(stderr, "PARSER ERROR: Statically typed implicit cast\n"); + fprintf(stderr, + "PARSER ERROR: Statically typed implicit cast (from %i to %i)\n", + op2->Type, op1->Type + ); ret = ERRPTR; break; } } + // NULL Check + if( op1 == NULL || op2 == NULL ) { + ret = NULL; + break; + } + // Do operation switch(op1->Type) { - case SS_DATATYPE_NULL: break; // String Concatenation case SS_DATATYPE_STRING: switch(Node->Type) @@ -515,18 +639,18 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) case SS_DATATYPE_INTEGER: switch(Node->Type) { - case NODETYPE_ADD: ret = Object_CreateInteger( op1->Integer + op2->Integer ); break; - case NODETYPE_SUBTRACT: ret = Object_CreateInteger( op1->Integer - op2->Integer ); break; - case NODETYPE_MULTIPLY: ret = Object_CreateInteger( op1->Integer * op2->Integer ); break; - case NODETYPE_DIVIDE: ret = Object_CreateInteger( op1->Integer / op2->Integer ); break; - case NODETYPE_MODULO: ret = Object_CreateInteger( op1->Integer % op2->Integer ); break; - case NODETYPE_BWAND: ret = Object_CreateInteger( op1->Integer & op2->Integer ); break; - case NODETYPE_BWOR: ret = Object_CreateInteger( op1->Integer | op2->Integer ); break; - case NODETYPE_BWXOR: ret = Object_CreateInteger( op1->Integer ^ op2->Integer ); break; - case NODETYPE_BITSHIFTLEFT: ret = Object_CreateInteger( op1->Integer << op2->Integer ); break; - case NODETYPE_BITSHIFTRIGHT:ret = Object_CreateInteger( op1->Integer >> op2->Integer ); break; + case NODETYPE_ADD: ret = SpiderScript_CreateInteger( op1->Integer + op2->Integer ); break; + case NODETYPE_SUBTRACT: ret = SpiderScript_CreateInteger( op1->Integer - op2->Integer ); break; + case NODETYPE_MULTIPLY: ret = SpiderScript_CreateInteger( op1->Integer * op2->Integer ); break; + case NODETYPE_DIVIDE: ret = SpiderScript_CreateInteger( op1->Integer / op2->Integer ); break; + case NODETYPE_MODULO: ret = SpiderScript_CreateInteger( op1->Integer % op2->Integer ); break; + case NODETYPE_BWAND: ret = SpiderScript_CreateInteger( op1->Integer & op2->Integer ); break; + case NODETYPE_BWOR: ret = SpiderScript_CreateInteger( op1->Integer | op2->Integer ); break; + case NODETYPE_BWXOR: ret = SpiderScript_CreateInteger( op1->Integer ^ op2->Integer ); break; + case NODETYPE_BITSHIFTLEFT: ret = SpiderScript_CreateInteger( op1->Integer << op2->Integer ); break; + case NODETYPE_BITSHIFTRIGHT:ret = SpiderScript_CreateInteger( op1->Integer >> op2->Integer ); break; case NODETYPE_BITROTATELEFT: - ret = Object_CreateInteger( (op1->Integer << op2->Integer) | (op1->Integer >> (64-op2->Integer)) ); + ret = SpiderScript_CreateInteger( (op1->Integer << op2->Integer) | (op1->Integer >> (64-op2->Integer)) ); break; default: fprintf(stderr, "SpiderScript internal error: Exec,BinOP,Integer unknown op %i\n", Node->Type); @@ -601,8 +725,9 @@ tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Nam /** * \brief Set the value of a variable + * \return Boolean Failure */ -void Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value) +int Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value) { tAST_Variable *var; tAST_BlockState *bs; @@ -615,12 +740,12 @@ void Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *V if( !Block->Script->Variant->bDyamicTyped && (Value && var->Type != Value->Type) ) { fprintf(stderr, "ERROR: Type mismatch assigning to '%s'\n", Name); - return ; + return -2; } Object_Reference(Value); Object_Dereference(var->Object); var->Object = Value; - return ; + return 0; } } } @@ -631,10 +756,12 @@ void Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *V var = Variable_Define(Block, Value->Type, Name); Object_Reference(Value); var->Object = Value; + return 0; } else { fprintf(stderr, "ERROR: Variable '%s' set while undefined\n", Name); + return -1; } }