Usermode/SpiderScript - Restructured namespace handling, fixed a few bytecode bugs
authorJohn Hodge <[email protected]>
Tue, 17 Apr 2012 14:13:40 +0000 (22:13 +0800)
committerJohn Hodge <[email protected]>
Tue, 17 Apr 2012 14:13:40 +0000 (22:13 +0800)
13 files changed:
Usermode/Libraries/libspiderscript.so_src/ast.c
Usermode/Libraries/libspiderscript.so_src/ast.h
Usermode/Libraries/libspiderscript.so_src/ast_to_bytecode.c
Usermode/Libraries/libspiderscript.so_src/bytecode.h
Usermode/Libraries/libspiderscript.so_src/bytecode_gen.c
Usermode/Libraries/libspiderscript.so_src/bytecode_gen.h
Usermode/Libraries/libspiderscript.so_src/bytecode_ops.h
Usermode/Libraries/libspiderscript.so_src/exec.c
Usermode/Libraries/libspiderscript.so_src/exec_ast.c
Usermode/Libraries/libspiderscript.so_src/exec_bytecode.c
Usermode/Libraries/libspiderscript.so_src/parse.c
Usermode/Libraries/libspiderscript.so_src/values.c
Usermode/include/spiderscript.h

index 9532adb..d37dc31 100644 (file)
@@ -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
  */
index 39a78fd..4109fb7 100644 (file)
@@ -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);
index 66437bc..8d94735 100644 (file)
@@ -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, ...)
 {
index bc3c91c..6f3734d 100644 (file)
@@ -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;
index e4e62ab..e4437c3 100644 (file)
@@ -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)
index b82b3b4..71c5af1 100644 (file)
@@ -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
index 00df615..4db753e 100644 (file)
@@ -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,
index f124497..f0bc697 100644 (file)
@@ -12,6 +12,8 @@
 #include <string.h>
 #include <stdarg.h>
 
+#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, ...)
index b6448d3..c26d887 100644 (file)
@@ -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
index afc63bf..6817c24 100644 (file)
@@ -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);
        }
        
 
index 5be878d..321c15f 100644 (file)
@@ -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);
index 2b87841..15afe1a 100644 (file)
@@ -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 )
index 92e6c13..56a48e6 100644 (file)
@@ -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
        );
 

UCC git Repository :: git.ucc.asn.au