From: John Hodge Date: Sat, 2 Apr 2011 09:00:49 +0000 (+0800) Subject: SpiderScript - Bugfixes and speed improvements X-Git-Tag: rel0.10~134 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=9b714e5ea3767470ab5c35f14da67bcb97275021;p=tpg%2Facess2.git SpiderScript - Bugfixes and speed improvements --- diff --git a/Usermode/Libraries/libspiderscript.so_src/ast.c b/Usermode/Libraries/libspiderscript.so_src/ast.c index 36568e69..5aa6e3dc 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast.c +++ b/Usermode/Libraries/libspiderscript.so_src/ast.c @@ -117,7 +117,7 @@ void AST_SetFunctionCode(tAST_Function *Function, tAST_Node *Root) size_t AST_WriteScript(void *Buffer, tAST_Script *Script) { tAST_Function *fcn; - size_t ret = 0, ptr; + size_t ret = 0, ptr = 0; for( fcn = Script->Functions; fcn; fcn = fcn->Next ) { @@ -128,8 +128,11 @@ size_t AST_WriteScript(void *Buffer, tAST_Script *Script) ret += AST_WriteNode(Buffer, ret, fcn->Code); WRITE_32(Buffer, ptr, ret); // Actually set next } - ptr -= 4; - WRITE_32(Buffer, ptr, 0); // Clear next for final + if( ptr ) + { + ptr -= 4; + WRITE_32(Buffer, ptr, 0); // Clear next for final + } return ret; } @@ -139,7 +142,6 @@ size_t AST_WriteScript(void *Buffer, tAST_Script *Script) */ size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node) { - size_t ptr; size_t baseOfs = Offset; if(!Node) { @@ -219,7 +221,11 @@ size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node) // Unary Operations case NODETYPE_RETURN: - ptr = Offset; + case NODETYPE_BWNOT: + case NODETYPE_LOGICALNOT: + case NODETYPE_NEGATE: + case NODETYPE_POSTINC: + case NODETYPE_POSTDEC: Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value); break; @@ -237,8 +243,8 @@ size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node) case NODETYPE_BWOR: case NODETYPE_LOGICALOR: case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR: case NODETYPE_EQUALS: - case NODETYPE_LESSTHAN: - case NODETYPE_GREATERTHAN: + case NODETYPE_LESSTHAN: case NODETYPE_LESSTHANEQUAL: + case NODETYPE_GREATERTHAN: case NODETYPE_GREATERTHANEQUAL: Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Left); Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Right); break; @@ -347,6 +353,11 @@ void AST_FreeNode(tAST_Node *Node) // Unary Operations case NODETYPE_RETURN: + case NODETYPE_BWNOT: + case NODETYPE_LOGICALNOT: + case NODETYPE_NEGATE: + case NODETYPE_POSTINC: + case NODETYPE_POSTDEC: AST_FreeNode(Node->UniOp.Value); break; @@ -364,8 +375,8 @@ void AST_FreeNode(tAST_Node *Node) case NODETYPE_BWOR: case NODETYPE_LOGICALOR: case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR: case NODETYPE_EQUALS: - case NODETYPE_LESSTHAN: - case NODETYPE_GREATERTHAN: + case NODETYPE_LESSTHAN: case NODETYPE_LESSTHANEQUAL: + case NODETYPE_GREATERTHAN: case NODETYPE_GREATERTHANEQUAL: AST_FreeNode( Node->BinOp.Left ); AST_FreeNode( Node->BinOp.Right ); break; @@ -386,6 +397,7 @@ tAST_Node *AST_NewCodeBlock(tParser *Parser) tAST_Node *ret = malloc( sizeof(tAST_Node) ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_BLOCK; ret->Block.FirstChild = NULL; @@ -427,6 +439,7 @@ tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAS { tAST_Node *ret = malloc( sizeof(tAST_Node) ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_IF; ret->If.Condition = Condition; @@ -439,6 +452,7 @@ tAST_Node *AST_NewLoop(tParser *Parser, tAST_Node *Init, int bPostCheck, tAST_No { tAST_Node *ret = malloc( sizeof(tAST_Node) ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_LOOP; ret->For.Init = Init; @@ -454,6 +468,7 @@ tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_N tAST_Node *ret = malloc( sizeof(tAST_Node) ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_ASSIGN; ret->Assign.Operation = Operation; @@ -468,6 +483,7 @@ tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value) tAST_Node *ret = malloc( sizeof(tAST_Node) ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_CAST; ret->Cast.DataType = Target; @@ -481,6 +497,7 @@ tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_No tAST_Node *ret = malloc( sizeof(tAST_Node) ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = Operation; ret->BinOp.Left = Left; @@ -496,6 +513,7 @@ tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value) tAST_Node *ret = malloc( sizeof(tAST_Node) ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = Operation; ret->UniOp.Value = Value; @@ -503,6 +521,18 @@ tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value) return ret; } +tAST_Node *AST_NewNop(tParser *Parser) +{ + tAST_Node *ret = malloc( sizeof(tAST_Node) ); + + ret->NextSibling = NULL; + ret->File = NULL; + ret->Line = Parser->CurLine; + ret->Type = NODETYPE_NOP; + + return ret; +} + /** * \brief Create a new string node */ @@ -511,6 +541,7 @@ tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length) tAST_Node *ret = malloc( sizeof(tAST_Node) + Length + 1 ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_STRING; ret->String.Length = Length; @@ -523,16 +554,31 @@ tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length) /** * \brief Create a new integer node */ -tAST_Node *AST_NewInteger(tParser *Parser, uint64_t Value) +tAST_Node *AST_NewInteger(tParser *Parser, int64_t Value) { tAST_Node *ret = malloc( sizeof(tAST_Node) ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_INTEGER; ret->Integer = Value; return ret; } +/** + * \brief Create a new real number node + */ +tAST_Node *AST_NewReal(tParser *Parser, double Value) +{ + tAST_Node *ret = malloc( sizeof(tAST_Node) ); + ret->NextSibling = NULL; + ret->File = NULL; + ret->Line = Parser->CurLine; + ret->Type = NODETYPE_REAL; + ret->Real = Value; + return ret; +} + /** * \brief Create a new variable reference node */ @@ -540,6 +586,7 @@ tAST_Node *AST_NewVariable(tParser *Parser, const char *Name) { tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_VARIABLE; strcpy(ret->Variable.Name, Name); @@ -553,6 +600,7 @@ tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name) { tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_DEFVAR; ret->DefVar.DataType = Type; @@ -568,6 +616,7 @@ tAST_Node *AST_NewConstant(tParser *Parser, const char *Name) { tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_CONSTANT; strcpy(ret->Variable.Name, Name); @@ -583,11 +632,13 @@ tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name) tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_FUNCTIONCALL; ret->FunctionCall.Object = NULL; ret->FunctionCall.FirstArg = NULL; ret->FunctionCall.LastArg = NULL; + ret->FunctionCall.NumArgs = 0; strcpy(ret->FunctionCall.Name, Name); return ret; } @@ -596,11 +647,13 @@ tAST_Node *AST_NewMethodCall(tParser *Parser, tAST_Node *Object, const char *Nam tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_METHODCALL; ret->FunctionCall.Object = Object; ret->FunctionCall.FirstArg = NULL; ret->FunctionCall.LastArg = NULL; + ret->FunctionCall.NumArgs = 0; strcpy(ret->FunctionCall.Name, Name); return ret; } @@ -610,11 +663,13 @@ tAST_Node *AST_NewCreateObject(tParser *Parser, const char *Name) tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_CREATEOBJECT; ret->FunctionCall.Object = NULL; ret->FunctionCall.FirstArg = NULL; ret->FunctionCall.LastArg = NULL; + ret->FunctionCall.NumArgs = 0; strcpy(ret->FunctionCall.Name, Name); return ret; } @@ -640,6 +695,7 @@ void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg) Node->FunctionCall.FirstArg = Arg; Node->FunctionCall.LastArg = Arg; } + Node->FunctionCall.NumArgs ++; } /** @@ -650,6 +706,7 @@ tAST_Node *AST_NewScopeDereference(tParser *Parser, const char *Name, tAST_Node tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_SCOPE; ret->Scope.Element = Child; @@ -665,6 +722,7 @@ tAST_Node *AST_NewClassElement(tParser *Parser, tAST_Node *Object, const char *N tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 ); ret->NextSibling = NULL; + ret->File = NULL; ret->Line = Parser->CurLine; ret->Type = NODETYPE_ELEMENT; ret->Scope.Element = Object; diff --git a/Usermode/Libraries/libspiderscript.so_src/ast.h b/Usermode/Libraries/libspiderscript.so_src/ast.h index c6593acf..a9cf1db2 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast.h +++ b/Usermode/Libraries/libspiderscript.so_src/ast.h @@ -35,6 +35,8 @@ enum eAST_NodeTypes NODETYPE_RETURN, //!< Return from a function (reserved word) NODETYPE_ASSIGN, //!< Variable assignment operator + NODETYPE_POSTINC, //!< Post-increment (i++) - Uniop + NODETYPE_POSTDEC, //!< Post-decrement (i--) - Uniop NODETYPE_FUNCTIONCALL, //!< Call a function NODETYPE_METHODCALL, //!< Call a class method NODETYPE_CREATEOBJECT, //!< Create an object @@ -44,14 +46,18 @@ enum eAST_NodeTypes NODETYPE_INDEX, //!< Index into an array + NODETYPE_LOGICALNOT, //!< Logical NOT operator NODETYPE_LOGICALAND, //!< Logical AND operator NODETYPE_LOGICALOR, //!< Logical OR operator NODETYPE_LOGICALXOR, //!< Logical XOR operator NODETYPE_EQUALS, //!< Comparison Equals NODETYPE_LESSTHAN, //!< Comparison Less Than + NODETYPE_LESSTHANEQUAL, //!< Comparison Less Than or Equal NODETYPE_GREATERTHAN, //!< Comparison Greater Than + NODETYPE_GREATERTHANEQUAL, //!< Comparison Greater Than or Equal + NODETYPE_BWNOT, //!< Bitwise NOT NODETYPE_BWAND, //!< Bitwise AND NODETYPE_BWOR, //!< Bitwise OR NODETYPE_BWXOR, //!< Bitwise XOR @@ -60,6 +66,7 @@ enum eAST_NodeTypes NODETYPE_BITSHIFTRIGHT, //!< Bitwise Shift Right (Shrink) NODETYPE_BITROTATELEFT, //!< Bitwise Rotate Left (Grow) + NODETYPE_NEGATE, //!< Negagte NODETYPE_ADD, //!< Add NODETYPE_SUBTRACT, //!< Subtract NODETYPE_MULTIPLY, //!< Multiply @@ -124,6 +131,7 @@ struct sAST_Node tAST_Node *Object; tAST_Node *FirstArg; tAST_Node *LastArg; + int NumArgs; char Name[]; } FunctionCall; @@ -207,8 +215,11 @@ extern tAST_Function *AST_AppendFunction(tAST_Script *Script, const char *Name); extern void AST_AppendFunctionArg(tAST_Function *Function, tAST_Node *Arg); extern void AST_SetFunctionCode(tAST_Function *Function, tAST_Node *Root); +extern tAST_Node *AST_NewNop(tParser *Parser); + extern tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length); -extern tAST_Node *AST_NewInteger(tParser *Parser, uint64_t Value); +extern tAST_Node *AST_NewInteger(tParser *Parser, int64_t Value); +extern tAST_Node *AST_NewReal(tParser *Parser, double Value); extern tAST_Node *AST_NewVariable(tParser *Parser, const char *Name); extern tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name); extern tAST_Node *AST_NewConstant(tParser *Parser, const char *Name); diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c index e0de9ff0..74d63835 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c @@ -22,6 +22,7 @@ char *SpiderScript_DumpValue(tSpiderValue *Value); tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node); tSpiderValue *AST_ExecuteNode_BinOp(tAST_BlockState *Block, int Operation, tSpiderValue *Left, tSpiderValue *Right); +tSpiderValue *AST_ExecuteNode_UniOp(tAST_BlockState *Block, int Operation, tSpiderValue *Value); tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name); int Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value); @@ -155,7 +156,16 @@ tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source) tSpiderValue *ret = ERRPTR; int len = 0; - if( !Source ) return NULL; + if( !Source ) + { + switch(Type) + { + case SS_DATATYPE_INTEGER: return SpiderScript_CreateInteger(0); + case SS_DATATYPE_REAL: return SpiderScript_CreateReal(0); + case SS_DATATYPE_STRING: return SpiderScript_CreateString(4, "null"); + } + return NULL; + } // Check if anything needs to be done if( Source->Type == Type ) { @@ -163,6 +173,20 @@ tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source) return Source; } + #if 0 + { + printf("Casting %i ", Source->Type); + switch(Source->Type) + { + case SS_DATATYPE_INTEGER: printf("0x%lx", Source->Integer); break; + case SS_DATATYPE_STRING: printf("\"%s\"", Source->String.Data); break; + case SS_DATATYPE_REAL: printf("%f", Source->Real); break; + default: break; + } + printf(" to %i\n", Type); + } + #endif + #if 0 if( Source->Type == SS_DATATYPE_OBJECT ) { @@ -213,11 +237,27 @@ tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source) } break; + case SS_DATATYPE_REAL: + ret = malloc(sizeof(tSpiderValue)); + ret->Type = SS_DATATYPE_REAL; + ret->ReferenceCount = 1; + switch(Source->Type) + { + case SS_DATATYPE_STRING: ret->Real = atof(Source->String.Data); break; + case SS_DATATYPE_INTEGER: ret->Real = Source->Integer; break; + default: + AST_RuntimeError(NULL, "Invalid cast from %i to Real", 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; + case SS_DATATYPE_REAL: len = snprintf(NULL, 0, "%g", Source->Real); break; default: break; } ret = malloc(sizeof(tSpiderValue) + len + 1); @@ -227,7 +267,8 @@ tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source) 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; + case SS_DATATYPE_REAL: + sprintf(ret->String.Data, "%g", Source->Real); break; default: AST_RuntimeError(NULL, "Invalid cast from %i to String", Source->Type); free(ret); @@ -237,7 +278,8 @@ tSpiderValue *SpiderScript_CastValueTo(int Type, tSpiderValue *Source) break; default: - AST_RuntimeError(NULL, "BUG - BUG REPORT: Unimplemented cast target"); + AST_RuntimeError(NULL, "BUG - BUG REPORT: Unimplemented cast target %i", Type); + ret = ERRPTR; break; } @@ -383,7 +425,7 @@ tSpiderValue *SpiderScript_ExecuteFunction(tSpiderScript *Script, bs.CurNamespace = NULL; bs.Script = Script; - + // Parse arguments for( arg = astFcn->Arguments; arg; arg = arg->NextSibling, i++ ) { // TODO: Type checks @@ -657,7 +699,7 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) tSpiderValue *ret = NULL, *tmpobj; tSpiderValue *op1, *op2; // Binary operations int cmp; // Used in comparisons - int i=0; + int i; switch(Node->Type) { @@ -668,20 +710,20 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) case NODETYPE_BLOCK: { tAST_BlockState blockInfo; - memcpy(&blockInfo, Block, sizeof(tAST_BlockState)); + blockInfo.Parent = Block; + blockInfo.Script = Block->Script; blockInfo.FirstVar = NULL; blockInfo.RetVal = NULL; - blockInfo.Parent = Block; + blockInfo.BaseNamespace = Block->BaseNamespace; + blockInfo.CurNamespace = NULL; ret = NULL; for(node = Node->Block.FirstChild; node && !blockInfo.RetVal; node = node->NextSibling ) { - tmpobj = AST_ExecuteNode(&blockInfo, node); - if(tmpobj == ERRPTR) { // Error check - ret = ERRPTR; + ret = AST_ExecuteNode(&blockInfo, node); + if(ret == ERRPTR) { // Error check break ; } - if(tmpobj) Object_Dereference(tmpobj); // Free unused value - tmpobj = NULL; + if(ret) Object_Dereference(ret); // Free unused value } // Clean up variables while(blockInfo.FirstVar) @@ -690,7 +732,8 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) Variable_Destroy( blockInfo.FirstVar ); blockInfo.FirstVar = nextVar; } - + if(ret != ERRPTR) + ret = NULL; if( blockInfo.RetVal ) Block->RetVal = blockInfo.RetVal; } @@ -715,7 +758,7 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) if( value == ERRPTR ) return ERRPTR; if(ret) Object_Dereference(ret); - Object_Dereference(varVal); + if(varVal) Object_Dereference(varVal); ret = value; } @@ -725,72 +768,96 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) } break; + case NODETYPE_POSTINC: + case NODETYPE_POSTDEC: + { + tSpiderValue *varVal, *value, *one; + if( Node->UniOp.Value->Type != NODETYPE_VARIABLE ) { + AST_RuntimeError(Node, "LVALUE of assignment is not a variable"); + return ERRPTR; + } + + varVal = Variable_GetValue(Block, Node->Assign.Dest->Variable.Name); + one = SpiderScript_CreateInteger(1); + + if( Node->Type == NODETYPE_POSTDEC ) + value = AST_ExecuteNode_BinOp(Block, NODETYPE_SUBTRACT, varVal, one); + else + value = AST_ExecuteNode_BinOp(Block, NODETYPE_ADD, varVal, one); + if( value == ERRPTR ) + return ERRPTR; + Object_Dereference(one); // Free constant one + + ret = varVal; + + if( Variable_SetValue( Block, Node->Assign.Dest->Variable.Name, value ) ) { + Object_Dereference( ret ); + return ERRPTR; + } + Object_Dereference( value ); + } + break; + // Function Call case NODETYPE_METHODCALL: case NODETYPE_FUNCTIONCALL: case NODETYPE_CREATEOBJECT: + // Logical block (used to allocate `params`) { - int nParams = 0; - for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) { - nParams ++; - } - // Logical block (used to allocate `params`) + tSpiderValue *params[Node->FunctionCall.NumArgs]; + i = 0; + for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) { - tSpiderValue *params[nParams]; - i = 0; - for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) - { - params[i] = AST_ExecuteNode(Block, node); - if( params[i] == ERRPTR ) { - while(i--) Object_Dereference(params[i]); - ret = ERRPTR; - goto _return; - } - i ++; - } - - if( !Block->CurNamespace ) - Block->CurNamespace = Block->BaseNamespace; - - // Call the function - if( Node->Type == NODETYPE_CREATEOBJECT ) - { - ret = SpiderScript_CreateObject(Block->Script, - Block->CurNamespace, - Node->FunctionCall.Name, - nParams, params - ); - } - else if( Node->Type == NODETYPE_METHODCALL ) - { - tSpiderValue *obj = AST_ExecuteNode(Block, Node->FunctionCall.Object); - if( !obj || obj->Type != SS_DATATYPE_OBJECT ) { - AST_RuntimeError(Node->FunctionCall.Object, - "Type Mismatch - Required SS_DATATYPE_OBJECT for method call"); - while(i--) Object_Dereference(params[i]); - ret = ERRPTR; - break; - } - ret = SpiderScript_ExecuteMethod(Block->Script, - obj->Object, Node->FunctionCall.Name, - nParams, params - ); - Object_Dereference(obj); + params[i] = AST_ExecuteNode(Block, node); + if( params[i] == ERRPTR ) { + while(i--) Object_Dereference(params[i]); + ret = ERRPTR; + goto _return; } - else - { - ret = SpiderScript_ExecuteFunction(Block->Script, - Block->CurNamespace, Node->FunctionCall.Name, - nParams, params - ); + i ++; + } + + if( !Block->CurNamespace ) + Block->CurNamespace = Block->BaseNamespace; + + // Call the function + if( Node->Type == NODETYPE_CREATEOBJECT ) + { + ret = SpiderScript_CreateObject(Block->Script, + Block->CurNamespace, + Node->FunctionCall.Name, + Node->FunctionCall.NumArgs, params + ); + } + else if( Node->Type == NODETYPE_METHODCALL ) + { + tSpiderValue *obj = AST_ExecuteNode(Block, Node->FunctionCall.Object); + if( !obj || obj->Type != SS_DATATYPE_OBJECT ) { + AST_RuntimeError(Node->FunctionCall.Object, + "Type Mismatch - Required SS_DATATYPE_OBJECT for method call"); + while(i--) Object_Dereference(params[i]); + ret = ERRPTR; + break; } - - - // Dereference parameters - while(i--) Object_Dereference(params[i]); - - // falls out + ret = SpiderScript_ExecuteMethod(Block->Script, + obj->Object, Node->FunctionCall.Name, + Node->FunctionCall.NumArgs, params + ); + Object_Dereference(obj); + } + else + { + ret = SpiderScript_ExecuteFunction(Block->Script, + Block->CurNamespace, Node->FunctionCall.Name, + Node->FunctionCall.NumArgs, params + ); } + + + // Dereference parameters + while(i--) Object_Dereference(params[i]); + + // falls out } break; @@ -981,6 +1048,12 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) // --- Operations --- // Boolean Operations + case NODETYPE_LOGICALNOT: // Logical NOT (!) + op1 = AST_ExecuteNode(Block, Node->UniOp.Value); + if(op1 == ERRPTR) return ERRPTR; + ret = SpiderScript_CreateInteger( !SpiderScript_IsValueTrue(op1) ); + Object_Dereference(op1); + break; case NODETYPE_LOGICALAND: // Logical AND (&&) case NODETYPE_LOGICALOR: // Logical OR (||) case NODETYPE_LOGICALXOR: // Logical XOR (^^) @@ -1015,12 +1088,23 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) case NODETYPE_EQUALS: case NODETYPE_LESSTHAN: case NODETYPE_GREATERTHAN: + case NODETYPE_LESSTHANEQUAL: + case NODETYPE_GREATERTHANEQUAL: op1 = AST_ExecuteNode(Block, Node->BinOp.Left); if(op1 == ERRPTR) return ERRPTR; op2 = AST_ExecuteNode(Block, Node->BinOp.Right); if(op2 == ERRPTR) { Object_Dereference(op1); - return ERRPTR; + ret = ERRPTR; + break; + } + + if( !op1 || !op2 ) { + AST_RuntimeError(Node, "NULL Comparison (%p and %p)\n", op1, op2); + if(op1) Object_Dereference(op1); + if(op2) Object_Dereference(op2); + ret = SpiderScript_CreateInteger( !op1 && !op2 ); + break; } // Convert types @@ -1073,6 +1157,10 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) else cmp = 1; break; + // - Real Number Comparisons + case SS_DATATYPE_REAL: + cmp = (op1->Real - op2->Real) / op2->Real * 10000; // < 0.1% difference is equality + break; default: AST_RuntimeError(Node, "TODO - Comparison of type %i", op1->Type); ret = ERRPTR; @@ -1093,6 +1181,8 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) 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; + case NODETYPE_LESSTHANEQUAL: ret = SpiderScript_CreateInteger(cmp <= 0); break; + case NODETYPE_GREATERTHANEQUAL: ret = SpiderScript_CreateInteger(cmp >= 0); break; default: AST_RuntimeError(Node, "Exec,CmpOp unknown op %i", Node->Type); ret = ERRPTR; @@ -1100,6 +1190,15 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) } break; + // General Unary Operations + case NODETYPE_BWNOT: // Bitwise NOT (~) + case NODETYPE_NEGATE: // Negation (-) + op1 = AST_ExecuteNode(Block, Node->UniOp.Value); + if(op1 == ERRPTR) return ERRPTR; + ret = AST_ExecuteNode_UniOp(Block, Node->Type, op1); + Object_Dereference(op1); + break; + // General Binary Operations case NODETYPE_ADD: case NODETYPE_SUBTRACT: @@ -1137,6 +1236,64 @@ _return: return ret; } +tSpiderValue *AST_ExecuteNode_UniOp(tAST_BlockState *Block, int Operation, tSpiderValue *Value) +{ + tSpiderValue *ret; + #if 0 + if( Value->Type == SS_DATATYPE_OBJECT ) + { + const char *fcnname; + switch(Operation) + { + case NODETYPE_NEGATE: fcnname = "-ve"; break; + case NODETYPE_BWNOT: fcnname = "~"; break; + default: fcnname = NULL; break; + } + + if( fcnname ) + { + ret = Object_ExecuteMethod(Value->Object, fcnname, ); + if( ret != ERRPTR ) + return ret; + // Fall through and try casting (which will usually fail) + } + } + #endif + switch(Value->Type) + { + // Integer Operations + case SS_DATATYPE_INTEGER: + switch(Operation) + { + case NODETYPE_NEGATE: ret = SpiderScript_CreateInteger( -Value->Integer ); break; + case NODETYPE_BWNOT: ret = SpiderScript_CreateInteger( ~Value->Integer ); break; + default: + AST_RuntimeError(NULL, "SpiderScript internal error: Exec,UniOP,Integer unknown op %i", Operation); + ret = ERRPTR; + break; + } + break; + // Real number Operations + case SS_DATATYPE_REAL: + switch(Operation) + { + case NODETYPE_NEGATE: ret = SpiderScript_CreateInteger( -Value->Real ); break; + default: + AST_RuntimeError(NULL, "SpiderScript internal error: Exec,UniOP,Real unknown op %i", Operation); + ret = ERRPTR; + break; + } + break; + + default: + AST_RuntimeError(NULL, "Invalid operation (%i) on type (%i)", Operation, Value->Type); + ret = ERRPTR; + break; + } + + return ret; +} + tSpiderValue *AST_ExecuteNode_BinOp(tAST_BlockState *Block, int Operation, tSpiderValue *Left, tSpiderValue *Right) { tSpiderValue *preCastValue = Right; @@ -1241,6 +1398,10 @@ tSpiderValue *AST_ExecuteNode_BinOp(tAST_BlockState *Block, int Operation, tSpid case SS_DATATYPE_REAL: 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; default: AST_RuntimeError(NULL, "SpiderScript internal error: Exec,BinOP,Real unknown op %i", Operation); ret = ERRPTR; diff --git a/Usermode/Libraries/libspiderscript.so_src/lex.c b/Usermode/Libraries/libspiderscript.so_src/lex.c index bd1712b4..be3a15b4 100644 --- a/Usermode/Libraries/libspiderscript.so_src/lex.c +++ b/Usermode/Libraries/libspiderscript.so_src/lex.c @@ -163,8 +163,22 @@ int GetToken(tParser *File) ret = TOK_AND; break; - case '/': ret = TOK_DIV; break; - case '*': ret = TOK_MUL; break; + case '/': + if( *File->CurPos == '=' ) { + File->CurPos ++; + ret = TOK_ASSIGN_DIV; + break; + } + ret = TOK_DIV; + break; + case '*': + if( *File->CurPos == '=' ) { + File->CurPos ++; + ret = TOK_ASSIGN_MUL; + break; + } + ret = TOK_MUL; + break; case '+': if( *File->CurPos == '+' ) { File->CurPos ++; @@ -201,8 +215,13 @@ int GetToken(tParser *File) case '"': while( *File->CurPos && !(*File->CurPos == '"' && *File->CurPos != '\\') ) File->CurPos ++; - File->CurPos ++; - ret = TOK_STR; + if( *File->CurPos ) + { + File->CurPos ++; + ret = TOK_STR; + } + else + ret = TOK_EOF; break; // Brackets @@ -254,6 +273,15 @@ int GetToken(tParser *File) ret = TOK_GT; break; + // Logical NOT + case '!': + ret = TOK_LOGICNOT; + break; + // Bitwise NOT + case '~': + ret = TOK_BWNOT; + break; + // Variables // \$[0-9]+ or \$[_a-zA-Z][_a-zA-Z0-9]* case '$': @@ -277,6 +305,7 @@ int GetToken(tParser *File) // Numbers if( isdigit(*File->CurPos) ) { + ret = TOK_INTEGER; if( *File->CurPos == '0' && File->CurPos[1] == 'x' ) { File->CurPos += 2; while(('0' <= *File->CurPos && *File->CurPos <= '9') @@ -289,21 +318,40 @@ int GetToken(tParser *File) else { while( isdigit(*File->CurPos) ) File->CurPos ++; + + // Decimal + if( *File->CurPos == '.' ) + { + ret = TOK_REAL; + File->CurPos ++; + while( isdigit(*File->CurPos) ) + File->CurPos ++; + } + // Exponent + if( *File->CurPos == 'e' || *File->CurPos == 'E' ) + { + ret = TOK_REAL; + File->CurPos ++; + if(*File->CurPos == '-' || *File->CurPos == '+') + File->CurPos ++; + while( isdigit(*File->CurPos) ) + File->CurPos ++; + } } - ret = TOK_INTEGER; break; } // Identifier if( is_ident(*File->CurPos) ) { + ret = TOK_IDENT; + // Identifier while( is_ident(*File->CurPos) || isdigit(*File->CurPos) ) File->CurPos ++; // This is set later too, but we use it below File->TokenLen = File->CurPos - File->TokenStr; - ret = TOK_IDENT; // Check if it's a reserved word { diff --git a/Usermode/Libraries/libspiderscript.so_src/main.c b/Usermode/Libraries/libspiderscript.so_src/main.c index 20554f55..919a6f2e 100644 --- a/Usermode/Libraries/libspiderscript.so_src/main.c +++ b/Usermode/Libraries/libspiderscript.so_src/main.c @@ -42,10 +42,6 @@ tSpiderScript *SpiderScript_ParseFile(tSpiderVariant *Variant, const char *Filen return NULL; } - // Create the script - ret = malloc(sizeof(tSpiderScript)); - ret->Variant = Variant; - fseek(fp, 0, SEEK_END); fLen = ftell(fp); fseek(fp, 0, SEEK_SET); @@ -53,11 +49,19 @@ tSpiderScript *SpiderScript_ParseFile(tSpiderVariant *Variant, const char *Filen // Allocate and read data data = malloc(fLen + 1); if(!data) return NULL; - fread(data, fLen, 1, fp); + fLen = fread(data, 1, fLen, fp); + if( fLen < 0 ) { + free(data); + return NULL; + } data[fLen] = '\0'; fclose(fp); + // Create the script + ret = malloc(sizeof(tSpiderScript)); + ret->Variant = Variant; + ret->CurNamespace = NULL; ret->Script = Parse_Buffer(Variant, data); if( ret->Script == NULL ) { diff --git a/Usermode/Libraries/libspiderscript.so_src/parse.c b/Usermode/Libraries/libspiderscript.so_src/parse.c index 907c7291..e04bc254 100644 --- a/Usermode/Libraries/libspiderscript.so_src/parse.c +++ b/Usermode/Libraries/libspiderscript.so_src/parse.c @@ -25,6 +25,8 @@ tAST_Node *Parse_DoExpr3(tParser *Parser); // Bitwise Operators tAST_Node *Parse_DoExpr4(tParser *Parser); // Bit Shifts tAST_Node *Parse_DoExpr5(tParser *Parser); // Arithmatic tAST_Node *Parse_DoExpr6(tParser *Parser); // Mult & Div +tAST_Node *Parse_DoExpr7(tParser *Parser); // Right Unary Operations +tAST_Node *Parse_DoExpr8(tParser *Parser); // Left Unary Operations tAST_Node *Parse_DoParen(tParser *Parser); // Parenthesis (Always Last) tAST_Node *Parse_DoValue(tParser *Parser); // Values @@ -218,6 +220,8 @@ tAST_Node *Parse_DoBlockLine(tParser *Parser) GetToken(Parser); false = Parse_DoCodeBlock(Parser); } + else + false = AST_NewNop(Parser); ret = AST_NewIf(Parser, cond, true, false); } return ret; @@ -249,22 +253,35 @@ tAST_Node *Parse_DoBlockLine(tParser *Parser) return ret; case TOK_RWD_DO: - case TOK_RWD_WHILE: - TODO(Parser, "Implement do and while\n"); + { + tAST_Node *code, *cond; + GetToken(Parser); // Eat 'do' + code = Parse_DoCodeBlock(Parser); + SyntaxAssert( Parser, GetToken(Parser), TOK_RWD_WHILE ); + SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN ); + cond = Parse_DoExpr0(Parser); + SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE ); + ret = AST_NewLoop(Parser, AST_NewNop(Parser), 1, cond, AST_NewNop(Parser), code); + } break; + case TOK_RWD_WHILE: + { + tAST_Node *code, *cond; + GetToken(Parser); // Eat 'while' + SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_OPEN ); + cond = Parse_DoExpr0(Parser); + SyntaxAssert( Parser, GetToken(Parser), TOK_PAREN_CLOSE ); + code = Parse_DoCodeBlock(Parser); + ret = AST_NewLoop(Parser, AST_NewNop(Parser), 0, cond, AST_NewNop(Parser), code); + } + return ret; // Define Variables case TOKEN_GROUP_TYPES: { int type; - - switch(GetToken(Parser)) - { - case TOK_RWD_INTEGER: type = SS_DATATYPE_INTEGER; break; - case TOK_RWD_OBJECT: type = SS_DATATYPE_OBJECT; break; - case TOK_RWD_REAL: type = SS_DATATYPE_REAL; break; - case TOK_RWD_STRING: type = SS_DATATYPE_STRING; break; - } + GetToken(Parser); + TOKEN_GET_DATATYPE(type, Parser->Token); SyntaxAssert(Parser, GetToken(Parser), TOK_VARIABLE); @@ -391,6 +408,12 @@ tAST_Node *Parse_DoExpr2(tParser *Parser) case TOK_GT: ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHAN, ret, Parse_DoExpr2(Parser)); break; + case TOK_LTE: + ret = AST_NewBinOp(Parser, NODETYPE_LESSTHANEQUAL, ret, Parse_DoExpr2(Parser)); + break; + case TOK_GTE: + ret = AST_NewBinOp(Parser, NODETYPE_GREATERTHANEQUAL, ret, Parse_DoExpr2(Parser)); + break; default: PutBack(Parser); break; @@ -475,7 +498,7 @@ tAST_Node *Parse_DoExpr5(tParser *Parser) // -------------------- tAST_Node *Parse_DoExpr6(tParser *Parser) { - tAST_Node *ret = Parse_DoParen(Parser); + tAST_Node *ret = Parse_DoExpr7(Parser); switch(GetToken(Parser)) { @@ -493,6 +516,46 @@ tAST_Node *Parse_DoExpr6(tParser *Parser) return ret; } +// Right Unary Operations +tAST_Node *Parse_DoExpr7(tParser *Parser) +{ + tAST_Node *ret = Parse_DoExpr8(Parser); + + switch(GetToken(Parser)) + { + case TOK_INCREMENT: + ret = AST_NewUniOp(Parser, NODETYPE_POSTINC, ret); + break; + case TOK_DECREMENT: + ret = AST_NewUniOp(Parser, NODETYPE_POSTDEC, ret); + break; + default: + PutBack(Parser); + break; + } + return ret; +} + +// Left Unary Operations +tAST_Node *Parse_DoExpr8(tParser *Parser) +{ + switch(GetToken(Parser)) + { + case TOK_INCREMENT: + return AST_NewAssign(Parser, NODETYPE_ADD, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1)); + case TOK_DECREMENT: + return AST_NewAssign(Parser, NODETYPE_SUBTRACT, Parse_DoExpr8(Parser), AST_NewInteger(Parser, 1)); + case TOK_MINUS: + return AST_NewUniOp(Parser, NODETYPE_NEGATE, Parse_DoExpr8(Parser)); + case TOK_LOGICNOT: + return AST_NewUniOp(Parser, NODETYPE_LOGICALNOT, Parse_DoExpr8(Parser)); + case TOK_BWNOT: + return AST_NewUniOp(Parser, NODETYPE_BWNOT, Parse_DoExpr8(Parser)); + default: + PutBack(Parser); + return Parse_DoParen(Parser); + } +} // -------------------- // 2nd Last Expression - Parens @@ -543,6 +606,10 @@ tAST_Node *Parse_DoValue(tParser *Parser) { case TOK_STR: return Parse_GetString(Parser); case TOK_INTEGER: return Parse_GetNumeric(Parser); + case TOK_REAL: + GetToken(Parser); + return AST_NewReal( Parser, atof(Parser->TokenStr) ); + case TOK_IDENT: return Parse_GetIdent(Parser, 0); case TOK_VARIABLE: return Parse_GetVariable(Parser); case TOK_RWD_NEW: @@ -601,7 +668,7 @@ tAST_Node *Parse_GetNumeric(tParser *Parser) { uint64_t value = 0; char *pos; - GetToken( Parser ); + SyntaxAssert( Parser, GetToken( Parser ), TOK_INTEGER ); pos = Parser->TokenStr; //printf("pos = %p, *pos = %c\n", pos, *pos); diff --git a/Usermode/Libraries/libspiderscript.so_src/tokens.h b/Usermode/Libraries/libspiderscript.so_src/tokens.h index 5a529f73..33128cfb 100644 --- a/Usermode/Libraries/libspiderscript.so_src/tokens.h +++ b/Usermode/Libraries/libspiderscript.so_src/tokens.h @@ -41,6 +41,7 @@ enum eTokens // Primitives TOK_STR, TOK_INTEGER, + TOK_REAL, TOK_VARIABLE, TOK_IDENT, @@ -80,6 +81,7 @@ enum eTokens TOK_GT, TOK_GTE, // Operations + TOK_BWNOT, TOK_LOGICNOT, TOK_DIV, TOK_MUL, TOK_PLUS, TOK_MINUS, TOK_SHL, TOK_SHR, @@ -116,7 +118,7 @@ enum eTokens case TOK_RWD_OBJECT: _type = SS_DATATYPE_OBJECT; break;\ case TOK_RWD_REAL: _type = SS_DATATYPE_REAL; break;\ case TOK_RWD_STRING: _type = SS_DATATYPE_STRING; break;\ - default:fprintf(stderr,\ + default:_type=SS_DATATYPE_UNDEF;fprintf(stderr,\ "ERROR: Unexpected %s, expected "TOKEN_GROUP_TYPES_STR"\n",csaTOKEN_NAMES[Parser->Token]);\ break;\ } } while(0) @@ -128,6 +130,7 @@ const char * const csaTOKEN_NAMES[] = { "TOK_STR", "TOK_INTEGER", + "TOK_REAL", "TOK_VARIABLE", "TOK_IDENT", @@ -162,6 +165,7 @@ const char * const csaTOKEN_NAMES[] = { "TOK_LT", "TOK_LTE", "TOK_GT", "TOK_GTE", + "TOK_BWNOT", "TOK_LOGICNOT", "TOK_DIV", "TOK_MUL", "TOK_PLUS", "TOK_MINUS", "TOK_SHL", "TOK_SHR",