Implement pow
[fur] / templates / program.c
1 #include <assert.h>
2 #include <inttypes.h>
3 #include <setjmp.h>
4 #include <stdbool.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 /* Some terminology used in function names:
9  * - initialize: These functions take a pointer and potentially some other arguments, and use those
10  *   to initialize the value pointed to by self. Initialize functions DO NOT allocate the function,
11  *   so they can be used to initialize stack-allocated variables.
12  * - construct: This allocates a value for a pointer, initializes it, and returns it. This is for
13  *   heap-allocated values. It may be as simple as allocating the memory, calling an initialize, and
14  *   returning it.
15  * - deinitialize: These functions dereference or free any objects pointed to by the self pointer's
16  *   value, but they don't actually free the self pointer. This is useful for stack-allocated objects
17  *   which point to heap-allocated objects.
18  * - destruct: This dereferences or frees memory pointed to by the self argument, and all the
19  *   pointers on the self argument.
20  */
21
22 {% for standard_library in standard_libraries %}
23 #include <{{standard_library}}>
24 {% endfor %}
25
26 enum Type;
27 typedef enum Type Type;
28 union Instance;
29 typedef union Instance Instance;
30 struct Object;
31 typedef struct Object Object;
32 struct EnvironmentNode;
33 typedef struct EnvironmentNode EnvironmentNode;
34 struct Environment;
35 typedef struct Environment Environment;
36 struct EnvironmentPool;
37 typedef struct EnvironmentPool EnvironmentPool;
38 struct Stack;
39 typedef struct Stack Stack;
40
41 const char* const STRING_LITERAL_LIST[] = {
42 {% for string_literal in string_literal_list %}
43   "{{ string_literal }}",
44 {% endfor %}
45 };
46
47 const char* const SYMBOL_LIST[] = {
48 {% for symbol in symbol_list %}
49   "{{ symbol }}",
50 {% endfor %}
51 };
52
53 enum Type
54 {
55   BOOLEAN,
56   CLOSURE,
57   INTEGER,
58   LIST,
59   STRING_CONCATENATION,
60   STRING_LITERAL,
61   STRUCTURE,
62   VOID
63 };
64
65 struct Closure;
66 typedef struct Closure Closure;
67 struct Closure
68 {
69   Environment* closed;
70   Object (*call)(EnvironmentPool*, Environment*, size_t, Stack*, const unsigned long, jmp_buf);
71 };
72
73 struct List;
74 typedef struct List List;
75 struct List
76 {
77   size_t allocated;
78   size_t length;
79   Object* items;
80 };
81
82 struct StringConcatenation;
83 typedef struct StringConcatenation StringConcatenation;
84
85 struct Structure;
86 typedef struct Structure Structure;
87 struct Structure
88 {
89   size_t reference_count;
90   size_t length;
91   const char** symbol_list;
92   Object* value_list;
93 };
94
95 union Instance
96 {
97   bool boolean;
98   Closure closure;
99   int32_t integer;
100   List list;
101   StringConcatenation* string_concatenation;
102   const char* string_literal;
103   Structure* structure;
104 };
105
106 struct Object
107 {
108   Type type;
109   Instance instance;
110 };
111
112 const Object builtin$true = { BOOLEAN, (Instance)(bool){ true } };
113 const Object builtin$false = { BOOLEAN, (Instance)(bool){ false } };
114 const Object builtin$nil = { VOID, { 0 } };
115
116 struct StringConcatenation
117 {
118   size_t referenceCount;
119   Object left;
120   Object right;
121 };
122
123 Object List_construct(size_t allocate)
124 {
125   Object* items = malloc(sizeof(Object) * allocate);
126   Object result = { LIST, (Instance)(List){ allocate, 0, items } };
127   return result;
128 }
129
130 void List_append(Object* list, Object item)
131 {
132   assert(list->type == LIST);
133
134   if(list->instance.list.allocated == list->instance.list.length)
135   {
136     list->instance.list.allocated *= 2;
137     list->instance.list.items = realloc(
138       list->instance.list.items,
139       sizeof(Object) * list->instance.list.allocated
140     );
141   }
142
143   list->instance.list.items[list->instance.list.length] = item;
144   list->instance.list.length++;
145 }
146
147 Object List_get(Object* list, Object index)
148 {
149   assert(list->type == LIST);
150   assert(index.type == INTEGER);
151
152   return list->instance.list.items[index.instance.integer];
153 }
154
155 struct Stack
156 {
157   uint16_t length;
158   Object items[256];
159 };
160
161 void Stack_initialize(Stack* self)
162 {
163   self->length = 0;
164 }
165
166 Stack* Stack_construct()
167 {
168   Stack* result = malloc(sizeof(Stack));
169   Stack_initialize(result);
170   return result;
171 }
172
173 void Stack_destruct(Stack* self)
174 {
175   free(self);
176 }
177
178 bool Stack_any(Stack* self)
179 {
180   return self->length > 0;
181 }
182
183 void Stack_push(Stack* self, Object item)
184 {
185   assert(self->length < 256);
186   self->items[self->length] = item;
187   self->length++;
188 }
189
190 Object Stack_pop(Stack* self)
191 {
192   assert(self->length > 0);
193   self->length--;
194   return self->items[self->length];
195 }
196
197 Object Object_rereference(Object self)
198 {
199   switch(self.type)
200   {
201     case BOOLEAN:
202     case CLOSURE:
203     case INTEGER:
204     case STRING_LITERAL:
205     case VOID:
206       return self;
207
208     case STRING_CONCATENATION:
209       self.instance.string_concatenation->referenceCount++;
210       return self;
211
212     case STRUCTURE:
213       self.instance.structure->reference_count++;
214       return self;
215
216     default:
217       assert(false);
218   }
219 }
220
221 Object Structure_construct(size_t length, const char** symbol_list, Object* value_list)
222 {
223   Structure* structure = malloc(sizeof(Structure));
224   structure->reference_count = 1;
225   structure->length = length;
226   structure->symbol_list = malloc(sizeof(const char*) * length);
227   structure->value_list = malloc(sizeof(Object) * length);
228
229   // TODO Don't allow assignment of mutable structures, as this screws up reference counting
230   for(size_t i = 0; i < length; i++)
231   {
232     structure->symbol_list[i] = symbol_list[i];
233     structure->value_list[i] = Object_rereference(value_list[i]);
234   }
235
236   Object result = { STRUCTURE, (Instance)structure };
237
238   return result;
239 }
240
241 Object Structure_get(Object* self, const char* symbol)
242 {
243   assert(self->type == STRUCTURE);
244
245   for(size_t i = 0; i < self->instance.structure->length; i++)
246   {
247     if(self->instance.structure->symbol_list[i] == symbol)
248     {
249       return self->instance.structure->value_list[i];
250     }
251   }
252
253   assert(false);
254 }
255
256 struct EnvironmentNode
257 {
258   const char* key;
259   Object value;
260   EnvironmentNode* next;
261 };
262
263 struct Environment
264 {
265   bool mark;
266   bool live;
267
268   Environment* parent;
269   EnvironmentNode* root;
270 };
271
272 void Environment_initialize(Environment* self, Environment* parent)
273 {
274   self->parent = parent;
275   self->root = NULL;
276
277   // We are currently only ever initializing environments at the beginning of running functions, so
278   // for now at least we can assume that we want it to be live immediately.
279   self->live = true;
280 }
281
282 void Object_deinitialize(Object* self)
283 {
284   switch(self->type)
285   {
286     case BOOLEAN:
287       break;
288     case CLOSURE:
289       break;
290     case INTEGER:
291       break;
292     case STRING_LITERAL:
293       break;
294     case VOID:
295       break;
296
297     case LIST:
298       for(size_t i = 0; i < self->instance.list.length; i++) {
299         Object_deinitialize(&(self->instance.list.items[i]));
300       }
301
302       free(self->instance.list.items);
303       break;
304
305     case STRING_CONCATENATION:
306       self->instance.string_concatenation->referenceCount--;
307
308       if(self->instance.string_concatenation->referenceCount == 0)
309       {
310         Object_deinitialize(&(self->instance.string_concatenation->left));
311         Object_deinitialize(&(self->instance.string_concatenation->right));
312         free(self->instance.string_concatenation);
313       }
314       break;
315
316     case STRUCTURE:
317       self->instance.structure->reference_count--;
318
319       if(self->instance.structure->reference_count == 0)
320       {
321         for(size_t i = 0; i < self->instance.structure->length; i++)
322         {
323           Object_deinitialize(&(self->instance.structure->value_list[i]));
324         }
325         free(self->instance.structure->symbol_list);
326         free(self->instance.structure->value_list);
327         free(self->instance.structure);
328       }
329       break;
330
331     default:
332       assert(false);
333   }
334 }
335
336 typedef uint32_t StackSnapshot;
337
338 StackSnapshot Stack_takeSnapshot(Stack* self)
339 {
340   return (StackSnapshot) self->length;
341 }
342
343 void Stack_rewind(Stack* self, StackSnapshot snapshot)
344 {
345   while(self->length > snapshot)
346   {
347     Object item = Stack_pop(self);
348     Object_deinitialize(&item);
349   }
350 }
351
352 void Environment_deinitialize(Environment* self)
353 {
354   EnvironmentNode* next;
355   for(EnvironmentNode* node = self->root; node != NULL; node = next)
356   {
357     next = node->next;
358     Object_deinitialize(&(node->value));
359     free(node);
360   }
361 }
362
363 void Environment_setLive(Environment* self, bool live)
364 {
365   self->live = live;
366 }
367
368 void Environment_mark(Environment* self)
369 {
370   if(self == NULL) return;
371   if(self->mark) return; // Prevents infinite recursion in the case of cycles
372
373   self->mark = true;
374
375   Environment_mark(self->parent);
376
377   for(EnvironmentNode* node = self->root; node != NULL; node = node->next)
378   {
379     switch(node->value.type)
380     {
381       case BOOLEAN:
382       case INTEGER:
383       case STRING_LITERAL:
384       case VOID:
385         break;
386
387       case CLOSURE:
388         Environment_mark(node->value.instance.closure.closed);
389         break;
390
391       default:
392         assert(false);
393     }
394   }
395 }
396
397 // This need not be thread safe because environments exist on one thread only
398 void Environment_set(Environment* self, const char* const key, Object value)
399 {
400   EnvironmentNode* node = malloc(sizeof(EnvironmentNode));
401   node->key = key;
402   node->value = value;
403   node->next = self->root;
404   self->root = node;
405 }
406
407 Object Environment_get(Environment* self, const char* const symbol)
408 {
409   for(EnvironmentNode* node = self->root; node != NULL; node = node->next)
410   {
411     // We can compare pointers because pointers are unique in the SYMBOL_LIST
412     if(node->key == symbol)
413     {
414       return node->value;
415     }
416   }
417
418   if(self->parent != NULL)
419   {
420     return Environment_get(self->parent, symbol);
421   }
422
423   // TODO Handle symbol errors
424   assert(false);
425 }
426
427 # define POOL_SIZE 64
428 struct EnvironmentPool
429 {
430   int8_t freeIndex;
431   bool allocatedFlags[POOL_SIZE];
432   Environment environments[POOL_SIZE];
433   EnvironmentPool* overflow;
434 };
435
436 EnvironmentPool* EnvironmentPool_construct();
437 void EnvironmentPool_initialize(EnvironmentPool*);
438 void EnvironmentPool_deinitialize(EnvironmentPool*);
439 void EnvironmentPool_destruct(EnvironmentPool*);
440
441 EnvironmentPool* EnvironmentPool_construct()
442 {
443   EnvironmentPool* result = malloc(sizeof(EnvironmentPool));
444   EnvironmentPool_initialize(result);
445   return result;
446 }
447
448 void EnvironmentPool_initialize(EnvironmentPool* self)
449 {
450   self->overflow = NULL;
451   self->freeIndex = 0;
452
453   for(size_t i = 0; i < POOL_SIZE; i++)
454   {
455     self->allocatedFlags[i] = false;
456     self->environments[i].live = false;
457   }
458 }
459
460 void EnvironmentPool_deinitialize(EnvironmentPool* self)
461 {
462   // We can assume if this is being called, none of the Environments are live
463   for(int8_t i = 0; i < POOL_SIZE; i++)
464   {
465     if(self->allocatedFlags[i]) Environment_deinitialize(&(self->environments[i]));
466   }
467
468   EnvironmentPool_destruct(self->overflow);
469 }
470
471 void EnvironmentPool_destruct(EnvironmentPool* self)
472 {
473   if(self == NULL) return;
474   EnvironmentPool_deinitialize(self);
475   free(self);
476 }
477
478 void EnvironmentPool_GC(EnvironmentPool* self)
479 {
480   // Unmark all the environments
481   for(EnvironmentPool* current = self; current != NULL; current = current->overflow)
482   {
483     for(int8_t i = 0; i < POOL_SIZE; i++)
484     {
485       current->environments[i].mark = false;
486     }
487   }
488
489   // Mark live enviroments and environments referenced by live environments
490   for(EnvironmentPool* current = self; current != NULL; current = current->overflow)
491   {
492     for(int8_t i = 0; i < POOL_SIZE; i++)
493     {
494       if(current->environments[i].live)
495       {
496         Environment_mark(&(current->environments[i]));
497       }
498     }
499   }
500
501   // TODO We never free pools until the very end--we could free a pool if two pools are empty
502   for(EnvironmentPool* current = self; current != NULL; current = current->overflow)
503   {
504     for(int8_t i = POOL_SIZE - 1; i >= 0; i--)
505     {
506       if(!current->environments[i].mark && current->allocatedFlags[i])
507       {
508         Environment_deinitialize(&(current->environments[i]));
509         current->allocatedFlags[i] = false;
510         current->freeIndex = i;
511       }
512     }
513   }
514 }
515
516 Environment* EnvironmentPool_allocate(EnvironmentPool* self)
517 {
518   for(EnvironmentPool* current = self; current != NULL; current = current->overflow)
519   {
520     for(; current->freeIndex < POOL_SIZE; current->freeIndex++)
521     {
522       if(!current->allocatedFlags[current->freeIndex])
523       {
524         current->allocatedFlags[current->freeIndex] = true;
525         return &(current->environments[current->freeIndex]);
526       }
527     }
528   }
529
530   EnvironmentPool_GC(self);
531
532   EnvironmentPool* previous;
533   for(EnvironmentPool* current = self; current != NULL; current = current->overflow)
534   {
535     for(; current->freeIndex < POOL_SIZE; current->freeIndex++)
536     {
537       if(!current->allocatedFlags[current->freeIndex])
538       {
539         current->allocatedFlags[current->freeIndex] = true;
540         return &(current->environments[current->freeIndex]);
541       }
542       else
543       {
544         previous = current;
545       }
546     }
547   }
548
549   previous->overflow = EnvironmentPool_construct();
550   return EnvironmentPool_allocate(previous->overflow);
551 }
552
553 Environment* Environment_construct(EnvironmentPool* environmentPool, Environment* parent)
554 {
555   Environment* environment = EnvironmentPool_allocate(environmentPool);
556   Environment_initialize(environment, parent);
557   return environment;
558 }
559
560 Object integerLiteral(int32_t literal)
561 {
562   Object result;
563   result.type = INTEGER;
564   result.instance.integer = literal;
565   return result;
566 }
567
568 Object stringLiteral(const char* literal)
569 {
570   Object result;
571   result.type = STRING_LITERAL;
572   result.instance.string_literal = literal;
573   return result;
574 }
575
576 {% if 'pow' in builtins %}
577 Object builtin$pow$implementation(
578     EnvironmentPool* environmentPool,
579     Environment* parent,
580     size_t argc,
581     Stack* stack,
582     const unsigned long line,
583     jmp_buf parentJump)
584 {
585   // Must unload items in reverse order
586   Object exponent = Stack_pop(stack);
587   Object base = Stack_pop(stack);
588
589   assert(base.type == INTEGER);
590   assert(exponent.type == INTEGER);
591
592   Object result;
593   result.type = INTEGER;
594   result.instance.integer = pow(base.instance.integer, exponent.instance.integer);
595   return result;
596 }
597
598 Object builtin$pow = { CLOSURE, (Instance)(Closure){ NULL, builtin$pow$implementation } };
599 {% endif %}
600
601 Object builtin$negate$implementation(
602   EnvironmentPool* environmentPool,
603   Environment* parent,
604   size_t argc,
605   Stack* stack,
606   const unsigned long line,
607   jmp_buf parentJump)
608 {
609   assert(argc == 1);
610
611   Object argument = Stack_pop(stack);
612
613   assert(argument.type == INTEGER);
614
615   Object result = (Object){
616     INTEGER,
617     (Instance)(int32_t) (-argument.instance.integer)
618   };
619
620   return result;
621 }
622 Object builtin$negate = { CLOSURE, (Instance)(Closure){ NULL, builtin$negate$implementation } };
623
624 {% for op in ['lt', 'gt', 'lte', 'gte', 'eq', 'neq'] %}
625 Object builtin${{ op }}$implementation(
626   EnvironmentPool* environmentPool,
627   Environment* parent,
628   size_t argc,
629   Stack* stack,
630   const unsigned long line,
631   jmp_buf parentJump)
632 {
633   assert(argc == 2);
634
635   Object right = Stack_pop(stack);
636   Object left = Stack_pop(stack);
637
638   assert(left.type == INTEGER);
639   assert(right.type == INTEGER);
640
641   {% if op == 'lt' %}
642   if(left.instance.integer < right.instance.integer)
643   {% elif op == 'gt' %}
644   if(left.instance.integer > right.instance.integer)
645   {% elif op == 'lte' %}
646   if(left.instance.integer <= right.instance.integer)
647   {% elif op == 'gte' %}
648   if(left.instance.integer >= right.instance.integer)
649   {% elif op == 'eq' %}
650   if(left.instance.integer == right.instance.integer)
651   {% elif op == 'neq' %}
652   if(left.instance.integer != right.instance.integer)
653   {% endif %}
654   {
655     return builtin$true;
656   }
657   else
658   {
659     return builtin$false;
660   }
661 }
662 Object builtin${{ op }} = { CLOSURE, (Instance)(Closure){ NULL, builtin${{ op }}$implementation } };
663 {% endfor %}
664
665 Object builtin$concat$implementation(
666   EnvironmentPool* environmentPool,
667   Environment* parent,
668   size_t argc,
669   Stack* stack,
670   const unsigned long line,
671   jmp_buf parentJump)
672 {
673   assert(argc == 2);
674
675   Object right = Stack_pop(stack);
676   Object left = Stack_pop(stack);
677
678   switch(left.type) {
679     case STRING_CONCATENATION:
680     case STRING_LITERAL:
681       break;
682
683     default:
684       assert(false);
685   }
686
687   switch(right.type) {
688     case STRING_CONCATENATION:
689     case STRING_LITERAL:
690       break;
691
692     default:
693       assert(false);
694   }
695
696   StringConcatenation* concatenation = malloc(sizeof(StringConcatenation));
697   concatenation->referenceCount = 1;
698   concatenation->left = Object_rereference(left);
699   concatenation->right = Object_rereference(right);
700
701   Object result = { STRING_CONCATENATION, (Instance)concatenation };
702   return result;
703 }
704 Object builtin$concat = { CLOSURE, (Instance)(Closure){ NULL, builtin$concat$implementation } };
705
706 Object builtin$add$implementation(
707   EnvironmentPool* environmentPool,
708   Environment* parent,
709   size_t argc,
710   Stack* stack,
711   const unsigned long line,
712   jmp_buf parentJump)
713 {
714   assert(argc == 2);
715
716   Object right = Stack_pop(stack);
717   Object left = Stack_pop(stack);
718
719   assert(left.type == INTEGER);
720   assert(right.type == INTEGER);
721
722   Object result = (Object){
723     INTEGER,
724     (Instance)(int32_t) (left.instance.integer + right.instance.integer)
725   };
726
727   return result;
728 }
729 Object builtin$add = { CLOSURE, (Instance)(Closure){ NULL, builtin$add$implementation } };
730
731 Object builtin$subtract$implementation(
732   EnvironmentPool* environmentPool,
733   Environment* parent,
734   size_t argc,
735   Stack* stack,
736   const unsigned long line,
737   jmp_buf parentJump)
738 {
739   assert(argc == 2);
740
741   Object right = Stack_pop(stack);
742   Object left = Stack_pop(stack);
743
744   assert(left.type == INTEGER);
745   assert(right.type == INTEGER);
746
747   Object result = (Object){
748     INTEGER,
749     (Instance)(int32_t) (left.instance.integer - right.instance.integer)
750   };
751
752   return result;
753 }
754 Object builtin$subtract = { CLOSURE, (Instance)(Closure){ NULL, builtin$subtract$implementation } };
755
756 Object builtin$multiply$implementation(
757   EnvironmentPool* environmentPool,
758   Environment* parent,
759   size_t argc,
760   Stack* stack,
761   const unsigned long line,
762   jmp_buf parentJump)
763 {
764   assert(argc == 2);
765
766   Object right = Stack_pop(stack);
767   Object left = Stack_pop(stack);
768
769   assert(left.type == INTEGER);
770   assert(right.type == INTEGER);
771
772   Object result = (Object){
773     INTEGER,
774     (Instance)(int32_t) (left.instance.integer * right.instance.integer)
775   };
776
777   return result;
778 }
779 Object builtin$multiply = { CLOSURE, (Instance)(Closure){ NULL, builtin$multiply$implementation } };
780
781 Object builtin$integer_divide$implementation(
782   EnvironmentPool* environmentPool,
783   Environment* parent,
784   size_t argc,
785   Stack* stack,
786   const unsigned long line,
787   jmp_buf parentJump)
788 {
789   assert(argc == 2);
790
791   Object right = Stack_pop(stack);
792   Object left = Stack_pop(stack);
793
794   assert(left.type == INTEGER);
795   assert(right.type == INTEGER);
796
797   if(right.instance.integer == 0)
798   {
799     fprintf(stderr, "DivisionByZeroError on line %zu\n", line);
800     longjmp(parentJump, 1);
801   }
802
803   Object result = (Object){
804     INTEGER,
805     (Instance)(int32_t) (left.instance.integer / right.instance.integer)
806   };
807
808   return result;
809 }
810 Object builtin$integer_divide = { CLOSURE, (Instance)(Closure){ NULL, builtin$integer_divide$implementation } };
811
812 Object builtin$modular_divide$implementation(
813   EnvironmentPool* environmentPool,
814   Environment* parent,
815   size_t argc,
816   Stack* stack,
817   const unsigned long line,
818   jmp_buf parentJump)
819 {
820   assert(argc == 2);
821
822   Object right = Stack_pop(stack);
823   Object left = Stack_pop(stack);
824
825   assert(left.type == INTEGER);
826   assert(right.type == INTEGER);
827
828   if(right.instance.integer == 0)
829   {
830     fprintf(stderr, "DivisionByZeroError on line %zu\n", line);
831     longjmp(parentJump, 1);
832   }
833
834   Object result = (Object){
835     INTEGER,
836     (Instance)(int32_t) (left.instance.integer % right.instance.integer)
837   };
838
839   return result;
840 }
841 Object builtin$modular_divide = { CLOSURE, (Instance)(Closure){ NULL, builtin$modular_divide$implementation } };
842
843 Object builtin$field$implementation(
844   EnvironmentPool* environmentPool,
845   Environment* parent,
846   size_t argc,
847   Stack* stack,
848   const unsigned long line,
849   jmp_buf parentJump)
850 {
851   assert(argc == 2);
852
853   Object right = Stack_pop(stack);
854   Object left = Stack_pop(stack);
855
856   assert(left.type == STRUCTURE);
857   assert(right.type == STRING_LITERAL);
858
859   Object result = (Object){
860     INTEGER,
861     (Instance)(int32_t) (left.instance.integer % right.instance.integer)
862   };
863
864   return result;
865 }
866 Object builtin$field = { CLOSURE, (Instance)(Closure){ NULL, builtin$field$implementation } };
867
868 Object builtin$get$implementation(
869   EnvironmentPool* environmentPool,
870   Environment* parent,
871   size_t argc,
872   Stack* stack,
873   const unsigned long line,
874   jmp_buf parentJump)
875 {
876   assert(argc == 2);
877
878   Object right = Stack_pop(stack);
879   Object left = Stack_pop(stack);
880
881   return List_get(&left, right);
882 }
883 Object builtin$get = { CLOSURE, (Instance)(Closure){ NULL, builtin$get$implementation } };
884
885 {% if 'print' in builtins %}
886 Object builtin$print$implementation(
887   EnvironmentPool* environmentPool,
888   Environment* parent,
889   size_t argc,
890   Stack* stack,
891   const unsigned long line,
892   jmp_buf parentJump)
893 {
894   Stack reverse_stack;
895   Stack_initialize(&reverse_stack);
896
897   for(size_t i = 0; i < argc; i++)
898   {
899     Stack_push(&reverse_stack, Stack_pop(stack));
900   }
901
902   while(reverse_stack.length > 0)
903   {
904     Object output = Stack_pop(&reverse_stack);
905     switch(output.type)
906     {
907       case BOOLEAN:
908         fputs(output.instance.boolean ? "true" : "false", stdout);
909         break;
910
911       case CLOSURE:
912         // TODO Print something better
913         printf("<Closure>");
914         break;
915
916       case INTEGER:
917         printf("%" PRId32, output.instance.integer);
918         break;
919
920       case STRING_CONCATENATION:
921         Stack_push(stack, output.instance.string_concatenation->left);
922         builtin$print$implementation(NULL, NULL, 1, stack, line, parentJump);
923         Stack_push(stack, output.instance.string_concatenation->right);
924         builtin$print$implementation(NULL, NULL, 1, stack, line, parentJump);
925         break;
926
927       case STRING_LITERAL:
928         // Using fwrite instead of printf to handle size_t length
929         printf("%s", output.instance.string_literal);
930         break;
931
932       case VOID:
933         printf("nil");
934         break;
935
936       default:
937         assert(false);
938     }
939     Object_deinitialize(&output);
940   }
941
942   // TODO Return something better
943   return builtin$false;
944 }
945
946 Object builtin$print = { CLOSURE, (Instance)(Closure){ NULL, builtin$print$implementation } };
947 {% endif %}
948 {% for function_definition in function_definition_list %}
949 {{ function_definition }}
950 {% endfor %}
951
952 int main(int argc, char** argv)
953 {
954   EnvironmentPool* environmentPool = EnvironmentPool_construct();
955   Environment* environment = EnvironmentPool_allocate(environmentPool);
956   Environment_initialize(environment, NULL);
957
958   Stack stackMemory;
959   Stack* stack = &stackMemory;
960   Stack_initialize(stack);
961
962   jmp_buf jump;
963   if(setjmp(jump) != 0)
964   {
965     fprintf(stderr, "\tin __main__\n");
966
967     while(Stack_any(stack))
968     {
969       Object item = Stack_pop(stack);
970       Object_deinitialize(&item);
971     }
972     Environment_setLive(environment, false);
973     EnvironmentPool_destruct(environmentPool);
974
975     // TODO We would like to return something nonzero here, but that messes up Valgrind so we couldn't catch memory leaks
976     return 0;
977   }
978
979   // TODO Use the symbol from SYMBOL_LIST
980   {% for builtin in builtins %}
981   Environment_set(environment, "{{ builtin }}", builtin${{ builtin }});
982   {% endfor %}
983
984   Environment_set(environment, "true", builtin$true);
985   Environment_set(environment, "false", builtin$false);
986   Environment_set(environment, "__add__", builtin$add);
987   Environment_set(environment, "__subtract__", builtin$subtract);
988   Environment_set(environment, "__multiply__", builtin$multiply);
989   Environment_set(environment, "__integer_divide__", builtin$integer_divide);
990   Environment_set(environment, "__modular_divide__", builtin$modular_divide);
991   Environment_set(environment, "__negate__", builtin$negate);
992   Environment_set(environment, "__concat__", builtin$concat);
993   Environment_set(environment, "__field__", builtin$field);
994   Environment_set(environment, "__get__", builtin$get);
995
996   {% for op in ['lt', 'gt', 'lte', 'gte', 'eq', 'neq'] %}
997   Environment_set(environment, "__{{ op }}__", builtin${{ op }});
998   {% endfor %}
999
1000   {% for statement in statements %}
1001   {{ statement }}
1002   {% endfor %}
1003
1004   Environment_setLive(environment, false);
1005   EnvironmentPool_destruct(environmentPool);
1006   return 0;
1007 }