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

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