Removed not-yet-relevant runtime
[fur] / templates / program.c
1 #include <assert.h>
2 #include <inttypes.h>
3 #include <stdbool.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 {% for standard_library in standard_libraries %}
8 #include <{{standard_library}}>
9 {% endfor %}
10
11 struct String;
12 typedef struct String String;
13 enum Type;
14 typedef enum Type Type;
15 union Instance;
16 typedef union Instance Instance;
17 struct Object;
18 typedef struct Object Object;
19 struct Runtime;
20 typedef struct Runtime Runtime;
21
22 const char * const SYMBOL_LIST[] = {
23 {% for symbol in symbol_list %}
24   "{{ symbol }}",
25 {% endfor %}
26 };
27
28 enum Type
29 {
30   BOOLEAN,
31   INTEGER,
32   STRING
33 };
34
35 union Instance
36 {
37   bool boolean;
38   int32_t integer;
39   char* string;
40 };
41
42 struct Object
43 {
44   Type type;
45   Instance instance;
46 };
47
48 const Object TRUE = {
49   BOOLEAN,
50   true
51 };
52
53 const Object FALSE = {
54   BOOLEAN,
55   false
56 };
57
58 struct EnvironmentNode;
59 typedef struct EnvironmentNode EnvironmentNode;
60 struct EnvironmentNode
61 {
62   const char* key;
63   Object value;
64   EnvironmentNode* next;
65 };
66
67 struct Environment;
68 typedef struct Environment Environment;
69 struct Environment
70 {
71   EnvironmentNode* root;
72 };
73
74 Environment* Environment_construct()
75 {
76   // TODO Handle malloc returning NULL
77   Environment* result = malloc(sizeof(Environment));
78   result->root = NULL;
79   return result;
80 }
81
82 void Environment_destruct(Environment* self)
83 {
84   EnvironmentNode* next;
85   for(EnvironmentNode* node = self->root; node != NULL; node = next)
86   {
87     // We don't need to destruct the permanent strings, because those will be destructed at the end when the Runtime is destructed
88     // The above comment represents all heap-allocated objects currently, so we don't need to destruct Objects (yet)
89     next = node->next;
90     free(node);
91   }
92 }
93
94 // This need not be thread safe because environments exist on one thread only
95 void Environment_set(Environment* self, const char* const key, Object value)
96 {
97   EnvironmentNode* node = malloc(sizeof(EnvironmentNode));
98   node->key = key;
99   node->value = value;
100   node->next = self->root;
101   self->root = node;
102 }
103
104 Object Environment_get(Environment* self, const char* const symbol)
105 {
106   for(EnvironmentNode* node = self->root; node != NULL; node = node->next)
107   {
108     // We can compare pointers because pointers are unique in the SYMBOLS_LIST
109     if(node->key == symbol)
110     {
111       return node->value;
112     }
113   }
114
115   // TODO Handle symbol errors
116   assert(false);
117 }
118
119 Object integerLiteral(int32_t literal)
120 {
121   Object result;
122   result.type = INTEGER;
123   result.instance.integer = literal;
124   return result;
125 }
126
127 Object stringLiteral(char* literal)
128 {
129   Object result;
130   result.type = STRING;
131   result.instance.string = literal;
132   return result;
133 }
134
135 // TODO Make this conditionally added
136 Object builtin$negate(Object input)
137 {
138   assert(input.type == INTEGER);
139
140   Object result;
141   result.type = INTEGER;
142   result.instance.integer = -input.instance.integer;
143   return result;
144 }
145
146 Object builtin$add(Object left, Object right)
147 {
148   assert(left.type == INTEGER);
149   assert(right.type == INTEGER);
150
151   Object result;
152   result.type = INTEGER;
153   result.instance.integer = left.instance.integer + right.instance.integer;
154   return result;
155 }
156
157 Object builtin$subtract(Object left, Object right)
158 {
159   assert(left.type == INTEGER);
160   assert(right.type == INTEGER);
161
162   Object result;
163   result.type = INTEGER;
164   result.instance.integer = left.instance.integer - right.instance.integer;
165   return result;
166 }
167
168 Object builtin$multiply(Object left, Object right)
169 {
170   assert(left.type == INTEGER);
171   assert(right.type == INTEGER);
172
173   Object result;
174   result.type = INTEGER;
175   result.instance.integer = left.instance.integer * right.instance.integer;
176   return result;
177 }
178
179 Object builtin$integerDivide(Object left, Object right)
180 {
181   assert(left.type == INTEGER);
182   assert(right.type == INTEGER);
183
184   Object result;
185   result.type = INTEGER;
186   result.instance.integer = left.instance.integer / right.instance.integer;
187   return result;
188 }
189
190 Object builtin$modularDivide(Object left, Object right)
191 {
192   assert(left.type == INTEGER);
193   assert(right.type == INTEGER);
194
195   Object result;
196   result.type = INTEGER;
197   result.instance.integer = left.instance.integer % right.instance.integer;
198   return result;
199 }
200
201 Object builtin$equals(Object left, Object right)
202 {
203   assert(left.type == INTEGER);
204   assert(right.type == INTEGER);
205
206   Object result = { BOOLEAN, left.instance.integer == right.instance.integer };
207   return result;
208 }
209
210 Object builtin$notEquals(Object left, Object right)
211 {
212   assert(left.type == INTEGER);
213   assert(right.type == INTEGER);
214
215   Object result = { BOOLEAN, left.instance.integer != right.instance.integer };
216   return result;
217 }
218
219 Object builtin$greaterThan(Object left, Object right)
220 {
221   assert(left.type == INTEGER);
222   assert(right.type == INTEGER);
223
224   Object result = { BOOLEAN, left.instance.integer > right.instance.integer };
225   return result;
226 }
227
228 Object builtin$lessThan(Object left, Object right)
229 {
230   assert(left.type == INTEGER);
231   assert(right.type == INTEGER);
232
233   Object result = { BOOLEAN, left.instance.integer < right.instance.integer };
234   return result;
235 }
236
237 Object builtin$greaterThanOrEqual(Object left, Object right)
238 {
239   assert(left.type == INTEGER);
240   assert(right.type == INTEGER);
241
242   Object result = { BOOLEAN, left.instance.integer >= right.instance.integer };
243   return result;
244 }
245
246 Object builtin$lessThanOrEqual(Object left, Object right)
247 {
248   assert(left.type == INTEGER);
249   assert(right.type == INTEGER);
250
251   Object result = { BOOLEAN, left.instance.integer <= right.instance.integer };
252   return result;
253 }
254
255 Object builtin$and(Object left, Object right)
256 {
257   assert(left.type == BOOLEAN);
258   assert(right.type == BOOLEAN);
259
260   Object result = { BOOLEAN, left.instance.boolean && right.instance.boolean };
261   return result;
262 }
263
264 Object builtin$or(Object left, Object right)
265 {
266   assert(left.type == BOOLEAN);
267   assert(right.type == BOOLEAN);
268
269   Object result = { BOOLEAN, left.instance.boolean || right.instance.boolean };
270   return result;
271 }
272
273 {% if 'pow' in builtins %}
274 Object builtin$pow(Object base, Object exponent)
275 {
276   assert(base.type == INTEGER);
277   assert(exponent.type == INTEGER);
278
279   Object result;
280   result.type = INTEGER;
281   result.instance.integer = pow(base.instance.integer, exponent.instance.integer);
282   return result;
283 }
284 {% endif %}
285
286 {% if 'print' in builtins %}
287 void builtin$print(Object output)
288 {
289   switch(output.type)
290   {
291     case BOOLEAN:
292       fputs(output.instance.boolean ? "true" : "false", stdout);
293       break;
294
295     case INTEGER:
296       printf("%" PRId32, output.instance.integer);
297       break;
298
299     case STRING:
300       // Using fwrite instead of printf to handle size_t length
301       printf("%s", output.instance.string);
302       break;
303
304     default:
305       assert(false);
306   }
307 }
308 {% endif %}
309
310 int main(int argc, char** argv)
311 {
312   Environment* environment = Environment_construct();
313
314   {% for statement in statements %}
315   {{ statement }}
316   {% endfor %}
317
318   Environment_destruct(environment);
319
320   return 0;
321 }