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