SpiderScript: String Casts, Escape Codes, Size for Opaque data types
[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->Line = giLineNumber;
177         ret->Type = NODETYPE_BLOCK;
178         ret->Block.FirstChild = NULL;
179         ret->Block.LastChild = NULL;
180         
181         return ret;
182 }
183
184 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
185 {
186         Child->NextSibling = NULL;
187         switch( Parent->Type )
188         {
189         case NODETYPE_BLOCK:
190                 if(Parent->Block.FirstChild == NULL) {
191                         Parent->Block.FirstChild = Parent->Block.LastChild = Child;
192                 }
193                 else {
194                         Parent->Block.LastChild->NextSibling = Child;
195                         Parent->Block.LastChild = Child;
196                 }
197                 break;
198         case NODETYPE_DEFVAR:
199                 if(Parent->DefVar.LevelSizes == NULL) {
200                         Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
201                 }
202                 else {
203                         Parent->DefVar.LevelSizes_Last->NextSibling = Child;
204                         Parent->DefVar.LevelSizes_Last = Child;
205                 }
206                 break;
207         default:
208                 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
209                 break;
210         }
211 }
212
213 tAST_Node *AST_NewIf(tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
214 {
215         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
216         ret->NextSibling = NULL;
217         //ret->Line = giLineNumber;
218         ret->Type = NODETYPE_IF;
219         ret->If.Condition = Condition;
220         ret->If.True = True;
221         ret->If.False = False;
222         return ret;
223 }
224
225 tAST_Node *AST_NewLoop(tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
226 {
227         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
228         ret->NextSibling = NULL;
229         //ret->Line = giLineNumber;
230         ret->Type = NODETYPE_LOOP;
231         ret->For.Init = Init;
232         ret->For.bCheckAfter = !!bPostCheck;
233         ret->For.Condition = Condition;
234         ret->For.Increment = Increment;
235         ret->For.Code = Code;
236         return ret;
237 }
238
239 tAST_Node *AST_NewAssign(int Operation, tAST_Node *Dest, tAST_Node *Value)
240 {
241         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
242         
243         ret->NextSibling = NULL;
244         //ret->Line = giLineNumber;
245         ret->Type = NODETYPE_ASSIGN;
246         ret->Assign.Operation = Operation;
247         ret->Assign.Dest = Dest;
248         ret->Assign.Value = Value;
249         
250         return ret;
251 }
252
253 tAST_Node *AST_NewCast(int Target, tAST_Node *Value)
254 {
255         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
256         
257         ret->NextSibling = NULL;
258         //ret->Line = giLineNumber;
259         ret->Type = NODETYPE_CAST;
260         ret->Cast.DataType = Target;
261         ret->Cast.Value = Value;
262         
263         return ret;
264 }
265
266 tAST_Node *AST_NewBinOp(int Operation, tAST_Node *Left, tAST_Node *Right)
267 {
268         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
269         
270         ret->NextSibling = NULL;
271         //ret->Line = giLineNumber;
272         ret->Type = Operation;
273         ret->BinOp.Left = Left;
274         ret->BinOp.Right = Right;
275         
276         return ret;
277 }
278
279 /**
280  */
281 tAST_Node *AST_NewUniOp(int Operation, tAST_Node *Value)
282 {
283         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
284         
285         ret->NextSibling = NULL;
286         //ret->Line = giLineNumber;
287         ret->Type = Operation;
288         ret->UniOp.Value = Value;
289         
290         return ret;
291 }
292
293 /**
294  * \brief Create a new string node
295  */
296 tAST_Node *AST_NewString(const char *String, int Length)
297 {
298         tAST_Node       *ret = malloc( sizeof(tAST_Node) + Length + 1 );
299         
300         ret->NextSibling = NULL;
301         //ret->Line = giLineNumber;
302         ret->Type = NODETYPE_STRING;
303         ret->String.Length = Length;
304         memcpy(ret->String.Data, String, Length);
305         ret->String.Data[Length] = '\0';
306         
307         return ret;
308 }
309
310 /**
311  * \brief Create a new integer node
312  */
313 tAST_Node *AST_NewInteger(uint64_t Value)
314 {
315         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
316         ret->NextSibling = NULL;
317         //ret->Line = giLineNumber;
318         ret->Type = NODETYPE_INTEGER;
319         ret->Integer = Value;
320         return ret;
321 }
322
323 /**
324  * \brief Create a new variable reference node
325  */
326 tAST_Node *AST_NewVariable(const char *Name)
327 {
328         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
329         ret->NextSibling = NULL;
330         //ret->Line = giLineNumber;
331         ret->Type = NODETYPE_VARIABLE;
332         strcpy(ret->Variable.Name, Name);
333         return ret;
334 }
335
336 /**
337  * \brief Create a new variable definition node
338  */
339 tAST_Node *AST_NewDefineVar(int Type, const char *Name)
340 {
341         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
342         ret->NextSibling = NULL;
343         //ret->Line = giLineNumber;
344         ret->Type = NODETYPE_DEFVAR;
345         ret->DefVar.DataType = Type;
346         ret->DefVar.LevelSizes = NULL;
347         strcpy(ret->DefVar.Name, Name);
348         return ret;
349 }
350
351 /**
352  * \brief Create a new runtime constant reference node
353  */
354 tAST_Node *AST_NewConstant(const char *Name)
355 {
356         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
357         ret->NextSibling = NULL;
358         //ret->Line = giLineNumber;
359         ret->Type = NODETYPE_CONSTANT;
360         strcpy(ret->Variable.Name, Name);
361         return ret;
362 }
363
364 /**
365  * \brief Create a function call node
366  * \note Argument list is manipulated using AST_AppendFunctionCallArg
367  */
368 tAST_Node *AST_NewFunctionCall(const char *Name)
369 {
370         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
371         
372         ret->NextSibling = NULL;
373         //ret->Line = giLineNumber;
374         ret->Type = NODETYPE_FUNCTIONCALL;
375         ret->FunctionCall.FirstArg = NULL;
376         ret->FunctionCall.LastArg = NULL;
377         strcpy(ret->FunctionCall.Name, Name);
378         return ret;
379 }
380
381 /**
382  * \brief Append an argument to a function call
383  */
384 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
385 {
386         if( Node->Type != NODETYPE_FUNCTIONCALL )       return ;
387         
388         if(Node->FunctionCall.LastArg) {
389                 Node->FunctionCall.LastArg->NextSibling = Arg;
390                 Node->FunctionCall.LastArg = Arg;
391         }
392         else {
393                 Node->FunctionCall.FirstArg = Arg;
394                 Node->FunctionCall.LastArg = Arg;
395         }
396 }
397
398 /**
399  * \}
400  */

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