};
struct Environment {
+ size_t referenceCount;
+ Environment* shadowed;
_EnvironmentNode* top;
};
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;
}
}
-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 };
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;
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;
int32_t integer;
};
-struct Object;
-typedef struct Object Object;
struct Object {
Type type;
Value value;
{% 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;
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) {
{% 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;