X-Git-Url: https://code.kerkeslager.com/?a=blobdiff_plain;f=templates%2Fprogram.c;h=25bb41348abf3a3454cad00da4c08e6cf51aca44;hb=151f60b119247efb1bcf05a664f4324b71fac782;hp=4ac6289f414a65030274c62f3dc5dc4db476ace6;hpb=a96e96f3f783930707122f691cd6a08a90416a74;p=fur diff --git a/templates/program.c b/templates/program.c index 4ac6289..25bb413 100644 --- a/templates/program.c +++ b/templates/program.c @@ -52,7 +52,9 @@ enum Type BOOLEAN, CLOSURE, INTEGER, - STRING, + LIST, + STRING_CONCATENATION, + STRING_LITERAL, VOID }; @@ -64,12 +66,26 @@ struct Closure Object (*call)(EnvironmentPool*, Environment*, size_t, Object*); }; +struct List; +typedef struct List List; +struct List +{ + size_t allocated; + size_t length; + Object* items; +}; + +struct StringConcatenation; +typedef struct StringConcatenation StringConcatenation; + union Instance { bool boolean; Closure closure; int32_t integer; - const char* string; + List list; + StringConcatenation* string_concatenation; + const char* string_literal; }; struct Object @@ -82,6 +98,45 @@ const Object builtin$true = { BOOLEAN, (Instance)(bool){ true } }; const Object builtin$false = { BOOLEAN, (Instance)(bool){ false } }; const Object builtin$nil = { VOID, { 0 } }; +struct StringConcatenation +{ + size_t referenceCount; + Object left; + Object right; +}; + +Object List_construct(size_t allocate) +{ + Object* items = malloc(sizeof(Object) * allocate); + Object result = { LIST, (Instance)(List){ allocate, 0, items } }; + return result; +} + +void List_append(Object* list, Object item) +{ + assert(list->type == LIST); + + if(list->instance.list.allocated == list->instance.list.length) + { + list->instance.list.allocated *= 2; + list->instance.list.items = realloc( + list->instance.list.items, + sizeof(Object) * list->instance.list.allocated + ); + } + + list->instance.list.items[list->instance.list.length] = item; + list->instance.list.length++; +} + +Object List_get(Object* list, Object index) +{ + assert(list->type == LIST); + assert(index.type == INTEGER); + + return list->instance.list.items[index.instance.integer]; +} + struct EnvironmentNode { const char* key; @@ -108,12 +163,52 @@ void Environment_initialize(Environment* self, Environment* parent) self->live = true; } +void Object_deinitialize(Object* self) +{ + switch(self->type) + { + case BOOLEAN: + break; + case CLOSURE: + break; + case INTEGER: + break; + case STRING_LITERAL: + break; + case VOID: + break; + + case LIST: + for(size_t i = 0; i < self->instance.list.length; i++) { + Object_deinitialize(&(self->instance.list.items[i])); + } + + free(self->instance.list.items); + break; + + case STRING_CONCATENATION: + self->instance.string_concatenation->referenceCount--; + + if(self->instance.string_concatenation->referenceCount == 0) + { + Object_deinitialize(&(self->instance.string_concatenation->left)); + Object_deinitialize(&(self->instance.string_concatenation->right)); + free(self->instance.string_concatenation); + } + break; + + default: + assert(false); + } +} + void Environment_deinitialize(Environment* self) { EnvironmentNode* next; for(EnvironmentNode* node = self->root; node != NULL; node = next) { next = node->next; + Object_deinitialize(&(node->value)); free(node); } } @@ -138,7 +233,7 @@ void Environment_mark(Environment* self) { case BOOLEAN: case INTEGER: - case STRING: + case STRING_LITERAL: case VOID: break; @@ -319,8 +414,8 @@ Object integerLiteral(int32_t literal) Object stringLiteral(const char* literal) { Object result; - result.type = STRING; - result.instance.string = literal; + result.type = STRING_LITERAL; + result.instance.string_literal = literal; return result; } @@ -335,6 +430,42 @@ Object operator$negate(Object input) return result; } +// TODO Make this conditionally added +Object operator$concatenate(Object left, Object right) +{ + switch(left.type) { + case STRING_CONCATENATION: + left.instance.string_concatenation->referenceCount++; + break; + + case STRING_LITERAL: + break; + + default: + assert(false); + } + + switch(right.type) { + case STRING_CONCATENATION: + right.instance.string_concatenation->referenceCount++; + break; + + case STRING_LITERAL: + break; + + default: + assert(false); + } + + StringConcatenation* concatenation = malloc(sizeof(StringConcatenation)); + concatenation->referenceCount = 1; + concatenation->left = left; + concatenation->right = right; + + Object result = { STRING_CONCATENATION, (Instance)concatenation }; + return result; +} + {% for id in infix_declarations %} Object operator${{ id.name }}(Object left, Object right) { @@ -389,9 +520,14 @@ Object builtin$print$implementation(EnvironmentPool* environmentPool, Environmen printf("%" PRId32, output.instance.integer); break; - case STRING: + case STRING_CONCATENATION: + builtin$print$implementation(NULL, NULL, 1, &(output.instance.string_concatenation->left)); + builtin$print$implementation(NULL, NULL, 1, &(output.instance.string_concatenation->right)); + break; + + case STRING_LITERAL: // Using fwrite instead of printf to handle size_t length - printf("%s", output.instance.string); + printf("%s", output.instance.string_literal); break; case VOID: @@ -401,6 +537,7 @@ Object builtin$print$implementation(EnvironmentPool* environmentPool, Environmen default: assert(false); } + Object_deinitialize(&output); } // TODO Return something better