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->Line = giLineNumber;
177 ret->Type = NODETYPE_BLOCK;
178 ret->Block.FirstChild = NULL;
179 ret->Block.LastChild = NULL;
184 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
186 Child->NextSibling = NULL;
187 switch( Parent->Type )
190 if(Parent->Block.FirstChild == NULL) {
191 Parent->Block.FirstChild = Parent->Block.LastChild = Child;
194 Parent->Block.LastChild->NextSibling = Child;
195 Parent->Block.LastChild = Child;
198 case NODETYPE_DEFVAR:
199 if(Parent->DefVar.LevelSizes == NULL) {
200 Parent->DefVar.LevelSizes = Parent->DefVar.LevelSizes_Last = Child;
203 Parent->DefVar.LevelSizes_Last->NextSibling = Child;
204 Parent->DefVar.LevelSizes_Last = Child;
208 fprintf(stderr, "BUG REPORT: AST_AppendNode on an invalid node type (%i)\n", Parent->Type);
213 tAST_Node *AST_NewIf(tAST_Node *Condition, tAST_Node *True, tAST_Node *False)
215 tAST_Node *ret = malloc( sizeof(tAST_Node) );
216 ret->NextSibling = NULL;
217 //ret->Line = giLineNumber;
218 ret->Type = NODETYPE_IF;
219 ret->If.Condition = Condition;
221 ret->If.False = False;
225 tAST_Node *AST_NewLoop(tAST_Node *Init, int bPostCheck, tAST_Node *Condition, tAST_Node *Increment, tAST_Node *Code)
227 tAST_Node *ret = malloc( sizeof(tAST_Node) );
228 ret->NextSibling = NULL;
229 //ret->Line = giLineNumber;
230 ret->Type = NODETYPE_LOOP;
231 ret->For.Init = Init;
232 ret->For.bCheckAfter = !!bPostCheck;
233 ret->For.Condition = Condition;
234 ret->For.Increment = Increment;
235 ret->For.Code = Code;
239 tAST_Node *AST_NewAssign(int Operation, tAST_Node *Dest, tAST_Node *Value)
241 tAST_Node *ret = malloc( sizeof(tAST_Node) );
243 ret->NextSibling = NULL;
244 //ret->Line = giLineNumber;
245 ret->Type = NODETYPE_ASSIGN;
246 ret->Assign.Operation = Operation;
247 ret->Assign.Dest = Dest;
248 ret->Assign.Value = Value;
253 tAST_Node *AST_NewCast(int Target, tAST_Node *Value)
255 tAST_Node *ret = malloc( sizeof(tAST_Node) );
257 ret->NextSibling = NULL;
258 //ret->Line = giLineNumber;
259 ret->Type = NODETYPE_CAST;
260 ret->Cast.DataType = Target;
261 ret->Cast.Value = Value;
266 tAST_Node *AST_NewBinOp(int Operation, tAST_Node *Left, tAST_Node *Right)
268 tAST_Node *ret = malloc( sizeof(tAST_Node) );
270 ret->NextSibling = NULL;
271 //ret->Line = giLineNumber;
272 ret->Type = Operation;
273 ret->BinOp.Left = Left;
274 ret->BinOp.Right = Right;
281 tAST_Node *AST_NewUniOp(int Operation, tAST_Node *Value)
283 tAST_Node *ret = malloc( sizeof(tAST_Node) );
285 ret->NextSibling = NULL;
286 //ret->Line = giLineNumber;
287 ret->Type = Operation;
288 ret->UniOp.Value = Value;
294 * \brief Create a new string node
296 tAST_Node *AST_NewString(const char *String, int Length)
298 tAST_Node *ret = malloc( sizeof(tAST_Node) + Length + 1 );
300 ret->NextSibling = NULL;
301 //ret->Line = giLineNumber;
302 ret->Type = NODETYPE_STRING;
303 ret->String.Length = Length;
304 memcpy(ret->String.Data, String, Length);
305 ret->String.Data[Length] = '\0';
311 * \brief Create a new integer node
313 tAST_Node *AST_NewInteger(uint64_t Value)
315 tAST_Node *ret = malloc( sizeof(tAST_Node) );
316 ret->NextSibling = NULL;
317 //ret->Line = giLineNumber;
318 ret->Type = NODETYPE_INTEGER;
319 ret->Integer = Value;
324 * \brief Create a new variable reference node
326 tAST_Node *AST_NewVariable(const char *Name)
328 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
329 ret->NextSibling = NULL;
330 //ret->Line = giLineNumber;
331 ret->Type = NODETYPE_VARIABLE;
332 strcpy(ret->Variable.Name, Name);
337 * \brief Create a new variable definition node
339 tAST_Node *AST_NewDefineVar(int Type, const char *Name)
341 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
342 ret->NextSibling = NULL;
343 //ret->Line = giLineNumber;
344 ret->Type = NODETYPE_DEFVAR;
345 ret->DefVar.DataType = Type;
346 ret->DefVar.LevelSizes = NULL;
347 strcpy(ret->DefVar.Name, Name);
352 * \brief Create a new runtime constant reference node
354 tAST_Node *AST_NewConstant(const char *Name)
356 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
357 ret->NextSibling = NULL;
358 //ret->Line = giLineNumber;
359 ret->Type = NODETYPE_CONSTANT;
360 strcpy(ret->Variable.Name, Name);
365 * \brief Create a function call node
366 * \note Argument list is manipulated using AST_AppendFunctionCallArg
368 tAST_Node *AST_NewFunctionCall(const char *Name)
370 tAST_Node *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
372 ret->NextSibling = NULL;
373 //ret->Line = giLineNumber;
374 ret->Type = NODETYPE_FUNCTIONCALL;
375 ret->FunctionCall.FirstArg = NULL;
376 ret->FunctionCall.LastArg = NULL;
377 strcpy(ret->FunctionCall.Name, Name);
382 * \brief Append an argument to a function call
384 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
386 if( Node->Type != NODETYPE_FUNCTIONCALL ) return ;
388 if(Node->FunctionCall.LastArg) {
389 Node->FunctionCall.LastArg->NextSibling = Arg;
390 Node->FunctionCall.LastArg = Arg;
393 Node->FunctionCall.FirstArg = Arg;
394 Node->FunctionCall.LastArg = Arg;