7 /* Some terminology used in function names:
8 * - initialize: These functions take a pointer and potentially some other arguments, and use those
9 * to initialize the value pointed to by self. Initialize functions DO NOT allocate the function,
10 * so they can be used to initialize stack-allocated variables.
11 * - construct: This allocates a value for a pointer, initializes it, and returns it. This is for
12 * heap-allocated values. It may be as simple as allocating the memory, calling an initialize, and
14 * - deinitialize: These functions dereference or free any objects pointed to by the self pointer's
15 * value, but they don't actually free the self pointer. This is useful for stack-allocated objects
16 * which point to heap-allocated objects.
17 * - destruct: This dereferences or frees memory pointed to by the self argument, and all the
18 * pointers on the self argument.
21 {% for standard_library in standard_libraries %}
22 #include <{{standard_library}}>
26 typedef enum Type Type;
28 typedef union Instance Instance;
30 typedef struct Object Object;
31 struct EnvironmentNode;
32 typedef struct EnvironmentNode EnvironmentNode;
34 typedef struct Environment Environment;
35 struct EnvironmentPool;
36 typedef struct EnvironmentPool EnvironmentPool;
38 const char* const STRING_LITERAL_LIST[] = {
39 {% for string_literal in string_literal_list %}
40 "{{ string_literal }}",
44 const char* const SYMBOL_LIST[] = {
45 {% for symbol in symbol_list %}
63 typedef struct Closure Closure;
67 Object (*call)(EnvironmentPool*, Environment*, size_t, Object*);
71 typedef struct List List;
79 struct StringConcatenation;
80 typedef struct StringConcatenation StringConcatenation;
83 typedef struct Structure Structure;
86 size_t reference_count;
88 const char** symbol_list;
98 StringConcatenation* string_concatenation;
99 const char* string_literal;
100 Structure* structure;
109 const Object builtin$true = { BOOLEAN, (Instance)(bool){ true } };
110 const Object builtin$false = { BOOLEAN, (Instance)(bool){ false } };
111 const Object builtin$nil = { VOID, { 0 } };
113 struct StringConcatenation
115 size_t referenceCount;
120 Object List_construct(size_t allocate)
122 Object* items = malloc(sizeof(Object) * allocate);
123 Object result = { LIST, (Instance)(List){ allocate, 0, items } };
127 void List_append(Object* list, Object item)
129 assert(list->type == LIST);
131 if(list->instance.list.allocated == list->instance.list.length)
133 list->instance.list.allocated *= 2;
134 list->instance.list.items = realloc(
135 list->instance.list.items,
136 sizeof(Object) * list->instance.list.allocated
140 list->instance.list.items[list->instance.list.length] = item;
141 list->instance.list.length++;
144 Object List_get(Object* list, Object index)
146 assert(list->type == LIST);
147 assert(index.type == INTEGER);
149 return list->instance.list.items[index.instance.integer];
152 Object Object_rereference(Object self)
163 case STRING_CONCATENATION:
164 self.instance.string_concatenation->referenceCount++;
168 self.instance.structure->reference_count++;
176 Object Structure_construct(size_t length, const char** symbol_list, Object* value_list)
178 Structure* structure = malloc(sizeof(Structure));
179 structure->reference_count = 1;
180 structure->length = length;
181 structure->symbol_list = malloc(sizeof(const char*) * length);
182 structure->value_list = malloc(sizeof(Object) * length);
184 // TODO Don't allow assignment of mutable structures, as this screws up reference counting
185 for(size_t i = 0; i < length; i++)
187 structure->symbol_list[i] = symbol_list[i];
188 structure->value_list[i] = Object_rereference(value_list[i]);
191 Object result = { STRUCTURE, (Instance)structure };
196 Object Structure_get(Object* self, const char* symbol)
198 assert(self->type == STRUCTURE);
200 for(size_t i = 0; i < self->instance.structure->length; i++)
202 if(self->instance.structure->symbol_list[i] == symbol)
204 return self->instance.structure->value_list[i];
211 struct EnvironmentNode
215 EnvironmentNode* next;
224 EnvironmentNode* root;
227 void Environment_initialize(Environment* self, Environment* parent)
229 self->parent = parent;
232 // We are currently only ever initializing environments at the beginning of running functions, so
233 // for now at least we can assume that we want it to be live immediately.
237 void Object_deinitialize(Object* self)
253 for(size_t i = 0; i < self->instance.list.length; i++) {
254 Object_deinitialize(&(self->instance.list.items[i]));
257 free(self->instance.list.items);
260 case STRING_CONCATENATION:
261 self->instance.string_concatenation->referenceCount--;
263 if(self->instance.string_concatenation->referenceCount == 0)
265 Object_deinitialize(&(self->instance.string_concatenation->left));
266 Object_deinitialize(&(self->instance.string_concatenation->right));
267 free(self->instance.string_concatenation);
272 self->instance.structure->reference_count--;
274 if(self->instance.structure->reference_count == 0)
276 for(size_t i = 0; i < self->instance.structure->length; i++)
278 Object_deinitialize(&(self->instance.structure->value_list[i]));
280 free(self->instance.structure->symbol_list);
281 free(self->instance.structure->value_list);
282 free(self->instance.structure);
291 void Environment_deinitialize(Environment* self)
293 EnvironmentNode* next;
294 for(EnvironmentNode* node = self->root; node != NULL; node = next)
297 Object_deinitialize(&(node->value));
302 void Environment_setLive(Environment* self, bool live)
307 void Environment_mark(Environment* self)
309 if(self == NULL) return;
310 if(self->mark) return; // Prevents infinite recursion in the case of cycles
314 Environment_mark(self->parent);
316 for(EnvironmentNode* node = self->root; node != NULL; node = node->next)
318 switch(node->value.type)
327 Environment_mark(node->value.instance.closure.closed);
336 // This need not be thread safe because environments exist on one thread only
337 void Environment_set(Environment* self, const char* const key, Object value)
339 EnvironmentNode* node = malloc(sizeof(EnvironmentNode));
342 node->next = self->root;
346 Object Environment_get(Environment* self, const char* const symbol)
348 for(EnvironmentNode* node = self->root; node != NULL; node = node->next)
350 // We can compare pointers because pointers are unique in the SYMBOL_LIST
351 if(node->key == symbol)
357 if(self->parent != NULL)
359 return Environment_get(self->parent, symbol);
362 // TODO Handle symbol errors
366 # define POOL_SIZE 64
367 struct EnvironmentPool
370 bool allocatedFlags[POOL_SIZE];
371 Environment environments[POOL_SIZE];
372 EnvironmentPool* overflow;
375 EnvironmentPool* EnvironmentPool_construct();
376 void EnvironmentPool_initialize(EnvironmentPool*);
377 void EnvironmentPool_deinitialize(EnvironmentPool*);
378 void EnvironmentPool_destruct(EnvironmentPool*);
380 EnvironmentPool* EnvironmentPool_construct()
382 EnvironmentPool* result = malloc(sizeof(EnvironmentPool));
383 EnvironmentPool_initialize(result);
387 void EnvironmentPool_initialize(EnvironmentPool* self)
389 self->overflow = NULL;
392 for(size_t i = 0; i < POOL_SIZE; i++)
394 self->allocatedFlags[i] = false;
395 self->environments[i].live = false;
399 void EnvironmentPool_deinitialize(EnvironmentPool* self)
401 // We can assume if this is being called, none of the Environments are live
402 for(int8_t i = 0; i < POOL_SIZE; i++)
404 if(self->allocatedFlags[i]) Environment_deinitialize(&(self->environments[i]));
407 EnvironmentPool_destruct(self->overflow);
410 void EnvironmentPool_destruct(EnvironmentPool* self)
412 if(self == NULL) return;
413 EnvironmentPool_deinitialize(self);
417 void EnvironmentPool_GC(EnvironmentPool* self)
419 // Unmark all the environments
420 for(EnvironmentPool* current = self; current != NULL; current = current->overflow)
422 for(int8_t i = 0; i < POOL_SIZE; i++)
424 current->environments[i].mark = false;
428 // Mark live enviroments and environments referenced by live environments
429 for(EnvironmentPool* current = self; current != NULL; current = current->overflow)
431 for(int8_t i = 0; i < POOL_SIZE; i++)
433 if(current->environments[i].live)
435 Environment_mark(&(current->environments[i]));
440 // TODO We never free pools until the very end--we could free a pool if two pools are empty
441 for(EnvironmentPool* current = self; current != NULL; current = current->overflow)
443 for(int8_t i = POOL_SIZE - 1; i >= 0; i--)
445 if(!current->environments[i].mark && current->allocatedFlags[i])
447 Environment_deinitialize(&(current->environments[i]));
448 current->allocatedFlags[i] = false;
449 current->freeIndex = i;
455 Environment* EnvironmentPool_allocate(EnvironmentPool* self)
457 for(EnvironmentPool* current = self; current != NULL; current = current->overflow)
459 for(; current->freeIndex < POOL_SIZE; current->freeIndex++)
461 if(!current->allocatedFlags[current->freeIndex])
463 current->allocatedFlags[current->freeIndex] = true;
464 return &(current->environments[current->freeIndex]);
469 EnvironmentPool_GC(self);
471 EnvironmentPool* previous;
472 for(EnvironmentPool* current = self; current != NULL; current = current->overflow)
474 for(; current->freeIndex < POOL_SIZE; current->freeIndex++)
476 if(!current->allocatedFlags[current->freeIndex])
478 current->allocatedFlags[current->freeIndex] = true;
479 return &(current->environments[current->freeIndex]);
488 previous->overflow = EnvironmentPool_construct();
489 return EnvironmentPool_allocate(previous->overflow);
492 Object integerLiteral(int32_t literal)
495 result.type = INTEGER;
496 result.instance.integer = literal;
500 Object stringLiteral(const char* literal)
503 result.type = STRING_LITERAL;
504 result.instance.string_literal = literal;
508 // TODO Make this conditionally added
509 Object operator$negate(Object input)
511 assert(input.type == INTEGER);
514 result.type = INTEGER;
515 result.instance.integer = -input.instance.integer;
519 // TODO Make this conditionally added
520 Object operator$concatenate(Object left, Object right)
523 case STRING_CONCATENATION:
532 case STRING_CONCATENATION:
540 StringConcatenation* concatenation = malloc(sizeof(StringConcatenation));
541 concatenation->referenceCount = 1;
542 concatenation->left = Object_rereference(left);
543 concatenation->right = Object_rereference(right);
545 Object result = { STRING_CONCATENATION, (Instance)concatenation };
549 {% for id in infix_declarations %}
550 Object operator${{ id.name }}(Object left, Object right)
552 assert(left.type == {{ id.in_type.upper() }});
553 assert(right.type == {{ id.in_type.upper() }});
556 result.type = {{ id.out_type.upper() }};
557 result.instance.{{ id.out_type.lower() }} = left.instance.{{ id.in_type.lower() }} {{ id.operator }} right.instance.{{ id.in_type.lower() }};
562 {% if 'pow' in builtins %}
563 Object builtin$pow$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Object* args)
567 Object base = args[0];
568 Object exponent = args[1];
570 assert(base.type == INTEGER);
571 assert(exponent.type == INTEGER);
574 result.type = INTEGER;
575 result.instance.integer = pow(base.instance.integer, exponent.instance.integer);
579 Object builtin$pow = { CLOSURE, (Instance)(Closure){ NULL, builtin$pow$implementation } };
582 {% if 'print' in builtins %}
583 Object builtin$print$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Object* args)
585 for(size_t i = 0; i < argc; i++)
587 Object output = args[i];
591 fputs(output.instance.boolean ? "true" : "false", stdout);
595 // TODO Print something better
600 printf("%" PRId32, output.instance.integer);
603 case STRING_CONCATENATION:
604 builtin$print$implementation(NULL, NULL, 1, &(output.instance.string_concatenation->left));
605 builtin$print$implementation(NULL, NULL, 1, &(output.instance.string_concatenation->right));
609 // Using fwrite instead of printf to handle size_t length
610 printf("%s", output.instance.string_literal);
620 Object_deinitialize(&output);
623 // TODO Return something better
624 return builtin$false;
627 Object builtin$print = { CLOSURE, (Instance)(Closure){ NULL, builtin$print$implementation } };
629 {% for function_definition in function_definition_list %}
630 {{ function_definition }}
633 int main(int argc, char** argv)
635 EnvironmentPool* environmentPool = EnvironmentPool_construct();
636 Environment* environment = EnvironmentPool_allocate(environmentPool);
637 Environment_initialize(environment, NULL);
639 // TODO Use the symbol from SYMBOL_LIST
640 {% for builtin in builtins %}
641 Environment_set(environment, "{{ builtin }}", builtin${{ builtin }});
644 {% for statement in statements %}
648 Environment_setLive(environment, false);
649 EnvironmentPool_destruct(environmentPool);