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