Added if() statement (and internal support for for,while and do{}while())
[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         
75         if(!Node)       return ;
76         
77         switch(Node->Type)
78         {
79         // Block of code
80         case NODETYPE_BLOCK:
81                 for( node = Node->Block.FirstChild; node; )
82                 {
83                         tAST_Node       *savedNext = node->NextSibling;
84                         AST_FreeNode(node);
85                         node = savedNext;
86                 }
87                 break;
88         
89         // Function Call
90         case NODETYPE_FUNCTIONCALL:
91                 for( node = Node->FunctionCall.FirstArg; node; )
92                 {
93                         tAST_Node       *savedNext = node->NextSibling;
94                         AST_FreeNode(node);
95                         node = savedNext;
96                 }
97                 break;
98         
99         // If node
100         case NODETYPE_IF:
101                 AST_FreeNode(Node->If.Condition);
102                 AST_FreeNode(Node->If.True);
103                 AST_FreeNode(Node->If.False);
104                 break;
105         
106         // Looping Construct (For loop node)
107         case NODETYPE_LOOP:
108                 AST_FreeNode(Node->For.Init);
109                 AST_FreeNode(Node->For.Condition);
110                 AST_FreeNode(Node->For.Increment);
111                 AST_FreeNode(Node->For.Code);
112                 break;
113         
114         // Asignment
115         case NODETYPE_ASSIGN:
116                 AST_FreeNode(Node->Assign.Dest);
117                 AST_FreeNode(Node->Assign.Value);
118                 break;
119         
120         // Casting
121         case NODETYPE_CAST:
122                 AST_FreeNode(Node->Cast.Value);
123                 break;
124         
125         // Define a variable
126         case NODETYPE_DEFVAR:
127                 for( node = Node->DefVar.LevelSizes; node; )
128                 {
129                         tAST_Node       *savedNext = node->NextSibling;
130                         AST_FreeNode(node);
131                         node = savedNext;
132                 }
133                 break;
134         
135         // Unary Operations
136         case NODETYPE_RETURN:
137                 AST_FreeNode(Node->UniOp.Value);
138                 break;
139         
140         // Binary Operations
141         case NODETYPE_INDEX:
142         case NODETYPE_ADD:
143         case NODETYPE_SUBTRACT:
144         case NODETYPE_MULTIPLY:
145         case NODETYPE_DIVIDE:
146         case NODETYPE_MODULO:
147         case NODETYPE_BITSHIFTLEFT:
148         case NODETYPE_BITSHIFTRIGHT:
149         case NODETYPE_BITROTATELEFT:
150         case NODETYPE_BWAND:    case NODETYPE_LOGICALAND:
151         case NODETYPE_BWOR:     case NODETYPE_LOGICALOR:
152         case NODETYPE_BWXOR:    case NODETYPE_LOGICALXOR:
153         case NODETYPE_EQUALS:
154         case NODETYPE_LESSTHAN:
155         case NODETYPE_GREATERTHAN:
156                 AST_FreeNode( Node->BinOp.Left );
157                 AST_FreeNode( Node->BinOp.Right );
158                 break;
159         
160         // Node types with no children
161         case NODETYPE_NOP:      break;
162         case NODETYPE_VARIABLE: break;
163         case NODETYPE_CONSTANT: break;
164         case NODETYPE_STRING:   break;
165         case NODETYPE_INTEGER:  break;
166         case NODETYPE_REAL:     break;
167         }
168         free( Node );
169 }
170
171 tAST_Node *AST_NewCodeBlock(void)
172 {
173         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
174         
175         ret->NextSibling = NULL;
176         ret->Type = NODETYPE_BLOCK;
177         ret->Block.FirstChild = NULL;
178         ret->Block.LastChild = NULL;
179         
180         return ret;
181 }
182
183 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
184 {
185         Child->NextSibling = NULL;
186         switch( Parent->Type )
187         {
188         case NODETYPE_BLOCK:
189                 if(Parent->Block.FirstChild == NULL) {
190                         Parent->Block.FirstChild = Parent->Block.LastChild = Child;
191                 }
192                 else {
193                         Parent->Block.LastChild->NextSibling = Child;
194                         Parent->Block.LastChild = Child;
195                 }
196                 break;
197         case NODETYPE_DEFVAR:
198                 if(Parent->DefVar.LevelSizes == NULL) {
199                         Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
200                 }
201                 else {
202                         Parent->DefVar.LevelSizes_Last->NextSibling = Child;
203                         Parent->DefVar.LevelSizes_Last = Child;
204                 }
205                 break;
206         default:
207                 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
208                 break;
209         }
210 }
211
212 tAST_Node *AST_NewIf(tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
213 {
214         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
215         ret->NextSibling = NULL;
216         ret->Type = NODETYPE_IF;
217         ret->If.Condition = Condition;
218         ret->If.True = True;
219         ret->If.False = False;
220         return ret;
221 }
222
223 tAST_Node *AST_NewLoop(tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
224 {
225         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
226         ret->NextSibling = NULL;
227         ret->Type = NODETYPE_LOOP;
228         ret->For.Init = Init;
229         ret->For.bCheckAfter = !!bPostCheck;
230         ret->For.Condition = Condition;
231         ret->For.Increment = Increment;
232         ret->For.Code = Code;
233         return ret;
234 }
235
236 tAST_Node *AST_NewAssign(int Operation, tAST_Node *Dest, tAST_Node *Value)
237 {
238         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
239         
240         ret->NextSibling = NULL;
241         ret->Type = NODETYPE_ASSIGN;
242         ret->Assign.Operation = Operation;
243         ret->Assign.Dest = Dest;
244         ret->Assign.Value = Value;
245         
246         return ret;
247 }
248
249 tAST_Node *AST_NewBinOp(int Operation, tAST_Node *Left, tAST_Node *Right)
250 {
251         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
252         
253         ret->NextSibling = NULL;
254         ret->Type = Operation;
255         ret->BinOp.Left = Left;
256         ret->BinOp.Right = Right;
257         
258         return ret;
259 }
260
261 /**
262  */
263 tAST_Node *AST_NewUniOp(int Operation, tAST_Node *Value)
264 {
265         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
266         
267         ret->NextSibling = NULL;
268         ret->Type = Operation;
269         ret->UniOp.Value = Value;
270         
271         return ret;
272 }
273
274 /**
275  * \brief Create a new string node
276  */
277 tAST_Node *AST_NewString(const char *String, int Length)
278 {
279         tAST_Node       *ret = malloc( sizeof(tAST_Node) + Length + 1 );
280         
281         ret->NextSibling = NULL;
282         ret->Type = NODETYPE_STRING;
283         ret->String.Length = Length;
284         memcpy(ret->String.Data, String, Length);
285         ret->String.Data[Length] = '\0';
286         
287         return ret;
288 }
289
290 /**
291  * \brief Create a new integer node
292  */
293 tAST_Node *AST_NewInteger(uint64_t Value)
294 {
295         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
296         ret->NextSibling = NULL;
297         ret->Type = NODETYPE_INTEGER;
298         ret->Integer = Value;
299         return ret;
300 }
301
302 /**
303  * \brief Create a new variable reference node
304  */
305 tAST_Node *AST_NewVariable(const char *Name)
306 {
307         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
308         ret->NextSibling = NULL;
309         ret->Type = NODETYPE_VARIABLE;
310         strcpy(ret->Variable.Name, Name);
311         return ret;
312 }
313
314 /**
315  * \brief Create a new variable definition node
316  */
317 tAST_Node *AST_NewDefineVar(int Type, const char *Name)
318 {
319         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
320         ret->NextSibling = NULL;
321         ret->Type = NODETYPE_DEFVAR;
322         ret->DefVar.DataType = Type;
323         ret->DefVar.LevelSizes = NULL;
324         strcpy(ret->DefVar.Name, Name);
325         return ret;
326 }
327
328 /**
329  * \brief Create a new runtime constant reference node
330  */
331 tAST_Node *AST_NewConstant(const char *Name)
332 {
333         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
334         ret->NextSibling = NULL;
335         ret->Type = NODETYPE_CONSTANT;
336         strcpy(ret->Variable.Name, Name);
337         return ret;
338 }
339
340 /**
341  * \brief Create a function call node
342  * \note Argument list is manipulated using AST_AppendFunctionCallArg
343  */
344 tAST_Node *AST_NewFunctionCall(const char *Name)
345 {
346         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
347         
348         ret->NextSibling = NULL;
349         ret->Type = NODETYPE_FUNCTIONCALL;
350         ret->FunctionCall.FirstArg = NULL;
351         ret->FunctionCall.LastArg = NULL;
352         strcpy(ret->FunctionCall.Name, Name);
353         return ret;
354 }
355
356 /**
357  * \brief Append an argument to a function call
358  */
359 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
360 {
361         if( Node->Type != NODETYPE_FUNCTIONCALL )       return ;
362         
363         if(Node->FunctionCall.LastArg) {
364                 Node->FunctionCall.LastArg->NextSibling = Arg;
365                 Node->FunctionCall.LastArg = Arg;
366         }
367         else {
368                 Node->FunctionCall.FirstArg = Arg;
369                 Node->FunctionCall.LastArg = Arg;
370         }
371 }
372
373 /**
374  * \}
375  */

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