6ebd277973ad75e8618e004d9f3287b8ae8c6974
[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 tSpiderFunction  *gpExports_First;
14 extern tAST_Variable *Variable_Define(tAST_BlockState *Block, int Type, const char *Name);
15 extern void     Variable_SetValue(tAST_BlockState *Block, const char *Name, tSpiderValue *Value);
16 extern void     Variable_Destroy(tAST_Variable *Variable);
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    cacheFilename[strlen(Filename)+6+1];
33         char    *data;
34          int    fLen;
35         FILE    *fp;
36         tSpiderScript   *ret;
37         
38         strcpy(cacheFilename, Filename);
39         strcat(cacheFilename, ".cache");
40         
41         fp = fopen(Filename, "r");
42         if( !fp ) {
43                 return NULL;
44         }
45         
46         // Create the script
47         ret = malloc(sizeof(tSpiderScript));
48         ret->Variant = Variant;
49         
50         fseek(fp, 0, SEEK_END);
51         fLen = ftell(fp);
52         fseek(fp, 0, SEEK_SET);
53         
54         // Allocate and read data
55         data = malloc(fLen + 1);
56         if(!data)       return NULL;
57         fread(data, fLen, 1, fp);
58         data[fLen] = '\0';
59         
60         fclose(fp);
61         
62         ret->CurNamespace = NULL;
63         ret->Script = Parse_Buffer(Variant, data);
64         if( ret->Script == NULL ) {
65                 free(data);
66                 free(ret);
67                 return NULL;
68         }
69         
70         free(data);
71         
72         
73         // HACK!!
74         {
75                 size_t  size;
76                 
77                 printf("Total Size: "); fflush(stdout);
78                 size = AST_WriteScript(NULL, ret->Script);
79                 printf("0x%x bytes\n", (unsigned)size);
80                 
81                 fp = fopen(cacheFilename, "wb");
82                 if(!fp) return ret;
83                 
84                 data = malloc(size);
85                 AST_WriteScript(data, ret->Script);
86                 fwrite(data, size, 1, fp);
87                 free(data);
88                 fclose(fp);
89         }
90         
91         return ret;
92 }
93
94 /**
95  * \brief Execute a script function
96  * \param Script        Script context to execute in
97  * \param Function      Function name to execute
98  * \param NArguments    Number of arguments to pass
99  * \param Arguments     Arguments passed
100  */
101 tSpiderValue *SpiderScript_ExecuteMethod(tSpiderScript *Script,
102         const char *Function, int NArguments, tSpiderValue **Arguments)
103 {
104         char    *trueName = NULL;
105          int    bFound = 0;     // Used to keep nesting levels down
106         tSpiderValue    *ret = ERRPTR;
107         
108         // Handle namespaces
109         if( Function[0] == '.' ) {
110                 trueName = (char*)&Function[1];
111         }
112         else if( !Script->CurNamespace ) {
113                 trueName = (char*)Function;
114         }
115         else {
116                  int    len = strlen(Script->CurNamespace) + 1 + strlen(Function);
117                 trueName = malloc( len + 1 );
118                 strcpy(trueName, Script->CurNamespace);
119                 strcat(trueName, ".");
120                 strcat(trueName, Function);
121         }
122         
123         // First: Find the function in the script
124         {
125                 tAST_Function   *fcn = Script->Script->Functions;
126                 for( ; fcn; fcn = fcn->Next ) {
127                         if( strcmp(fcn->Name, trueName) == 0 )
128                                 break;
129                 }
130                 // Execute!
131                 if(fcn) {
132                         tAST_BlockState bs;
133                         bs.FirstVar = NULL;
134                         bs.RetVal = NULL;
135                         bs.Parent = NULL;
136                         bs.Script = Script;
137                         {
138                                 tAST_Node       *arg;
139                                  int    i = 0;
140                                 for( arg = fcn->Arguments; arg; arg = arg->NextSibling, i++ )
141                                 {
142                                         // TODO: Type checks
143                                         Variable_Define(&bs, arg->DefVar.DataType, arg->DefVar.Name);
144                                         if( i >= NArguments )   break;  // TODO: Return gracefully
145                                         Variable_SetValue(&bs, arg->DefVar.Name, Arguments[i]);
146                                 }
147                         }
148                         ret = AST_ExecuteNode(&bs, fcn->Code);
149                         Object_Dereference(ret);
150                         ret = bs.RetVal;
151                         bFound = 1;
152                         
153                         while(bs.FirstVar)
154                         {
155                                 tAST_Variable   *nextVar = bs.FirstVar->Next;
156                                 Variable_Destroy( bs.FirstVar );
157                                 bs.FirstVar = nextVar;
158                         }
159                 }
160         }
161         
162         // Didn't find it in script?
163         if(!bFound)
164         {
165                 tSpiderFunction *fcn;
166                 // Second: Search the variant's exports
167                 for( fcn = Script->Variant->Functions; fcn; fcn = fcn->Next )
168                 {
169                         if( strcmp( fcn->Name, trueName ) == 0 )
170                                 break;
171                 }
172                 // Execute!
173                 if(fcn) {
174                         // TODO: Type Checking
175                         ret = fcn->Handler( Script, NArguments, Arguments );
176                         bFound = 1;
177                 }
178         }
179         
180         // Not in variant exports? Search the language internal ones
181         if(!bFound)
182         {
183                 tSpiderFunction *fcn;
184                 // Third: Search language exports
185                 for( fcn = gpExports_First; fcn; fcn = fcn->Next )
186                 {
187                         if( strcmp( fcn->Name, trueName ) == 0 )
188                                 break;
189                 }
190                 // Execute!
191                 if(fcn) {
192                         ret = fcn->Handler( Script, NArguments, Arguments );
193                         bFound = 1;
194                 }
195         }
196         
197         // Not found?
198         if(!bFound)
199         {
200                 fprintf(stderr, "Undefined reference to '%s'\n", trueName);
201         }
202         
203         if( trueName != Function && trueName != &Function[1] )
204                 free(trueName);
205         
206         return ret;
207         
208 }
209
210 /**
211  * \brief Free a script
212  */
213 void SpiderScript_Free(tSpiderScript *Script)
214 {
215         tAST_Function   *fcn = Script->Script->Functions;
216         tAST_Function   *nextFcn;
217         tAST_Node       *var, *nextVar;
218         
219         // Free functions
220         while(fcn)
221         {
222                 
223                 AST_FreeNode( fcn->Code );
224                 
225                 var = fcn->Arguments;
226                 while(var)
227                 {
228                         nextVar = var->NextSibling;
229                         AST_FreeNode( var );
230                         var = nextVar;
231                 }
232                 
233                 nextFcn = fcn->Next;
234                 free( fcn );
235                 fcn = nextFcn;
236         }
237         
238         // TODO: Pass this off to AST for a proper cleanup
239         free(Script->Script);
240         
241         free(Script);
242 }

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