SpiderScript - A day of debugging and improvements
[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 #if 1
192
193 #define WRITE_N(_buffer, _offset, _len, _dataptr) do { \
194         if(_buffer)     memcpy((char*)_buffer + _offset, _dataptr, _len);\
195         _offset += _len; \
196 } while(0)
197
198 #define WRITE_8(_buffer, _offset, _val) do {\
199         uint8_t v = (_val);\
200         WRITE_N(_buffer, _offset, 1, &v);\
201 } while(0)
202 #define WRITE_16(_buffer, _offset, _val) do {\
203         uint16_t        v = (_val);\
204         WRITE_N(_buffer, _offset, 2, &v);\
205 } while(0)
206 #define WRITE_32(_buffer, _offset, _val) do {\
207         uint32_t        v = (_val);\
208         WRITE_N(_buffer, _offset, 4, &v);\
209 } while(0)
210 #define WRITE_64(_buffer, _offset, _val) do {\
211         uint64_t        v = (_val);\
212         WRITE_N(_buffer, _offset, 8, &v);\
213 } while(0)
214 #define WRITE_REAL(_buffer, _offset, _val) do {\
215         double  v = (_val);\
216         WRITE_N(_buffer, _offset, sizeof(double), &v);\
217 } while(0)
218
219 #define WRITE_STR(_buffer, _offset, _string) do {\
220         int len = strlen(_string);\
221         WRITE_16(_buffer, _offset, len);\
222         WRITE_N(_buffer, _offset, len, _string);\
223 } while(0)
224 #define WRITE_NODELIST(_buffer, _offset, _listHead)     do {\
225         tAST_Node *node; \
226         size_t ptr = -1;\
227         for(node=(_listHead); node; node = node->NextSibling) {\
228                 ptr = _offset;\
229                 _offset += AST_WriteNode(_buffer, _offset, node); \
230                 WRITE_32(_buffer, ptr, ptr); \
231         } \
232         if(ptr != -1){ptr -= 4; WRITE_32(_buffer, ptr, 0);} \
233 } while(0)
234
235 /**
236  * \brief Writes a script dump to a buffer
237  * \return Size of encoded data
238  * \note If \a Buffer is NULL, no write is done, but the size is still returned
239  */
240 size_t AST_WriteScript(void *Buffer, tAST_Script *Script)
241 {
242         tAST_Function   *fcn;
243         size_t  ret = 0, ptr;
244         
245         for( fcn = Script->Functions; fcn; fcn = fcn->Next )
246         {
247                 ptr = ret;
248                 WRITE_32(Buffer, ret, 0);       // Next
249                 WRITE_STR(Buffer, ret, fcn->Name);
250                 WRITE_NODELIST(Buffer, ret, fcn->Arguments);    // TODO: Cheaper way
251                 ret += AST_WriteNode(Buffer, ret, fcn->Code);
252                 WRITE_32(Buffer, ptr, ret);     // Actually set next
253         }
254         ptr -= 4;
255         WRITE_32(Buffer, ptr, 0);       // Clear next for final
256         
257         return ret;
258 }
259
260 /**
261  * \brief Write a node to a file
262  */
263 size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node)
264 {
265         off_t   ptr;
266         typeof(Offset)  baseOfs = Offset;
267         
268         if(!Node) {
269                 fprintf(stderr, "Possible Bug - NULL passed to AST_WriteNode\n");
270                 return 0;
271         }
272         
273         WRITE_32(Buffer, Offset, 0);    // Next
274         WRITE_8(Buffer, Offset, Node->Type);
275         //WRITE_32(Buffer, Offset, 0);  // File
276         WRITE_16(Buffer, Offset, Node->Line);   // Line
277         
278         switch(Node->Type)
279         {
280         // Block of code
281         case NODETYPE_BLOCK:
282                 WRITE_NODELIST(Buffer, Offset, Node->Block.FirstChild);
283                 break;
284         
285         // Function Call
286         case NODETYPE_FUNCTIONCALL:
287                 WRITE_STR(Buffer, Offset, Node->FunctionCall.Name);
288                 WRITE_NODELIST(Buffer, Offset, Node->FunctionCall.FirstArg);
289                 break;
290         
291         // If node
292         case NODETYPE_IF:
293                 ptr = Offset;
294                 WRITE_32(Buffer, Offset, 0);    // Condition
295                 WRITE_32(Buffer, Offset, 0);    // True
296                 WRITE_32(Buffer, Offset, 0);    // False
297                 
298                 Offset += AST_WriteNode(Buffer, Offset, Node->If.Condition);
299                 WRITE_32(Buffer, ptr, Offset);
300                 Offset += AST_WriteNode(Buffer, Offset, Node->If.True);
301                 WRITE_32(Buffer, ptr, Offset);
302                 Offset += AST_WriteNode(Buffer, Offset, Node->If.False);
303                 WRITE_32(Buffer, ptr, Offset);
304                 break;
305         
306         // Looping Construct (For loop node)
307         case NODETYPE_LOOP:
308                 WRITE_8(Buffer, Offset, Node->For.bCheckAfter);
309                 ptr = Offset;
310                 WRITE_32(Buffer, Offset, 0);    // Init
311                 WRITE_32(Buffer, Offset, 0);    // Condition
312                 WRITE_32(Buffer, Offset, 0);    // Increment
313                 WRITE_32(Buffer, Offset, 0);    // Code
314                 
315                 Offset += AST_WriteNode(Buffer, Offset, Node->For.Init);
316                 WRITE_32(Buffer, ptr, Offset);
317                 Offset += AST_WriteNode(Buffer, Offset, Node->For.Condition);
318                 WRITE_32(Buffer, ptr, Offset);
319                 Offset += AST_WriteNode(Buffer, Offset, Node->For.Increment);
320                 WRITE_32(Buffer, ptr, Offset);
321                 Offset += AST_WriteNode(Buffer, Offset, Node->For.Code);
322                 WRITE_32(Buffer, ptr, Offset);
323                 break;
324         
325         // Asignment
326         case NODETYPE_ASSIGN:
327                 WRITE_8(Buffer, Offset, Node->Assign.Operation);
328                 ptr = Offset;
329                 WRITE_32(Buffer, Offset, 0);    // Dest
330                 WRITE_32(Buffer, Offset, 0);    // Value
331                 
332                 Offset += AST_WriteNode(Buffer, Offset, Node->Assign.Dest);
333                 WRITE_32(Buffer, ptr, Offset);
334                 Offset += AST_WriteNode(Buffer, Offset, Node->Assign.Value);
335                 WRITE_32(Buffer, ptr, Offset);
336                 break;
337         
338         // Casting
339         case NODETYPE_CAST:
340                 WRITE_8(Buffer, Offset, Node->Cast.DataType);
341                 ptr = Offset;
342                 WRITE_32(Buffer, Offset, 0);
343                 
344                 Offset += AST_WriteNode(Buffer, Offset, Node->Cast.Value);
345                 WRITE_32(Buffer, ptr, Offset);
346                 break;
347         
348         // Define a variable
349         case NODETYPE_DEFVAR:
350                 WRITE_8(Buffer, Offset, Node->DefVar.DataType);
351                 WRITE_8(Buffer, Offset, Node->DefVar.Depth);
352                 WRITE_STR(Buffer, Offset, Node->DefVar.Name);
353                 
354                 WRITE_NODELIST(Buffer, Offset, Node->DefVar.LevelSizes);
355                 break;
356         
357         // Unary Operations
358         case NODETYPE_RETURN:
359                 ptr = Offset;
360                 WRITE_32(Buffer, Offset, 0);
361                 Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value);
362                 WRITE_32(Buffer, ptr, Offset);
363                 break;
364         
365         // Binary Operations
366         case NODETYPE_INDEX:
367         case NODETYPE_ADD:
368         case NODETYPE_SUBTRACT:
369         case NODETYPE_MULTIPLY:
370         case NODETYPE_DIVIDE:
371         case NODETYPE_MODULO:
372         case NODETYPE_BITSHIFTLEFT:
373         case NODETYPE_BITSHIFTRIGHT:
374         case NODETYPE_BITROTATELEFT:
375         case NODETYPE_BWAND:    case NODETYPE_LOGICALAND:
376         case NODETYPE_BWOR:     case NODETYPE_LOGICALOR:
377         case NODETYPE_BWXOR:    case NODETYPE_LOGICALXOR:
378         case NODETYPE_EQUALS:
379         case NODETYPE_LESSTHAN:
380         case NODETYPE_GREATERTHAN:
381                 ptr = Offset;
382                 WRITE_32(Buffer, Offset, 0);    // Left
383                 WRITE_32(Buffer, Offset, 0);    // Right
384                 Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Left);
385                 WRITE_32(Buffer, ptr, Offset);
386                 Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Right);
387                 WRITE_32(Buffer, ptr, Offset);
388                 break;
389         
390         // Node types with no children
391         case NODETYPE_NOP:
392                 break;
393         case NODETYPE_VARIABLE:
394         case NODETYPE_CONSTANT:
395                 WRITE_STR(Buffer, Offset, Node->Variable.Name);
396                 break;
397         case NODETYPE_STRING:
398                 WRITE_32(Buffer, Offset, Node->String.Length);
399                 WRITE_N(Buffer, Offset, Node->String.Length, Node->String.Data);
400                 break;
401         case NODETYPE_INTEGER:
402                 WRITE_64(Buffer, Offset, Node->Integer);
403                 break;
404         case NODETYPE_REAL:
405                 WRITE_REAL(Buffer, Offset, Node->Real);
406                 break;
407         
408         default:
409                 fprintf(stderr, "AST_WriteNode: Unknown node type %i\n", Node->Type);
410                 break;
411         }
412         
413         return Offset - baseOfs;
414 }
415 #elif 0
416 /**
417  * \brief Write a node to a file
418  */
419 void AST_WriteNode(FILE *FP, tAST_Node *Node)
420 {
421         tAST_Node       *node;
422         intptr_t        ptr;
423          int    ret;
424         
425         if(!Node)       return ;
426         
427         ptr = ftell(FP) + AST_GetNodeSize(Node);
428         fwrite(&ptr, sizeof(ptr), 1, FP);
429         fwrite(&Node->Type, sizeof(Node->Type), 1, FP);
430         ptr = 0;        fwrite(&ptr, sizeof(ptr), 1, FP);       // File
431         fwrite(&Node->Line, sizeof(Node->Line), 1, FP);
432         
433         ret = sizeof(tAST_Node*) + sizeof(tAST_NodeType)
434                 + sizeof(const char *) + sizeof(int);
435         
436         switch(Node->Type)
437         {
438         // Block of code
439         case NODETYPE_BLOCK:
440                 ret += sizeof(Node->Block);
441                 for( node = Node->Block.FirstChild; node; )
442                 {
443                         ret += AST_GetNodeSize(node);
444                         node = node->NextSibling;
445                 }
446                 break;
447         
448         // Function Call
449         case NODETYPE_FUNCTIONCALL:
450                 ret += sizeof(Node->FunctionCall) + strlen(Node->FunctionCall.Name) + 1;
451                 for( node = Node->FunctionCall.FirstArg; node; )
452                 {
453                         ret += AST_GetNodeSize(node);
454                         node = node->NextSibling;
455                 }
456                 break;
457         
458         // If node
459         case NODETYPE_IF:
460                 ret += sizeof(Node->If);
461                 ret += AST_GetNodeSize(Node->If.Condition);
462                 ret += AST_GetNodeSize(Node->If.True);
463                 ret += AST_GetNodeSize(Node->If.False);
464                 break;
465         
466         // Looping Construct (For loop node)
467         case NODETYPE_LOOP:
468                 ret += sizeof(Node->For);
469                 ret += AST_GetNodeSize(Node->For.Init);
470                 ret += AST_GetNodeSize(Node->For.Condition);
471                 ret += AST_GetNodeSize(Node->For.Increment);
472                 ret += AST_GetNodeSize(Node->For.Code);
473                 break;
474         
475         // Asignment
476         case NODETYPE_ASSIGN:
477                 ret += sizeof(Node->Assign);
478                 ret += AST_GetNodeSize(Node->Assign.Dest);
479                 ret += AST_GetNodeSize(Node->Assign.Value);
480                 break;
481         
482         // Casting
483         case NODETYPE_CAST:
484                 ret += sizeof(Node->Cast);
485                 ret += AST_GetNodeSize(Node->Cast.Value);
486                 break;
487         
488         // Define a variable
489         case NODETYPE_DEFVAR:
490                 ret += sizeof(Node->DefVar) + strlen(Node->DefVar.Name) + 1;
491                 for( node = Node->DefVar.LevelSizes; node; )
492                 {
493                         ret += AST_GetNodeSize(node);
494                         node = node->NextSibling;
495                 }
496                 break;
497         
498         // Unary Operations
499         case NODETYPE_RETURN:
500                 ret += sizeof(Node->UniOp);
501                 ret += AST_GetNodeSize(Node->UniOp.Value);
502                 break;
503         
504         // Binary Operations
505         case NODETYPE_INDEX:
506         case NODETYPE_ADD:
507         case NODETYPE_SUBTRACT:
508         case NODETYPE_MULTIPLY:
509         case NODETYPE_DIVIDE:
510         case NODETYPE_MODULO:
511         case NODETYPE_BITSHIFTLEFT:
512         case NODETYPE_BITSHIFTRIGHT:
513         case NODETYPE_BITROTATELEFT:
514         case NODETYPE_BWAND:    case NODETYPE_LOGICALAND:
515         case NODETYPE_BWOR:     case NODETYPE_LOGICALOR:
516         case NODETYPE_BWXOR:    case NODETYPE_LOGICALXOR:
517         case NODETYPE_EQUALS:
518         case NODETYPE_LESSTHAN:
519         case NODETYPE_GREATERTHAN:
520                 ret += sizeof(Node->BinOp);
521                 ret += AST_GetNodeSize( Node->BinOp.Left );
522                 ret += AST_GetNodeSize( Node->BinOp.Right );
523                 break;
524         
525         // Node types with no children
526         case NODETYPE_NOP:
527                 break;
528         case NODETYPE_VARIABLE:
529         case NODETYPE_CONSTANT:
530                 ret += sizeof(Node->Variable) + strlen(Node->Variable.Name) + 1;
531                 break;
532         case NODETYPE_STRING:
533                 ret += sizeof(Node->String) + Node->String.Length;
534                 break;
535         case NODETYPE_INTEGER:
536                 ret += sizeof(Node->Integer);
537                 break;
538         case NODETYPE_REAL:
539                 ret += sizeof(Node->Real);
540                 break;
541         }
542         return ret;
543 }
544 #endif
545
546 /**
547  * \brief Free a node and all subnodes
548  */
549 void AST_FreeNode(tAST_Node *Node)
550 {
551         tAST_Node       *node;
552         
553         if(!Node)       return ;
554         
555         switch(Node->Type)
556         {
557         // Block of code
558         case NODETYPE_BLOCK:
559                 for( node = Node->Block.FirstChild; node; )
560                 {
561                         tAST_Node       *savedNext = node->NextSibling;
562                         AST_FreeNode(node);
563                         node = savedNext;
564                 }
565                 break;
566         
567         // Function Call
568         case NODETYPE_FUNCTIONCALL:
569                 for( node = Node->FunctionCall.FirstArg; node; )
570                 {
571                         tAST_Node       *savedNext = node->NextSibling;
572                         AST_FreeNode(node);
573                         node = savedNext;
574                 }
575                 break;
576         
577         // If node
578         case NODETYPE_IF:
579                 AST_FreeNode(Node->If.Condition);
580                 AST_FreeNode(Node->If.True);
581                 AST_FreeNode(Node->If.False);
582                 break;
583         
584         // Looping Construct (For loop node)
585         case NODETYPE_LOOP:
586                 AST_FreeNode(Node->For.Init);
587                 AST_FreeNode(Node->For.Condition);
588                 AST_FreeNode(Node->For.Increment);
589                 AST_FreeNode(Node->For.Code);
590                 break;
591         
592         // Asignment
593         case NODETYPE_ASSIGN:
594                 AST_FreeNode(Node->Assign.Dest);
595                 AST_FreeNode(Node->Assign.Value);
596                 break;
597         
598         // Casting
599         case NODETYPE_CAST:
600                 AST_FreeNode(Node->Cast.Value);
601                 break;
602         
603         // Define a variable
604         case NODETYPE_DEFVAR:
605                 for( node = Node->DefVar.LevelSizes; node; )
606                 {
607                         tAST_Node       *savedNext = node->NextSibling;
608                         AST_FreeNode(node);
609                         node = savedNext;
610                 }
611                 break;
612         
613         // Unary Operations
614         case NODETYPE_RETURN:
615                 AST_FreeNode(Node->UniOp.Value);
616                 break;
617         
618         // Binary Operations
619         case NODETYPE_INDEX:
620         case NODETYPE_ADD:
621         case NODETYPE_SUBTRACT:
622         case NODETYPE_MULTIPLY:
623         case NODETYPE_DIVIDE:
624         case NODETYPE_MODULO:
625         case NODETYPE_BITSHIFTLEFT:
626         case NODETYPE_BITSHIFTRIGHT:
627         case NODETYPE_BITROTATELEFT:
628         case NODETYPE_BWAND:    case NODETYPE_LOGICALAND:
629         case NODETYPE_BWOR:     case NODETYPE_LOGICALOR:
630         case NODETYPE_BWXOR:    case NODETYPE_LOGICALXOR:
631         case NODETYPE_EQUALS:
632         case NODETYPE_LESSTHAN:
633         case NODETYPE_GREATERTHAN:
634                 AST_FreeNode( Node->BinOp.Left );
635                 AST_FreeNode( Node->BinOp.Right );
636                 break;
637         
638         // Node types with no children
639         case NODETYPE_NOP:      break;
640         case NODETYPE_VARIABLE: break;
641         case NODETYPE_CONSTANT: break;
642         case NODETYPE_STRING:   break;
643         case NODETYPE_INTEGER:  break;
644         case NODETYPE_REAL:     break;
645         }
646         free( Node );
647 }
648
649 tAST_Node *AST_NewCodeBlock(void)
650 {
651         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
652         
653         ret->NextSibling = NULL;
654         //ret->Line = Parser->CurLine;
655         ret->Type = NODETYPE_BLOCK;
656         ret->Block.FirstChild = NULL;
657         ret->Block.LastChild = NULL;
658         
659         return ret;
660 }
661
662 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
663 {
664         Child->NextSibling = NULL;
665         switch( Parent->Type )
666         {
667         case NODETYPE_BLOCK:
668                 if(Parent->Block.FirstChild == NULL) {
669                         Parent->Block.FirstChild = Parent->Block.LastChild = Child;
670                 }
671                 else {
672                         Parent->Block.LastChild->NextSibling = Child;
673                         Parent->Block.LastChild = Child;
674                 }
675                 break;
676         case NODETYPE_DEFVAR:
677                 if(Parent->DefVar.LevelSizes == NULL) {
678                         Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
679                 }
680                 else {
681                         Parent->DefVar.LevelSizes_Last->NextSibling = Child;
682                         Parent->DefVar.LevelSizes_Last = Child;
683                 }
684                 break;
685         default:
686                 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
687                 break;
688         }
689 }
690
691 tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
692 {
693         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
694         ret->NextSibling = NULL;
695         ret->Line = Parser->CurLine;
696         ret->Type = NODETYPE_IF;
697         ret->If.Condition = Condition;
698         ret->If.True = True;
699         ret->If.False = False;
700         return ret;
701 }
702
703 tAST_Node *AST_NewLoop(tParser *Parser, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
704 {
705         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
706         ret->NextSibling = NULL;
707         ret->Line = Parser->CurLine;
708         ret->Type = NODETYPE_LOOP;
709         ret->For.Init = Init;
710         ret->For.bCheckAfter = !!bPostCheck;
711         ret->For.Condition = Condition;
712         ret->For.Increment = Increment;
713         ret->For.Code = Code;
714         return ret;
715 }
716
717 tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value)
718 {
719         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
720         
721         ret->NextSibling = NULL;
722         ret->Line = Parser->CurLine;
723         ret->Type = NODETYPE_ASSIGN;
724         ret->Assign.Operation = Operation;
725         ret->Assign.Dest = Dest;
726         ret->Assign.Value = Value;
727         
728         return ret;
729 }
730
731 tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value)
732 {
733         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
734         
735         ret->NextSibling = NULL;
736         ret->Line = Parser->CurLine;
737         ret->Type = NODETYPE_CAST;
738         ret->Cast.DataType = Target;
739         ret->Cast.Value = Value;
740         
741         return ret;
742 }
743
744 tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right)
745 {
746         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
747         
748         ret->NextSibling = NULL;
749         ret->Line = Parser->CurLine;
750         ret->Type = Operation;
751         ret->BinOp.Left = Left;
752         ret->BinOp.Right = Right;
753         
754         return ret;
755 }
756
757 /**
758  */
759 tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value)
760 {
761         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
762         
763         ret->NextSibling = NULL;
764         ret->Line = Parser->CurLine;
765         ret->Type = Operation;
766         ret->UniOp.Value = Value;
767         
768         return ret;
769 }
770
771 /**
772  * \brief Create a new string node
773  */
774 tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length)
775 {
776         tAST_Node       *ret = malloc( sizeof(tAST_Node) + Length + 1 );
777         
778         ret->NextSibling = NULL;
779         ret->Line = Parser->CurLine;
780         ret->Type = NODETYPE_STRING;
781         ret->String.Length = Length;
782         memcpy(ret->String.Data, String, Length);
783         ret->String.Data[Length] = '\0';
784         
785         return ret;
786 }
787
788 /**
789  * \brief Create a new integer node
790  */
791 tAST_Node *AST_NewInteger(tParser *Parser, uint64_t Value)
792 {
793         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
794         ret->NextSibling = NULL;
795         ret->Line = Parser->CurLine;
796         ret->Type = NODETYPE_INTEGER;
797         ret->Integer = Value;
798         return ret;
799 }
800
801 /**
802  * \brief Create a new variable reference node
803  */
804 tAST_Node *AST_NewVariable(tParser *Parser, const char *Name)
805 {
806         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
807         ret->NextSibling = NULL;
808         ret->Line = Parser->CurLine;
809         ret->Type = NODETYPE_VARIABLE;
810         strcpy(ret->Variable.Name, Name);
811         return ret;
812 }
813
814 /**
815  * \brief Create a new variable definition node
816  */
817 tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name)
818 {
819         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
820         ret->NextSibling = NULL;
821         ret->Line = Parser->CurLine;
822         ret->Type = NODETYPE_DEFVAR;
823         ret->DefVar.DataType = Type;
824         ret->DefVar.LevelSizes = NULL;
825         strcpy(ret->DefVar.Name, Name);
826         return ret;
827 }
828
829 /**
830  * \brief Create a new runtime constant reference node
831  */
832 tAST_Node *AST_NewConstant(tParser *Parser, const char *Name)
833 {
834         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
835         ret->NextSibling = NULL;
836         ret->Line = Parser->CurLine;
837         ret->Type = NODETYPE_CONSTANT;
838         strcpy(ret->Variable.Name, Name);
839         return ret;
840 }
841
842 /**
843  * \brief Create a function call node
844  * \note Argument list is manipulated using AST_AppendFunctionCallArg
845  */
846 tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name)
847 {
848         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
849         
850         ret->NextSibling = NULL;
851         ret->Line = Parser->CurLine;
852         ret->Type = NODETYPE_FUNCTIONCALL;
853         ret->FunctionCall.FirstArg = NULL;
854         ret->FunctionCall.LastArg = NULL;
855         strcpy(ret->FunctionCall.Name, Name);
856         return ret;
857 }
858
859 /**
860  * \brief Append an argument to a function call
861  */
862 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
863 {
864         if( Node->Type != NODETYPE_FUNCTIONCALL )       return ;
865         
866         if(Node->FunctionCall.LastArg) {
867                 Node->FunctionCall.LastArg->NextSibling = Arg;
868                 Node->FunctionCall.LastArg = Arg;
869         }
870         else {
871                 Node->FunctionCall.FirstArg = Arg;
872                 Node->FunctionCall.LastArg = Arg;
873         }
874 }
875
876 /**
877  * \}
878  */

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