0c3cb072c89b4769139a3bccc1f52db29c09889d
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / main.c
1 /*
2  * Acess2 - SpiderScript
3  * Interpreter Library
4  */
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <spiderscript.h>
9 #include "ast.h"
10
11 // === IMPORTS ===
12 extern tAST_Script      *Parse_Buffer(tSpiderVariant *Variant, char *Buffer);
13 extern const int        giSpiderScript_NumExports;
14 extern tSpiderFunction  gaSpiderScript_Exports[];
15 extern tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name);
16 extern void     Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value);
17
18 // === CODE ===
19 /**
20  * \brief Library Entry Point
21  */
22 int SoMain()
23 {
24         return 0;
25 }
26
27 /**
28  * \brief Parse a script
29  */
30 tSpiderScript *SpiderScript_ParseFile(tSpiderVariant *Variant, const char *Filename)
31 {
32         char    *data;
33          int    fLen;
34         FILE    *fp;
35         tSpiderScript   *ret;
36         
37         fp = fopen(Filename, "r");
38         if( !fp ) {
39                 return NULL;
40         }
41         
42         ret = malloc(sizeof(tSpiderScript));
43         ret->Variant = Variant;
44         
45         fseek(fp, 0, SEEK_END);
46         fLen = ftell(fp);
47         fseek(fp, 0, SEEK_SET);
48         
49         // Allocate and read data
50         data = malloc(fLen + 1);
51         if(!data)       return NULL;
52         fread(data, fLen, 1, fp);
53         data[fLen] = '\0';
54         
55         fclose(fp);
56         
57         ret->CurNamespace = NULL;
58         ret->Script = Parse_Buffer(Variant, data);
59         if( ret->Script == NULL ) {
60                 free(data);
61                 free(ret);
62                 return NULL;
63         }
64         
65         free(data);
66         
67         return ret;
68 }
69
70 /**
71  * \brief Execute a script function
72  * \param Script        Script context to execute in
73  * \param Function      Function name to execute
74  * \param NArguments    Number of arguments to pass
75  * \param Arguments     Arguments passed
76  */
77 tSpiderValue *SpiderScript_ExecuteMethod(tSpiderScript *Script,
78         const char *Function, int NArguments, tSpiderValue **Arguments)
79 {
80         char    *trueName = NULL;
81          int    i;
82          int    bFound = 0;     // Used to keep nesting levels down
83         tSpiderValue    *ret = ERRPTR;
84         
85         // Handle namespaces
86         if( Function[0] == '.' ) {
87                 trueName = (char*)&Function[1];
88         }
89         else if( !Script->CurNamespace ) {
90                 trueName = (char*)Function;
91         }
92         else {
93                  int    len = strlen(Script->CurNamespace) + 1 + strlen(Function);
94                 trueName = malloc( len + 1 );
95                 strcpy(trueName, Script->CurNamespace);
96                 strcat(trueName, ".");
97                 strcat(trueName, Function);
98         }
99         
100         // First: Find the function in the script
101         {
102                 tAST_Function   *fcn = Script->Script->Functions;
103                 for( ; fcn; fcn = fcn->Next ) {
104                         if( strcmp(fcn->Name, trueName) == 0 )
105                                 break;
106                 }
107                 // Execute!
108                 if(fcn) {
109                         tAST_BlockState bs;
110                         bs.FirstVar = NULL;
111                         bs.RetVal = NULL;
112                         bs.Parent = NULL;
113                         bs.Script = Script;
114                         {
115                                 tAST_Node       *arg;
116                                  int    i = 0;
117                                 for( arg = fcn->Arguments; arg; arg = arg->NextSibling, i++ )
118                                 {
119                                         // TODO: Type checks
120                                         Variable_Define(&bs, arg->DefVar.DataType, arg->DefVar.Name);
121                                         if( i >= NArguments )   break;  // TODO: Return gracefully
122                                         Variable_SetValue(&bs, arg->DefVar.Name, Arguments[i]);
123                                 }
124                         }
125                         ret = AST_ExecuteNode(&bs, fcn->Code);
126                         //Object_Dereference(ret);
127                         ret = bs.RetVal;
128                         bFound = 1;
129                 }
130         }
131                 
132         // Didn't find it in script?
133         if(!bFound)
134         {       
135                 // Second: Search the variant's exports
136                 for( i = 0; i < Script->Variant->NFunctions; i ++ )
137                 {
138                         if( strcmp( Script->Variant->Functions[i].Name, trueName) == 0 )
139                                 break;
140                 }
141                 // Execute!
142                 if(i < Script->Variant->NFunctions) {
143                         ret = Script->Variant->Functions[i].Handler( Script, NArguments, Arguments );
144                         bFound = 1;
145                 }
146         }
147         
148         // Not in variant exports? Search the language internal ones
149         if(!bFound)
150         {
151                 for( i = 0; i < giSpiderScript_NumExports; i ++ )
152                 {
153                         if( strcmp( gaSpiderScript_Exports[i].Name, trueName ) == 0 )
154                                 break;
155                 }
156                 // Execute!
157                 if(i < giSpiderScript_NumExports) {
158                         ret = gaSpiderScript_Exports[i].Handler( Script, NArguments, Arguments );
159                         bFound = 1;
160                 }
161         }
162         
163         // Not found?
164         if(!bFound)
165         {
166                 fprintf(stderr, "Undefined reference to '%s'\n", trueName);
167         }
168         
169         if( trueName != Function && trueName != &Function[1] )
170                 free(trueName);
171         
172         return ret;
173         
174 }
175
176 /**
177  * \brief Free a script
178  */
179 void SpiderScript_Free(tSpiderScript *Script)
180 {
181         tAST_Function   *fcn = Script->Script->Functions;
182         tAST_Function   *nextFcn;
183         tAST_Node       *var, *nextVar;
184         
185         // Free functions
186         while(fcn) {
187                 AST_FreeNode( fcn->Code );
188                 
189                 var = fcn->Arguments;
190                 while(var)
191                 {
192                         nextVar = var->NextSibling;
193                         AST_FreeNode( var );
194                         var = nextVar;
195                 }
196                 
197                 nextFcn = fcn->Next;
198                 free( fcn );
199                 fcn = nextFcn;
200         }
201         
202         // TODO: Pass this off to AST for a proper cleanup
203         free(Script->Script);
204         
205         free(Script);
206 }

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