X-Git-Url: https://code.kerkeslager.com/?p=fur;a=blobdiff_plain;f=templates%2Fprogram2.c;h=01203fd92eb47ac133e0667280bc3759ef84d05c;hp=919fb8300ba288dfebfc990a80b9cb9e0a1f5c83;hb=c24be69b26aedc427c7831f150e86ca00182d8e0;hpb=7abf5e459b2ef02c8e59c05f0a83d8213ade0427 diff --git a/templates/program2.c b/templates/program2.c index 919fb83..01203fd 100644 --- a/templates/program2.c +++ b/templates/program2.c @@ -12,7 +12,10 @@ enum Type { BUILTIN, CLOSURE, INTEGER, - STRING + LIST, + STRING, + STRUCTURE, + SYMBOL }; enum Builtin; @@ -23,8 +26,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; @@ -33,23 +40,41 @@ struct Closure { size_t entry; }; +struct List; +typedef struct List List; + +struct Structure; +typedef struct Structure Structure; + union Value; typedef union Value Value; union Value { Builtin builtin; - Closure closure; bool boolean; - char* string; + Closure closure; int32_t integer; + List* list; + char* string; + Structure* structure; + char* symbol; }; -struct Object; -typedef struct Object Object; struct Object { Type type; Value value; }; +struct List { + Object head; + List* tail; +}; + +struct Structure { + char* key; + Object value; + Structure* next; +}; + #define BUILTIN_NIL (Object) { BUILTIN, (Value)(Builtin)NIL } void Object_deinitialize(Object* self) { @@ -57,26 +82,39 @@ void Object_deinitialize(Object* self) { {% include "environment.c" %} {% include "stack.c" %} +{% include "frame.c" %} -struct Thread; -typedef struct Thread Thread; struct Thread { - Environment* environment; + Frame frame; Stack stack; - size_t program_counter; }; -void Thread_initialize(Thread* self, size_t program_counter) { - self->environment = Environment_construct(); +void Thread_initialize(Thread* self, size_t programCounter) { + Frame_initialize(&(self->frame), Environment_construct(NULL), NULL, programCounter); Stack_initialize(&(self->stack)); - self->program_counter = program_counter; } void Thread_deinitialize(Thread* self) { - Environment_destruct(self->environment); + Frame_deinitialize(&(self->frame)); Stack_deinitialize(&(self->stack)); } +Environment* Thread_getEnvironment(Thread* self) { + return self->frame.environment; +} + +void Thread_setProgramCounter(Thread* self, size_t programCounter) { + self->frame.programCounter = programCounter; +} + +void Thread_incrementProgramCounter(Thread* self) { + self->frame.programCounter++; +} + +size_t Thread_getProgramCounter(Thread* self) { + return self->frame.programCounter; +} + union Argument; typedef const union Argument Argument; union Argument { @@ -84,6 +122,7 @@ union Argument { void* pointer; char* string; int32_t integer; + char* symbol; }; void callBuiltinPow(Thread* thread, size_t argumentCount) { @@ -138,7 +177,7 @@ void callBuiltinPrint(Thread* thread, size_t argumentCount) { break; default: - assert(0); + assert(false); } } @@ -150,6 +189,7 @@ void callBuiltin(Thread* thread, Builtin b, size_t argumentCount) { case POW: callBuiltinPow(thread, argumentCount); break; + case PRINT: callBuiltinPrint(thread, argumentCount); break; @@ -159,7 +199,20 @@ void callBuiltin(Thread* thread, Builtin b, size_t argumentCount) { } } -void inst_call(struct Thread* thread, Argument argument) { +void callClosure(Thread* thread, Closure closure, size_t argumentCount) { + // TODO Find a way to assert the argument count + + 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) { assert(!Stack_isEmpty(&(thread->stack))); Object f = Stack_pop(&(thread->stack)); size_t argumentCount = argument.label; @@ -170,9 +223,7 @@ void inst_call(struct Thread* thread, Argument argument) { break; case CLOSURE: - { - assert(false); - } + callClosure(thread, f.value.closure, argumentCount); break; default: @@ -180,12 +231,40 @@ void inst_call(struct Thread* thread, Argument argument) { } } +void inst_concat(Thread* thread, Argument argument) { + assert(!Stack_isEmpty(&(thread->stack))); + Object left = Stack_pop(&(thread->stack)); + assert(!Stack_isEmpty(&(thread->stack))); + Object right = Stack_pop(&(thread->stack)); + + assert(left.type == STRING); + assert(right.type == STRING); + + char* resultString = malloc(strlen(left.value.string) + strlen(right.value.string) + 1); + resultString[0] = '\0'; + + strcat(resultString, left.value.string); + strcat(resultString, right.value.string); + + Object resultObject = (Object) { + STRING, + (Value)resultString + }; + + Stack_push(&(thread->stack), resultObject); +} + {% with name='add', operation='+' %} {% include "arithmetic_instruction.c" %} {% endwith %} void inst_close(Thread* thread, Argument argument) { - assert(false); + Object result; + result.type = CLOSURE; + result.value.closure.environment = Thread_getEnvironment(thread); + result.value.closure.entry = argument.label; + + Stack_push(&(thread->stack), result); } void inst_drop(Thread* thread, Argument argument) { @@ -194,13 +273,54 @@ void inst_drop(Thread* thread, Argument argument) { Object_deinitialize(&result); } -void inst_end(struct Thread* thread, Argument argument) { +void inst_end(Thread* thread, Argument argument) { } {% with name='eq', operation='==' %} {% include "comparison_instruction.c" %} {% endwith %} +void inst_field(Thread* thread, Argument argument) { + assert(!Stack_isEmpty(&(thread->stack))); + Object key = Stack_pop(&(thread->stack)); + assert(key.type == SYMBOL); + + assert(!Stack_isEmpty(&(thread->stack))); + Object structure = Stack_pop(&(thread->stack)); + assert(structure.type == STRUCTURE); + + while(structure.value.structure != NULL) { + if(strcmp(structure.value.structure->key, key.value.string) == 0) { + Stack_push(&(thread->stack), structure.value.structure->value); + return; + } + structure.value.structure = structure.value.structure->next; + } + + assert(false); // Symbol wasn't found in structure +} + +void inst_get(Thread* thread, Argument argument) { + assert(!Stack_isEmpty(&(thread->stack))); + Object indexObject = Stack_pop(&(thread->stack)); + assert(indexObject.type == INTEGER); + int32_t index = indexObject.value.integer; + + assert(!Stack_isEmpty(&(thread->stack))); + Object listObject = Stack_pop(&(thread->stack)); + assert(listObject.type == LIST); + List* list = listObject.value.list; + + while(index > 0) { + assert(list != NULL); + list = list->tail; + index--; + } + + assert(list != NULL); + Stack_push(&(thread->stack), list->head); +} + {% with name='gt', operation='>' %} {% include "comparison_instruction.c" %} {% endwith %} @@ -214,7 +334,7 @@ void inst_end(struct Thread* thread, Argument argument) { {% endwith %} void inst_jump(Thread* thread, Argument argument) { - thread->program_counter = argument.label - 1; // We will increment before running + Thread_setProgramCounter(thread, argument.label - 1); // We will increment before running } void inst_jump_if_false(Thread* thread, Argument argument) { @@ -227,6 +347,28 @@ void inst_jump_if_false(Thread* thread, Argument argument) { } } +void inst_list(Thread* thread, Argument argument) { + Object result; + result.type = LIST; + result.value.list = NULL; + + int32_t count = argument.integer; + + while(count > 0) { + assert(!Stack_isEmpty(&(thread->stack))); + Object item = Stack_pop(&(thread->stack)); + + List* node = malloc(sizeof(List)); + node->head = item; + node->tail = result.value.list; + + result.value.list = node; + count--; + } + + Stack_push(&(thread->stack), result); +} + {% with name='lt', operation='<' %} {% include "comparison_instruction.c" %} {% endwith %} @@ -257,7 +399,7 @@ void inst_neg(Thread* thread, Argument argument) { Stack_push(&(thread->stack), result); } -void inst_pop(struct Thread* thread, Argument argument) { +void inst_pop(Thread* thread, Argument argument) { char* argumentString = argument.string; assert(!Stack_isEmpty(&(thread->stack))); @@ -270,15 +412,15 @@ void inst_pop(struct Thread* thread, Argument argument) { } - Environment_set(thread->environment, argumentString, result); + Environment_set(Thread_getEnvironment(thread), argumentString, result); } -void inst_push(struct Thread* thread, Argument argument) { +void inst_push(Thread* thread, Argument argument) { char* argumentString = argument.string; if(strcmp(argumentString, "false") == 0) { Stack_push(&(thread->stack), (Object){ BOOLEAN, false }); - }else if(strcmp(argumentString, "pow") == 0) { + } else if(strcmp(argumentString, "pow") == 0) { Object result; result.type = BUILTIN; result.value.builtin = POW; @@ -291,7 +433,10 @@ void inst_push(struct Thread* thread, Argument argument) { } else if(strcmp(argumentString, "true") == 0) { Stack_push(&(thread->stack), (Object){ BOOLEAN, true }); } else { - Environment_get_Result result = Environment_get(thread->environment, argumentString); + Environment_get_Result result = Environment_get( + Thread_getEnvironment(thread), + argumentString + ); if(!result.found) { fprintf(stderr, "Variable `%s` not found", argumentString); assert(false); @@ -316,18 +461,66 @@ void inst_push_string(Thread* thread, Argument argument) { Stack_push(&(thread->stack), result); } +void inst_push_symbol(Thread* thread, Argument argument) { + // TODO Store symbols in a symbol table so they can be looked up by reference + // without string comparison + Object result; + result.type = SYMBOL; + result.value.symbol = argument.symbol; + + Stack_push(&(thread->stack), result); +} + {% with name='sub', operation='-' %} {% include "arithmetic_instruction.c" %} {% 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); +} + +void inst_structure(Thread* thread, Argument argument) { + Object result; + result.type = STRUCTURE; + result.value.structure = NULL; + + int32_t count = argument.integer; + + while(count > 0) { + assert(!Stack_isEmpty(&(thread->stack))); + Object key = Stack_pop(&(thread->stack)); + assert(key.type == SYMBOL); + + assert(!Stack_isEmpty(&(thread->stack))); + Object value = Stack_pop(&(thread->stack)); + + Structure* node = malloc(sizeof(Structure)); + node->key = key.value.string; + node->value = value; + node->next = result.value.structure; + + result.value.structure = node; + count--; + } + + Stack_push(&(thread->stack), result); } struct Instruction; typedef const struct Instruction Instruction; struct Instruction { - void (*instruction)(struct Thread*,Argument); + void (*instruction)(Thread*,Argument); Argument argument; }; @@ -345,10 +538,10 @@ int main() { Thread thread; Thread_initialize(&thread, LABEL___main__); - for(; program[thread.program_counter].instruction != inst_end; thread.program_counter++) { - program[thread.program_counter].instruction( + for(; program[Thread_getProgramCounter(&thread)].instruction != inst_end; Thread_incrementProgramCounter(&thread)) { + program[Thread_getProgramCounter(&thread)].instruction( &thread, - program[thread.program_counter].argument + program[Thread_getProgramCounter(&thread)].argument ); }