SpiderScript - Moar fixes, mostly speedups (caching values and lookups)
[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->Constant.String.Length);
262                 WRITE_N(Buffer, Offset, Node->Constant.String.Length, Node->Constant.String.Data);
263                 break;
264         case NODETYPE_INTEGER:
265                 WRITE_64(Buffer, Offset, Node->Constant.Integer);
266                 break;
267         case NODETYPE_REAL:
268                 WRITE_REAL(Buffer, Offset, Node->Constant.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         
389         case NODETYPE_STRING:
390         case NODETYPE_INTEGER:
391         case NODETYPE_REAL:
392                 if( Node->ValueCache )
393                         Object_Dereference(Node->ValueCache);
394                 Node->ValueCache = NULL;
395                 break;
396         }
397         free( Node );
398 }
399
400 tAST_Node *AST_int_AllocateNode(tParser *Parser, int Type, int ExtraSize)
401 {
402         tAST_Node       *ret = malloc( sizeof(tAST_Node) + ExtraSize );
403         ret->NextSibling = NULL;
404         ret->File = "<unk>";
405         ret->Line = Parser->CurLine;
406         ret->Type = Type;
407         
408         // Runtime Caching
409         ret->BlockState = NULL;
410         ret->BlockIdent = 0;
411         ret->ValueCache = NULL;
412         
413         return ret;
414 }
415
416 tAST_Node *AST_NewCodeBlock(tParser *Parser)
417 {
418         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_BLOCK, 0 );
419         
420         ret->Block.FirstChild = NULL;
421         ret->Block.LastChild = NULL;
422         
423         return ret;
424 }
425
426 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
427 {
428         Child->NextSibling = NULL;
429         switch( Parent->Type )
430         {
431         case NODETYPE_BLOCK:
432                 if(Parent->Block.FirstChild == NULL) {
433                         Parent->Block.FirstChild = Parent->Block.LastChild = Child;
434                 }
435                 else {
436                         Parent->Block.LastChild->NextSibling = Child;
437                         Parent->Block.LastChild = Child;
438                 }
439                 break;
440         case NODETYPE_DEFVAR:
441                 if(Parent->DefVar.LevelSizes == NULL) {
442                         Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
443                 }
444                 else {
445                         Parent->DefVar.LevelSizes_Last->NextSibling = Child;
446                         Parent->DefVar.LevelSizes_Last = Child;
447                 }
448                 break;
449         default:
450                 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
451                 break;
452         }
453 }
454
455 tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
456 {
457         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_IF, 0);
458         ret->If.Condition = Condition;
459         ret->If.True = True;
460         ret->If.False = False;
461         return ret;
462 }
463
464 tAST_Node *AST_NewLoop(tParser *Parser, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
465 {
466         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_LOOP, 0);
467         ret->For.Init = Init;
468         ret->For.bCheckAfter = !!bPostCheck;
469         ret->For.Condition = Condition;
470         ret->For.Increment = Increment;
471         ret->For.Code = Code;
472         return ret;
473 }
474
475 tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value)
476 {
477         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_ASSIGN, 0);
478         
479         ret->Assign.Operation = Operation;
480         ret->Assign.Dest = Dest;
481         ret->Assign.Value = Value;
482         
483         return ret;
484 }
485
486 tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value)
487 {
488         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_CAST, 0);
489         
490         ret->Cast.DataType = Target;
491         ret->Cast.Value = Value;
492         
493         return ret;
494 }
495
496 tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right)
497 {
498         tAST_Node       *ret = AST_int_AllocateNode(Parser, Operation, 0);
499         
500         ret->BinOp.Left = Left;
501         ret->BinOp.Right = Right;
502         
503         return ret;
504 }
505
506 /**
507  */
508 tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value)
509 {
510         tAST_Node       *ret = AST_int_AllocateNode(Parser, Operation, 0);
511         
512         ret->UniOp.Value = Value;
513         
514         return ret;
515 }
516
517 tAST_Node *AST_NewNop(tParser *Parser)
518 {
519         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_NOP, 0);
520         
521         return ret;
522 }
523
524 /**
525  * \brief Create a new string node
526  */
527 tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length)
528 {
529         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_STRING, Length + 1);
530         
531         ret->Constant.Type = SS_DATATYPE_STRING;
532         ret->Constant.ReferenceCount = 1;
533         ret->Constant.String.Length = Length;
534         memcpy(ret->Constant.String.Data, String, Length);
535         ret->Constant.String.Data[Length] = '\0';
536         
537         return ret;
538 }
539
540 /**
541  * \brief Create a new integer node
542  */
543 tAST_Node *AST_NewInteger(tParser *Parser, int64_t Value)
544 {
545         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_INTEGER, 0);
546         ret->Constant.Type = SS_DATATYPE_INTEGER;
547         ret->Constant.ReferenceCount = 1;
548         ret->Constant.Integer = Value;
549         return ret;
550 }
551
552 /**
553  * \brief Create a new real number node
554  */
555 tAST_Node *AST_NewReal(tParser *Parser, double Value)
556 {
557         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_REAL, 0);
558         ret->Constant.Type = SS_DATATYPE_REAL;
559         ret->Constant.ReferenceCount = 1;
560         ret->Constant.Real = Value;
561         return ret;
562 }
563
564 /**
565  * \brief Create a new variable reference node
566  */
567 tAST_Node *AST_NewVariable(tParser *Parser, const char *Name)
568 {
569         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_VARIABLE, strlen(Name) + 1 );
570         strcpy(ret->Variable.Name, Name);
571         return ret;
572 }
573
574 /**
575  * \brief Create a new variable definition node
576  */
577 tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name)
578 {
579         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_DEFVAR, strlen(Name) + 1 );
580         
581         ret->DefVar.DataType = Type;
582         ret->DefVar.LevelSizes = NULL;
583         strcpy(ret->DefVar.Name, Name);
584         
585         return ret;
586 }
587
588 /**
589  * \brief Create a new runtime constant reference node
590  */
591 tAST_Node *AST_NewConstant(tParser *Parser, const char *Name)
592 {
593         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_CONSTANT, strlen(Name) + 1 );
594         
595         strcpy(ret->Variable.Name, Name);
596         
597         return ret;
598 }
599
600 /**
601  * \brief Create a function call node
602  * \note Argument list is manipulated using AST_AppendFunctionCallArg
603  */
604 tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name)
605 {
606         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_FUNCTIONCALL, strlen(Name) + 1 );
607         
608         ret->FunctionCall.Object = NULL;
609         ret->FunctionCall.FirstArg = NULL;
610         ret->FunctionCall.LastArg = NULL;
611         ret->FunctionCall.NumArgs = 0;
612         strcpy(ret->FunctionCall.Name, Name);
613         
614         return ret;
615 }
616 tAST_Node *AST_NewMethodCall(tParser *Parser, tAST_Node *Object, const char *Name)
617 {
618         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_METHODCALL, strlen(Name) + 1 );
619         
620         ret->FunctionCall.Object = Object;
621         ret->FunctionCall.FirstArg = NULL;
622         ret->FunctionCall.LastArg = NULL;
623         ret->FunctionCall.NumArgs = 0;
624         strcpy(ret->FunctionCall.Name, Name);
625         
626         return ret;
627 }
628
629 tAST_Node *AST_NewCreateObject(tParser *Parser, const char *Name)
630 {
631         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_CREATEOBJECT, strlen(Name) + 1 );
632         
633         ret->FunctionCall.Object = NULL;
634         ret->FunctionCall.FirstArg = NULL;
635         ret->FunctionCall.LastArg = NULL;
636         ret->FunctionCall.NumArgs = 0;
637         strcpy(ret->FunctionCall.Name, Name);
638         
639         return ret;
640 }
641
642 /**
643  * \brief Append an argument to a function call
644  */
645 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
646 {
647         if( Node->Type != NODETYPE_FUNCTIONCALL
648          && Node->Type != NODETYPE_CREATEOBJECT
649          && Node->Type != NODETYPE_METHODCALL)
650         {
651                 fprintf(stderr, "BUG REPORT: AST_AppendFunctionCallArg on an invalid node type (%i)\n", Node->Type);
652                 return ;
653         }
654         
655         if(Node->FunctionCall.LastArg) {
656                 Node->FunctionCall.LastArg->NextSibling = Arg;
657                 Node->FunctionCall.LastArg = Arg;
658         }
659         else {
660                 Node->FunctionCall.FirstArg = Arg;
661                 Node->FunctionCall.LastArg = Arg;
662         }
663         Node->FunctionCall.NumArgs ++;
664 }
665
666 /**
667  * \brief Add a scope node
668  */
669 tAST_Node *AST_NewScopeDereference(tParser *Parser, const char *Name, tAST_Node *Child)
670 {
671         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_SCOPE, strlen(Name) + 1 );
672         ret->Scope.Element = Child;
673         strcpy(ret->Scope.Name, Name);
674         return ret;
675 }
676
677 /**
678  * \brief Add a scope node
679  */
680 tAST_Node *AST_NewClassElement(tParser *Parser, tAST_Node *Object, const char *Name)
681 {
682         tAST_Node       *ret = AST_int_AllocateNode(Parser, NODETYPE_ELEMENT, strlen(Name) + 1 );
683         ret->Scope.Element = Object;
684         strcpy(ret->Scope.Name, Name);
685         return ret;
686 }
687
688 /**
689  * \}
690  */

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