From: David Kerkeslager Date: Tue, 1 Oct 2019 19:31:13 +0000 (-0400) Subject: Implemented closures X-Git-Url: https://code.kerkeslager.com/?p=fur;a=commitdiff_plain;h=40cd5f86db884963c917943377ca4e6e8f419f8e Implemented closures --- diff --git a/templates/environment.c b/templates/environment.c index 2de6b59..483e38a 100644 --- a/templates/environment.c +++ b/templates/environment.c @@ -7,6 +7,8 @@ struct _EnvironmentNode { }; struct Environment { + size_t referenceCount; + Environment* shadowed; _EnvironmentNode* top; }; @@ -17,11 +19,15 @@ struct Environment_get_Result { Object result; }; -void Environment_initialize(Environment* self) { +void Environment_initialize(Environment* self, Environment* shadowed) { + self->referenceCount = 1; + self->shadowed = shadowed; self->top = NULL; } void Environment_deinitialize(Environment* self) { + assert(self->referenceCount == 0); + while(self->top != NULL) { _EnvironmentNode* en = self->top; self->top = en->next; @@ -30,18 +36,26 @@ void Environment_deinitialize(Environment* self) { } } -Environment* Environment_construct() { +Environment* Environment_construct(Environment* shadowed) { Environment* result = malloc(sizeof(Environment)); - Environment_initialize(result); + Environment_initialize(result, shadowed); return result; } +Environment* Environment_reference(Environment* self) { + self->referenceCount++; // TODO Do we need to make this thread safe? + return self; +} + void Environment_destruct(Environment* self) { - Environment_deinitialize(self); - free(self); + self->referenceCount--; // TODO Do we need to make this thread safe? + if(self->referenceCount == 0) { + Environment_deinitialize(self); + free(self); + } } -Environment_get_Result Environment_get(Environment* self, char* symbol) { +Environment_get_Result Environment_getShallow(Environment* self, char* symbol) { for(_EnvironmentNode* current = self->top; current != NULL; current = current->next) { if(strcmp(current->symbol, symbol) == 0) { return (Environment_get_Result) { true, current->value }; @@ -50,8 +64,16 @@ Environment_get_Result Environment_get(Environment* self, char* symbol) { return (Environment_get_Result) { false, BUILTIN_NIL }; } +Environment_get_Result Environment_get(Environment* self, char* symbol) { + for(; self != NULL; self = self->shadowed) { + Environment_get_Result result = Environment_getShallow(self, symbol); + if(result.found) return result; + } + return (Environment_get_Result) { false, BUILTIN_NIL }; +} + void Environment_set(Environment* self, char* symbol, Object value) { - assert(!(Environment_get(self, symbol).found)); + assert(!(Environment_getShallow(self, symbol).found)); _EnvironmentNode* en = malloc(sizeof(_EnvironmentNode)); en->symbol = symbol; diff --git a/templates/program2.c b/templates/program2.c index f307b85..5ca9f61 100644 --- a/templates/program2.c +++ b/templates/program2.c @@ -23,8 +23,12 @@ enum Builtin { PRINT }; +struct Object; +typedef struct Object Object; struct Environment; typedef struct Environment Environment; +struct Thread; +typedef struct Thread Thread; struct Closure; typedef struct Closure Closure; @@ -43,8 +47,6 @@ union Value { int32_t integer; }; -struct Object; -typedef struct Object Object; struct Object { Type type; Value value; @@ -59,39 +61,35 @@ void Object_deinitialize(Object* self) { {% include "stack.c" %} {% include "frame.c" %} -struct Thread; -typedef struct Thread Thread; struct Thread { - Environment* environment; + Frame frame; Stack stack; - size_t programCounter; }; void Thread_initialize(Thread* self, size_t programCounter) { - self->environment = Environment_construct(); + Frame_initialize(&(self->frame), Environment_construct(NULL), NULL, programCounter); Stack_initialize(&(self->stack)); - self->programCounter = programCounter; } void Thread_deinitialize(Thread* self) { - Environment_destruct(self->environment); + Frame_deinitialize(&(self->frame)); Stack_deinitialize(&(self->stack)); } Environment* Thread_getEnvironment(Thread* self) { - return self->environment; + return self->frame.environment; } void Thread_setProgramCounter(Thread* self, size_t programCounter) { - self->programCounter = programCounter; + self->frame.programCounter = programCounter; } void Thread_incrementProgramCounter(Thread* self) { - self->programCounter++; + self->frame.programCounter++; } size_t Thread_getProgramCounter(Thread* self) { - return self->programCounter; + return self->frame.programCounter; } union Argument; @@ -179,7 +177,14 @@ void callBuiltin(Thread* thread, Builtin b, size_t argumentCount) { void callClosure(Thread* thread, Closure closure, size_t argumentCount) { assert(argumentCount == 0); - + Frame* returnFrame = malloc(sizeof(Frame)); + *returnFrame = thread->frame; + Frame_initialize( + &(thread->frame), + Environment_construct(Environment_reference(closure.environment)), + returnFrame, + closure.entry - 1 // We will increment the frame immediately after this + ); } void inst_call(Thread* thread, Argument argument) { @@ -350,7 +355,18 @@ void inst_push_string(Thread* thread, Argument argument) { {% endwith %} void inst_return(Thread* thread, Argument argument) { - assert(false); + Frame* returnFrame = thread->frame.returnFrame; + + Frame_deinitialize(&(thread->frame)); + + Frame_initialize( + &(thread->frame), + returnFrame->environment, + returnFrame->returnFrame, + returnFrame->programCounter + ); + + free(returnFrame); } struct Instruction;