SpiderScript - For loop, #if'd out experimental code
[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 /**
69  * \brief Get the in-memory size of a node
70  */
71 size_t AST_GetNodeSize(tAST_Node *Node)
72 {
73         size_t  ret;
74         tAST_Node       *node;
75         
76         if(!Node)
77                 return 0;
78         
79         ret = sizeof(tAST_Node*) + sizeof(tAST_NodeType)
80                 + sizeof(const char *) + sizeof(int);
81         
82         switch(Node->Type)
83         {
84         // Block of code
85         case NODETYPE_BLOCK:
86                 ret += sizeof(Node->Block);
87                 for( node = Node->Block.FirstChild; node; )
88                 {
89                         ret += AST_GetNodeSize(node);
90                         node = node->NextSibling;
91                 }
92                 break;
93         
94         // Function Call
95         case NODETYPE_FUNCTIONCALL:
96                 ret += sizeof(Node->FunctionCall) + strlen(Node->FunctionCall.Name) + 1;
97                 for( node = Node->FunctionCall.FirstArg; node; )
98                 {
99                         ret += AST_GetNodeSize(node);
100                         node = node->NextSibling;
101                 }
102                 break;
103         
104         // If node
105         case NODETYPE_IF:
106                 ret += sizeof(Node->If);
107                 ret += AST_GetNodeSize(Node->If.Condition);
108                 ret += AST_GetNodeSize(Node->If.True);
109                 ret += AST_GetNodeSize(Node->If.False);
110                 break;
111         
112         // Looping Construct (For loop node)
113         case NODETYPE_LOOP:
114                 ret += sizeof(Node->For);
115                 ret += AST_GetNodeSize(Node->For.Init);
116                 ret += AST_GetNodeSize(Node->For.Condition);
117                 ret += AST_GetNodeSize(Node->For.Increment);
118                 ret += AST_GetNodeSize(Node->For.Code);
119                 break;
120         
121         // Asignment
122         case NODETYPE_ASSIGN:
123                 ret += sizeof(Node->Assign);
124                 ret += AST_GetNodeSize(Node->Assign.Dest);
125                 ret += AST_GetNodeSize(Node->Assign.Value);
126                 break;
127         
128         // Casting
129         case NODETYPE_CAST:
130                 ret += sizeof(Node->Cast);
131                 ret += AST_GetNodeSize(Node->Cast.Value);
132                 break;
133         
134         // Define a variable
135         case NODETYPE_DEFVAR:
136                 ret += sizeof(Node->DefVar) + strlen(Node->DefVar.Name) + 1;
137                 for( node = Node->DefVar.LevelSizes; node; )
138                 {
139                         ret += AST_GetNodeSize(node);
140                         node = node->NextSibling;
141                 }
142                 break;
143         
144         // Unary Operations
145         case NODETYPE_RETURN:
146                 ret += sizeof(Node->UniOp);
147                 ret += AST_GetNodeSize(Node->UniOp.Value);
148                 break;
149         
150         // Binary Operations
151         case NODETYPE_INDEX:
152         case NODETYPE_ADD:
153         case NODETYPE_SUBTRACT:
154         case NODETYPE_MULTIPLY:
155         case NODETYPE_DIVIDE:
156         case NODETYPE_MODULO:
157         case NODETYPE_BITSHIFTLEFT:
158         case NODETYPE_BITSHIFTRIGHT:
159         case NODETYPE_BITROTATELEFT:
160         case NODETYPE_BWAND:    case NODETYPE_LOGICALAND:
161         case NODETYPE_BWOR:     case NODETYPE_LOGICALOR:
162         case NODETYPE_BWXOR:    case NODETYPE_LOGICALXOR:
163         case NODETYPE_EQUALS:
164         case NODETYPE_LESSTHAN:
165         case NODETYPE_GREATERTHAN:
166                 ret += sizeof(Node->BinOp);
167                 ret += AST_GetNodeSize( Node->BinOp.Left );
168                 ret += AST_GetNodeSize( Node->BinOp.Right );
169                 break;
170         
171         // Node types with no children
172         case NODETYPE_NOP:
173                 break;
174         case NODETYPE_VARIABLE:
175         case NODETYPE_CONSTANT:
176                 ret += sizeof(Node->Variable) + strlen(Node->Variable.Name) + 1;
177                 break;
178         case NODETYPE_STRING:
179                 ret += sizeof(Node->String) + Node->String.Length;
180                 break;
181         case NODETYPE_INTEGER:
182                 ret += sizeof(Node->Integer);
183                 break;
184         case NODETYPE_REAL:
185                 ret += sizeof(Node->Real);
186                 break;
187         }
188         return ret;
189 }
190
191 #if 0
192 /**
193  * \brief Write a node to a file
194  */
195 void AST_WriteNode(FILE *FP, tAST_Node *Node)
196 {
197         tAST_Node       *node;
198         intptr_t        ptr;
199          int    ret;
200         
201         if(!Node)       return ;
202         
203         ptr = ftell(FP) + AST_GetNodeSize(Node);
204         fwrite(&ptr, sizeof(ptr), 1, FP);
205         fwrite(&Node->Type, sizeof(Node->Type), 1, FP);
206         ptr = 0;        fwrite(&ptr, sizeof(ptr), 1, FP);       // File
207         fwrite(&Node->Line, sizeof(Node->Line), 1, FP);
208         
209         ret = sizeof(tAST_Node*) + sizeof(tAST_NodeType)
210                 + sizeof(const char *) + sizeof(int);
211         
212         switch(Node->Type)
213         {
214         // Block of code
215         case NODETYPE_BLOCK:
216                 ret += sizeof(Node->Block);
217                 for( node = Node->Block.FirstChild; node; )
218                 {
219                         ret += AST_GetNodeSize(node);
220                         node = node->NextSibling;
221                 }
222                 break;
223         
224         // Function Call
225         case NODETYPE_FUNCTIONCALL:
226                 ret += sizeof(Node->FunctionCall) + strlen(Node->FunctionCall.Name) + 1;
227                 for( node = Node->FunctionCall.FirstArg; node; )
228                 {
229                         ret += AST_GetNodeSize(node);
230                         node = node->NextSibling;
231                 }
232                 break;
233         
234         // If node
235         case NODETYPE_IF:
236                 ret += sizeof(Node->If);
237                 ret += AST_GetNodeSize(Node->If.Condition);
238                 ret += AST_GetNodeSize(Node->If.True);
239                 ret += AST_GetNodeSize(Node->If.False);
240                 break;
241         
242         // Looping Construct (For loop node)
243         case NODETYPE_LOOP:
244                 ret += sizeof(Node->For);
245                 ret += AST_GetNodeSize(Node->For.Init);
246                 ret += AST_GetNodeSize(Node->For.Condition);
247                 ret += AST_GetNodeSize(Node->For.Increment);
248                 ret += AST_GetNodeSize(Node->For.Code);
249                 break;
250         
251         // Asignment
252         case NODETYPE_ASSIGN:
253                 ret += sizeof(Node->Assign);
254                 ret += AST_GetNodeSize(Node->Assign.Dest);
255                 ret += AST_GetNodeSize(Node->Assign.Value);
256                 break;
257         
258         // Casting
259         case NODETYPE_CAST:
260                 ret += sizeof(Node->Cast);
261                 ret += AST_GetNodeSize(Node->Cast.Value);
262                 break;
263         
264         // Define a variable
265         case NODETYPE_DEFVAR:
266                 ret += sizeof(Node->DefVar) + strlen(Node->DefVar.Name) + 1;
267                 for( node = Node->DefVar.LevelSizes; node; )
268                 {
269                         ret += AST_GetNodeSize(node);
270                         node = node->NextSibling;
271                 }
272                 break;
273         
274         // Unary Operations
275         case NODETYPE_RETURN:
276                 ret += sizeof(Node->UniOp);
277                 ret += AST_GetNodeSize(Node->UniOp.Value);
278                 break;
279         
280         // Binary Operations
281         case NODETYPE_INDEX:
282         case NODETYPE_ADD:
283         case NODETYPE_SUBTRACT:
284         case NODETYPE_MULTIPLY:
285         case NODETYPE_DIVIDE:
286         case NODETYPE_MODULO:
287         case NODETYPE_BITSHIFTLEFT:
288         case NODETYPE_BITSHIFTRIGHT:
289         case NODETYPE_BITROTATELEFT:
290         case NODETYPE_BWAND:    case NODETYPE_LOGICALAND:
291         case NODETYPE_BWOR:     case NODETYPE_LOGICALOR:
292         case NODETYPE_BWXOR:    case NODETYPE_LOGICALXOR:
293         case NODETYPE_EQUALS:
294         case NODETYPE_LESSTHAN:
295         case NODETYPE_GREATERTHAN:
296                 ret += sizeof(Node->BinOp);
297                 ret += AST_GetNodeSize( Node->BinOp.Left );
298                 ret += AST_GetNodeSize( Node->BinOp.Right );
299                 break;
300         
301         // Node types with no children
302         case NODETYPE_NOP:
303                 break;
304         case NODETYPE_VARIABLE:
305         case NODETYPE_CONSTANT:
306                 ret += sizeof(Node->Variable) + strlen(Node->Variable.Name) + 1;
307                 break;
308         case NODETYPE_STRING:
309                 ret += sizeof(Node->String) + Node->String.Length;
310                 break;
311         case NODETYPE_INTEGER:
312                 ret += sizeof(Node->Integer);
313                 break;
314         case NODETYPE_REAL:
315                 ret += sizeof(Node->Real);
316                 break;
317         }
318         return ret;
319 }
320 #endif
321
322 /**
323  * \brief Free a node and all subnodes
324  */
325 void AST_FreeNode(tAST_Node *Node)
326 {
327         tAST_Node       *node;
328         
329         if(!Node)       return ;
330         
331         switch(Node->Type)
332         {
333         // Block of code
334         case NODETYPE_BLOCK:
335                 for( node = Node->Block.FirstChild; node; )
336                 {
337                         tAST_Node       *savedNext = node->NextSibling;
338                         AST_FreeNode(node);
339                         node = savedNext;
340                 }
341                 break;
342         
343         // Function Call
344         case NODETYPE_FUNCTIONCALL:
345                 for( node = Node->FunctionCall.FirstArg; node; )
346                 {
347                         tAST_Node       *savedNext = node->NextSibling;
348                         AST_FreeNode(node);
349                         node = savedNext;
350                 }
351                 break;
352         
353         // If node
354         case NODETYPE_IF:
355                 AST_FreeNode(Node->If.Condition);
356                 AST_FreeNode(Node->If.True);
357                 AST_FreeNode(Node->If.False);
358                 break;
359         
360         // Looping Construct (For loop node)
361         case NODETYPE_LOOP:
362                 AST_FreeNode(Node->For.Init);
363                 AST_FreeNode(Node->For.Condition);
364                 AST_FreeNode(Node->For.Increment);
365                 AST_FreeNode(Node->For.Code);
366                 break;
367         
368         // Asignment
369         case NODETYPE_ASSIGN:
370                 AST_FreeNode(Node->Assign.Dest);
371                 AST_FreeNode(Node->Assign.Value);
372                 break;
373         
374         // Casting
375         case NODETYPE_CAST:
376                 AST_FreeNode(Node->Cast.Value);
377                 break;
378         
379         // Define a variable
380         case NODETYPE_DEFVAR:
381                 for( node = Node->DefVar.LevelSizes; node; )
382                 {
383                         tAST_Node       *savedNext = node->NextSibling;
384                         AST_FreeNode(node);
385                         node = savedNext;
386                 }
387                 break;
388         
389         // Unary Operations
390         case NODETYPE_RETURN:
391                 AST_FreeNode(Node->UniOp.Value);
392                 break;
393         
394         // Binary Operations
395         case NODETYPE_INDEX:
396         case NODETYPE_ADD:
397         case NODETYPE_SUBTRACT:
398         case NODETYPE_MULTIPLY:
399         case NODETYPE_DIVIDE:
400         case NODETYPE_MODULO:
401         case NODETYPE_BITSHIFTLEFT:
402         case NODETYPE_BITSHIFTRIGHT:
403         case NODETYPE_BITROTATELEFT:
404         case NODETYPE_BWAND:    case NODETYPE_LOGICALAND:
405         case NODETYPE_BWOR:     case NODETYPE_LOGICALOR:
406         case NODETYPE_BWXOR:    case NODETYPE_LOGICALXOR:
407         case NODETYPE_EQUALS:
408         case NODETYPE_LESSTHAN:
409         case NODETYPE_GREATERTHAN:
410                 AST_FreeNode( Node->BinOp.Left );
411                 AST_FreeNode( Node->BinOp.Right );
412                 break;
413         
414         // Node types with no children
415         case NODETYPE_NOP:      break;
416         case NODETYPE_VARIABLE: break;
417         case NODETYPE_CONSTANT: break;
418         case NODETYPE_STRING:   break;
419         case NODETYPE_INTEGER:  break;
420         case NODETYPE_REAL:     break;
421         }
422         free( Node );
423 }
424
425 tAST_Node *AST_NewCodeBlock(void)
426 {
427         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
428         
429         ret->NextSibling = NULL;
430         //ret->Line = Parser->CurLine;
431         ret->Type = NODETYPE_BLOCK;
432         ret->Block.FirstChild = NULL;
433         ret->Block.LastChild = NULL;
434         
435         return ret;
436 }
437
438 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
439 {
440         Child->NextSibling = NULL;
441         switch( Parent->Type )
442         {
443         case NODETYPE_BLOCK:
444                 if(Parent->Block.FirstChild == NULL) {
445                         Parent->Block.FirstChild = Parent->Block.LastChild = Child;
446                 }
447                 else {
448                         Parent->Block.LastChild->NextSibling = Child;
449                         Parent->Block.LastChild = Child;
450                 }
451                 break;
452         case NODETYPE_DEFVAR:
453                 if(Parent->DefVar.LevelSizes == NULL) {
454                         Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
455                 }
456                 else {
457                         Parent->DefVar.LevelSizes_Last->NextSibling = Child;
458                         Parent->DefVar.LevelSizes_Last = Child;
459                 }
460                 break;
461         default:
462                 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
463                 break;
464         }
465 }
466
467 tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
468 {
469         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
470         ret->NextSibling = NULL;
471         ret->Line = Parser->CurLine;
472         ret->Type = NODETYPE_IF;
473         ret->If.Condition = Condition;
474         ret->If.True = True;
475         ret->If.False = False;
476         return ret;
477 }
478
479 tAST_Node *AST_NewLoop(tParser *Parser, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
480 {
481         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
482         ret->NextSibling = NULL;
483         ret->Line = Parser->CurLine;
484         ret->Type = NODETYPE_LOOP;
485         ret->For.Init = Init;
486         ret->For.bCheckAfter = !!bPostCheck;
487         ret->For.Condition = Condition;
488         ret->For.Increment = Increment;
489         ret->For.Code = Code;
490         return ret;
491 }
492
493 tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value)
494 {
495         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
496         
497         ret->NextSibling = NULL;
498         ret->Line = Parser->CurLine;
499         ret->Type = NODETYPE_ASSIGN;
500         ret->Assign.Operation = Operation;
501         ret->Assign.Dest = Dest;
502         ret->Assign.Value = Value;
503         
504         return ret;
505 }
506
507 tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value)
508 {
509         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
510         
511         ret->NextSibling = NULL;
512         ret->Line = Parser->CurLine;
513         ret->Type = NODETYPE_CAST;
514         ret->Cast.DataType = Target;
515         ret->Cast.Value = Value;
516         
517         return ret;
518 }
519
520 tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right)
521 {
522         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
523         
524         ret->NextSibling = NULL;
525         ret->Line = Parser->CurLine;
526         ret->Type = Operation;
527         ret->BinOp.Left = Left;
528         ret->BinOp.Right = Right;
529         
530         return ret;
531 }
532
533 /**
534  */
535 tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value)
536 {
537         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
538         
539         ret->NextSibling = NULL;
540         ret->Line = Parser->CurLine;
541         ret->Type = Operation;
542         ret->UniOp.Value = Value;
543         
544         return ret;
545 }
546
547 /**
548  * \brief Create a new string node
549  */
550 tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length)
551 {
552         tAST_Node       *ret = malloc( sizeof(tAST_Node) + Length + 1 );
553         
554         ret->NextSibling = NULL;
555         ret->Line = Parser->CurLine;
556         ret->Type = NODETYPE_STRING;
557         ret->String.Length = Length;
558         memcpy(ret->String.Data, String, Length);
559         ret->String.Data[Length] = '\0';
560         
561         return ret;
562 }
563
564 /**
565  * \brief Create a new integer node
566  */
567 tAST_Node *AST_NewInteger(tParser *Parser, uint64_t Value)
568 {
569         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
570         ret->NextSibling = NULL;
571         ret->Line = Parser->CurLine;
572         ret->Type = NODETYPE_INTEGER;
573         ret->Integer = Value;
574         return ret;
575 }
576
577 /**
578  * \brief Create a new variable reference node
579  */
580 tAST_Node *AST_NewVariable(tParser *Parser, const char *Name)
581 {
582         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
583         ret->NextSibling = NULL;
584         ret->Line = Parser->CurLine;
585         ret->Type = NODETYPE_VARIABLE;
586         strcpy(ret->Variable.Name, Name);
587         return ret;
588 }
589
590 /**
591  * \brief Create a new variable definition node
592  */
593 tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name)
594 {
595         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
596         ret->NextSibling = NULL;
597         ret->Line = Parser->CurLine;
598         ret->Type = NODETYPE_DEFVAR;
599         ret->DefVar.DataType = Type;
600         ret->DefVar.LevelSizes = NULL;
601         strcpy(ret->DefVar.Name, Name);
602         return ret;
603 }
604
605 /**
606  * \brief Create a new runtime constant reference node
607  */
608 tAST_Node *AST_NewConstant(tParser *Parser, const char *Name)
609 {
610         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
611         ret->NextSibling = NULL;
612         ret->Line = Parser->CurLine;
613         ret->Type = NODETYPE_CONSTANT;
614         strcpy(ret->Variable.Name, Name);
615         return ret;
616 }
617
618 /**
619  * \brief Create a function call node
620  * \note Argument list is manipulated using AST_AppendFunctionCallArg
621  */
622 tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name)
623 {
624         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
625         
626         ret->NextSibling = NULL;
627         ret->Line = Parser->CurLine;
628         ret->Type = NODETYPE_FUNCTIONCALL;
629         ret->FunctionCall.FirstArg = NULL;
630         ret->FunctionCall.LastArg = NULL;
631         strcpy(ret->FunctionCall.Name, Name);
632         return ret;
633 }
634
635 /**
636  * \brief Append an argument to a function call
637  */
638 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
639 {
640         if( Node->Type != NODETYPE_FUNCTIONCALL )       return ;
641         
642         if(Node->FunctionCall.LastArg) {
643                 Node->FunctionCall.LastArg->NextSibling = Arg;
644                 Node->FunctionCall.LastArg = Arg;
645         }
646         else {
647                 Node->FunctionCall.FirstArg = Arg;
648                 Node->FunctionCall.LastArg = Arg;
649         }
650 }
651
652 /**
653  * \}
654  */

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