Fixed behavior of VTerm when driver is set at runtime
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / ast.c
1 /*
2  * Acess2 Init
3  * - Script AST Manipulator
4  */
5 #include <stdlib.h>
6 #include <string.h>
7 #include "ast.h"
8
9 // === CODE ===
10 tAST_Script *AST_NewScript(void)
11 {
12         tAST_Script     *ret = malloc( sizeof(tAST_Script) );
13         
14         ret->Functions = NULL;
15         ret->LastFunction = NULL;
16         
17         return ret;
18 }
19
20 /**
21  * \brief Append a function to a script
22  */
23 tAST_Function *AST_AppendFunction(tAST_Script *Script, const char *Name)
24 {
25         tAST_Function   *ret;
26         
27         ret = malloc( sizeof(tAST_Function) );
28         ret->Next = NULL;
29         ret->Name = strdup(Name);
30         ret->Code = NULL;
31         ret->Arguments = NULL;
32         
33         if(Script->LastFunction == NULL) {
34                 Script->Functions = Script->LastFunction = ret;
35         }
36         else {
37                 Script->LastFunction->Next = ret;
38                 Script->LastFunction = ret;
39         }
40         
41         return ret;
42 }
43
44 void AST_SetFunctionCode(tAST_Function *Function, tAST_Node *Root)
45 {
46         Function->Code = Root;
47 }
48
49 /**
50  * \name Node Manipulation
51  * \{
52  */
53 void AST_FreeNode(tAST_Node *Node)
54 {
55         tAST_Node       *node;
56         switch(Node->Type)
57         {
58         // Block of code
59         case NODETYPE_BLOCK:
60                 for( node = Node->Block.FirstChild; node; )
61                 {
62                         tAST_Node       *savedNext = node->NextSibling;
63                         AST_FreeNode(node);
64                         node = savedNext;
65                 }
66                 break;
67         
68         // Function Call
69         case NODETYPE_FUNCTIONCALL:
70                 for( node = Node->FunctionCall.FirstArg; node; )
71                 {
72                         tAST_Node       *savedNext = node->NextSibling;
73                         AST_FreeNode(node);
74                         node = savedNext;
75                 }
76                 break;
77         
78         // Asignment
79         case NODETYPE_ASSIGN:
80                 AST_FreeNode(Node->Assign.Dest);
81                 AST_FreeNode(Node->Assign.Value);
82                 break;
83         
84         // Unary Operations
85         case NODETYPE_RETURN:
86                 AST_FreeNode(Node->UniOp.Value);
87                 break;
88         
89         // Binary Operations
90         case NODETYPE_ADD:
91         case NODETYPE_SUBTRACT:
92         case NODETYPE_MULTIPLY:
93         case NODETYPE_DIVIDE:
94         case NODETYPE_MODULO:
95         case NODETYPE_BITSHIFTLEFT:
96         case NODETYPE_BITSHIFTRIGHT:
97         case NODETYPE_BITROTATELEFT:
98         case NODETYPE_BWAND:    case NODETYPE_LOGICALAND:
99         case NODETYPE_BWOR:     case NODETYPE_LOGICALOR:
100         case NODETYPE_BWXOR:    case NODETYPE_LOGICALXOR:
101         case NODETYPE_EQUALS:
102         case NODETYPE_LESSTHAN:
103         case NODETYPE_GREATERTHAN:
104                 AST_FreeNode( Node->BinOp.Left );
105                 AST_FreeNode( Node->BinOp.Right );
106                 break;
107         
108         // Node types with no children
109         case NODETYPE_NOP:      break;
110         case NODETYPE_VARIABLE: break;
111         case NODETYPE_CONSTANT: break;
112         case NODETYPE_STRING:   break;
113         case NODETYPE_INTEGER:  break;
114         case NODETYPE_REAL:     break;
115         }
116         free( Node );
117 }
118
119 tAST_Node *AST_NewCodeBlock(void)
120 {
121         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
122         
123         ret->NextSibling = NULL;
124         ret->Type = NODETYPE_BLOCK;
125         ret->Block.FirstChild = NULL;
126         ret->Block.LastChild = NULL;
127         
128         return ret;
129 }
130
131 void AST_AppendNode(tAST_Node *Parent, tAST_Node *Child)
132 {
133         if(Parent->Type != NODETYPE_BLOCK)      return ;
134         
135         if(Parent->Block.FirstChild == NULL) {
136                 Parent->Block.FirstChild = Parent->Block.LastChild = Child;
137         }
138         else {
139                 Parent->Block.LastChild->NextSibling = Child;
140                 Parent->Block.LastChild = Child;
141         }
142 }
143
144 tAST_Node *AST_NewAssign(int Operation, tAST_Node *Dest, tAST_Node *Value)
145 {
146         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
147         
148         ret->NextSibling = NULL;
149         ret->Type = NODETYPE_ASSIGN;
150         ret->Assign.Operation = Operation;
151         ret->Assign.Dest = Dest;
152         ret->Assign.Value = Value;
153         
154         return ret;
155 }
156
157 tAST_Node *AST_NewBinOp(int Operation, tAST_Node *Left, tAST_Node *Right)
158 {
159         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
160         
161         ret->NextSibling = NULL;
162         ret->Type = Operation;
163         ret->BinOp.Left = Left;
164         ret->BinOp.Right = Right;
165         
166         return ret;
167 }
168
169 /**
170  * \brief Create a new string node
171  */
172 tAST_Node *AST_NewString(const char *String, int Length)
173 {
174         tAST_Node       *ret = malloc( sizeof(tAST_Node) + Length + 1 );
175         
176         ret->NextSibling = NULL;
177         ret->Type = NODETYPE_STRING;
178         ret->String.Length = Length;
179         memcpy(ret->String.Data, String, Length);
180         ret->String.Data[Length] = '\0';
181         
182         return ret;
183 }
184
185 /**
186  * \brief Create a new integer node
187  */
188 tAST_Node *AST_NewInteger(uint64_t Value)
189 {
190         tAST_Node       *ret = malloc( sizeof(tAST_Node) );
191         ret->NextSibling = NULL;
192         ret->Type = NODETYPE_INTEGER;
193         ret->Integer = Value;
194         return ret;
195 }
196
197 /**
198  * \brief Create a new variable reference node
199  */
200 tAST_Node *AST_NewVariable(const char *Name)
201 {
202         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
203         ret->NextSibling = NULL;
204         ret->Type = NODETYPE_VARIABLE;
205         strcpy(ret->Variable.Name, Name);
206         return ret;
207 }
208
209 /**
210  * \brief Create a new runtime constant reference node
211  */
212 tAST_Node *AST_NewConstant(const char *Name)
213 {
214         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
215         ret->NextSibling = NULL;
216         ret->Type = NODETYPE_CONSTANT;
217         strcpy(ret->Variable.Name, Name);
218         return ret;
219 }
220
221 /**
222  * \brief Create a function call node
223  * \note Argument list is manipulated using AST_AppendFunctionCallArg
224  */
225 tAST_Node *AST_NewFunctionCall(const char *Name)
226 {
227         tAST_Node       *ret = malloc( sizeof(tAST_Node) + strlen(Name) + 1 );
228         
229         ret->NextSibling = NULL;
230         ret->Type = NODETYPE_FUNCTIONCALL;
231         ret->FunctionCall.FirstArg = NULL;
232         ret->FunctionCall.LastArg = NULL;
233         strcpy(ret->FunctionCall.Name, Name);
234         return ret;
235 }
236
237 /**
238  * \brief Append an argument to a function call
239  */
240 void AST_AppendFunctionCallArg(tAST_Node *Node, tAST_Node *Arg)
241 {
242         if( Node->Type != NODETYPE_FUNCTIONCALL )       return ;
243         
244         if(Node->FunctionCall.LastArg) {
245                 Node->FunctionCall.LastArg->NextSibling = Arg;
246                 Node->FunctionCall.LastArg = Arg;
247         }
248         else {
249                 Node->FunctionCall.FirstArg = Arg;
250                 Node->FunctionCall.LastArg = Arg;
251         }
252 }
253
254 /**
255  * \}
256  */

UCC git Repository :: git.ucc.asn.au