3 * - Script AST Manipulator
11 tAST_Script *AST_NewScript(void)
13 tAST_Script *ret = malloc( sizeof(tAST_Script) );
15 ret->Functions = NULL;
16 ret->LastFunction = NULL;
22 * \brief Append a function to a script
24 tAST_Function *AST_AppendFunction(tAST_Script *Script, const char *Name)
28 ret = malloc( sizeof(tAST_Function) + strlen(Name) + 1 );
30 strcpy(ret->Name, Name);
32 ret->Arguments = NULL;
34 if(Script->LastFunction == NULL) {
35 Script->Functions = Script->LastFunction = ret;
38 Script->LastFunction->Next = ret;
39 Script->LastFunction = ret;
45 void AST_AppendFunctionArg(tAST_Function *Function, tAST_Node *Node)
47 if( !Function->Arguments ) {
48 Function->Arguments_Last = Function->Arguments = Node;
51 Function->Arguments_Last->NextSibling = Node;
52 Function->Arguments_Last = Node;
57 * \brief Set the code for a function
59 void AST_SetFunctionCode(tAST_Function *Function, tAST_Node *Root)
61 Function->Code = Root;
65 * \name Node Manipulation
69 * \brief Get the in-memory size of a node
71 size_t AST_GetNodeSize(tAST_Node *Node)
79 ret = sizeof(tAST_Node*) + sizeof(tAST_NodeType)
80 + sizeof(const char *) + sizeof(int);
86 ret += sizeof(Node->Block);
87 for( node = Node->Block.FirstChild; node; )
89 ret += AST_GetNodeSize(node);
90 node = node->NextSibling;
95 case NODETYPE_FUNCTIONCALL:
96 ret += sizeof(Node->FunctionCall) + strlen(Node->FunctionCall.Name) + 1;
97 for( node = Node->FunctionCall.FirstArg; node; )
99 ret += AST_GetNodeSize(node);
100 node = node->NextSibling;
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);
112 // Looping Construct (For loop node)
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);
122 case NODETYPE_ASSIGN:
123 ret += sizeof(Node->Assign);
124 ret += AST_GetNodeSize(Node->Assign.Dest);
125 ret += AST_GetNodeSize(Node->Assign.Value);
130 ret += sizeof(Node->Cast);
131 ret += AST_GetNodeSize(Node->Cast.Value);
135 case NODETYPE_DEFVAR:
136 ret += sizeof(Node->DefVar) + strlen(Node->DefVar.Name) + 1;
137 for( node = Node->DefVar.LevelSizes; node; )
139 ret += AST_GetNodeSize(node);
140 node = node->NextSibling;
145 case NODETYPE_RETURN:
146 ret += sizeof(Node->UniOp);
147 ret += AST_GetNodeSize(Node->UniOp.Value);
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 );
171 // Node types with no children
174 case NODETYPE_VARIABLE:
175 case NODETYPE_CONSTANT:
176 ret += sizeof(Node->Variable) + strlen(Node->Variable.Name) + 1;
178 case NODETYPE_STRING:
179 ret += sizeof(Node->String) + Node->String.Length;
181 case NODETYPE_INTEGER:
182 ret += sizeof(Node->Integer);
185 ret += sizeof(Node->Real);
193 * \brief Write a node to a file
195 void AST_WriteNode(FILE *FP, tAST_Node *Node)
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);
209 ret = sizeof(tAST_Node*) + sizeof(tAST_NodeType)
210 + sizeof(const char *) + sizeof(int);
216 ret += sizeof(Node->Block);
217 for( node = Node->Block.FirstChild; node; )
219 ret += AST_GetNodeSize(node);
220 node = node->NextSibling;
225 case NODETYPE_FUNCTIONCALL:
226 ret += sizeof(Node->FunctionCall) + strlen(Node->FunctionCall.Name) + 1;
227 for( node = Node->FunctionCall.FirstArg; node; )
229 ret += AST_GetNodeSize(node);
230 node = node->NextSibling;
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);
242 // Looping Construct (For loop node)
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);
252 case NODETYPE_ASSIGN:
253 ret += sizeof(Node->Assign);
254 ret += AST_GetNodeSize(Node->Assign.Dest);
255 ret += AST_GetNodeSize(Node->Assign.Value);
260 ret += sizeof(Node->Cast);
261 ret += AST_GetNodeSize(Node->Cast.Value);
265 case NODETYPE_DEFVAR:
266 ret += sizeof(Node->DefVar) + strlen(Node->DefVar.Name) + 1;
267 for( node = Node->DefVar.LevelSizes; node; )
269 ret += AST_GetNodeSize(node);
270 node = node->NextSibling;
275 case NODETYPE_RETURN:
276 ret += sizeof(Node->UniOp);
277 ret += AST_GetNodeSize(Node->UniOp.Value);
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 );
301 // Node types with no children
304 case NODETYPE_VARIABLE:
305 case NODETYPE_CONSTANT:
306 ret += sizeof(Node->Variable) + strlen(Node->Variable.Name) + 1;
308 case NODETYPE_STRING:
309 ret += sizeof(Node->String) + Node->String.Length;
311 case NODETYPE_INTEGER:
312 ret += sizeof(Node->Integer);
315 ret += sizeof(Node->Real);
323 * \brief Free a node and all subnodes
325 void AST_FreeNode(tAST_Node *Node)
335 for( node = Node->Block.FirstChild; node; )
337 tAST_Node *savedNext = node->NextSibling;
344 case NODETYPE_FUNCTIONCALL:
345 for( node = Node->FunctionCall.FirstArg; node; )
347 tAST_Node *savedNext = node->NextSibling;
355 AST_FreeNode(Node->If.Condition);
356 AST_FreeNode(Node->If.True);
357 AST_FreeNode(Node->If.False);
360 // Looping Construct (For loop node)
362 AST_FreeNode(Node->For.Init);
363 AST_FreeNode(Node->For.Condition);
364 AST_FreeNode(Node->For.Increment);
365 AST_FreeNode(Node->For.Code);
369 case NODETYPE_ASSIGN:
370 AST_FreeNode(Node->Assign.Dest);
371 AST_FreeNode(Node->Assign.Value);
376 AST_FreeNode(Node->Cast.Value);
380 case NODETYPE_DEFVAR:
381 for( node = Node->DefVar.LevelSizes; node; )
383 tAST_Node *savedNext = node->NextSibling;
390 case NODETYPE_RETURN:
391 AST_FreeNode(Node->UniOp.Value);
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 );
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;
425 tAST_Node *AST_NewCodeBlock(void)
427 tAST_Node *ret = malloc( sizeof(tAST_Node) );
429 ret->NextSibling = NULL;
430 //ret->Line = Parser->CurLine;
431 ret->Type = NODETYPE_BLOCK;
432 ret->Block.FirstChild = NULL;
433 ret->Block.LastChild = NULL;
438 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
440 Child->NextSibling = NULL;
441 switch( Parent->Type )
444 if(Parent->Block.FirstChild == NULL) {
445 Parent->Block.FirstChild = Parent->Block.LastChild = Child;
448 Parent->Block.LastChild->NextSibling = Child;
449 Parent->Block.LastChild = Child;
452 case NODETYPE_DEFVAR:
453 if(Parent->DefVar.LevelSizes == NULL) {
454 Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
457 Parent->DefVar.LevelSizes_Last->NextSibling = Child;
458 Parent->DefVar.LevelSizes_Last = Child;
462 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
467 tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
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;
475 ret->If.False = False;
479 tAST_Node *AST_NewLoop(tParser *Parser, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
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;
493 tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value)
495 tAST_Node *ret = malloc( sizeof(tAST_Node) );
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;
507 tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value)
509 tAST_Node *ret = malloc( sizeof(tAST_Node) );
511 ret->NextSibling = NULL;
512 ret->Line = Parser->CurLine;
513 ret->Type = NODETYPE_CAST;
514 ret->Cast.DataType = Target;
515 ret->Cast.Value = Value;
520 tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right)
522 tAST_Node *ret = malloc( sizeof(tAST_Node) );
524 ret->NextSibling = NULL;
525 ret->Line = Parser->CurLine;
526 ret->Type = Operation;
527 ret->BinOp.Left = Left;
528 ret->BinOp.Right = Right;
535 tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value)
537 tAST_Node *ret = malloc( sizeof(tAST_Node) );
539 ret->NextSibling = NULL;
540 ret->Line = Parser->CurLine;
541 ret->Type = Operation;
542 ret->UniOp.Value = Value;
548 * \brief Create a new string node
550 tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length)
552 tAST_Node *ret = malloc( sizeof(tAST_Node) + Length + 1 );
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';
565 * \brief Create a new integer node
567 tAST_Node *AST_NewInteger(tParser *Parser, uint64_t Value)
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;
578 * \brief Create a new variable reference node
580 tAST_Node *AST_NewVariable(tParser *Parser, const char *Name)
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);
591 * \brief Create a new variable definition node
593 tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name)
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);
606 * \brief Create a new runtime constant reference node
608 tAST_Node *AST_NewConstant(tParser *Parser, const char *Name)
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);
619 * \brief Create a function call node
620 * \note Argument list is manipulated using AST_AppendFunctionCallArg
622 tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name)
624 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
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);
636 * \brief Append an argument to a function call
638 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
640 if( Node->Type != NODETYPE_FUNCTIONCALL ) return ;
642 if(Node->FunctionCall.LastArg) {
643 Node->FunctionCall.LastArg->NextSibling = Arg;
644 Node->FunctionCall.LastArg = Arg;
647 Node->FunctionCall.FirstArg = Arg;
648 Node->FunctionCall.LastArg = Arg;