SpiderScript - Bugfixes and speed 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 #define WRITE_N(_buffer, _offset, _len, _dataptr) do { \
69         if(_buffer)     memcpy((char*)_buffer + _offset, _dataptr, _len);\
70         _offset += _len; \
71 } while(0)
72
73 #define WRITE_8(_buffer, _offset, _val) do {\
74         uint8_t v = (_val);\
75         WRITE_N(_buffer, _offset, 1, &v);\
76 } while(0)
77 #define WRITE_16(_buffer, _offset, _val) do {\
78         uint16_t        v = (_val);\
79         WRITE_N(_buffer, _offset, 2, &v);\
80 } while(0)
81 #define WRITE_32(_buffer, _offset, _val) do {\
82         uint32_t        v = (_val);\
83         WRITE_N(_buffer, _offset, 4, &v);\
84 } while(0)
85 #define WRITE_64(_buffer, _offset, _val) do {\
86         uint64_t        v = (_val);\
87         WRITE_N(_buffer, _offset, 8, &v);\
88 } while(0)
89 #define WRITE_REAL(_buffer, _offset, _val) do {\
90         double  v = (_val);\
91         WRITE_N(_buffer, _offset, sizeof(double), &v);\
92 } while(0)
93
94 #define WRITE_STR(_buffer, _offset, _string) do {\
95         int len = strlen(_string);\
96         WRITE_16(_buffer, _offset, len);\
97         WRITE_N(_buffer, _offset, len, _string);\
98         if((_offset & 1) == 1)WRITE_8(_buffer, _offset, 0); \
99         if((_offset & 3) == 2)WRITE_16(_buffer, _offset, 0); \
100 } while(0)
101 #define WRITE_NODELIST(_buffer, _offset, _listHead)     do {\
102         tAST_Node *node; \
103         size_t ptr = -1;\
104         for(node=(_listHead); node; node = node->NextSibling) {\
105                 ptr = _offset;\
106                 _offset += AST_WriteNode(_buffer, _offset, node); \
107                 WRITE_32(_buffer, ptr, ptr); \
108         } \
109         if(ptr != -1){ptr -= 4; WRITE_32(_buffer, ptr, 0);} \
110 } while(0)
111
112 /**
113  * \brief Writes a script dump to a buffer
114  * \return Size of encoded data
115  * \note If \a Buffer is NULL, no write is done, but the size is still returned
116  */
117 size_t AST_WriteScript(void *Buffer, tAST_Script *Script)
118 {
119         tAST_Function   *fcn;
120         size_t  ret = 0, ptr = 0;
121         
122         for( fcn = Script->Functions; fcn; fcn = fcn->Next )
123         {
124                 ptr = ret;
125                 WRITE_32(Buffer, ret, 0);       // Next
126                 WRITE_STR(Buffer, ret, fcn->Name);
127                 WRITE_NODELIST(Buffer, ret, fcn->Arguments);    // TODO: Cheaper way
128                 ret += AST_WriteNode(Buffer, ret, fcn->Code);
129                 WRITE_32(Buffer, ptr, ret);     // Actually set next
130         }
131         if( ptr )
132         {
133                 ptr -= 4;
134                 WRITE_32(Buffer, ptr, 0);       // Clear next for final
135         }
136         
137         return ret;
138 }
139
140 /**
141  * \brief Write a node to a file
142  */
143 size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node)
144 {
145         size_t  baseOfs = Offset;
146         
147         if(!Node) {
148                 fprintf(stderr, "Possible Bug - NULL passed to AST_WriteNode\n");
149                 return 0;
150         }
151         
152         WRITE_32(Buffer, Offset, 0);    // Next
153         WRITE_16(Buffer, Offset, Node->Type);
154         // TODO: Scan the buffer for the location of the filename (with NULL byte)
155         //       else, write the string at the end of the node
156         WRITE_16(Buffer, Offset, Node->Line);   // Line
157         //WRITE_32(Buffer, Offset, 0);  // File
158         
159         switch(Node->Type)
160         {
161         // Block of code
162         case NODETYPE_BLOCK:
163                 WRITE_NODELIST(Buffer, Offset, Node->Block.FirstChild);
164                 break;
165         
166         // Function Call
167         case NODETYPE_METHODCALL:
168                 Offset += AST_WriteNode(Buffer, Offset, Node->FunctionCall.Object);
169         case NODETYPE_FUNCTIONCALL:
170         case NODETYPE_CREATEOBJECT:
171                 // TODO: Search for the same function name and add a pointer
172                 WRITE_STR(Buffer, Offset, Node->FunctionCall.Name);
173                 WRITE_NODELIST(Buffer, Offset, Node->FunctionCall.FirstArg);
174                 break;
175         
176         // If node
177         case NODETYPE_IF:
178                 Offset += AST_WriteNode(Buffer, Offset, Node->If.Condition);
179                 Offset += AST_WriteNode(Buffer, Offset, Node->If.True);
180                 Offset += AST_WriteNode(Buffer, Offset, Node->If.False);
181                 break;
182         
183         // Looping Construct (For loop node)
184         case NODETYPE_LOOP:
185                 WRITE_8(Buffer, Offset, Node->For.bCheckAfter);
186                 
187                 Offset += AST_WriteNode(Buffer, Offset, Node->For.Init);
188                 Offset += AST_WriteNode(Buffer, Offset, Node->For.Condition);
189                 Offset += AST_WriteNode(Buffer, Offset, Node->For.Increment);
190                 Offset += AST_WriteNode(Buffer, Offset, Node->For.Code);
191                 break;
192         
193         // Asignment
194         case NODETYPE_ASSIGN:
195                 WRITE_8(Buffer, Offset, Node->Assign.Operation);
196                 Offset += AST_WriteNode(Buffer, Offset, Node->Assign.Dest);
197                 Offset += AST_WriteNode(Buffer, Offset, Node->Assign.Value);
198                 break;
199         
200         // Casting
201         case NODETYPE_CAST:
202                 WRITE_8(Buffer, Offset, Node->Cast.DataType);
203                 Offset += AST_WriteNode(Buffer, Offset, Node->Cast.Value);
204                 break;
205         
206         // Define a variable
207         case NODETYPE_DEFVAR:
208                 WRITE_8(Buffer, Offset, Node->DefVar.DataType);
209                 // TODO: Duplicate compress the strings
210                 WRITE_STR(Buffer, Offset, Node->DefVar.Name);
211                 
212                 WRITE_NODELIST(Buffer, Offset, Node->DefVar.LevelSizes);
213                 break;
214         
215         // Scope Reference
216         case NODETYPE_SCOPE:
217         case NODETYPE_ELEMENT:
218                 WRITE_STR(Buffer, Offset, Node->Scope.Name);
219                 Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value);
220                 break;
221         
222         // Unary Operations
223         case NODETYPE_RETURN:
224         case NODETYPE_BWNOT:
225         case NODETYPE_LOGICALNOT:
226         case NODETYPE_NEGATE:
227         case NODETYPE_POSTINC:
228         case NODETYPE_POSTDEC:
229                 Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value);
230                 break;
231         
232         // Binary Operations
233         case NODETYPE_INDEX:
234         case NODETYPE_ADD:
235         case NODETYPE_SUBTRACT:
236         case NODETYPE_MULTIPLY:
237         case NODETYPE_DIVIDE:
238         case NODETYPE_MODULO:
239         case NODETYPE_BITSHIFTLEFT:
240         case NODETYPE_BITSHIFTRIGHT:
241         case NODETYPE_BITROTATELEFT:
242         case NODETYPE_BWAND:    case NODETYPE_LOGICALAND:
243         case NODETYPE_BWOR:     case NODETYPE_LOGICALOR:
244         case NODETYPE_BWXOR:    case NODETYPE_LOGICALXOR:
245         case NODETYPE_EQUALS:
246         case NODETYPE_LESSTHAN: case NODETYPE_LESSTHANEQUAL:
247         case NODETYPE_GREATERTHAN:      case NODETYPE_GREATERTHANEQUAL:
248                 Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Left);
249                 Offset += AST_WriteNode(Buffer, Offset, Node->BinOp.Right);
250                 break;
251         
252         // Node types with no children
253         case NODETYPE_NOP:
254                 break;
255         case NODETYPE_VARIABLE:
256         case NODETYPE_CONSTANT:
257                 // TODO: De-Duplicate the strings
258                 WRITE_STR(Buffer, Offset, Node->Variable.Name);
259                 break;
260         case NODETYPE_STRING:
261                 WRITE_32(Buffer, Offset, Node->String.Length);
262                 WRITE_N(Buffer, Offset, Node->String.Length, Node->String.Data);
263                 break;
264         case NODETYPE_INTEGER:
265                 WRITE_64(Buffer, Offset, Node->Integer);
266                 break;
267         case NODETYPE_REAL:
268                 WRITE_REAL(Buffer, Offset, Node->Real);
269                 break;
270         
271         //default:
272         //      fprintf(stderr, "AST_WriteNode: Unknown node type %i\n", Node->Type);
273         //      break;
274         }
275         
276         return Offset - baseOfs;
277 }
278
279 /**
280  * \brief Free a node and all subnodes
281  */
282 void AST_FreeNode(tAST_Node *Node)
283 {
284         tAST_Node       *node;
285         
286         if(!Node)       return ;
287         
288         switch(Node->Type)
289         {
290         // Block of code
291         case NODETYPE_BLOCK:
292                 for( node = Node->Block.FirstChild; node; )
293                 {
294                         tAST_Node       *savedNext = node->NextSibling;
295                         AST_FreeNode(node);
296                         node = savedNext;
297                 }
298                 break;
299         
300         // Function Call
301         case NODETYPE_METHODCALL:
302                 AST_FreeNode(Node->FunctionCall.Object);
303         case NODETYPE_FUNCTIONCALL:
304         case NODETYPE_CREATEOBJECT:
305                 for( node = Node->FunctionCall.FirstArg; node; )
306                 {
307                         tAST_Node       *savedNext = node->NextSibling;
308                         AST_FreeNode(node);
309                         node = savedNext;
310                 }
311                 break;
312         
313         // If node
314         case NODETYPE_IF:
315                 AST_FreeNode(Node->If.Condition);
316                 AST_FreeNode(Node->If.True);
317                 AST_FreeNode(Node->If.False);
318                 break;
319         
320         // Looping Construct (For loop node)
321         case NODETYPE_LOOP:
322                 AST_FreeNode(Node->For.Init);
323                 AST_FreeNode(Node->For.Condition);
324                 AST_FreeNode(Node->For.Increment);
325                 AST_FreeNode(Node->For.Code);
326                 break;
327         
328         // Asignment
329         case NODETYPE_ASSIGN:
330                 AST_FreeNode(Node->Assign.Dest);
331                 AST_FreeNode(Node->Assign.Value);
332                 break;
333         
334         // Casting
335         case NODETYPE_CAST:
336                 AST_FreeNode(Node->Cast.Value);
337                 break;
338         
339         case NODETYPE_SCOPE:
340         case NODETYPE_ELEMENT:
341                 AST_FreeNode(Node->Scope.Element);
342                 break;
343         
344         // Define a variable
345         case NODETYPE_DEFVAR:
346                 for( node = Node->DefVar.LevelSizes; node; )
347                 {
348                         tAST_Node       *savedNext = node->NextSibling;
349                         AST_FreeNode(node);
350                         node = savedNext;
351                 }
352                 break;
353         
354         // Unary Operations
355         case NODETYPE_RETURN:
356         case NODETYPE_BWNOT:
357         case NODETYPE_LOGICALNOT:
358         case NODETYPE_NEGATE:
359         case NODETYPE_POSTINC:
360         case NODETYPE_POSTDEC:
361                 AST_FreeNode(Node->UniOp.Value);
362                 break;
363         
364         // Binary Operations
365         case NODETYPE_INDEX:
366         case NODETYPE_ADD:
367         case NODETYPE_SUBTRACT:
368         case NODETYPE_MULTIPLY:
369         case NODETYPE_DIVIDE:
370         case NODETYPE_MODULO:
371         case NODETYPE_BITSHIFTLEFT:
372         case NODETYPE_BITSHIFTRIGHT:
373         case NODETYPE_BITROTATELEFT:
374         case NODETYPE_BWAND:    case NODETYPE_LOGICALAND:
375         case NODETYPE_BWOR:     case NODETYPE_LOGICALOR:
376         case NODETYPE_BWXOR:    case NODETYPE_LOGICALXOR:
377         case NODETYPE_EQUALS:
378         case NODETYPE_LESSTHAN: case NODETYPE_LESSTHANEQUAL:
379         case NODETYPE_GREATERTHAN:      case NODETYPE_GREATERTHANEQUAL:
380                 AST_FreeNode( Node->BinOp.Left );
381                 AST_FreeNode( Node->BinOp.Right );
382                 break;
383         
384         // Node types with no children
385         case NODETYPE_NOP:      break;
386         case NODETYPE_VARIABLE: break;
387         case NODETYPE_CONSTANT: break;
388         case NODETYPE_STRING:   break;
389         case NODETYPE_INTEGER:  break;
390         case NODETYPE_REAL:     break;
391         }
392         free( Node );
393 }
394
395 tAST_Node *AST_NewCodeBlock(tParser *Parser)
396 {
397         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
398         
399         ret->NextSibling = NULL;
400         ret->File = NULL;
401         ret->Line = Parser->CurLine;
402         ret->Type = NODETYPE_BLOCK;
403         ret->Block.FirstChild = NULL;
404         ret->Block.LastChild = NULL;
405         
406         return ret;
407 }
408
409 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
410 {
411         Child->NextSibling = NULL;
412         switch( Parent->Type )
413         {
414         case NODETYPE_BLOCK:
415                 if(Parent->Block.FirstChild == NULL) {
416                         Parent->Block.FirstChild = Parent->Block.LastChild = Child;
417                 }
418                 else {
419                         Parent->Block.LastChild->NextSibling = Child;
420                         Parent->Block.LastChild = Child;
421                 }
422                 break;
423         case NODETYPE_DEFVAR:
424                 if(Parent->DefVar.LevelSizes == NULL) {
425                         Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
426                 }
427                 else {
428                         Parent->DefVar.LevelSizes_Last->NextSibling = Child;
429                         Parent->DefVar.LevelSizes_Last = Child;
430                 }
431                 break;
432         default:
433                 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
434                 break;
435         }
436 }
437
438 tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
439 {
440         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
441         ret->NextSibling = NULL;
442         ret->File = NULL;
443         ret->Line = Parser->CurLine;
444         ret->Type = NODETYPE_IF;
445         ret->If.Condition = Condition;
446         ret->If.True = True;
447         ret->If.False = False;
448         return ret;
449 }
450
451 tAST_Node *AST_NewLoop(tParser *Parser, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
452 {
453         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
454         ret->NextSibling = NULL;
455         ret->File = NULL;
456         ret->Line = Parser->CurLine;
457         ret->Type = NODETYPE_LOOP;
458         ret->For.Init = Init;
459         ret->For.bCheckAfter = !!bPostCheck;
460         ret->For.Condition = Condition;
461         ret->For.Increment = Increment;
462         ret->For.Code = Code;
463         return ret;
464 }
465
466 tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value)
467 {
468         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
469         
470         ret->NextSibling = NULL;
471         ret->File = NULL;
472         ret->Line = Parser->CurLine;
473         ret->Type = NODETYPE_ASSIGN;
474         ret->Assign.Operation = Operation;
475         ret->Assign.Dest = Dest;
476         ret->Assign.Value = Value;
477         
478         return ret;
479 }
480
481 tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value)
482 {
483         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
484         
485         ret->NextSibling = NULL;
486         ret->File = NULL;
487         ret->Line = Parser->CurLine;
488         ret->Type = NODETYPE_CAST;
489         ret->Cast.DataType = Target;
490         ret->Cast.Value = Value;
491         
492         return ret;
493 }
494
495 tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right)
496 {
497         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
498         
499         ret->NextSibling = NULL;
500         ret->File = NULL;
501         ret->Line = Parser->CurLine;
502         ret->Type = Operation;
503         ret->BinOp.Left = Left;
504         ret->BinOp.Right = Right;
505         
506         return ret;
507 }
508
509 /**
510  */
511 tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value)
512 {
513         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
514         
515         ret->NextSibling = NULL;
516         ret->File = NULL;
517         ret->Line = Parser->CurLine;
518         ret->Type = Operation;
519         ret->UniOp.Value = Value;
520         
521         return ret;
522 }
523
524 tAST_Node *AST_NewNop(tParser *Parser)
525 {
526         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
527         
528         ret->NextSibling = NULL;
529         ret->File = NULL;
530         ret->Line = Parser->CurLine;
531         ret->Type = NODETYPE_NOP;
532         
533         return ret;
534 }
535
536 /**
537  * \brief Create a new string node
538  */
539 tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length)
540 {
541         tAST_Node       *ret = malloc( sizeof(tAST_Node) + Length + 1 );
542         
543         ret->NextSibling = NULL;
544         ret->File = NULL;
545         ret->Line = Parser->CurLine;
546         ret->Type = NODETYPE_STRING;
547         ret->String.Length = Length;
548         memcpy(ret->String.Data, String, Length);
549         ret->String.Data[Length] = '\0';
550         
551         return ret;
552 }
553
554 /**
555  * \brief Create a new integer node
556  */
557 tAST_Node *AST_NewInteger(tParser *Parser, int64_t Value)
558 {
559         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
560         ret->NextSibling = NULL;
561         ret->File = NULL;
562         ret->Line = Parser->CurLine;
563         ret->Type = NODETYPE_INTEGER;
564         ret->Integer = Value;
565         return ret;
566 }
567
568 /**
569  * \brief Create a new real number node
570  */
571 tAST_Node *AST_NewReal(tParser *Parser, double Value)
572 {
573         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
574         ret->NextSibling = NULL;
575         ret->File = NULL;
576         ret->Line = Parser->CurLine;
577         ret->Type = NODETYPE_REAL;
578         ret->Real = Value;
579         return ret;
580 }
581
582 /**
583  * \brief Create a new variable reference node
584  */
585 tAST_Node *AST_NewVariable(tParser *Parser, const char *Name)
586 {
587         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
588         ret->NextSibling = NULL;
589         ret->File = NULL;
590         ret->Line = Parser->CurLine;
591         ret->Type = NODETYPE_VARIABLE;
592         strcpy(ret->Variable.Name, Name);
593         return ret;
594 }
595
596 /**
597  * \brief Create a new variable definition node
598  */
599 tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name)
600 {
601         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
602         ret->NextSibling = NULL;
603         ret->File = NULL;
604         ret->Line = Parser->CurLine;
605         ret->Type = NODETYPE_DEFVAR;
606         ret->DefVar.DataType = Type;
607         ret->DefVar.LevelSizes = NULL;
608         strcpy(ret->DefVar.Name, Name);
609         return ret;
610 }
611
612 /**
613  * \brief Create a new runtime constant reference node
614  */
615 tAST_Node *AST_NewConstant(tParser *Parser, const char *Name)
616 {
617         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
618         ret->NextSibling = NULL;
619         ret->File = NULL;
620         ret->Line = Parser->CurLine;
621         ret->Type = NODETYPE_CONSTANT;
622         strcpy(ret->Variable.Name, Name);
623         return ret;
624 }
625
626 /**
627  * \brief Create a function call node
628  * \note Argument list is manipulated using AST_AppendFunctionCallArg
629  */
630 tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name)
631 {
632         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
633         
634         ret->NextSibling = NULL;
635         ret->File = NULL;
636         ret->Line = Parser->CurLine;
637         ret->Type = NODETYPE_FUNCTIONCALL;
638         ret->FunctionCall.Object = NULL;
639         ret->FunctionCall.FirstArg = NULL;
640         ret->FunctionCall.LastArg = NULL;
641         ret->FunctionCall.NumArgs = 0;
642         strcpy(ret->FunctionCall.Name, Name);
643         return ret;
644 }
645 tAST_Node *AST_NewMethodCall(tParser *Parser, tAST_Node *Object, const char *Name)
646 {
647         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
648         
649         ret->NextSibling = NULL;
650         ret->File = NULL;
651         ret->Line = Parser->CurLine;
652         ret->Type = NODETYPE_METHODCALL;
653         ret->FunctionCall.Object = Object;
654         ret->FunctionCall.FirstArg = NULL;
655         ret->FunctionCall.LastArg = NULL;
656         ret->FunctionCall.NumArgs = 0;
657         strcpy(ret->FunctionCall.Name, Name);
658         return ret;
659 }
660
661 tAST_Node *AST_NewCreateObject(tParser *Parser, const char *Name)
662 {
663         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
664         
665         ret->NextSibling = NULL;
666         ret->File = NULL;
667         ret->Line = Parser->CurLine;
668         ret->Type = NODETYPE_CREATEOBJECT;
669         ret->FunctionCall.Object = NULL;
670         ret->FunctionCall.FirstArg = NULL;
671         ret->FunctionCall.LastArg = NULL;
672         ret->FunctionCall.NumArgs = 0;
673         strcpy(ret->FunctionCall.Name, Name);
674         return ret;
675 }
676
677 /**
678  * \brief Append an argument to a function call
679  */
680 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
681 {
682         if( Node->Type != NODETYPE_FUNCTIONCALL
683          && Node->Type != NODETYPE_CREATEOBJECT
684          && Node->Type != NODETYPE_METHODCALL)
685         {
686                 fprintf(stderr, "BUG REPORT: AST_AppendFunctionCallArg on an invalid node type (%i)\n", Node->Type);
687                 return ;
688         }
689         
690         if(Node->FunctionCall.LastArg) {
691                 Node->FunctionCall.LastArg->NextSibling = Arg;
692                 Node->FunctionCall.LastArg = Arg;
693         }
694         else {
695                 Node->FunctionCall.FirstArg = Arg;
696                 Node->FunctionCall.LastArg = Arg;
697         }
698         Node->FunctionCall.NumArgs ++;
699 }
700
701 /**
702  * \brief Add a scope node
703  */
704 tAST_Node *AST_NewScopeDereference(tParser *Parser, const char *Name, tAST_Node *Child)
705 {
706         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
707         
708         ret->NextSibling = NULL;
709         ret->File = NULL;
710         ret->Line = Parser->CurLine;
711         ret->Type = NODETYPE_SCOPE;
712         ret->Scope.Element = Child;
713         strcpy(ret->Scope.Name, Name);
714         return ret;
715 }
716
717 /**
718  * \brief Add a scope node
719  */
720 tAST_Node *AST_NewClassElement(tParser *Parser, tAST_Node *Object, const char *Name)
721 {
722         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
723         
724         ret->NextSibling = NULL;
725         ret->File = NULL;
726         ret->Line = Parser->CurLine;
727         ret->Type = NODETYPE_ELEMENT;
728         ret->Scope.Element = Object;
729         strcpy(ret->Scope.Name, Name);
730         return ret;
731 }
732
733 /**
734  * \}
735  */

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