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

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