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

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