X-Git-Url: https://code.kerkeslager.com/?a=blobdiff_plain;ds=sidebyside;f=templates%2Fprogram.c;h=7cfd1e3ed31a0ebbdd651b914282fdb46f7873eb;hb=4c47216656579a0e5b81cc3fbab17362ffde3e94;hp=d6df73289dd8bf5028d58861a1d5fca03646ce53;hpb=62bbcc8f9242c7f404db4756460a927b1ce90aec;p=fur diff --git a/templates/program.c b/templates/program.c index d6df732..7cfd1e3 100644 --- a/templates/program.c +++ b/templates/program.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -34,6 +35,8 @@ struct Environment; typedef struct Environment Environment; struct EnvironmentPool; typedef struct EnvironmentPool EnvironmentPool; +struct Stack; +typedef struct Stack Stack; const char* const STRING_LITERAL_LIST[] = { {% for string_literal in string_literal_list %} @@ -64,7 +67,7 @@ typedef struct Closure Closure; struct Closure { Environment* closed; - Object (*call)(EnvironmentPool*, Environment*, size_t, Object*); + Object (*call)(EnvironmentPool*, Environment*, size_t, Stack*, jmp_buf); }; struct List; @@ -149,6 +152,36 @@ Object List_get(Object* list, Object index) return list->instance.list.items[index.instance.integer]; } +struct Stack +{ + uint16_t length; + Object items[256]; +}; + +void Stack_initialize(Stack* self) +{ + self->length = 0; +} + +bool Stack_any(Stack* self) +{ + return self->length > 0; +} + +void Stack_push(Stack* self, Object item) +{ + assert(self->length < 256); + self->items[self->length] = item; + self->length++; +} + +Object Stack_pop(Stack* self) +{ + assert(self->length > 0); + self->length--; + return self->items[self->length]; +} + Object Object_rereference(Object self) { switch(self.type) @@ -517,8 +550,11 @@ Object operator$negate(Object input) } // TODO Make this conditionally added -Object operator$concatenate(Object left, Object right) +Object operator$concatenate(Stack* stack, jmp_buf parent_jump, size_t line) { + Object right = Stack_pop(stack); + Object left = Stack_pop(stack); + switch(left.type) { case STRING_CONCATENATION: case STRING_LITERAL: @@ -547,11 +583,22 @@ Object operator$concatenate(Object left, Object right) } {% for id in infix_declarations %} -Object operator${{ id.name }}(Object left, Object right) +Object operator${{ id.name }}(Stack* stack, jmp_buf parent_jump, size_t line) { + Object right = Stack_pop(stack); + Object left = Stack_pop(stack); + assert(left.type == {{ id.in_type.upper() }}); assert(right.type == {{ id.in_type.upper() }}); + {% if id.name == 'integerDivide' or id.name == 'modularDivide' %} + if(right.instance.integer == 0) + { + fprintf(stderr, "DivisionByZeroError on line %zu\n", line); + longjmp(parent_jump, 1); + } + {% endif %} + Object result; result.type = {{ id.out_type.upper() }}; result.instance.{{ id.out_type.lower() }} = left.instance.{{ id.in_type.lower() }} {{ id.operator }} right.instance.{{ id.in_type.lower() }}; @@ -560,12 +607,11 @@ Object operator${{ id.name }}(Object left, Object right) {% endfor %} {% if 'pow' in builtins %} -Object builtin$pow$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Object* args) +Object builtin$pow$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Stack* stack, jmp_buf parent_jump) { - assert(argc == 2); - - Object base = args[0]; - Object exponent = args[1]; + // Must unload items in reverse order + Object exponent = Stack_pop(stack); + Object base = Stack_pop(stack); assert(base.type == INTEGER); assert(exponent.type == INTEGER); @@ -580,11 +626,19 @@ Object builtin$pow = { CLOSURE, (Instance)(Closure){ NULL, builtin$pow$implement {% endif %} {% if 'print' in builtins %} -Object builtin$print$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Object* args) +Object builtin$print$implementation(EnvironmentPool* environmentPool, Environment* parent, size_t argc, Stack* stack, jmp_buf parent_jump) { + Stack reverse_stack; + Stack_initialize(&reverse_stack); + for(size_t i = 0; i < argc; i++) { - Object output = args[i]; + Stack_push(&reverse_stack, Stack_pop(stack)); + } + + while(reverse_stack.length > 0) + { + Object output = Stack_pop(&reverse_stack); switch(output.type) { case BOOLEAN: @@ -601,8 +655,10 @@ Object builtin$print$implementation(EnvironmentPool* environmentPool, Environmen break; 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)); + Stack_push(stack, output.instance.string_concatenation->left); + builtin$print$implementation(NULL, NULL, 1, stack, parent_jump); + Stack_push(stack, output.instance.string_concatenation->right); + builtin$print$implementation(NULL, NULL, 1, stack, parent_jump); break; case STRING_LITERAL: @@ -636,6 +692,27 @@ int main(int argc, char** argv) Environment* environment = EnvironmentPool_allocate(environmentPool); Environment_initialize(environment, NULL); + Stack stackMemory; + Stack* stack = &stackMemory; + Stack_initialize(stack); + + jmp_buf jump; + if(setjmp(jump) != 0) + { + fprintf(stderr, "\tin __main__\n"); + + while(Stack_any(stack)) + { + Object item = Stack_pop(stack); + Object_deinitialize(&item); + } + Environment_setLive(environment, false); + EnvironmentPool_destruct(environmentPool); + + // TODO We would like to return something nonzero here, but that messes up Valgrind so we couldn't catch memory leaks + return 0; + } + // TODO Use the symbol from SYMBOL_LIST {% for builtin in builtins %} Environment_set(environment, "{{ builtin }}", builtin${{ builtin }});