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