c589e048520bb3044beb8307fdf3ad00788c6a2b
[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 {% for od in operator_declarations %}
164 Object operator${{ od.name }}(Object left, Object right)
165 {
166   assert(left.type == {{ od.input_type.upper() }});
167   assert(right.type == {{ od.input_type.upper() }});
168
169   Object result;
170   result.type = {{ od.result_type.upper() }};
171   result.instance.{{ od.result_type.lower() }} = left.instance.{{ od.input_type.lower() }} {{ od.c_operator }} right.instance.{{ od.input_type.lower() }};
172   return result;
173 }
174 {% endfor %}
175
176 Object operator$equals(Object left, Object right)
177 {
178   assert(left.type == INTEGER);
179   assert(right.type == INTEGER);
180
181   Object result = { BOOLEAN, { left.instance.integer == right.instance.integer } };
182   return result;
183 }
184
185 Object operator$notEquals(Object left, Object right)
186 {
187   assert(left.type == INTEGER);
188   assert(right.type == INTEGER);
189
190   Object result = { BOOLEAN, { left.instance.integer != right.instance.integer } };
191   return result;
192 }
193
194 Object operator$greaterThan(Object left, Object right)
195 {
196   assert(left.type == INTEGER);
197   assert(right.type == INTEGER);
198
199   Object result = { BOOLEAN, { left.instance.integer > right.instance.integer } };
200   return result;
201 }
202
203 Object operator$lessThan(Object left, Object right)
204 {
205   assert(left.type == INTEGER);
206   assert(right.type == INTEGER);
207
208   Object result = { BOOLEAN, { left.instance.integer < right.instance.integer } };
209   return result;
210 }
211
212 Object operator$greaterThanOrEqual(Object left, Object right)
213 {
214   assert(left.type == INTEGER);
215   assert(right.type == INTEGER);
216
217   Object result = { BOOLEAN, { left.instance.integer >= right.instance.integer } };
218   return result;
219 }
220
221 Object operator$lessThanOrEqual(Object left, Object right)
222 {
223   assert(left.type == INTEGER);
224   assert(right.type == INTEGER);
225
226   Object result = { BOOLEAN, { left.instance.integer <= right.instance.integer } };
227   return result;
228 }
229
230 {% if 'pow' in builtins %}
231 Object builtin$pow$implementation(Environment* parent, size_t argc, Object* args)
232 {
233   assert(argc == 2);
234
235   Object base = args[0];
236   Object exponent = args[1];
237
238   assert(base.type == INTEGER);
239   assert(exponent.type == INTEGER);
240
241   Object result;
242   result.type = INTEGER;
243   result.instance.integer = pow(base.instance.integer, exponent.instance.integer);
244   return result;
245 }
246
247 Object builtin$pow = { CLOSURE, (Instance)builtin$pow$implementation };
248 {% endif %}
249
250 {% if 'print' in builtins %}
251 Object builtin$print$implementation(Environment* parent, size_t argc, Object* args)
252 {
253   for(size_t i = 0; i < argc; i++)
254   {
255     Object output = args[i];
256     switch(output.type)
257     {
258       case BOOLEAN:
259         fputs(output.instance.boolean ? "true" : "false", stdout);
260         break;
261
262       case INTEGER:
263         printf("%" PRId32, output.instance.integer);
264         break;
265
266       case STRING:
267         // Using fwrite instead of printf to handle size_t length
268         printf("%s", output.instance.string);
269         break;
270
271       default:
272         assert(false);
273     }
274   }
275
276   // TODO Return something better
277   return FALSE;
278 }
279
280 Object builtin$print = { CLOSURE, (Instance)builtin$print$implementation };
281 {% endif %}
282
283 {% for function_definition in function_definition_list %}
284 Object user${{function_definition.name}}$implementation(Environment* parent, size_t argc, Object* args)
285 {
286   Environment* environment = Environment_construct(parent);
287
288   {% for statement in function_definition.statement_list[:-1] %}
289   {{ generate_statement(statement) }}
290   {% endfor %}
291
292   Object result = {{ generate_statement(function_definition.statement_list[-1]) }}
293   Environment_destruct(environment);
294   return result;
295 }
296
297 Object user${{function_definition.name}} = { CLOSURE, (Instance)user${{function_definition.name}}$implementation };
298 {% endfor %}
299
300 int main(int argc, char** argv)
301 {
302   Environment* environment = Environment_construct(NULL);
303
304   // TODO Use the symbol from SYMBOL_LIST
305   {% for builtin in builtins %}
306   Environment_set(environment, "{{ builtin }}", builtin${{ builtin }});
307   {% endfor %}
308
309   {% for statement in statements %}
310   {{ generate_statement(statement) }}
311   {% endfor %}
312
313   Environment_destruct(environment);
314
315   return 0;
316 }