X-Git-Url: https://code.kerkeslager.com/?p=fur;a=blobdiff_plain;f=templates%2Fprogram.c;h=25bb41348abf3a3454cad00da4c08e6cf51aca44;hp=17669674a01e41d8ca4a1eb8c514a0daef6ef658;hb=151f60b119247efb1bcf05a664f4324b71fac782;hpb=3297817843cd6bd087505a70d8e108f1baa35cff diff --git a/templates/program.c b/templates/program.c index 1766967..25bb413 100644 --- a/templates/program.c +++ b/templates/program.c @@ -53,7 +53,8 @@ enum Type CLOSURE, INTEGER, LIST, - STRING, + STRING_CONCATENATION, + STRING_LITERAL, VOID }; @@ -74,13 +75,17 @@ struct List Object* items; }; +struct StringConcatenation; +typedef struct StringConcatenation StringConcatenation; + union Instance { bool boolean; Closure closure; int32_t integer; List list; - const char* string; + StringConcatenation* string_concatenation; + const char* string_literal; }; struct Object @@ -93,6 +98,13 @@ 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); @@ -151,30 +163,52 @@ void Environment_initialize(Environment* self, Environment* parent) self->live = true; } -void Environment_deinitialize(Environment* self) +void Object_deinitialize(Object* self) { - EnvironmentNode* next; - for(EnvironmentNode* node = self->root; node != NULL; node = next) + switch(self->type) { - next = node->next; + 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])); + } - switch(node->value.type) - { - case BOOLEAN: - case CLOSURE: - case INTEGER: - case STRING: - case VOID: - break; + free(self->instance.list.items); + break; - case LIST: - free(node->value.instance.list.items); - break; + case STRING_CONCATENATION: + self->instance.string_concatenation->referenceCount--; - default: - assert(false); - } + 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); } } @@ -199,7 +233,7 @@ void Environment_mark(Environment* self) { case BOOLEAN: case INTEGER: - case STRING: + case STRING_LITERAL: case VOID: break; @@ -380,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; } @@ -396,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) { @@ -450,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: @@ -462,6 +537,7 @@ Object builtin$print$implementation(EnvironmentPool* environmentPool, Environmen default: assert(false); } + Object_deinitialize(&output); } // TODO Return something better