SpiderScript: Working on dumping the AST to disk
[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 Get the in-memory size of a node
70  */
71 size_t AST_GetNodeSize(tAST_Node *Node)
72 {
73         size_t  ret;
74         tAST_Node       *node;
75         
76         if(!Node)
77                 return 0;
78         
79         ret = sizeof(tAST_Node*) + sizeof(tAST_NodeType)
80                 + sizeof(const char *) + sizeof(int);
81         
82         switch(Node->Type)
83         {
84         // Block of code
85         case NODETYPE_BLOCK:
86                 ret += sizeof(Node->Block);
87                 for( node = Node->Block.FirstChild; node; )
88                 {
89                         ret += AST_GetNodeSize(node);
90                         node = node->NextSibling;
91                 }
92                 break;
93         
94         // Function Call
95         case NODETYPE_FUNCTIONCALL:
96                 ret += sizeof(Node->FunctionCall) + strlen(Node->FunctionCall.Name) + 1;
97                 for( node = Node->FunctionCall.FirstArg; node; )
98                 {
99                         ret += AST_GetNodeSize(node);
100                         node = node->NextSibling;
101                 }
102                 break;
103         
104         // If node
105         case NODETYPE_IF:
106                 ret += sizeof(Node->If);
107                 ret += AST_GetNodeSize(Node->If.Condition);
108                 ret += AST_GetNodeSize(Node->If.True);
109                 ret += AST_GetNodeSize(Node->If.False);
110                 break;
111         
112         // Looping Construct (For loop node)
113         case NODETYPE_LOOP:
114                 ret += sizeof(Node->For);
115                 ret += AST_GetNodeSize(Node->For.Init);
116                 ret += AST_GetNodeSize(Node->For.Condition);
117                 ret += AST_GetNodeSize(Node->For.Increment);
118                 ret += AST_GetNodeSize(Node->For.Code);
119                 break;
120         
121         // Asignment
122         case NODETYPE_ASSIGN:
123                 ret += sizeof(Node->Assign);
124                 ret += AST_GetNodeSize(Node->Assign.Dest);
125                 ret += AST_GetNodeSize(Node->Assign.Value);
126                 break;
127         
128         // Casting
129         case NODETYPE_CAST:
130                 ret += sizeof(Node->Cast);
131                 ret += AST_GetNodeSize(Node->Cast.Value);
132                 break;
133         
134         // Define a variable
135         case NODETYPE_DEFVAR:
136                 ret += sizeof(Node->DefVar) + strlen(Node->DefVar.Name) + 1;
137                 for( node = Node->DefVar.LevelSizes; node; )
138                 {
139                         ret += AST_GetNodeSize(node);
140                         node = node->NextSibling;
141                 }
142                 break;
143         
144         // Unary Operations
145         case NODETYPE_RETURN:
146                 ret += sizeof(Node->UniOp);
147                 ret += AST_GetNodeSize(Node->UniOp.Value);
148                 break;
149         
150         // Binary Operations
151         case NODETYPE_INDEX:
152         case NODETYPE_ADD:
153         case NODETYPE_SUBTRACT:
154         case NODETYPE_MULTIPLY:
155         case NODETYPE_DIVIDE:
156         case NODETYPE_MODULO:
157         case NODETYPE_BITSHIFTLEFT:
158         case NODETYPE_BITSHIFTRIGHT:
159         case NODETYPE_BITROTATELEFT:
160         case NODETYPE_BWAND:    case NODETYPE_LOGICALAND:
161         case NODETYPE_BWOR:     case NODETYPE_LOGICALOR:
162         case NODETYPE_BWXOR:    case NODETYPE_LOGICALXOR:
163         case NODETYPE_EQUALS:
164         case NODETYPE_LESSTHAN:
165         case NODETYPE_GREATERTHAN:
166                 ret += sizeof(Node->BinOp);
167                 ret += AST_GetNodeSize( Node->BinOp.Left );
168                 ret += AST_GetNodeSize( Node->BinOp.Right );
169                 break;
170         
171         // Node types with no children
172         case NODETYPE_NOP:
173                 break;
174         case NODETYPE_VARIABLE:
175         case NODETYPE_CONSTANT:
176                 ret += sizeof(Node->Variable) + strlen(Node->Variable.Name) + 1;
177                 break;
178         case NODETYPE_STRING:
179                 ret += sizeof(Node->String) + Node->String.Length;
180                 break;
181         case NODETYPE_INTEGER:
182                 ret += sizeof(Node->Integer);
183                 break;
184         case NODETYPE_REAL:
185                 ret += sizeof(Node->Real);
186                 break;
187         }
188         return ret;
189 }
190
191 /**
192  * \brief Write a node to a file
193  */
194 void AST_WriteNode(FILE *FP, tAST_Node *Node)
195 {
196         tAST_Node       *node;
197         intptr_t        ptr;
198         
199         if(!Node)       return ;
200         
201         ptr = ftell(FP) + AST_GetNodeSize(Node);
202         fwrite(&ptr, sizeof(ptr), 1, FP);
203         fwrite(&Node->Type, sizeof(Node->Type), 1, FP);
204         ptr = 0;        fwrite(&ptr, sizeof(ptr), 1, FP);       // File
205         fwrite(&Node->Line, sizeof(Node->Line), 1, FP);
206         
207         ret = sizeof(tAST_Node*) + sizeof(tAST_NodeType)
208                 + sizeof(const char *) + sizeof(int);
209         
210         switch(Node->Type)
211         {
212         // Block of code
213         case NODETYPE_BLOCK:
214                 ret += sizeof(Node->Block);
215                 for( node = Node->Block.FirstChild; node; )
216                 {
217                         ret += AST_GetNodeSize(node);
218                         node = node->NextSibling;
219                 }
220                 break;
221         
222         // Function Call
223         case NODETYPE_FUNCTIONCALL:
224                 ret += sizeof(Node->FunctionCall) + strlen(Node->FunctionCall.Name) + 1;
225                 for( node = Node->FunctionCall.FirstArg; node; )
226                 {
227                         ret += AST_GetNodeSize(node);
228                         node = node->NextSibling;
229                 }
230                 break;
231         
232         // If node
233         case NODETYPE_IF:
234                 ret += sizeof(Node->If);
235                 ret += AST_GetNodeSize(Node->If.Condition);
236                 ret += AST_GetNodeSize(Node->If.True);
237                 ret += AST_GetNodeSize(Node->If.False);
238                 break;
239         
240         // Looping Construct (For loop node)
241         case NODETYPE_LOOP:
242                 ret += sizeof(Node->For);
243                 ret += AST_GetNodeSize(Node->For.Init);
244                 ret += AST_GetNodeSize(Node->For.Condition);
245                 ret += AST_GetNodeSize(Node->For.Increment);
246                 ret += AST_GetNodeSize(Node->For.Code);
247                 break;
248         
249         // Asignment
250         case NODETYPE_ASSIGN:
251                 ret += sizeof(Node->Assign);
252                 ret += AST_GetNodeSize(Node->Assign.Dest);
253                 ret += AST_GetNodeSize(Node->Assign.Value);
254                 break;
255         
256         // Casting
257         case NODETYPE_CAST:
258                 ret += sizeof(Node->Cast);
259                 ret += AST_GetNodeSize(Node->Cast.Value);
260                 break;
261         
262         // Define a variable
263         case NODETYPE_DEFVAR:
264                 ret += sizeof(Node->DefVar) + strlen(Node->DefVar.Name) + 1;
265                 for( node = Node->DefVar.LevelSizes; node; )
266                 {
267                         ret += AST_GetNodeSize(node);
268                         node = node->NextSibling;
269                 }
270                 break;
271         
272         // Unary Operations
273         case NODETYPE_RETURN:
274                 ret += sizeof(Node->UniOp);
275                 ret += AST_GetNodeSize(Node->UniOp.Value);
276                 break;
277         
278         // Binary Operations
279         case NODETYPE_INDEX:
280         case NODETYPE_ADD:
281         case NODETYPE_SUBTRACT:
282         case NODETYPE_MULTIPLY:
283         case NODETYPE_DIVIDE:
284         case NODETYPE_MODULO:
285         case NODETYPE_BITSHIFTLEFT:
286         case NODETYPE_BITSHIFTRIGHT:
287         case NODETYPE_BITROTATELEFT:
288         case NODETYPE_BWAND:    case NODETYPE_LOGICALAND:
289         case NODETYPE_BWOR:     case NODETYPE_LOGICALOR:
290         case NODETYPE_BWXOR:    case NODETYPE_LOGICALXOR:
291         case NODETYPE_EQUALS:
292         case NODETYPE_LESSTHAN:
293         case NODETYPE_GREATERTHAN:
294                 ret += sizeof(Node->BinOp);
295                 ret += AST_GetNodeSize( Node->BinOp.Left );
296                 ret += AST_GetNodeSize( Node->BinOp.Right );
297                 break;
298         
299         // Node types with no children
300         case NODETYPE_NOP:
301                 break;
302         case NODETYPE_VARIABLE:
303         case NODETYPE_CONSTANT:
304                 ret += sizeof(Node->Variable) + strlen(Node->Variable.Name) + 1;
305                 break;
306         case NODETYPE_STRING:
307                 ret += sizeof(Node->String) + Node->String.Length;
308                 break;
309         case NODETYPE_INTEGER:
310                 ret += sizeof(Node->Integer);
311                 break;
312         case NODETYPE_REAL:
313                 ret += sizeof(Node->Real);
314                 break;
315         }
316         return ret;
317 }
318
319 /**
320  * \brief Free a node and all subnodes
321  */
322 void AST_FreeNode(tAST_Node *Node)
323 {
324         tAST_Node       *node;
325         
326         if(!Node)       return ;
327         
328         switch(Node->Type)
329         {
330         // Block of code
331         case NODETYPE_BLOCK:
332                 for( node = Node->Block.FirstChild; node; )
333                 {
334                         tAST_Node       *savedNext = node->NextSibling;
335                         AST_FreeNode(node);
336                         node = savedNext;
337                 }
338                 break;
339         
340         // Function Call
341         case NODETYPE_FUNCTIONCALL:
342                 for( node = Node->FunctionCall.FirstArg; node; )
343                 {
344                         tAST_Node       *savedNext = node->NextSibling;
345                         AST_FreeNode(node);
346                         node = savedNext;
347                 }
348                 break;
349         
350         // If node
351         case NODETYPE_IF:
352                 AST_FreeNode(Node->If.Condition);
353                 AST_FreeNode(Node->If.True);
354                 AST_FreeNode(Node->If.False);
355                 break;
356         
357         // Looping Construct (For loop node)
358         case NODETYPE_LOOP:
359                 AST_FreeNode(Node->For.Init);
360                 AST_FreeNode(Node->For.Condition);
361                 AST_FreeNode(Node->For.Increment);
362                 AST_FreeNode(Node->For.Code);
363                 break;
364         
365         // Asignment
366         case NODETYPE_ASSIGN:
367                 AST_FreeNode(Node->Assign.Dest);
368                 AST_FreeNode(Node->Assign.Value);
369                 break;
370         
371         // Casting
372         case NODETYPE_CAST:
373                 AST_FreeNode(Node->Cast.Value);
374                 break;
375         
376         // Define a variable
377         case NODETYPE_DEFVAR:
378                 for( node = Node->DefVar.LevelSizes; node; )
379                 {
380                         tAST_Node       *savedNext = node->NextSibling;
381                         AST_FreeNode(node);
382                         node = savedNext;
383                 }
384                 break;
385         
386         // Unary Operations
387         case NODETYPE_RETURN:
388                 AST_FreeNode(Node->UniOp.Value);
389                 break;
390         
391         // Binary Operations
392         case NODETYPE_INDEX:
393         case NODETYPE_ADD:
394         case NODETYPE_SUBTRACT:
395         case NODETYPE_MULTIPLY:
396         case NODETYPE_DIVIDE:
397         case NODETYPE_MODULO:
398         case NODETYPE_BITSHIFTLEFT:
399         case NODETYPE_BITSHIFTRIGHT:
400         case NODETYPE_BITROTATELEFT:
401         case NODETYPE_BWAND:    case NODETYPE_LOGICALAND:
402         case NODETYPE_BWOR:     case NODETYPE_LOGICALOR:
403         case NODETYPE_BWXOR:    case NODETYPE_LOGICALXOR:
404         case NODETYPE_EQUALS:
405         case NODETYPE_LESSTHAN:
406         case NODETYPE_GREATERTHAN:
407                 AST_FreeNode( Node->BinOp.Left );
408                 AST_FreeNode( Node->BinOp.Right );
409                 break;
410         
411         // Node types with no children
412         case NODETYPE_NOP:      break;
413         case NODETYPE_VARIABLE: break;
414         case NODETYPE_CONSTANT: break;
415         case NODETYPE_STRING:   break;
416         case NODETYPE_INTEGER:  break;
417         case NODETYPE_REAL:     break;
418         }
419         free( Node );
420 }
421
422 tAST_Node *AST_NewCodeBlock(void)
423 {
424         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
425         
426         ret->NextSibling = NULL;
427         //ret->Line = Parser->CurLine;
428         ret->Type = NODETYPE_BLOCK;
429         ret->Block.FirstChild = NULL;
430         ret->Block.LastChild = NULL;
431         
432         return ret;
433 }
434
435 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
436 {
437         Child->NextSibling = NULL;
438         switch( Parent->Type )
439         {
440         case NODETYPE_BLOCK:
441                 if(Parent->Block.FirstChild == NULL) {
442                         Parent->Block.FirstChild = Parent->Block.LastChild = Child;
443                 }
444                 else {
445                         Parent->Block.LastChild->NextSibling = Child;
446                         Parent->Block.LastChild = Child;
447                 }
448                 break;
449         case NODETYPE_DEFVAR:
450                 if(Parent->DefVar.LevelSizes == NULL) {
451                         Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
452                 }
453                 else {
454                         Parent->DefVar.LevelSizes_Last->NextSibling = Child;
455                         Parent->DefVar.LevelSizes_Last = Child;
456                 }
457                 break;
458         default:
459                 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
460                 break;
461         }
462 }
463
464 tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
465 {
466         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
467         ret->NextSibling = NULL;
468         ret->Line = Parser->CurLine;
469         ret->Type = NODETYPE_IF;
470         ret->If.Condition = Condition;
471         ret->If.True = True;
472         ret->If.False = False;
473         return ret;
474 }
475
476 tAST_Node *AST_NewLoop(tParser *Parser, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
477 {
478         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
479         ret->NextSibling = NULL;
480         ret->Line = Parser->CurLine;
481         ret->Type = NODETYPE_LOOP;
482         ret->For.Init = Init;
483         ret->For.bCheckAfter = !!bPostCheck;
484         ret->For.Condition = Condition;
485         ret->For.Increment = Increment;
486         ret->For.Code = Code;
487         return ret;
488 }
489
490 tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value)
491 {
492         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
493         
494         ret->NextSibling = NULL;
495         ret->Line = Parser->CurLine;
496         ret->Type = NODETYPE_ASSIGN;
497         ret->Assign.Operation = Operation;
498         ret->Assign.Dest = Dest;
499         ret->Assign.Value = Value;
500         
501         return ret;
502 }
503
504 tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value)
505 {
506         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
507         
508         ret->NextSibling = NULL;
509         ret->Line = Parser->CurLine;
510         ret->Type = NODETYPE_CAST;
511         ret->Cast.DataType = Target;
512         ret->Cast.Value = Value;
513         
514         return ret;
515 }
516
517 tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right)
518 {
519         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
520         
521         ret->NextSibling = NULL;
522         ret->Line = Parser->CurLine;
523         ret->Type = Operation;
524         ret->BinOp.Left = Left;
525         ret->BinOp.Right = Right;
526         
527         return ret;
528 }
529
530 /**
531  */
532 tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value)
533 {
534         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
535         
536         ret->NextSibling = NULL;
537         ret->Line = Parser->CurLine;
538         ret->Type = Operation;
539         ret->UniOp.Value = Value;
540         
541         return ret;
542 }
543
544 /**
545  * \brief Create a new string node
546  */
547 tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length)
548 {
549         tAST_Node       *ret = malloc( sizeof(tAST_Node) + Length + 1 );
550         
551         ret->NextSibling = NULL;
552         ret->Line = Parser->CurLine;
553         ret->Type = NODETYPE_STRING;
554         ret->String.Length = Length;
555         memcpy(ret->String.Data, String, Length);
556         ret->String.Data[Length] = '\0';
557         
558         return ret;
559 }
560
561 /**
562  * \brief Create a new integer node
563  */
564 tAST_Node *AST_NewInteger(tParser *Parser, uint64_t Value)
565 {
566         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
567         ret->NextSibling = NULL;
568         ret->Line = Parser->CurLine;
569         ret->Type = NODETYPE_INTEGER;
570         ret->Integer = Value;
571         return ret;
572 }
573
574 /**
575  * \brief Create a new variable reference node
576  */
577 tAST_Node *AST_NewVariable(tParser *Parser, const char *Name)
578 {
579         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
580         ret->NextSibling = NULL;
581         ret->Line = Parser->CurLine;
582         ret->Type = NODETYPE_VARIABLE;
583         strcpy(ret->Variable.Name, Name);
584         return ret;
585 }
586
587 /**
588  * \brief Create a new variable definition node
589  */
590 tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name)
591 {
592         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
593         ret->NextSibling = NULL;
594         ret->Line = Parser->CurLine;
595         ret->Type = NODETYPE_DEFVAR;
596         ret->DefVar.DataType = Type;
597         ret->DefVar.LevelSizes = NULL;
598         strcpy(ret->DefVar.Name, Name);
599         return ret;
600 }
601
602 /**
603  * \brief Create a new runtime constant reference node
604  */
605 tAST_Node *AST_NewConstant(tParser *Parser, const char *Name)
606 {
607         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
608         ret->NextSibling = NULL;
609         ret->Line = Parser->CurLine;
610         ret->Type = NODETYPE_CONSTANT;
611         strcpy(ret->Variable.Name, Name);
612         return ret;
613 }
614
615 /**
616  * \brief Create a function call node
617  * \note Argument list is manipulated using AST_AppendFunctionCallArg
618  */
619 tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name)
620 {
621         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
622         
623         ret->NextSibling = NULL;
624         ret->Line = Parser->CurLine;
625         ret->Type = NODETYPE_FUNCTIONCALL;
626         ret->FunctionCall.FirstArg = NULL;
627         ret->FunctionCall.LastArg = NULL;
628         strcpy(ret->FunctionCall.Name, Name);
629         return ret;
630 }
631
632 /**
633  * \brief Append an argument to a function call
634  */
635 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
636 {
637         if( Node->Type != NODETYPE_FUNCTIONCALL )       return ;
638         
639         if(Node->FunctionCall.LastArg) {
640                 Node->FunctionCall.LastArg->NextSibling = Arg;
641                 Node->FunctionCall.LastArg = Arg;
642         }
643         else {
644                 Node->FunctionCall.FirstArg = Arg;
645                 Node->FunctionCall.LastArg = Arg;
646         }
647 }
648
649 /**
650  * \}
651  */

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