From a247aec9111b29faf9200ebff7dc0f476f0babc9 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 17 Apr 2012 22:13:40 +0800 Subject: [PATCH] Usermode/SpiderScript - Restructured namespace handling, fixed a few bytecode bugs --- .../Libraries/libspiderscript.so_src/ast.c | 13 + .../Libraries/libspiderscript.so_src/ast.h | 13 +- .../libspiderscript.so_src/ast_to_bytecode.c | 73 +++- .../libspiderscript.so_src/bytecode.h | 3 + .../libspiderscript.so_src/bytecode_gen.c | 2 + .../libspiderscript.so_src/bytecode_gen.h | 1 + .../libspiderscript.so_src/bytecode_ops.h | 17 +- .../Libraries/libspiderscript.so_src/exec.c | 318 +++++++++++------- .../libspiderscript.so_src/exec_ast.c | 25 +- .../libspiderscript.so_src/exec_bytecode.c | 35 +- .../Libraries/libspiderscript.so_src/parse.c | 2 +- .../Libraries/libspiderscript.so_src/values.c | 4 +- Usermode/include/spiderscript.h | 7 +- 13 files changed, 323 insertions(+), 190 deletions(-) diff --git a/Usermode/Libraries/libspiderscript.so_src/ast.c b/Usermode/Libraries/libspiderscript.so_src/ast.c index 9532adb7..d37dc31e 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast.c +++ b/Usermode/Libraries/libspiderscript.so_src/ast.c @@ -281,6 +281,8 @@ size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node) case NODETYPE_REAL: WRITE_REAL(Buffer, Offset, Node->Constant.Real); break; + case NODETYPE_NULL: + break; //default: // fprintf(stderr, "AST_WriteNode: Unknown node type %i\n", Node->Type); @@ -403,6 +405,7 @@ void AST_FreeNode(tAST_Node *Node) // Node types with no children case NODETYPE_NOP: break; + case NODETYPE_NULL: break; case NODETYPE_VARIABLE: break; case NODETYPE_CONSTANT: break; case NODETYPE_BREAK: @@ -614,6 +617,16 @@ tAST_Node *AST_NewReal(tParser *Parser, double Value) return ret; } +/** + * \brief Return a null value + */ +tAST_Node *AST_NewNull(tParser *Parser) +{ + tAST_Node *ret = AST_int_AllocateNode(Parser, NODETYPE_NULL, 0); + + return ret; +} + /** * \brief Create a new variable reference node */ diff --git a/Usermode/Libraries/libspiderscript.so_src/ast.h b/Usermode/Libraries/libspiderscript.so_src/ast.h index 39a78fd4..4109fb70 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast.h +++ b/Usermode/Libraries/libspiderscript.so_src/ast.h @@ -28,14 +28,15 @@ enum eAST_NodeTypes NODETYPE_STRING, //!< String Constant NODETYPE_INTEGER, //!< Integer Constant NODETYPE_REAL, //!< Real Constant + NODETYPE_NULL, - // 7 + // 8 NODETYPE_DEFVAR, //!< Define a variable (Variable) NODETYPE_SCOPE, //!< Dereference a Namespace/Class static NODETYPE_ELEMENT, //!< Reference a class attribute NODETYPE_CAST, //!< Cast a value to another (Uniop) - // 11 + // 12 NODETYPE_RETURN, //!< Return from a function (reserved word) NODETYPE_BREAK, //!< Break out of a loop NODETYPE_CONTINUE, //!< Next loop iteration @@ -46,14 +47,14 @@ enum eAST_NodeTypes NODETYPE_METHODCALL, //!< Call a class method NODETYPE_CREATEOBJECT, //!< Create an object - // 20 + // 21 NODETYPE_IF, //!< Conditional NODETYPE_LOOP, //!< Looping Construct - // 22 + // 23 NODETYPE_INDEX, //!< Index into an array - // 23 + // 24 NODETYPE_LOGICALNOT, //!< Logical NOT operator NODETYPE_LOGICALAND, //!< Logical AND operator NODETYPE_LOGICALOR, //!< Logical OR operator @@ -207,6 +208,8 @@ 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, int64_t Value); extern tAST_Node *AST_NewReal(tParser *Parser, double Value); +extern tAST_Node *AST_NewNull(tParser *Parser); + 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/ast_to_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c index 66437bc8..8d94735b 100644 --- a/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c @@ -47,6 +47,7 @@ typedef struct sAST_BlockInfo int BC_Variable_Define(tAST_BlockInfo *Block, int Type, const char *Name); int BC_Variable_SetValue(tAST_BlockInfo *Block, tAST_Node *VarNode); int BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode); +void BC_Variable_Clear(tAST_BlockInfo *Block); // - Errors void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...); void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); @@ -76,6 +77,7 @@ tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn) { tBC_Function *ret; tAST_BlockInfo bi = {0}; + int i; // TODO: Return BCFcn instead? if(Fcn->BCFcn) return Fcn->BCFcn; @@ -84,12 +86,22 @@ tBC_Function *Bytecode_ConvertFunction(tScript_Function *Fcn) if(!ret) return NULL; bi.Handle = ret; + + // Parse arguments + for( i = 0; i < Fcn->ArgumentCount; i ++ ) + { + BC_Variable_Define(&bi, Fcn->Arguments[i].Type, Fcn->Arguments[i].Name); + } + if( AST_ConvertNode(&bi, Fcn->ASTFcn, 0) ) { AST_RuntimeError(Fcn->ASTFcn, "Error in converting function"); Bytecode_DeleteFunction(ret); + BC_Variable_Clear(&bi); return NULL; } + BC_Variable_Clear(&bi); + Bytecode_AppendConstInt(ret, 0); // TODO: NULL Bytecode_AppendReturn(ret); @@ -136,12 +148,14 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) node; node = node->NextSibling ) { - ret = AST_ConvertNode(Block, node, 0); + ret = AST_ConvertNode(&blockInfo, node, 0); if(ret) return ret; if( blockInfo.StackDepth != 0 ) { AST_RuntimeError(node, "Stack not reset at end of node"); } } + + BC_Variable_Clear(&blockInfo); } Bytecode_AppendLeaveContext(Block->Handle); // Leave this context break; @@ -275,16 +289,18 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) for( i = 0; i < Block->NamespaceDepth; i ++ ) newnamelen += strlen(Block->CurNamespaceStack[i]) + 1; newnamelen += strlen(Node->FunctionCall.Name) + 1; +// newnamelen += 1; + manglename = alloca(newnamelen); - manglename[0] = 0; + newnamelen = 0; for( i = 0; i < Block->NamespaceDepth; i ++ ) { - int pos; - strcat(manglename, Block->CurNamespaceStack[i]); - pos = strlen(manglename); - manglename[pos] = BC_NS_SEPARATOR; - manglename[pos+1] = '\0'; + strcpy(manglename+newnamelen, Block->CurNamespaceStack[i]); + newnamelen += strlen(Block->CurNamespaceStack[i]) + 1; + manglename[ newnamelen - 1 ] = BC_NS_SEPARATOR; } - strcat(manglename, Node->FunctionCall.Name); + strcpy(manglename + newnamelen, Node->FunctionCall.Name); + newnamelen += strlen(Node->FunctionCall.Name) + 1; +// manglename[ newnamelen ] = '\0'; // Zero length terminator Block->NamespaceDepth = 0; // Push arguments to the stack @@ -356,7 +372,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) // Loop case NODETYPE_LOOP: { - int loop_start, loop_end; + int loop_start, loop_end, code_end; int saved_break, saved_continue; const char *saved_tag; @@ -365,13 +381,14 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) if(ret) return ret; loop_start = Bytecode_AllocateLabel(Block->Handle); + code_end = Bytecode_AllocateLabel(Block->Handle); loop_end = Bytecode_AllocateLabel(Block->Handle); saved_break = Block->BreakTarget; saved_continue = Block->ContinueTarget; saved_tag = Block->Tag; Block->BreakTarget = loop_end; - Block->ContinueTarget = loop_end; + Block->ContinueTarget = code_end; Block->Tag = Node->For.Tag; Bytecode_SetLabel(Block->Handle, loop_start); @@ -390,7 +407,9 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) // Code ret = AST_ConvertNode(Block, Node->For.Code, 0); if(ret) return ret; - + + Bytecode_SetLabel(Block->Handle, code_end); + // Increment ret = AST_ConvertNode(Block, Node->For.Increment, 0); if(ret) return ret; @@ -431,7 +450,12 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) case NODETYPE_CONTINUE: { tAST_BlockInfo *bi = Block; if( Node->Variable.Name[0] ) { - while(bi && strcmp(bi->Tag, Node->Variable.Name) == 0) bi = bi->Parent; + while(bi && (!bi->Tag || strcmp(bi->Tag, Node->Variable.Name) != 0)) + bi = bi->Parent; + } + else { + while(bi && !bi->Tag) + bi = bi->Parent; } if( !bi ) return 1; // TODO: Check if BreakTarget/ContinueTarget are valid @@ -544,8 +568,7 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) // TODO: Scan namespace for constant name AST_RuntimeError(Node, "TODO - Runtime Constants"); Block->NamespaceDepth = 0; - ret = -1; - break; + return -1; // Constant Values case NODETYPE_STRING: @@ -566,7 +589,13 @@ int AST_ConvertNode(tAST_BlockInfo *Block, tAST_Node *Node, int bKeepValue) if(ret < 0) return -1; CHECK_IF_NEEDED(1); break; - + case NODETYPE_NULL: + Bytecode_AppendConstNull(Block->Handle); + ret = _StackPush(Block, Node, SS_DATATYPE_UNDEF); + if(ret < 0) return -1; + CHECK_IF_NEEDED(1); + break; + // --- Operations --- // Boolean Operations case NODETYPE_LOGICALNOT: // Logical NOT (!) @@ -724,7 +753,7 @@ tAST_Variable *BC_Variable_Lookup(tAST_BlockInfo *Block, tAST_Node *VarNode, int } if(var) break; } - + if( !var ) { // if( Block->Script->Variant->bDyamicTyped && CreateType != SS_DATATYPE_UNDEF ) { @@ -780,6 +809,18 @@ int BC_Variable_GetValue(tAST_BlockInfo *Block, tAST_Node *VarNode) return 0; } +void BC_Variable_Clear(tAST_BlockInfo *Block) +{ + tAST_Variable *var; + for( var = Block->FirstVar; var; ) + { + tAST_Variable *tv = var->Next; + free( var ); + var = tv; + } + Block->FirstVar = NULL; +} + #if 0 void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...) { diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode.h b/Usermode/Libraries/libspiderscript.so_src/bytecode.h index bc3c91cd..6f3734d2 100644 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode.h +++ b/Usermode/Libraries/libspiderscript.so_src/bytecode.h @@ -18,6 +18,9 @@ struct sBC_Op int Operation; char bUseInteger; // Used for serialisation char bUseString; // Used for serialisation + + void *CacheEnt; // Used to runtime cache function calls + union { struct { int Integer; diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c index e4e62ab5..e4437c3c 100644 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c +++ b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c @@ -412,6 +412,8 @@ void Bytecode_AppendConstString(tBC_Function *Handle, const void *Data, size_t L op->Content.StringInt.String[Length] = 0; Bytecode_int_AppendOp(Handle, op); } +void Bytecode_AppendConstNull(tBC_Function *Handle) + DEF_BC_NONE(BC_OP_LOADNULL) // --- Indexing / Scoping void Bytecode_AppendElement(tBC_Function *Handle, const char *Name) diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h index b82b3b44..71c5af1d 100644 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h +++ b/Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h @@ -55,6 +55,7 @@ extern void Bytecode_AppendSaveVar(tBC_Function *Handle, const char *Name); // ( extern void Bytecode_AppendConstInt(tBC_Function *Handle, uint64_t Value); extern void Bytecode_AppendConstReal(tBC_Function *Handle, double Value); extern void Bytecode_AppendConstString(tBC_Function *Handle, const void *Data, size_t Length); +extern void Bytecode_AppendConstNull(tBC_Function *Handle); // > Scoping extern void Bytecode_AppendElement(tBC_Function *Handle, const char *Name); // Obj->SubObj extern void Bytecode_AppendSetElement(tBC_Function *Handle, const char *Name); // Set an object member diff --git a/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h b/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h index 00df615f..4db753ec 100644 --- a/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h +++ b/Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h @@ -22,43 +22,44 @@ enum eBC_Ops BC_OP_LOADINT, // = 10 BC_OP_LOADREAL, BC_OP_LOADSTR, + BC_OP_LOADNULL, - BC_OP_DUPSTACK, // = 13 + BC_OP_DUPSTACK, // = 14 BC_OP_DELSTACK, // BC_OP_CAST, // - BC_OP_ELEMENT, // = 16 + BC_OP_ELEMENT, // = 17 BC_OP_SETELEMENT, BC_OP_INDEX, BC_OP_SETINDEX, - BC_OP_ENTERCONTEXT, // = 20 + BC_OP_ENTERCONTEXT, // = 21 BC_OP_LEAVECONTEXT, BC_OP_DEFINEVAR, // Operations - BC_OP_LOGICNOT, // 23 + BC_OP_LOGICNOT, // 24 BC_OP_LOGICAND, BC_OP_LOGICOR, BC_OP_LOGICXOR, - BC_OP_BITNOT, // 27 + BC_OP_BITNOT, // 28 BC_OP_BITAND, BC_OP_BITOR, BC_OP_BITXOR, - BC_OP_BITSHIFTLEFT, // 31 + BC_OP_BITSHIFTLEFT, // 32 BC_OP_BITSHIFTRIGHT, BC_OP_BITROTATELEFT, - BC_OP_NEG, // 34 + BC_OP_NEG, // 35 BC_OP_ADD, BC_OP_SUBTRACT, BC_OP_MULTIPLY, BC_OP_DIVIDE, BC_OP_MODULO, - BC_OP_EQUALS, // 40 + BC_OP_EQUALS, // 41 BC_OP_NOTEQUALS, BC_OP_LESSTHAN, BC_OP_LESSTHANOREQUAL, diff --git a/Usermode/Libraries/libspiderscript.so_src/exec.c b/Usermode/Libraries/libspiderscript.so_src/exec.c index f1244974..f0bc6975 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec.c @@ -12,6 +12,8 @@ #include #include +#define BC_NS_SEPARATOR '@' + // === IMPORTS === extern tSpiderFunction *gpExports_First; extern tSpiderValue *AST_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, int NArguments, tSpiderValue **Arguments); @@ -22,6 +24,104 @@ void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, . void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); // === CODE === +void *SpiderScript_int_GetNamespace(tSpiderScript *Script, tSpiderNamespace *RootNamespace, + const char *BasePath, const char *ItemPath, + const char **ItemName + ) +{ + int len; + const char *name; + const char *end; + int bTriedBase; + + tSpiderNamespace *lastns, *ns; + + // Prepend the base namespace + if( BasePath ) { + name = BasePath; + bTriedBase = 0; + } + else { + bTriedBase = 1; + name = ItemPath; + } + + // Scan + lastns = RootNamespace; + do { + end = strchr(name, BC_NS_SEPARATOR); + if(!end) { + if( !bTriedBase ) + len = strlen(name); + else + break; + } + else { + len = end - name; + } + + // Check for this level + for( ns = lastns->FirstChild; ns; ns = ns->Next ) + { + if( strncmp(name, ns->Name, len) == 0 && ns->Name[len] == 0 ) + break ; + } + + if(!ns) return NULL; + + if(!end && !bTriedBase) { + end = ItemPath - 1; // -1 to counter (name = end + 1) + bTriedBase = 1; + } + + lastns = ns; + name = end + 1; + } while( end ); + + *ItemName = name; + + return lastns; +} + +tSpiderFunction *SpiderScript_int_GetNativeFunction(tSpiderScript *Script, tSpiderNamespace *RootNamespace, + const char *BasePath, const char *FunctionPath) +{ + tSpiderNamespace *ns; + const char *name; + tSpiderFunction *fcn; + + ns = SpiderScript_int_GetNamespace(Script, RootNamespace, BasePath, FunctionPath, &name); + if(!ns) return NULL; + + for( fcn = ns->Functions; fcn; fcn = fcn->Next ) + { + if( strcmp(name, fcn->Name) == 0 ) + return fcn; + } + + return NULL; +} + +tSpiderObjectDef *SpiderScript_int_GetNativeClass(tSpiderScript *Script, tSpiderNamespace *RootNamespace, + const char *BasePath, const char *ClassPath + ) +{ + tSpiderNamespace *ns; + const char *name; + tSpiderObjectDef *class; + + ns = SpiderScript_int_GetNamespace(Script, RootNamespace, BasePath, ClassPath, &name); + if(!ns) return NULL; + + for( class = ns->Classes; class; class = class->Next ) + { + if( strcmp(name, class->Name) == 0 ) + return class; + } + + return NULL; +} + /** * \brief Execute a script function * \param Script Script context to execute in @@ -31,87 +131,91 @@ void AST_RuntimeError(tAST_Node *Node, const char *Format, ...); * \param Arguments Arguments passed */ tSpiderValue *SpiderScript_ExecuteFunction(tSpiderScript *Script, - tSpiderNamespace *Namespace, const char *Function, - int NArguments, tSpiderValue **Arguments) + const char *Function, + const char *DefaultNamespaces[], + int NArguments, tSpiderValue **Arguments, + void **FunctionIdent + ) { - int bFound = 0; // Used to keep nesting levels down tSpiderValue *ret = ERRPTR; - - // First: Find the function in the script - if( !Namespace ) + tSpiderFunction *fcn = NULL; + int i; + + // Scan list, Last item should always be NULL, so abuse that to check non-prefixed + for( i = 0; i == 0 || (DefaultNamespaces && DefaultNamespaces[i-1]); i ++ ) { - tScript_Function *fcn; - for( fcn = Script->Functions; fcn; fcn = fcn->Next ) + const char *ns = DefaultNamespaces ? DefaultNamespaces[i] : NULL; + fcn = SpiderScript_int_GetNativeFunction(Script, &Script->Variant->RootNamespace, + ns, Function); + if( fcn ) break; + + // TODO: Script namespacing + } + + // Search the variant's global exports + if( !fcn ) + { + for( fcn = Script->Variant->Functions; fcn; fcn = fcn->Next ) { - if( strcmp(fcn->Name, Function) == 0 ) + if( strcmp( fcn->Name, Function ) == 0 ) break; } - // Execute! - if(fcn) - { - if( fcn->BCFcn ) - ret = Bytecode_ExecuteFunction(Script, fcn, NArguments, Arguments); - else - ret = AST_ExecuteFunction(Script, fcn, NArguments, Arguments); - bFound = 1; - return ret; - } } - // Didn't find it in script? - if(!bFound) + // Fourth: Search language exports + if( !fcn ) { - tSpiderFunction *fcn; - fcn = NULL; // Just to allow the below code to be neat - - // Second: Scan current namespace - if( !fcn && Namespace ) + for( fcn = gpExports_First; fcn; fcn = fcn->Next ) { - for( fcn = Namespace->Functions; fcn; fcn = fcn->Next ) - { - if( strcmp( fcn->Name, Function ) == 0 ) - break; - } - } - - // Third: Search the variant's global exports - if( !fcn ) - { - for( fcn = Script->Variant->Functions; fcn; fcn = fcn->Next ) - { - if( strcmp( fcn->Name, Function ) == 0 ) - break; - } + if( strcmp( fcn->Name, Function ) == 0 ) + break; } - - // Fourth: Search language exports - if( !fcn ) + } + + // Find the function in the script? + // TODO: Script namespacing + if( !fcn && strchr(Function, BC_NS_SEPARATOR) == NULL ) + { + tScript_Function *sfcn; + for( sfcn = Script->Functions; sfcn; sfcn = sfcn->Next ) { - for( fcn = gpExports_First; fcn; fcn = fcn->Next ) - { - if( strcmp( fcn->Name, Function ) == 0 ) - break; - } + if( strcmp(sfcn->Name, Function) == 0 ) + break; } - // Execute! - if(fcn) + if(sfcn) { - // TODO: Type Checking - ret = fcn->Handler( Script, NArguments, Arguments ); - bFound = 1; + if( sfcn->BCFcn ) + ret = Bytecode_ExecuteFunction(Script, sfcn, NArguments, Arguments); + else + ret = AST_ExecuteFunction(Script, sfcn, NArguments, Arguments); + + if( FunctionIdent ) { + *FunctionIdent = sfcn; + // Abuses alignment requirements on almost all platforms + *(intptr_t*)FunctionIdent |= 1; + } + + return ret; } } - // Not found? - if(!bFound) + if(fcn) { - fprintf(stderr, "Undefined reference to function '%s' (ns='%s')\n", - Function, Namespace->Name); + // Execute! + // TODO: Type Checking + ret = fcn->Handler( Script, NArguments, Arguments ); + + if( FunctionIdent ) + *FunctionIdent = fcn; + + return ret; + } + else + { + fprintf(stderr, "Undefined reference to function '%s'\n", Function); return ERRPTR; } - - return ret; } /** @@ -183,13 +287,23 @@ tSpiderValue *SpiderScript_ExecuteMethod(tSpiderScript *Script, * \param Arguments Arguments passed */ tSpiderValue *SpiderScript_CreateObject(tSpiderScript *Script, - tSpiderNamespace *Namespace, const char *ClassName, + const char *ClassPath, const char *DefaultNamespaces[], int NArguments, tSpiderValue **Arguments) { - int bFound = 0; // Used to keep nesting levels down tSpiderValue *ret = ERRPTR; tSpiderObjectDef *class; - + int i; + + // Scan list, Last item should always be NULL, so abuse that to check non-prefixed + for( i = 0; i == 0 || DefaultNamespaces[i-1]; i ++ ) + { + class = SpiderScript_int_GetNativeClass(Script, &Script->Variant->RootNamespace, + DefaultNamespaces[i], ClassPath); + if( class != NULL ) break; + + // TODO: Language defined classes + } + // First: Find the function in the script // TODO: Implement script-defined classes #if 0 @@ -244,76 +358,30 @@ tSpiderValue *SpiderScript_CreateObject(tSpiderScript *Script, } #endif - // Didn't find it in script? - if(!bFound) + // Execute! + if(class) { - class = NULL; // Just to allow the below code to be neat - - //if( !Namespace ) - // Namespace = &Script->Variant->RootNamespace; + tSpiderObject *obj; + // TODO: Type Checking - // Second: Scan current namespace - if( !class && Namespace ) - { - for( class = Namespace->Classes; class; class = class->Next ) - { - if( strcmp( class->Name, ClassName ) == 0 ) - break; - } - } - - #if 0 - // Third: Search the variant's global exports - if( !class ) - { - for( class = Script->Variant->Classes; class; class = fcn->Next ) - { - if( strcmp( class->Name, Function ) == 0 ) - break; - } - } - #endif + // Call constructor + obj = class->Constructor( NArguments, Arguments ); + if( obj == NULL || obj == ERRPTR ) + return (void *)obj; - #if 0 - // Fourth: Search language exports - if( !class ) - { - for( class = gpExports_First; class; class = fcn->Next ) - { - if( strcmp( class->Name, ClassName ) == 0 ) - break; - } - } - #endif + // Creatue return object + ret = malloc( sizeof(tSpiderValue) ); + ret->Type = SS_DATATYPE_OBJECT; + ret->ReferenceCount = 1; + ret->Object = obj; - // Execute! - if(class) - { - tSpiderObject *obj; - // TODO: Type Checking - - // Call constructor - obj = class->Constructor( NArguments, Arguments ); - if( obj == NULL || obj == ERRPTR ) - return (void *)obj; - - // Creatue return object - ret = malloc( sizeof(tSpiderValue) ); - ret->Type = SS_DATATYPE_OBJECT; - ret->ReferenceCount = 1; - ret->Object = obj; - bFound = 1; - } + return ret; } - - // Not found? - if(!bFound) + else // Not found? { - fprintf(stderr, "Undefined reference to class '%s'\n", ClassName); + fprintf(stderr, "Undefined reference to class '%s'\n", ClassPath); return ERRPTR; } - - return ret; } void AST_RuntimeMessage(tAST_Node *Node, const char *Type, const char *Format, ...) diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c index b6448d3b..c26d8876 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_ast.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_ast.c @@ -234,9 +234,11 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) case NODETYPE_CREATEOBJECT: // Logical block (used to allocate `params`) { - tSpiderNamespace *ns = Block->CurNamespace; + const char *namespaces[] = {NULL}; // TODO: Default namespaces? tSpiderValue *params[Node->FunctionCall.NumArgs]; i = 0; + + // Get arguments for(node = Node->FunctionCall.FirstArg; node; node = node->NextSibling) { params[i] = AST_ExecuteNode(Block, node); @@ -247,15 +249,15 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) } i ++; } - - if( !ns ) ns = Block->BaseNamespace; - + + // TODO: Check for cached function reference + // Call the function if( Node->Type == NODETYPE_CREATEOBJECT ) { ret = SpiderScript_CreateObject(Block->Script, - ns, Node->FunctionCall.Name, + namespaces, Node->FunctionCall.NumArgs, params ); } @@ -278,8 +280,10 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) else { ret = SpiderScript_ExecuteFunction(Block->Script, - ns, Node->FunctionCall.Name, - Node->FunctionCall.NumArgs, params + Node->FunctionCall.Name, + namespaces, + Node->FunctionCall.NumArgs, params, + NULL ); } @@ -426,7 +430,9 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) break; } Block->CurNamespace = ns; - + + // TODO: Check type of child node (Scope, Constant or Function) + ret = AST_ExecuteNode(Block, Node->Scope.Element); } break; @@ -545,6 +551,9 @@ tSpiderValue *AST_ExecuteNode(tAST_BlockState *Block, tAST_Node *Node) ret = &Node->Constant; SpiderScript_ReferenceValue(ret); break; + case NODETYPE_NULL: + ret = NULL; + break; // --- Operations --- // Boolean Operations diff --git a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c index afc63bf0..6817c243 100644 --- a/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c +++ b/Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c @@ -272,6 +272,7 @@ tSpiderValue *Bytecode_ExecuteFunction(tSpiderScript *Script, tScript_Function * return NULL; } free(stack); + ret = Bytecode_int_GetSpiderValue(&val, &tmpsval); // Ensure it's a heap value if(ret == &tmpsval) { @@ -311,10 +312,10 @@ int Bytecode_int_CallExternFunction(tSpiderScript *Script, tBC_Stack *Stack, tSp const char *name = OP_STRING(op); int arg_count = OP_INDX(op); int i, ret = 0; - tSpiderNamespace *ns = NULL; tSpiderValue *args[arg_count]; tSpiderValue *rv; - tBC_StackEnt val1; + tBC_StackEnt val1; + const char *namespaces[] = {NULL}; // TODO: Default/imported namespaces DEBUG_F("CALL (general) %s %i args\n", name, arg_count); @@ -326,31 +327,14 @@ int Bytecode_int_CallExternFunction(tSpiderScript *Script, tBC_Stack *Stack, tSp Bytecode_int_DerefStackValue(&val1); } - // Resolve namespace into pointer - if( op->Operation != BC_OP_CALLMETHOD ) { - const char *name_orig = name; - 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(DefaultNS, name, &name); - } - if( !ns ) { - AST_RuntimeError(NULL, "Namespace '%s' not found in '%s'", name, name_orig); - return -1; - } - } - // Call the function etc. if( op->Operation == BC_OP_CALLFUNCTION ) { - rv = SpiderScript_ExecuteFunction(Script, ns, name, arg_count, args); + rv = SpiderScript_ExecuteFunction(Script, name, namespaces, arg_count, args, &op->CacheEnt); } else if( op->Operation == BC_OP_CREATEOBJ ) { - rv = SpiderScript_CreateObject(Script, ns, name, arg_count, args); + rv = SpiderScript_CreateObject(Script, name, namespaces, arg_count, args); } else if( op->Operation == BC_OP_CALLMETHOD ) { @@ -595,6 +579,13 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t val1.Reference = SpiderScript_CreateString(OP_INDX(op), OP_STRING(op)); PUT_STACKVAL(val1); break; + case BC_OP_LOADNULL: + STATE_HDR(); + DEBUG_F("LOADNULL\n"); + val1.Type = ET_REFERENCE; + val1.Reference = NULL; + PUT_STACKVAL(val1); + break; case BC_OP_CAST: STATE_HDR(); @@ -872,7 +863,7 @@ int Bytecode_int_ExecuteFunction(tSpiderScript *Script, tScript_Function *Fcn, t n_rolled ++; } PUT_STACKVAL(val1); - DEBUG_F("Rolled back %i entried\n", n_rolled); + DEBUG_F("Rolled back %i entries\n", n_rolled); } diff --git a/Usermode/Libraries/libspiderscript.so_src/parse.c b/Usermode/Libraries/libspiderscript.so_src/parse.c index 5be878df..321c15fd 100644 --- a/Usermode/Libraries/libspiderscript.so_src/parse.c +++ b/Usermode/Libraries/libspiderscript.so_src/parse.c @@ -853,7 +853,7 @@ tAST_Node *Parse_DoValue(tParser *Parser) return Parse_GetVariable(Parser); case TOK_RWD_NULL: GetToken(Parser); - return AST_NewNop(Parser); // NODETYPE_NOP returns NULL + return AST_NewNull(Parser); // nODETYPE_NOP returns NULL case TOK_RWD_NEW: GetToken(Parser); return Parse_GetIdent(Parser, 1); diff --git a/Usermode/Libraries/libspiderscript.so_src/values.c b/Usermode/Libraries/libspiderscript.so_src/values.c index 2b878415..15afe1a3 100644 --- a/Usermode/Libraries/libspiderscript.so_src/values.c +++ b/Usermode/Libraries/libspiderscript.so_src/values.c @@ -38,8 +38,8 @@ void SpiderScript_DereferenceValue(tSpiderValue *Object) { if(!Object || Object == ERRPTR) return ; Object->ReferenceCount --; - if(Object->Type == SS_DATATYPE_OBJECT) { - } +// if(Object->Type == SS_DATATYPE_OBJECT) { +// } if( Object->ReferenceCount == 0 ) { switch( (enum eSpiderScript_DataTypes) Object->Type ) diff --git a/Usermode/include/spiderscript.h b/Usermode/include/spiderscript.h index 92e6c139..56a48e65 100644 --- a/Usermode/include/spiderscript.h +++ b/Usermode/include/spiderscript.h @@ -263,8 +263,9 @@ extern tSpiderScript *SpiderScript_ParseFile(tSpiderVariant *Variant, const char * \return Return value */ extern tSpiderValue *SpiderScript_ExecuteFunction(tSpiderScript *Script, - tSpiderNamespace *Namespace, const char *Function, - int NArguments, tSpiderValue **Arguments + const char *Function, const char *DefaultNamespaces[], + int NArguments, tSpiderValue **Arguments, + void **FunctionIdent ); /** * \brief Execute an object method @@ -277,7 +278,7 @@ extern tSpiderValue *SpiderScript_ExecuteMethod(tSpiderScript *Script, * \brief Creates an object instance */ extern tSpiderValue *SpiderScript_CreateObject(tSpiderScript *Script, - tSpiderNamespace *Namespace, const char *ClassName, + const char *ClassName, const char *DefaultNamespaces[], int NArguments, tSpiderValue **Arguments ); -- 2.20.1