Finish conditional compilation of operators
[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 id in infix_declarations %}
164 Object operator${{ id.name }}(Object left, Object right)
165 {
166   assert(left.type == {{ id.in_type.upper() }});
167   assert(right.type == {{ id.in_type.upper() }});
168
169   Object result;
170   result.type = {{ id.out_type.upper() }};
171   result.instance.{{ id.out_type.lower() }} = left.instance.{{ id.in_type.lower() }} {{ id.operator }} right.instance.{{ id.in_type.lower() }};
172   return result;
173 }
174 {% endfor %}
175
176 {% if 'pow' in builtins %}
177 Object builtin$pow$implementation(Environment* parent, size_t argc, Object* args)
178 {
179   assert(argc == 2);
180
181   Object base = args[0];
182   Object exponent = args[1];
183
184   assert(base.type == INTEGER);
185   assert(exponent.type == INTEGER);
186
187   Object result;
188   result.type = INTEGER;
189   result.instance.integer = pow(base.instance.integer, exponent.instance.integer);
190   return result;
191 }
192
193 Object builtin$pow = { CLOSURE, (Instance)builtin$pow$implementation };
194 {% endif %}
195
196 {% if 'print' in builtins %}
197 Object builtin$print$implementation(Environment* parent, size_t argc, Object* args)
198 {
199   for(size_t i = 0; i < argc; i++)
200   {
201     Object output = args[i];
202     switch(output.type)
203     {
204       case BOOLEAN:
205         fputs(output.instance.boolean ? "true" : "false", stdout);
206         break;
207
208       case INTEGER:
209         printf("%" PRId32, output.instance.integer);
210         break;
211
212       case STRING:
213         // Using fwrite instead of printf to handle size_t length
214         printf("%s", output.instance.string);
215         break;
216
217       default:
218         assert(false);
219     }
220   }
221
222   // TODO Return something better
223   return FALSE;
224 }
225
226 Object builtin$print = { CLOSURE, (Instance)builtin$print$implementation };
227 {% endif %}
228
229 {% for function_definition in function_definition_list %}
230 Object user${{function_definition.name}}$implementation(Environment* parent, size_t argc, Object* args)
231 {
232   Environment* environment = Environment_construct(parent);
233
234   {% for statement in function_definition.statement_list[:-1] %}
235   {{ generate_statement(statement) }}
236   {% endfor %}
237
238   Object result = {{ generate_statement(function_definition.statement_list[-1]) }}
239   Environment_destruct(environment);
240   return result;
241 }
242
243 Object user${{function_definition.name}} = { CLOSURE, (Instance)user${{function_definition.name}}$implementation };
244 {% endfor %}
245
246 int main(int argc, char** argv)
247 {
248   Environment* environment = Environment_construct(NULL);
249
250   // TODO Use the symbol from SYMBOL_LIST
251   {% for builtin in builtins %}
252   Environment_set(environment, "{{ builtin }}", builtin${{ builtin }});
253   {% endfor %}
254
255   {% for statement in statements %}
256   {{ generate_statement(statement) }}
257   {% endfor %}
258
259   Environment_destruct(environment);
260
261   return 0;
262 }