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
68 #define WRITE_N(_buffer, _offset, _len, _dataptr) do { \
69 if(_buffer) memcpy((char*)_buffer + _offset, _dataptr, _len);\
73 #define WRITE_8(_buffer, _offset, _val) do {\
75 WRITE_N(_buffer, _offset, 1, &v);\
77 #define WRITE_16(_buffer, _offset, _val) do {\
79 WRITE_N(_buffer, _offset, 2, &v);\
81 #define WRITE_32(_buffer, _offset, _val) do {\
83 WRITE_N(_buffer, _offset, 4, &v);\
85 #define WRITE_64(_buffer, _offset, _val) do {\
87 WRITE_N(_buffer, _offset, 8, &v);\
89 #define WRITE_REAL(_buffer, _offset, _val) do {\
91 WRITE_N(_buffer, _offset, sizeof(double), &v);\
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); \
101 #define WRITE_NODELIST(_buffer, _offset, _listHead) do {\
104 for(node=(_listHead); node; node = node->NextSibling) {\
106 _offset += AST_WriteNode(_buffer, _offset, node); \
107 WRITE_32(_buffer, ptr, ptr); \
109 if(ptr != -1){ptr -= 4; WRITE_32(_buffer, ptr, 0);} \
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
117 size_t AST_WriteScript(void *Buffer, tAST_Script *Script)
122 for( fcn = Script->Functions; fcn; fcn = fcn->Next )
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
132 WRITE_32(Buffer, ptr, 0); // Clear next for final
138 * \brief Write a node to a file
140 size_t AST_WriteNode(void *Buffer, size_t Offset, tAST_Node *Node)
143 size_t baseOfs = Offset;
146 fprintf(stderr, "Possible Bug - NULL passed to AST_WriteNode\n");
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
161 WRITE_NODELIST(Buffer, Offset, Node->Block.FirstChild);
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);
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);
181 // Looping Construct (For loop node)
183 WRITE_8(Buffer, Offset, Node->For.bCheckAfter);
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);
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);
200 WRITE_8(Buffer, Offset, Node->Cast.DataType);
201 Offset += AST_WriteNode(Buffer, Offset, Node->Cast.Value);
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);
210 WRITE_NODELIST(Buffer, Offset, Node->DefVar.LevelSizes);
215 case NODETYPE_ELEMENT:
216 WRITE_STR(Buffer, Offset, Node->Scope.Name);
217 Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value);
221 case NODETYPE_RETURN:
223 Offset += AST_WriteNode(Buffer, Offset, Node->UniOp.Value);
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);
246 // Node types with no children
249 case NODETYPE_VARIABLE:
250 case NODETYPE_CONSTANT:
251 // TODO: De-Duplicate the strings
252 WRITE_STR(Buffer, Offset, Node->Variable.Name);
254 case NODETYPE_STRING:
255 WRITE_32(Buffer, Offset, Node->String.Length);
256 WRITE_N(Buffer, Offset, Node->String.Length, Node->String.Data);
258 case NODETYPE_INTEGER:
259 WRITE_64(Buffer, Offset, Node->Integer);
262 WRITE_REAL(Buffer, Offset, Node->Real);
266 // fprintf(stderr, "AST_WriteNode: Unknown node type %i\n", Node->Type);
270 return Offset - baseOfs;
274 * \brief Free a node and all subnodes
276 void AST_FreeNode(tAST_Node *Node)
286 for( node = Node->Block.FirstChild; node; )
288 tAST_Node *savedNext = node->NextSibling;
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; )
301 tAST_Node *savedNext = node->NextSibling;
309 AST_FreeNode(Node->If.Condition);
310 AST_FreeNode(Node->If.True);
311 AST_FreeNode(Node->If.False);
314 // Looping Construct (For loop node)
316 AST_FreeNode(Node->For.Init);
317 AST_FreeNode(Node->For.Condition);
318 AST_FreeNode(Node->For.Increment);
319 AST_FreeNode(Node->For.Code);
323 case NODETYPE_ASSIGN:
324 AST_FreeNode(Node->Assign.Dest);
325 AST_FreeNode(Node->Assign.Value);
330 AST_FreeNode(Node->Cast.Value);
334 case NODETYPE_ELEMENT:
335 AST_FreeNode(Node->Scope.Element);
339 case NODETYPE_DEFVAR:
340 for( node = Node->DefVar.LevelSizes; node; )
342 tAST_Node *savedNext = node->NextSibling;
349 case NODETYPE_RETURN:
350 AST_FreeNode(Node->UniOp.Value);
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 );
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;
384 tAST_Node *AST_NewCodeBlock(tParser *Parser)
386 tAST_Node *ret = malloc( sizeof(tAST_Node) );
388 ret->NextSibling = NULL;
389 ret->Line = Parser->CurLine;
390 ret->Type = NODETYPE_BLOCK;
391 ret->Block.FirstChild = NULL;
392 ret->Block.LastChild = NULL;
397 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
399 Child->NextSibling = NULL;
400 switch( Parent->Type )
403 if(Parent->Block.FirstChild == NULL) {
404 Parent->Block.FirstChild = Parent->Block.LastChild = Child;
407 Parent->Block.LastChild->NextSibling = Child;
408 Parent->Block.LastChild = Child;
411 case NODETYPE_DEFVAR:
412 if(Parent->DefVar.LevelSizes == NULL) {
413 Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
416 Parent->DefVar.LevelSizes_Last->NextSibling = Child;
417 Parent->DefVar.LevelSizes_Last = Child;
421 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
426 tAST_Node *AST_NewIf(tParser *Parser, tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
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;
434 ret->If.False = False;
438 tAST_Node *AST_NewLoop(tParser *Parser, tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
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;
452 tAST_Node *AST_NewAssign(tParser *Parser, int Operation, tAST_Node *Dest, tAST_Node *Value)
454 tAST_Node *ret = malloc( sizeof(tAST_Node) );
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;
466 tAST_Node *AST_NewCast(tParser *Parser, int Target, tAST_Node *Value)
468 tAST_Node *ret = malloc( sizeof(tAST_Node) );
470 ret->NextSibling = NULL;
471 ret->Line = Parser->CurLine;
472 ret->Type = NODETYPE_CAST;
473 ret->Cast.DataType = Target;
474 ret->Cast.Value = Value;
479 tAST_Node *AST_NewBinOp(tParser *Parser, int Operation, tAST_Node *Left, tAST_Node *Right)
481 tAST_Node *ret = malloc( sizeof(tAST_Node) );
483 ret->NextSibling = NULL;
484 ret->Line = Parser->CurLine;
485 ret->Type = Operation;
486 ret->BinOp.Left = Left;
487 ret->BinOp.Right = Right;
494 tAST_Node *AST_NewUniOp(tParser *Parser, int Operation, tAST_Node *Value)
496 tAST_Node *ret = malloc( sizeof(tAST_Node) );
498 ret->NextSibling = NULL;
499 ret->Line = Parser->CurLine;
500 ret->Type = Operation;
501 ret->UniOp.Value = Value;
507 * \brief Create a new string node
509 tAST_Node *AST_NewString(tParser *Parser, const char *String, int Length)
511 tAST_Node *ret = malloc( sizeof(tAST_Node) + Length + 1 );
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';
524 * \brief Create a new integer node
526 tAST_Node *AST_NewInteger(tParser *Parser, uint64_t Value)
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;
537 * \brief Create a new variable reference node
539 tAST_Node *AST_NewVariable(tParser *Parser, const char *Name)
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);
550 * \brief Create a new variable definition node
552 tAST_Node *AST_NewDefineVar(tParser *Parser, int Type, const char *Name)
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);
565 * \brief Create a new runtime constant reference node
567 tAST_Node *AST_NewConstant(tParser *Parser, const char *Name)
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);
578 * \brief Create a function call node
579 * \note Argument list is manipulated using AST_AppendFunctionCallArg
581 tAST_Node *AST_NewFunctionCall(tParser *Parser, const char *Name)
583 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
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);
594 tAST_Node *AST_NewMethodCall(tParser *Parser, tAST_Node *Object, const char *Name)
596 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
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);
608 tAST_Node *AST_NewCreateObject(tParser *Parser, const char *Name)
610 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
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);
623 * \brief Append an argument to a function call
625 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
627 if( Node->Type != NODETYPE_FUNCTIONCALL
628 && Node->Type != NODETYPE_CREATEOBJECT
629 && Node->Type != NODETYPE_METHODCALL)
631 fprintf(stderr, "BUG REPORT: AST_AppendFunctionCallArg on an invalid node type (%i)\n", Node->Type);
635 if(Node->FunctionCall.LastArg) {
636 Node->FunctionCall.LastArg->NextSibling = Arg;
637 Node->FunctionCall.LastArg = Arg;
640 Node->FunctionCall.FirstArg = Arg;
641 Node->FunctionCall.LastArg = Arg;
646 * \brief Add a scope node
648 tAST_Node *AST_NewScopeDereference(tParser *Parser, const char *Name, tAST_Node *Child)
650 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
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);
661 * \brief Add a scope node
663 tAST_Node *AST_NewClassElement(tParser *Parser, tAST_Node *Object, const char *Name)
665 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
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);