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);
192 * \brief Write a node to a file
194 void AST_WriteNode(FILE *FP, tAST_Node *Node)
201 ptr = ftell(FP) + AST_GetNodeSize(Node);
202 fwrite(&ptr, sizeof(ptr), 1, FP);
203 fwrite(&Node->Type, sizeof(Node->Type), 1, FP);
204 ptr = 0; fwrite(&ptr, sizeof(ptr), 1, FP); // File
205 fwrite(&Node->Line, sizeof(Node->Line), 1, FP);
207 ret = sizeof(tAST_Node*) + sizeof(tAST_NodeType)
208 + sizeof(const char *) + sizeof(int);
214 ret += sizeof(Node->Block);
215 for( node = Node->Block.FirstChild; node; )
217 ret += AST_GetNodeSize(node);
218 node = node->NextSibling;
223 case NODETYPE_FUNCTIONCALL:
224 ret += sizeof(Node->FunctionCall) + strlen(Node->FunctionCall.Name) + 1;
225 for( node = Node->FunctionCall.FirstArg; node; )
227 ret += AST_GetNodeSize(node);
228 node = node->NextSibling;
234 ret += sizeof(Node->If);
235 ret += AST_GetNodeSize(Node->If.Condition);
236 ret += AST_GetNodeSize(Node->If.True);
237 ret += AST_GetNodeSize(Node->If.False);
240 // Looping Construct (For loop node)
242 ret += sizeof(Node->For);
243 ret += AST_GetNodeSize(Node->For.Init);
244 ret += AST_GetNodeSize(Node->For.Condition);
245 ret += AST_GetNodeSize(Node->For.Increment);
246 ret += AST_GetNodeSize(Node->For.Code);
250 case NODETYPE_ASSIGN:
251 ret += sizeof(Node->Assign);
252 ret += AST_GetNodeSize(Node->Assign.Dest);
253 ret += AST_GetNodeSize(Node->Assign.Value);
258 ret += sizeof(Node->Cast);
259 ret += AST_GetNodeSize(Node->Cast.Value);
263 case NODETYPE_DEFVAR:
264 ret += sizeof(Node->DefVar) + strlen(Node->DefVar.Name) + 1;
265 for( node = Node->DefVar.LevelSizes; node; )
267 ret += AST_GetNodeSize(node);
268 node = node->NextSibling;
273 case NODETYPE_RETURN:
274 ret += sizeof(Node->UniOp);
275 ret += AST_GetNodeSize(Node->UniOp.Value);
281 case NODETYPE_SUBTRACT:
282 case NODETYPE_MULTIPLY:
283 case NODETYPE_DIVIDE:
284 case NODETYPE_MODULO:
285 case NODETYPE_BITSHIFTLEFT:
286 case NODETYPE_BITSHIFTRIGHT:
287 case NODETYPE_BITROTATELEFT:
288 case NODETYPE_BWAND: case NODETYPE_LOGICALAND:
289 case NODETYPE_BWOR: case NODETYPE_LOGICALOR:
290 case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR:
291 case NODETYPE_EQUALS:
292 case NODETYPE_LESSTHAN:
293 case NODETYPE_GREATERTHAN:
294 ret += sizeof(Node->BinOp);
295 ret += AST_GetNodeSize( Node->BinOp.Left );
296 ret += AST_GetNodeSize( Node->BinOp.Right );
299 // Node types with no children
302 case NODETYPE_VARIABLE:
303 case NODETYPE_CONSTANT:
304 ret += sizeof(Node->Variable) + strlen(Node->Variable.Name) + 1;
306 case NODETYPE_STRING:
307 ret += sizeof(Node->String) + Node->String.Length;
309 case NODETYPE_INTEGER:
310 ret += sizeof(Node->Integer);
313 ret += sizeof(Node->Real);
320 * \brief Free a node and all subnodes
322 void AST_FreeNode(tAST_Node *Node)
332 for( node = Node->Block.FirstChild; node; )
334 tAST_Node *savedNext = node->NextSibling;
341 case NODETYPE_FUNCTIONCALL:
342 for( node = Node->FunctionCall.FirstArg; node; )
344 tAST_Node *savedNext = node->NextSibling;
352 AST_FreeNode(Node->If.Condition);
353 AST_FreeNode(Node->If.True);
354 AST_FreeNode(Node->If.False);
357 // Looping Construct (For loop node)
359 AST_FreeNode(Node->For.Init);
360 AST_FreeNode(Node->For.Condition);
361 AST_FreeNode(Node->For.Increment);
362 AST_FreeNode(Node->For.Code);
366 case NODETYPE_ASSIGN:
367 AST_FreeNode(Node->Assign.Dest);
368 AST_FreeNode(Node->Assign.Value);
373 AST_FreeNode(Node->Cast.Value);
377 case NODETYPE_DEFVAR:
378 for( node = Node->DefVar.LevelSizes; node; )
380 tAST_Node *savedNext = node->NextSibling;
387 case NODETYPE_RETURN:
388 AST_FreeNode(Node->UniOp.Value);
394 case NODETYPE_SUBTRACT:
395 case NODETYPE_MULTIPLY:
396 case NODETYPE_DIVIDE:
397 case NODETYPE_MODULO:
398 case NODETYPE_BITSHIFTLEFT:
399 case NODETYPE_BITSHIFTRIGHT:
400 case NODETYPE_BITROTATELEFT:
401 case NODETYPE_BWAND: case NODETYPE_LOGICALAND:
402 case NODETYPE_BWOR: case NODETYPE_LOGICALOR:
403 case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR:
404 case NODETYPE_EQUALS:
405 case NODETYPE_LESSTHAN:
406 case NODETYPE_GREATERTHAN:
407 AST_FreeNode( Node->BinOp.Left );
408 AST_FreeNode( Node->BinOp.Right );
411 // Node types with no children
412 case NODETYPE_NOP: break;
413 case NODETYPE_VARIABLE: break;
414 case NODETYPE_CONSTANT: break;
415 case NODETYPE_STRING: break;
416 case NODETYPE_INTEGER: break;
417 case NODETYPE_REAL: break;
422 tAST_Node *AST_NewCodeBlock(void)
424 tAST_Node *ret = malloc( sizeof(tAST_Node) );
426 ret->NextSibling = NULL;
427 //ret->Line = Parser->CurLine;
428 ret->Type = NODETYPE_BLOCK;
429 ret->Block.FirstChild = NULL;
430 ret->Block.LastChild = NULL;
435 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
437 Child->NextSibling = NULL;
438 switch( Parent->Type )
441 if(Parent->Block.FirstChild == NULL) {
442 Parent->Block.FirstChild = Parent->Block.LastChild = Child;
445 Parent->Block.LastChild->NextSibling = Child;
446 Parent->Block.LastChild = Child;
449 case NODETYPE_DEFVAR:
450 if(Parent->DefVar.LevelSizes == NULL) {
451 Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
454 Parent->DefVar.LevelSizes_Last->NextSibling = Child;
455 Parent->DefVar.LevelSizes_Last = Child;
459 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
464 tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
466 tAST_Node *ret = malloc( sizeof(tAST_Node) );
467 ret->NextSibling = NULL;
468 ret->Line = Parser->CurLine;
469 ret->Type = NODETYPE_IF;
470 ret->If.Condition = Condition;
472 ret->If.False = False;
476 tAST_Node *AST_NewLoop(tParser *Parser, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
478 tAST_Node *ret = malloc( sizeof(tAST_Node) );
479 ret->NextSibling = NULL;
480 ret->Line = Parser->CurLine;
481 ret->Type = NODETYPE_LOOP;
482 ret->For.Init = Init;
483 ret->For.bCheckAfter = !!bPostCheck;
484 ret->For.Condition = Condition;
485 ret->For.Increment = Increment;
486 ret->For.Code = Code;
490 tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value)
492 tAST_Node *ret = malloc( sizeof(tAST_Node) );
494 ret->NextSibling = NULL;
495 ret->Line = Parser->CurLine;
496 ret->Type = NODETYPE_ASSIGN;
497 ret->Assign.Operation = Operation;
498 ret->Assign.Dest = Dest;
499 ret->Assign.Value = Value;
504 tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value)
506 tAST_Node *ret = malloc( sizeof(tAST_Node) );
508 ret->NextSibling = NULL;
509 ret->Line = Parser->CurLine;
510 ret->Type = NODETYPE_CAST;
511 ret->Cast.DataType = Target;
512 ret->Cast.Value = Value;
517 tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right)
519 tAST_Node *ret = malloc( sizeof(tAST_Node) );
521 ret->NextSibling = NULL;
522 ret->Line = Parser->CurLine;
523 ret->Type = Operation;
524 ret->BinOp.Left = Left;
525 ret->BinOp.Right = Right;
532 tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value)
534 tAST_Node *ret = malloc( sizeof(tAST_Node) );
536 ret->NextSibling = NULL;
537 ret->Line = Parser->CurLine;
538 ret->Type = Operation;
539 ret->UniOp.Value = Value;
545 * \brief Create a new string node
547 tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length)
549 tAST_Node *ret = malloc( sizeof(tAST_Node) + Length + 1 );
551 ret->NextSibling = NULL;
552 ret->Line = Parser->CurLine;
553 ret->Type = NODETYPE_STRING;
554 ret->String.Length = Length;
555 memcpy(ret->String.Data, String, Length);
556 ret->String.Data[Length] = '\0';
562 * \brief Create a new integer node
564 tAST_Node *AST_NewInteger(tParser *Parser, uint64_t Value)
566 tAST_Node *ret = malloc( sizeof(tAST_Node) );
567 ret->NextSibling = NULL;
568 ret->Line = Parser->CurLine;
569 ret->Type = NODETYPE_INTEGER;
570 ret->Integer = Value;
575 * \brief Create a new variable reference node
577 tAST_Node *AST_NewVariable(tParser *Parser, const char *Name)
579 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
580 ret->NextSibling = NULL;
581 ret->Line = Parser->CurLine;
582 ret->Type = NODETYPE_VARIABLE;
583 strcpy(ret->Variable.Name, Name);
588 * \brief Create a new variable definition node
590 tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name)
592 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
593 ret->NextSibling = NULL;
594 ret->Line = Parser->CurLine;
595 ret->Type = NODETYPE_DEFVAR;
596 ret->DefVar.DataType = Type;
597 ret->DefVar.LevelSizes = NULL;
598 strcpy(ret->DefVar.Name, Name);
603 * \brief Create a new runtime constant reference node
605 tAST_Node *AST_NewConstant(tParser *Parser, const char *Name)
607 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
608 ret->NextSibling = NULL;
609 ret->Line = Parser->CurLine;
610 ret->Type = NODETYPE_CONSTANT;
611 strcpy(ret->Variable.Name, Name);
616 * \brief Create a function call node
617 * \note Argument list is manipulated using AST_AppendFunctionCallArg
619 tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name)
621 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
623 ret->NextSibling = NULL;
624 ret->Line = Parser->CurLine;
625 ret->Type = NODETYPE_FUNCTIONCALL;
626 ret->FunctionCall.FirstArg = NULL;
627 ret->FunctionCall.LastArg = NULL;
628 strcpy(ret->FunctionCall.Name, Name);
633 * \brief Append an argument to a function call
635 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
637 if( Node->Type != NODETYPE_FUNCTIONCALL ) return ;
639 if(Node->FunctionCall.LastArg) {
640 Node->FunctionCall.LastArg->NextSibling = Arg;
641 Node->FunctionCall.LastArg = Arg;
644 Node->FunctionCall.FirstArg = Arg;
645 Node->FunctionCall.LastArg = Arg;