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)
81 for( node = Node->Block.FirstChild; node; )
83 tAST_Node *savedNext = node->NextSibling;
90 case NODETYPE_FUNCTIONCALL:
91 for( node = Node->FunctionCall.FirstArg; node; )
93 tAST_Node *savedNext = node->NextSibling;
101 AST_FreeNode(Node->If.Condition);
102 AST_FreeNode(Node->If.True);
103 AST_FreeNode(Node->If.False);
106 // Looping Construct (For loop node)
108 AST_FreeNode(Node->For.Init);
109 AST_FreeNode(Node->For.Condition);
110 AST_FreeNode(Node->For.Increment);
111 AST_FreeNode(Node->For.Code);
115 case NODETYPE_ASSIGN:
116 AST_FreeNode(Node->Assign.Dest);
117 AST_FreeNode(Node->Assign.Value);
122 AST_FreeNode(Node->Cast.Value);
126 case NODETYPE_DEFVAR:
127 for( node = Node->DefVar.LevelSizes; node; )
129 tAST_Node *savedNext = node->NextSibling;
136 case NODETYPE_RETURN:
137 AST_FreeNode(Node->UniOp.Value);
143 case NODETYPE_SUBTRACT:
144 case NODETYPE_MULTIPLY:
145 case NODETYPE_DIVIDE:
146 case NODETYPE_MODULO:
147 case NODETYPE_BITSHIFTLEFT:
148 case NODETYPE_BITSHIFTRIGHT:
149 case NODETYPE_BITROTATELEFT:
150 case NODETYPE_BWAND: case NODETYPE_LOGICALAND:
151 case NODETYPE_BWOR: case NODETYPE_LOGICALOR:
152 case NODETYPE_BWXOR: case NODETYPE_LOGICALXOR:
153 case NODETYPE_EQUALS:
154 case NODETYPE_LESSTHAN:
155 case NODETYPE_GREATERTHAN:
156 AST_FreeNode( Node->BinOp.Left );
157 AST_FreeNode( Node->BinOp.Right );
160 // Node types with no children
161 case NODETYPE_NOP: break;
162 case NODETYPE_VARIABLE: break;
163 case NODETYPE_CONSTANT: break;
164 case NODETYPE_STRING: break;
165 case NODETYPE_INTEGER: break;
166 case NODETYPE_REAL: break;
171 tAST_Node *AST_NewCodeBlock(void)
173 tAST_Node *ret = malloc( sizeof(tAST_Node) );
175 ret->NextSibling = NULL;
176 ret->Type = NODETYPE_BLOCK;
177 ret->Block.FirstChild = NULL;
178 ret->Block.LastChild = NULL;
183 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
185 Child->NextSibling = NULL;
186 switch( Parent->Type )
189 if(Parent->Block.FirstChild == NULL) {
190 Parent->Block.FirstChild = Parent->Block.LastChild = Child;
193 Parent->Block.LastChild->NextSibling = Child;
194 Parent->Block.LastChild = Child;
197 case NODETYPE_DEFVAR:
198 if(Parent->DefVar.LevelSizes == NULL) {
199 Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
202 Parent->DefVar.LevelSizes_Last->NextSibling = Child;
203 Parent->DefVar.LevelSizes_Last = Child;
207 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
212 tAST_Node *AST_NewIf(tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
214 tAST_Node *ret = malloc( sizeof(tAST_Node) );
215 ret->NextSibling = NULL;
216 ret->Type = NODETYPE_IF;
217 ret->If.Condition = Condition;
219 ret->If.False = False;
223 tAST_Node *AST_NewLoop(tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
225 tAST_Node *ret = malloc( sizeof(tAST_Node) );
226 ret->NextSibling = NULL;
227 ret->Type = NODETYPE_LOOP;
228 ret->For.Init = Init;
229 ret->For.bCheckAfter = !!bPostCheck;
230 ret->For.Condition = Condition;
231 ret->For.Increment = Increment;
232 ret->For.Code = Code;
236 tAST_Node *AST_NewAssign(int Operation, tAST_Node *Dest, tAST_Node *Value)
238 tAST_Node *ret = malloc( sizeof(tAST_Node) );
240 ret->NextSibling = NULL;
241 ret->Type = NODETYPE_ASSIGN;
242 ret->Assign.Operation = Operation;
243 ret->Assign.Dest = Dest;
244 ret->Assign.Value = Value;
249 tAST_Node *AST_NewBinOp(int Operation, tAST_Node *Left, tAST_Node *Right)
251 tAST_Node *ret = malloc( sizeof(tAST_Node) );
253 ret->NextSibling = NULL;
254 ret->Type = Operation;
255 ret->BinOp.Left = Left;
256 ret->BinOp.Right = Right;
263 tAST_Node *AST_NewUniOp(int Operation, tAST_Node *Value)
265 tAST_Node *ret = malloc( sizeof(tAST_Node) );
267 ret->NextSibling = NULL;
268 ret->Type = Operation;
269 ret->UniOp.Value = Value;
275 * \brief Create a new string node
277 tAST_Node *AST_NewString(const char *String, int Length)
279 tAST_Node *ret = malloc( sizeof(tAST_Node) + Length + 1 );
281 ret->NextSibling = NULL;
282 ret->Type = NODETYPE_STRING;
283 ret->String.Length = Length;
284 memcpy(ret->String.Data, String, Length);
285 ret->String.Data[Length] = '\0';
291 * \brief Create a new integer node
293 tAST_Node *AST_NewInteger(uint64_t Value)
295 tAST_Node *ret = malloc( sizeof(tAST_Node) );
296 ret->NextSibling = NULL;
297 ret->Type = NODETYPE_INTEGER;
298 ret->Integer = Value;
303 * \brief Create a new variable reference node
305 tAST_Node *AST_NewVariable(const char *Name)
307 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
308 ret->NextSibling = NULL;
309 ret->Type = NODETYPE_VARIABLE;
310 strcpy(ret->Variable.Name, Name);
315 * \brief Create a new variable definition node
317 tAST_Node *AST_NewDefineVar(int Type, const char *Name)
319 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
320 ret->NextSibling = NULL;
321 ret->Type = NODETYPE_DEFVAR;
322 ret->DefVar.DataType = Type;
323 ret->DefVar.LevelSizes = NULL;
324 strcpy(ret->DefVar.Name, Name);
329 * \brief Create a new runtime constant reference node
331 tAST_Node *AST_NewConstant(const char *Name)
333 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
334 ret->NextSibling = NULL;
335 ret->Type = NODETYPE_CONSTANT;
336 strcpy(ret->Variable.Name, Name);
341 * \brief Create a function call node
342 * \note Argument list is manipulated using AST_AppendFunctionCallArg
344 tAST_Node *AST_NewFunctionCall(const char *Name)
346 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
348 ret->NextSibling = NULL;
349 ret->Type = NODETYPE_FUNCTIONCALL;
350 ret->FunctionCall.FirstArg = NULL;
351 ret->FunctionCall.LastArg = NULL;
352 strcpy(ret->FunctionCall.Name, Name);
357 * \brief Append an argument to a function call
359 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
361 if( Node->Type != NODETYPE_FUNCTIONCALL ) return ;
363 if(Node->FunctionCall.LastArg) {
364 Node->FunctionCall.LastArg->NextSibling = Arg;
365 Node->FunctionCall.LastArg = Arg;
368 Node->FunctionCall.FirstArg = Arg;
369 Node->FunctionCall.LastArg = Arg;