SpiderScript! (with a sample script)
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / ast.c
1 /*
2  * Acess2 Init
3  * - Script AST Manipulator
4  */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include "ast.h"
9
10 // === CODE ===
11 tAST_Script *AST_NewScript(void)
12 {
13         tAST_Script     *ret = malloc( sizeof(tAST_Script) );
14         
15         ret->Functions = NULL;
16         ret->LastFunction = NULL;
17         
18         return ret;
19 }
20
21 /**
22  * \brief Append a function to a script
23  */
24 tAST_Function *AST_AppendFunction(tAST_Script *Script, const char *Name)
25 {
26         tAST_Function   *ret;
27         
28         ret = malloc( sizeof(tAST_Function) + strlen(Name) + 1 );
29         ret->Next = NULL;
30         strcpy(ret->Name, Name);
31         ret->Code = NULL;
32         ret->Arguments = NULL;
33         
34         if(Script->LastFunction == NULL) {
35                 Script->Functions = Script->LastFunction = ret;
36         }
37         else {
38                 Script->LastFunction->Next = ret;
39                 Script->LastFunction = ret;
40         }
41         
42         return ret;
43 }
44
45 void AST_AppendFunctionArg(tAST_Function *Function, tAST_Node *Node)
46 {
47         if( !Function->Arguments ) {
48                 Function->Arguments_Last = Function->Arguments = Node;
49         }
50         else {
51                 Function->Arguments_Last->NextSibling = Node;
52                 Function->Arguments_Last = Node;
53         }
54 }
55
56 /**
57  * \brief Set the code for a function
58  */
59 void AST_SetFunctionCode(tAST_Function *Function, tAST_Node *Root)
60 {
61         Function->Code = Root;
62 }
63
64 /**
65  * \name Node Manipulation
66  * \{
67  */
68 /**
69  * \brief Free a node and all subnodes
70  */
71 void AST_FreeNode(tAST_Node *Node)
72 {
73         tAST_Node       *node;
74         switch(Node->Type)
75         {
76         // Block of code
77         case NODETYPE_BLOCK:
78                 for( node = Node->Block.FirstChild; node; )
79                 {
80                         tAST_Node       *savedNext = node->NextSibling;
81                         AST_FreeNode(node);
82                         node = savedNext;
83                 }
84                 break;
85         
86         // Function Call
87         case NODETYPE_FUNCTIONCALL:
88                 for( node = Node->FunctionCall.FirstArg; node; )
89                 {
90                         tAST_Node       *savedNext = node->NextSibling;
91                         AST_FreeNode(node);
92                         node = savedNext;
93                 }
94                 break;
95         
96         // Asignment
97         case NODETYPE_ASSIGN:
98                 AST_FreeNode(Node->Assign.Dest);
99                 AST_FreeNode(Node->Assign.Value);
100                 break;
101         
102         // Casting
103         case NODETYPE_CAST:
104                 AST_FreeNode(Node->Cast.Value);
105                 break;
106         
107         // Define a variable
108         case NODETYPE_DEFVAR:
109                 for( node = Node->DefVar.LevelSizes; node; )
110                 {
111                         tAST_Node       *savedNext = node->NextSibling;
112                         AST_FreeNode(node);
113                         node = savedNext;
114                 }
115                 break;
116         
117         // Unary Operations
118         case NODETYPE_RETURN:
119                 AST_FreeNode(Node->UniOp.Value);
120                 break;
121         
122         // Binary Operations
123         case NODETYPE_INDEX:
124         case NODETYPE_ADD:
125         case NODETYPE_SUBTRACT:
126         case NODETYPE_MULTIPLY:
127         case NODETYPE_DIVIDE:
128         case NODETYPE_MODULO:
129         case NODETYPE_BITSHIFTLEFT:
130         case NODETYPE_BITSHIFTRIGHT:
131         case NODETYPE_BITROTATELEFT:
132         case NODETYPE_BWAND:    case NODETYPE_LOGICALAND:
133         case NODETYPE_BWOR:     case NODETYPE_LOGICALOR:
134         case NODETYPE_BWXOR:    case NODETYPE_LOGICALXOR:
135         case NODETYPE_EQUALS:
136         case NODETYPE_LESSTHAN:
137         case NODETYPE_GREATERTHAN:
138                 AST_FreeNode( Node->BinOp.Left );
139                 AST_FreeNode( Node->BinOp.Right );
140                 break;
141         
142         // Node types with no children
143         case NODETYPE_NOP:      break;
144         case NODETYPE_VARIABLE: break;
145         case NODETYPE_CONSTANT: break;
146         case NODETYPE_STRING:   break;
147         case NODETYPE_INTEGER:  break;
148         case NODETYPE_REAL:     break;
149         }
150         free( Node );
151 }
152
153 tAST_Node *AST_NewCodeBlock(void)
154 {
155         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
156         
157         ret->NextSibling = NULL;
158         ret->Type = NODETYPE_BLOCK;
159         ret->Block.FirstChild = NULL;
160         ret->Block.LastChild = NULL;
161         
162         return ret;
163 }
164
165 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
166 {
167         Child->NextSibling = NULL;
168         switch( Parent->Type )
169         {
170         case NODETYPE_BLOCK:
171                 if(Parent->Block.FirstChild == NULL) {
172                         Parent->Block.FirstChild = Parent->Block.LastChild = Child;
173                 }
174                 else {
175                         Parent->Block.LastChild->NextSibling = Child;
176                         Parent->Block.LastChild = Child;
177                 }
178                 break;
179         case NODETYPE_DEFVAR:
180                 if(Parent->DefVar.LevelSizes == NULL) {
181                         Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
182                 }
183                 else {
184                         Parent->DefVar.LevelSizes_Last->NextSibling = Child;
185                         Parent->DefVar.LevelSizes_Last = Child;
186                 }
187                 break;
188         default:
189                 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
190                 break;
191         }
192 }
193
194 tAST_Node *AST_NewAssign(int Operation, tAST_Node *Dest, tAST_Node *Value)
195 {
196         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
197         
198         ret->NextSibling = NULL;
199         ret->Type = NODETYPE_ASSIGN;
200         ret->Assign.Operation = Operation;
201         ret->Assign.Dest = Dest;
202         ret->Assign.Value = Value;
203         
204         return ret;
205 }
206
207 tAST_Node *AST_NewBinOp(int Operation, tAST_Node *Left, tAST_Node *Right)
208 {
209         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
210         
211         ret->NextSibling = NULL;
212         ret->Type = Operation;
213         ret->BinOp.Left = Left;
214         ret->BinOp.Right = Right;
215         
216         return ret;
217 }
218
219 /**
220  */
221 tAST_Node *AST_NewUniOp(int Operation, tAST_Node *Value)
222 {
223         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
224         
225         ret->NextSibling = NULL;
226         ret->Type = Operation;
227         ret->UniOp.Value = Value;
228         
229         return ret;
230 }
231
232 /**
233  * \brief Create a new string node
234  */
235 tAST_Node *AST_NewString(const char *String, int Length)
236 {
237         tAST_Node       *ret = malloc( sizeof(tAST_Node) + Length + 1 );
238         
239         ret->NextSibling = NULL;
240         ret->Type = NODETYPE_STRING;
241         ret->String.Length = Length;
242         memcpy(ret->String.Data, String, Length);
243         ret->String.Data[Length] = '\0';
244         
245         return ret;
246 }
247
248 /**
249  * \brief Create a new integer node
250  */
251 tAST_Node *AST_NewInteger(uint64_t Value)
252 {
253         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
254         ret->NextSibling = NULL;
255         ret->Type = NODETYPE_INTEGER;
256         ret->Integer = Value;
257         return ret;
258 }
259
260 /**
261  * \brief Create a new variable reference node
262  */
263 tAST_Node *AST_NewVariable(const char *Name)
264 {
265         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
266         ret->NextSibling = NULL;
267         ret->Type = NODETYPE_VARIABLE;
268         strcpy(ret->Variable.Name, Name);
269         return ret;
270 }
271
272 /**
273  * \brief Create a new variable definition node
274  */
275 tAST_Node *AST_NewDefineVar(int Type, const char *Name)
276 {
277         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
278         ret->NextSibling = NULL;
279         ret->Type = NODETYPE_DEFVAR;
280         ret->DefVar.DataType = Type;
281         ret->DefVar.LevelSizes = NULL;
282         strcpy(ret->DefVar.Name, Name);
283         return ret;
284 }
285
286 /**
287  * \brief Create a new runtime constant reference node
288  */
289 tAST_Node *AST_NewConstant(const char *Name)
290 {
291         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
292         ret->NextSibling = NULL;
293         ret->Type = NODETYPE_CONSTANT;
294         strcpy(ret->Variable.Name, Name);
295         return ret;
296 }
297
298 /**
299  * \brief Create a function call node
300  * \note Argument list is manipulated using AST_AppendFunctionCallArg
301  */
302 tAST_Node *AST_NewFunctionCall(const char *Name)
303 {
304         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
305         
306         ret->NextSibling = NULL;
307         ret->Type = NODETYPE_FUNCTIONCALL;
308         ret->FunctionCall.FirstArg = NULL;
309         ret->FunctionCall.LastArg = NULL;
310         strcpy(ret->FunctionCall.Name, Name);
311         return ret;
312 }
313
314 /**
315  * \brief Append an argument to a function call
316  */
317 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
318 {
319         if( Node->Type != NODETYPE_FUNCTIONCALL )       return ;
320         
321         if(Node->FunctionCall.LastArg) {
322                 Node->FunctionCall.LastArg->NextSibling = Arg;
323                 Node->FunctionCall.LastArg = Arg;
324         }
325         else {
326                 Node->FunctionCall.FirstArg = Arg;
327                 Node->FunctionCall.LastArg = Arg;
328         }
329 }
330
331 /**
332  * \}
333  */

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