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

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