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

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