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

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