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 Free a node and all subnodes
71 void AST_FreeNode(tAST_Node *Node)
78 for( node = Node->Block.FirstChild; node; )
80 tAST_Node *savedNext = node->NextSibling;
87 case NODETYPE_FUNCTIONCALL:
88 for( node = Node->FunctionCall.FirstArg; node; )
90 tAST_Node *savedNext = node->NextSibling;
98 AST_FreeNode(Node->Assign.Dest);
99 AST_FreeNode(Node->Assign.Value);
104 AST_FreeNode(Node->Cast.Value);
108 case NODETYPE_DEFVAR:
109 for( node = Node->DefVar.LevelSizes; node; )
111 tAST_Node *savedNext = node->NextSibling;
118 case NODETYPE_RETURN:
119 AST_FreeNode(Node->UniOp.Value);
125 case NODETYPE_SUBTRACT:
126 case NODETYPE_MULTIPLY:
127 case NODETYPE_DIVIDE:
128 case NODETYPE_MODULO:
129 case NODETYPE_BITSHIFTLEFT:
130 case NODETYPE_BITSHIFTRIGHT:
131 case NODETYPE_BITROTATELEFT:
132 case NODETYPE_BWAND: case NODETYPE_LOGICALAND:
133 case NODETYPE_BWOR: case NODETYPE_LOGICALOR:
134 case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR:
135 case NODETYPE_EQUALS:
136 case NODETYPE_LESSTHAN:
137 case NODETYPE_GREATERTHAN:
138 AST_FreeNode( Node->BinOp.Left );
139 AST_FreeNode( Node->BinOp.Right );
142 // Node types with no children
143 case NODETYPE_NOP: break;
144 case NODETYPE_VARIABLE: break;
145 case NODETYPE_CONSTANT: break;
146 case NODETYPE_STRING: break;
147 case NODETYPE_INTEGER: break;
148 case NODETYPE_REAL: break;
153 tAST_Node *AST_NewCodeBlock(void)
155 tAST_Node *ret = malloc( sizeof(tAST_Node) );
157 ret->NextSibling = NULL;
158 ret->Type = NODETYPE_BLOCK;
159 ret->Block.FirstChild = NULL;
160 ret->Block.LastChild = NULL;
165 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
167 Child->NextSibling = NULL;
168 switch( Parent->Type )
171 if(Parent->Block.FirstChild == NULL) {
172 Parent->Block.FirstChild = Parent->Block.LastChild = Child;
175 Parent->Block.LastChild->NextSibling = Child;
176 Parent->Block.LastChild = Child;
179 case NODETYPE_DEFVAR:
180 if(Parent->DefVar.LevelSizes == NULL) {
181 Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
184 Parent->DefVar.LevelSizes_Last->NextSibling = Child;
185 Parent->DefVar.LevelSizes_Last = Child;
189 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
194 tAST_Node *AST_NewAssign(int Operation, tAST_Node *Dest, tAST_Node *Value)
196 tAST_Node *ret = malloc( sizeof(tAST_Node) );
198 ret->NextSibling = NULL;
199 ret->Type = NODETYPE_ASSIGN;
200 ret->Assign.Operation = Operation;
201 ret->Assign.Dest = Dest;
202 ret->Assign.Value = Value;
207 tAST_Node *AST_NewBinOp(int Operation, tAST_Node *Left, tAST_Node *Right)
209 tAST_Node *ret = malloc( sizeof(tAST_Node) );
211 ret->NextSibling = NULL;
212 ret->Type = Operation;
213 ret->BinOp.Left = Left;
214 ret->BinOp.Right = Right;
221 tAST_Node *AST_NewUniOp(int Operation, tAST_Node *Value)
223 tAST_Node *ret = malloc( sizeof(tAST_Node) );
225 ret->NextSibling = NULL;
226 ret->Type = Operation;
227 ret->UniOp.Value = Value;
233 * \brief Create a new string node
235 tAST_Node *AST_NewString(const char *String, int Length)
237 tAST_Node *ret = malloc( sizeof(tAST_Node) + Length + 1 );
239 ret->NextSibling = NULL;
240 ret->Type = NODETYPE_STRING;
241 ret->String.Length = Length;
242 memcpy(ret->String.Data, String, Length);
243 ret->String.Data[Length] = '\0';
249 * \brief Create a new integer node
251 tAST_Node *AST_NewInteger(uint64_t Value)
253 tAST_Node *ret = malloc( sizeof(tAST_Node) );
254 ret->NextSibling = NULL;
255 ret->Type = NODETYPE_INTEGER;
256 ret->Integer = Value;
261 * \brief Create a new variable reference node
263 tAST_Node *AST_NewVariable(const char *Name)
265 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
266 ret->NextSibling = NULL;
267 ret->Type = NODETYPE_VARIABLE;
268 strcpy(ret->Variable.Name, Name);
273 * \brief Create a new variable definition node
275 tAST_Node *AST_NewDefineVar(int Type, const char *Name)
277 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
278 ret->NextSibling = NULL;
279 ret->Type = NODETYPE_DEFVAR;
280 ret->DefVar.DataType = Type;
281 ret->DefVar.LevelSizes = NULL;
282 strcpy(ret->DefVar.Name, Name);
287 * \brief Create a new runtime constant reference node
289 tAST_Node *AST_NewConstant(const char *Name)
291 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
292 ret->NextSibling = NULL;
293 ret->Type = NODETYPE_CONSTANT;
294 strcpy(ret->Variable.Name, Name);
299 * \brief Create a function call node
300 * \note Argument list is manipulated using AST_AppendFunctionCallArg
302 tAST_Node *AST_NewFunctionCall(const char *Name)
304 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
306 ret->NextSibling = NULL;
307 ret->Type = NODETYPE_FUNCTIONCALL;
308 ret->FunctionCall.FirstArg = NULL;
309 ret->FunctionCall.LastArg = NULL;
310 strcpy(ret->FunctionCall.Name, Name);
315 * \brief Append an argument to a function call
317 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
319 if( Node->Type != NODETYPE_FUNCTIONCALL ) return ;
321 if(Node->FunctionCall.LastArg) {
322 Node->FunctionCall.LastArg->NextSibling = Arg;
323 Node->FunctionCall.LastArg = Arg;
326 Node->FunctionCall.FirstArg = Arg;
327 Node->FunctionCall.LastArg = Arg;