X-Git-Url: https://code.kerkeslager.com/?p=fur;a=blobdiff_plain;f=templates%2Fprogram2.c;h=679bbfb65124c920f28b181e873f3e00a9c95839;hp=5ca9f61986c91bfa6583c721c21c146545ac6b10;hb=4f86ad3f093ca0c51e77a28b208e7751629d4948;hpb=40cd5f86db884963c917943377ca4e6e8f419f8e diff --git a/templates/program2.c b/templates/program2.c index 5ca9f61..679bbfb 100644 --- a/templates/program2.c +++ b/templates/program2.c @@ -12,12 +12,16 @@ enum Type { BUILTIN, CLOSURE, INTEGER, - STRING + LIST, + STRING, + STRUCTURE, + SYMBOL }; enum Builtin; typedef enum Builtin Builtin; enum Builtin { + __FIELD__, NIL, POW, PRINT @@ -37,14 +41,23 @@ 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 { @@ -52,6 +65,17 @@ struct Object { 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) { @@ -99,8 +123,31 @@ union Argument { void* pointer; char* string; int32_t integer; + char* symbol; }; +void callBuiltinField(Thread* thread, size_t argumentCount) { + assert(argumentCount == 2); + + assert(!Stack_isEmpty(&(thread->stack))); + Object key = Stack_pop(&(thread->stack)); + assert(key.type == STRING); // TODO Make this a 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 callBuiltinPow(Thread* thread, size_t argumentCount) { assert(argumentCount == 2); assert(!Stack_isEmpty(&(thread->stack))); @@ -162,9 +209,14 @@ void callBuiltinPrint(Thread* thread, size_t argumentCount) { void callBuiltin(Thread* thread, Builtin b, size_t argumentCount) { switch(b) { + case __FIELD__: + callBuiltinField(thread, argumentCount); + break; + case POW: callBuiltinPow(thread, argumentCount); break; + case PRINT: callBuiltinPrint(thread, argumentCount); break; @@ -175,7 +227,7 @@ void callBuiltin(Thread* thread, Builtin b, size_t argumentCount) { } void callClosure(Thread* thread, Closure closure, size_t argumentCount) { - assert(argumentCount == 0); + // TODO Find a way to assert the argument count Frame* returnFrame = malloc(sizeof(Frame)); *returnFrame = thread->frame; @@ -206,6 +258,29 @@ void inst_call(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 %} @@ -232,6 +307,27 @@ void inst_end(Thread* thread, Argument argument) { {% include "comparison_instruction.c" %} {% endwith %} +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 %} @@ -258,6 +354,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 %} @@ -307,9 +425,15 @@ void inst_pop(Thread* thread, Argument argument) { void inst_push(Thread* thread, Argument argument) { char* argumentString = argument.string; - if(strcmp(argumentString, "false") == 0) { + if(strcmp(argumentString, "__field__") == 0) { + // TODO Make this an instruction + Object result; + result.type = BUILTIN; + result.value.builtin = __FIELD__; + Stack_push(&(thread->stack), result); + } else 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; @@ -350,6 +474,16 @@ 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 %} @@ -369,6 +503,33 @@ void inst_return(Thread* thread, Argument argument) { 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 {