7 {% for standard_library in standard_libraries %}
8 #include <{{standard_library}}>
12 typedef struct String String;
14 typedef enum Type Type;
16 typedef union Instance Instance;
18 typedef struct Object Object;
20 typedef struct Runtime Runtime;
28 const char * const SYMBOL_LIST[] = {
29 {% for symbol in symbol_list %}
59 const Object FALSE = {
64 struct EnvironmentNode;
65 typedef struct EnvironmentNode EnvironmentNode;
66 struct EnvironmentNode
70 EnvironmentNode* next;
74 typedef struct Environment Environment;
77 EnvironmentNode* root;
80 Environment* Environment_construct()
82 // TODO Handle malloc returning NULL
83 Environment* result = malloc(sizeof(Environment));
88 void Environment_destruct(Environment* self)
90 EnvironmentNode* next;
91 for(EnvironmentNode* node = self->root; node != NULL; node = next)
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)
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)
103 EnvironmentNode* node = malloc(sizeof(EnvironmentNode));
106 node->next = self->root;
110 Object Environment_get(Environment* self, const char* const symbol)
112 for(EnvironmentNode* node = self->root; node != NULL; node = node->next)
114 // We can compare pointers because pointers are unique in the SYMBOLS_LIST
115 if(node->key == symbol)
121 // TODO Handle symbol errors
128 size_t permanentStringsLength;
129 size_t permanentStringsAllocated;
130 String** permanentStrings;
133 Runtime* Runtime_construct()
135 Runtime* result = malloc(sizeof(Runtime));
136 result->permanentStringsLength = 0;
137 result->permanentStringsAllocated = 0;
138 result->permanentStrings = NULL;
142 void Runtime_destruct(Runtime* self)
144 for(size_t i = 0; i < self->permanentStringsLength; i++)
146 free(self->permanentStrings[i]);
149 free(self->permanentStrings);
153 void Runtime_addPermanentString(Runtime* self, String* string)
155 // TODO Make this function thread-safe
156 if(self->permanentStringsLength == self->permanentStringsAllocated)
158 if(self->permanentStringsAllocated == 0)
160 self->permanentStringsAllocated = 8;
164 self->permanentStringsAllocated = self->permanentStringsAllocated * 2;
167 self->permanentStrings = realloc(
168 self->permanentStrings,
169 sizeof(String*) * self->permanentStringsAllocated
172 // TODO Handle realloc returning NULL
175 self->permanentStrings[self->permanentStringsLength] = string;
176 self->permanentStringsLength++;
179 Object integerLiteral(int32_t literal)
182 result.type = INTEGER;
183 result.instance.integer = literal;
187 Object stringLiteral(Runtime* runtime, const char* literal)
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);
196 result.type = STRING;
197 result.instance.string = resultString;
201 // TODO Make this conditionally added
202 Object builtin$negate(Object input)
204 assert(input.type == INTEGER);
207 result.type = INTEGER;
208 result.instance.integer = -input.instance.integer;
212 Object builtin$add(Object left, Object right)
214 assert(left.type == INTEGER);
215 assert(right.type == INTEGER);
218 result.type = INTEGER;
219 result.instance.integer = left.instance.integer + right.instance.integer;
223 Object builtin$subtract(Object left, Object right)
225 assert(left.type == INTEGER);
226 assert(right.type == INTEGER);
229 result.type = INTEGER;
230 result.instance.integer = left.instance.integer - right.instance.integer;
234 Object builtin$multiply(Object left, Object right)
236 assert(left.type == INTEGER);
237 assert(right.type == INTEGER);
240 result.type = INTEGER;
241 result.instance.integer = left.instance.integer * right.instance.integer;
245 Object builtin$integerDivide(Object left, Object right)
247 assert(left.type == INTEGER);
248 assert(right.type == INTEGER);
251 result.type = INTEGER;
252 result.instance.integer = left.instance.integer / right.instance.integer;
256 Object builtin$modularDivide(Object left, Object right)
258 assert(left.type == INTEGER);
259 assert(right.type == INTEGER);
262 result.type = INTEGER;
263 result.instance.integer = left.instance.integer % right.instance.integer;
267 Object builtin$equals(Object left, Object right)
269 assert(left.type == INTEGER);
270 assert(right.type == INTEGER);
272 Object result = { BOOLEAN, left.instance.integer == right.instance.integer };
276 Object builtin$notEquals(Object left, Object right)
278 assert(left.type == INTEGER);
279 assert(right.type == INTEGER);
281 Object result = { BOOLEAN, left.instance.integer != right.instance.integer };
285 Object builtin$greaterThan(Object left, Object right)
287 assert(left.type == INTEGER);
288 assert(right.type == INTEGER);
290 Object result = { BOOLEAN, left.instance.integer > right.instance.integer };
294 Object builtin$lessThan(Object left, Object right)
296 assert(left.type == INTEGER);
297 assert(right.type == INTEGER);
299 Object result = { BOOLEAN, left.instance.integer < right.instance.integer };
303 Object builtin$greaterThanOrEqual(Object left, Object right)
305 assert(left.type == INTEGER);
306 assert(right.type == INTEGER);
308 Object result = { BOOLEAN, left.instance.integer >= right.instance.integer };
312 Object builtin$lessThanOrEqual(Object left, Object right)
314 assert(left.type == INTEGER);
315 assert(right.type == INTEGER);
317 Object result = { BOOLEAN, left.instance.integer <= right.instance.integer };
321 Object builtin$and(Object left, Object right)
323 assert(left.type == BOOLEAN);
324 assert(right.type == BOOLEAN);
326 Object result = { BOOLEAN, left.instance.boolean && right.instance.boolean };
330 Object builtin$or(Object left, Object right)
332 assert(left.type == BOOLEAN);
333 assert(right.type == BOOLEAN);
335 Object result = { BOOLEAN, left.instance.boolean || right.instance.boolean };
339 {% if 'pow' in builtins %}
340 Object builtin$pow(Object base, Object exponent)
342 assert(base.type == INTEGER);
343 assert(exponent.type == INTEGER);
346 result.type = INTEGER;
347 result.instance.integer = pow(base.instance.integer, exponent.instance.integer);
352 {% if 'print' in builtins %}
353 void builtin$print(Object output)
358 fputs(output.instance.boolean ? "true" : "false", stdout);
362 printf("%" PRId32, output.instance.integer);
366 // Using fwrite instead of printf to handle size_t length
367 fwrite(output.instance.string->characters, 1, output.instance.string->length, stdout);
376 int main(int argc, char** argv)
378 Runtime* runtime = Runtime_construct();
379 Environment* environment = Environment_construct();
381 {% for statement in statements %}
385 Environment_destruct(environment);
386 Runtime_destruct(runtime);