SpiderScript! (with a sample script)
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / main.c
index ce39c08..e5c225c 100644 (file)
 
 // === IMPORTS ===
 extern tAST_Script     *Parse_Buffer(tSpiderVariant *Variant, char *Buffer);
+extern const int       giSpiderScript_NumExports;
+extern tSpiderFunction gaSpiderScript_Exports[];
+extern tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name);
+extern void    Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderObject *Value);
 
 // === CODE ===
 /**
@@ -42,13 +46,21 @@ tSpiderScript *SpiderScript_ParseFile(tSpiderVariant *Variant, const char *Filen
        fLen = ftell(fp);
        fseek(fp, 0, SEEK_SET);
        
-       data = malloc(fLen);
+       // Allocate and read data
+       data = malloc(fLen + 1);
        if(!data)       return NULL;
        fread(data, fLen, 1, fp);
+       data[fLen] = '\0';
        
        fclose(fp);
        
+       ret->CurNamespace = NULL;
        ret->Script = Parse_Buffer(Variant, data);
+       if( ret->Script == NULL ) {
+               free(data);
+               free(ret);
+               return NULL;
+       }
        
        free(data);
        
@@ -57,21 +69,105 @@ tSpiderScript *SpiderScript_ParseFile(tSpiderVariant *Variant, const char *Filen
 
 /**
  * \brief Execute a script function
- * \todo Arguments?
+ * \param Script       Script context to execute in
+ * \param Function     Function name to execute
+ * \param NArguments   Number of arguments to pass
+ * \param Arguments    Arguments passed
  */
-tSpiderVariable *SpiderScript_ExecuteMethod(tSpiderScript *Script, const char *Function)
+tSpiderObject *SpiderScript_ExecuteMethod(tSpiderScript *Script,
+       const char *Function, int NArguments, tSpiderObject **Arguments)
 {
-       tAST_Function   *fcn = Script->Script->Functions;
+       char    *trueName = NULL;
+        int    i;
+        int    bFound = 0;     // Used to keep nesting levels down
+       tSpiderObject   *ret = ERRPTR;
+       
+       // Handle namespaces
+       if( Function[0] == '.' ) {
+               trueName = (char*)&Function[1];
+       }
+       else if( !Script->CurNamespace ) {
+               trueName = (char*)Function;
+       }
+       else {
+                int    len = strlen(Script->CurNamespace) + 1 + strlen(Function);
+               trueName = malloc( len + 1 );
+               strcpy(trueName, Script->CurNamespace);
+               strcat(trueName, ".");
+               strcat(trueName, Function);
+       }
+       
+       // First: Find the function in the script
+       {
+               tAST_Function   *fcn = Script->Script->Functions;
+               for( ; fcn; fcn = fcn->Next ) {
+                       if( strcmp(fcn->Name, trueName) == 0 )
+                               break;
+               }
+               // Execute!
+               if(fcn) {
+                       tAST_BlockState bs;
+                       bs.FirstVar = NULL;     //< TODO: Parameters
+                       bs.Parent = NULL;
+                       bs.Script = Script;
+                       {
+                               tAST_Node       *arg;
+                                int    i = 0;
+                               for( arg = fcn->Arguments; arg; arg = arg->NextSibling, i++ )
+                               {
+                                       // TODO: Type checks
+                                       Variable_Define(&bs, arg->DefVar.DataType, arg->DefVar.Name);
+                                       if( i >= NArguments )   break;  // TODO: Return gracefully
+                                       Variable_SetValue(&bs, arg->DefVar.Name, Arguments[i]);
+                               }
+                       }
+                       ret = AST_ExecuteNode(&bs, fcn->Code);
+                       bFound = 1;
+               }
+       }
+               
+       // Didn't find it in script?
+       if(!bFound)
+       {       
+               // Second: Search the variant's exports
+               for( i = 0; i < Script->Variant->NFunctions; i ++ )
+               {
+                       if( strcmp( Script->Variant->Functions[i].Name, trueName) == 0 )
+                               break;
+               }
+               // Execute!
+               if(i < Script->Variant->NFunctions) {
+                       ret = Script->Variant->Functions[i].Handler( Script, NArguments, Arguments );
+                       bFound = 1;
+               }
+       }
        
-       // Find the function
-       for( ; fcn; fcn = fcn->Next ) {
-               if( strcmp(fcn->Name, Function) == 0 )
-                       break;
+       // Not in variant exports? Search the language internal ones
+       if(!bFound)
+       {
+               for( i = 0; i < giSpiderScript_NumExports; i ++ )
+               {
+                       if( strcmp( gaSpiderScript_Exports[i].Name, trueName ) == 0 )
+                               break;
+               }
+               // Execute!
+               if(i < giSpiderScript_NumExports) {
+                       ret = gaSpiderScript_Exports[i].Handler( Script, NArguments, Arguments );
+                       bFound = 1;
+               }
        }
-       if(!fcn)        return NULL;
        
-       // Execute!
-       return AST_ExecuteNode(Script, fcn->Code);
+       // Not found?
+       if(!bFound)
+       {
+               fprintf(stderr, "Undefined reference to '%s'\n", trueName);
+       }
+       
+       if( trueName != Function && trueName != &Function[1] )
+               free(trueName);
+       
+       return ret;
+       
 }
 
 /**
@@ -99,4 +195,9 @@ void SpiderScript_Free(tSpiderScript *Script)
                free( fcn );
                fcn = nextFcn;
        }
+       
+       // TODO: Pass this off to AST for a proper cleanup
+       free(Script->Script);
+       
+       free(Script);
 }

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