X-Git-Url: https://code.kerkeslager.com/?p=fur;a=blobdiff_plain;f=templates%2Fprogram2.c;h=919fb8300ba288dfebfc990a80b9cb9e0a1f5c83;hp=6e21ce07d13d26937a3427bf7558ed999e108472;hb=7abf5e459b2ef02c8e59c05f0a83d8213ade0427;hpb=c45c61444aae3df328e4dc84acf7e31e58a1f64e diff --git a/templates/program2.c b/templates/program2.c index 6e21ce0..919fb83 100644 --- a/templates/program2.c +++ b/templates/program2.c @@ -8,7 +8,9 @@ enum Type; typedef enum Type Type; enum Type { + BOOLEAN, BUILTIN, + CLOSURE, INTEGER, STRING }; @@ -17,13 +19,26 @@ enum Builtin; typedef enum Builtin Builtin; enum Builtin { NIL, + POW, PRINT }; +struct Environment; +typedef struct Environment Environment; + +struct Closure; +typedef struct Closure Closure; +struct Closure { + Environment* environment; + size_t entry; +}; + union Value; typedef union Value Value; union Value { Builtin builtin; + Closure closure; + bool boolean; char* string; int32_t integer; }; @@ -40,21 +55,25 @@ struct Object { void Object_deinitialize(Object* self) { } +{% include "environment.c" %} {% include "stack.c" %} struct Thread; typedef struct Thread Thread; struct Thread { + Environment* environment; Stack stack; size_t program_counter; }; void Thread_initialize(Thread* self, size_t program_counter) { + self->environment = Environment_construct(); Stack_initialize(&(self->stack)); self->program_counter = program_counter; } void Thread_deinitialize(Thread* self) { + Environment_destruct(self->environment); Stack_deinitialize(&(self->stack)); } @@ -67,38 +86,92 @@ union Argument { int32_t integer; }; -void call(struct Thread* thread, const union Argument argument) { +void callBuiltinPow(Thread* thread, size_t argumentCount) { + assert(argumentCount == 2); + assert(!Stack_isEmpty(&(thread->stack))); + Object exponent = Stack_pop(&(thread->stack)); + assert(exponent.type == INTEGER); + assert(exponent.value.integer >= 0); + + assert(!Stack_isEmpty(&(thread->stack))); + Object base = Stack_pop(&(thread->stack)); + assert(base.type == INTEGER); + + Object result; + result.type = INTEGER; + result.value.integer = 1; + + while(exponent.value.integer > 0) { + result.value.integer *= base.value.integer; + exponent.value.integer--; + } + + Stack_push(&(thread->stack), result); +} + +void callBuiltinPrint(Thread* thread, size_t argumentCount) { + assert(argumentCount > 0); + + Object arguments[argumentCount]; + size_t count; + + for(count = 0; count < argumentCount; count++) { + assert(!Stack_isEmpty(&(thread->stack))); + arguments[argumentCount - count - 1] = Stack_pop(&(thread->stack)); + } + + for(count = 0; count < argumentCount; count ++) { + Object arg = arguments[count]; + + switch(arg.type) { + case BOOLEAN: + if(arg.value.boolean) printf("true"); + else printf("false"); + break; + + case INTEGER: + printf("%i", arg.value.integer); + break; + + case STRING: + printf("%s", arg.value.string); + break; + + default: + assert(0); + } + } + + Stack_push(&(thread->stack), BUILTIN_NIL); +} + +void callBuiltin(Thread* thread, Builtin b, size_t argumentCount) { + switch(b) { + case POW: + callBuiltinPow(thread, argumentCount); + break; + case PRINT: + callBuiltinPrint(thread, argumentCount); + break; + + default: + assert(false); + } +} + +void inst_call(struct Thread* thread, Argument argument) { assert(!Stack_isEmpty(&(thread->stack))); Object f = Stack_pop(&(thread->stack)); + size_t argumentCount = argument.label; switch(f.type) { case BUILTIN: - switch(f.value.builtin) { - case PRINT: - { - // TODO Handle multiple arguments - assert(!Stack_isEmpty(&(thread->stack))); - Object arg = Stack_pop(&(thread->stack)); - - switch(arg.type) { - case INTEGER: - printf("%i", arg.value.integer); - break; - - case STRING: - printf("%s", arg.value.string); - break; - - default: - assert(0); - } - - Stack_push(&(thread->stack), BUILTIN_NIL); - } - break; - - default: - assert(false); + callBuiltin(thread, f.value.builtin, argumentCount); + break; + + case CLOSURE: + { + assert(false); } break; @@ -107,31 +180,127 @@ void call(struct Thread* thread, const union Argument argument) { } } -void drop(struct Thread* thread, const union Argument argument) { +{% with name='add', operation='+' %} + {% include "arithmetic_instruction.c" %} +{% endwith %} + +void inst_close(Thread* thread, Argument argument) { + assert(false); +} + +void inst_drop(Thread* thread, Argument argument) { assert(!Stack_isEmpty(&(thread->stack))); Object result = Stack_pop(&(thread->stack)); Object_deinitialize(&result); } -void end(struct Thread* thread, const union Argument argument) { +void inst_end(struct Thread* thread, Argument argument) { +} + +{% with name='eq', operation='==' %} + {% include "comparison_instruction.c" %} +{% endwith %} + +{% with name='gt', operation='>' %} + {% include "comparison_instruction.c" %} +{% endwith %} + +{% with name='gte', operation='>=' %} + {% include "comparison_instruction.c" %} +{% endwith %} + +{% with name='idiv', operation='/' %} + {% include "arithmetic_instruction.c" %} +{% endwith %} + +void inst_jump(Thread* thread, Argument argument) { + thread->program_counter = argument.label - 1; // We will increment before running +} + +void inst_jump_if_false(Thread* thread, Argument argument) { + assert(!Stack_isEmpty(&(thread->stack))); + Object result = Stack_pop(&(thread->stack)); + assert(result.type == BOOLEAN); + + if(!(result.value.boolean)) { + inst_jump(thread, argument); + } +} + +{% with name='lt', operation='<' %} + {% include "comparison_instruction.c" %} +{% endwith %} + +{% with name='lte', operation='<=' %} + {% include "comparison_instruction.c" %} +{% endwith %} + +{% with name='mod', operation='%' %} + {% include "arithmetic_instruction.c" %} +{% endwith %} + +{% with name='mul', operation='*' %} + {% include "arithmetic_instruction.c" %} +{% endwith %} + +{% with name='neq', operation='!=' %} + {% include "comparison_instruction.c" %} +{% endwith %} + +void inst_neg(Thread* thread, Argument argument) { + assert(!Stack_isEmpty(&(thread->stack))); + Object result = Stack_pop(&(thread->stack)); + assert(result.type == INTEGER); + + result.value.integer = -(result.value.integer); + + Stack_push(&(thread->stack), result); } -void push(struct Thread* thread, const union Argument argument) { +void inst_pop(struct Thread* thread, Argument argument) { char* argumentString = argument.string; - Object result; + assert(!Stack_isEmpty(&(thread->stack))); + Object result = Stack_pop(&(thread->stack)); if(strcmp(argumentString, "print") == 0) { + assert(false); + } else if(strcmp(argumentString, "pow") == 0) { + assert(false); + } + + + Environment_set(thread->environment, argumentString, result); +} + +void inst_push(struct 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) { + Object result; + result.type = BUILTIN; + result.value.builtin = POW; + Stack_push(&(thread->stack), result); + } else if(strcmp(argumentString, "print") == 0) { + Object result; result.type = BUILTIN; result.value.builtin = PRINT; + Stack_push(&(thread->stack), result); + } else if(strcmp(argumentString, "true") == 0) { + Stack_push(&(thread->stack), (Object){ BOOLEAN, true }); } else { - assert(false); + Environment_get_Result result = Environment_get(thread->environment, argumentString); + if(!result.found) { + fprintf(stderr, "Variable `%s` not found", argumentString); + assert(false); + } + Stack_push(&(thread->stack), result.result); } - - Stack_push(&(thread->stack), result); } -void push_integer(struct Thread* thread, const union Argument argument) { +void inst_push_integer(Thread* thread, Argument argument) { Object result; result.type = INTEGER; result.value.integer = argument.integer; @@ -139,7 +308,7 @@ void push_integer(struct Thread* thread, const union Argument argument) { Stack_push(&(thread->stack), result); } -void push_string(struct Thread* thread, const union Argument argument) { +void inst_push_string(Thread* thread, Argument argument) { Object result; result.type = STRING; result.value.string = argument.string; @@ -147,10 +316,18 @@ void push_string(struct Thread* thread, const union Argument argument) { Stack_push(&(thread->stack), result); } +{% with name='sub', operation='-' %} + {% include "arithmetic_instruction.c" %} +{% endwith %} + +void inst_return(Thread* thread, Argument argument) { + assert(false); +} + struct Instruction; typedef const struct Instruction Instruction; struct Instruction { - void (*instruction)(struct Thread*,const union Argument); + void (*instruction)(struct Thread*,Argument); Argument argument; }; @@ -160,15 +337,15 @@ struct Instruction { const Instruction program[] = { {% for instruction in instruction_list %} - (Instruction){ {{ instruction.instruction }}, (Argument){{ generate_argument(instruction) }} }, + (Instruction){ inst_{{ instruction.instruction }}, (Argument){{ generate_argument(instruction) }} }, {% endfor %} }; int main() { Thread thread; - Thread_initialize(&thread, 0); + Thread_initialize(&thread, LABEL___main__); - for(; program[thread.program_counter].instruction != end; thread.program_counter++) { + for(; program[thread.program_counter].instruction != inst_end; thread.program_counter++) { program[thread.program_counter].instruction( &thread, program[thread.program_counter].argument