From 7abf5e459b2ef02c8e59c05f0a83d8213ade0427 Mon Sep 17 00:00:00 2001 From: David Kerkeslager Date: Tue, 1 Oct 2019 03:37:11 -0400 Subject: [PATCH] Start implementing functions --- c_generation.py | 2 + templates/arithmetic_instruction.c | 2 +- templates/comparison_instruction.c | 2 +- templates/environment.c | 2 - templates/program2.c | 189 +++++++++++++++++------------ 5 files changed, 115 insertions(+), 82 deletions(-) diff --git a/c_generation.py b/c_generation.py index 821048f..78a80b1 100644 --- a/c_generation.py +++ b/c_generation.py @@ -52,6 +52,7 @@ def generate_argument(instruction): return { 'add': generate_null_argument_from(2), 'call': generate_size_t_argument, + 'close': generate_label_argument, 'drop': generate_null_argument, 'end': generate_null_argument, 'eq': generate_null_argument_from(2), @@ -70,6 +71,7 @@ def generate_argument(instruction): 'push': generate_symbol_argument, 'push_integer': generate_integer_argument, 'push_string': generate_string_argument, + 'return': generate_null_argument, 'sub': generate_null_argument_from(2), }[instruction.instruction](instruction.argument) diff --git a/templates/arithmetic_instruction.c b/templates/arithmetic_instruction.c index 5b68efd..037679a 100644 --- a/templates/arithmetic_instruction.c +++ b/templates/arithmetic_instruction.c @@ -1,4 +1,4 @@ -void {{ name }}(struct Thread* thread, const union Argument argument) { +void inst_{{ name }}(struct Thread* thread, const union Argument argument) { // We're going to reuse result as both the first input and the result assert(!Stack_isEmpty(&(thread->stack))); Object result = Stack_pop(&(thread->stack)); diff --git a/templates/comparison_instruction.c b/templates/comparison_instruction.c index dabd905..d8139ce 100644 --- a/templates/comparison_instruction.c +++ b/templates/comparison_instruction.c @@ -1,4 +1,4 @@ -void {{ name }}(struct Thread* thread, const union Argument argument) { +void inst_{{ name }}(struct Thread* thread, const union Argument argument) { // We're going to reuse result as both the first input and the result assert(!Stack_isEmpty(&(thread->stack))); Object result = Stack_pop(&(thread->stack)); diff --git a/templates/environment.c b/templates/environment.c index 4ed5302..2de6b59 100644 --- a/templates/environment.c +++ b/templates/environment.c @@ -6,8 +6,6 @@ struct _EnvironmentNode { _EnvironmentNode* next; }; -struct Environment; -typedef struct Environment Environment; struct Environment { _EnvironmentNode* top; }; diff --git a/templates/program2.c b/templates/program2.c index 89d80de..919fb83 100644 --- a/templates/program2.c +++ b/templates/program2.c @@ -10,6 +10,7 @@ typedef enum Type Type; enum Type { BOOLEAN, BUILTIN, + CLOSURE, INTEGER, STRING }; @@ -22,10 +23,21 @@ enum Builtin { 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; @@ -74,78 +86,92 @@ union Argument { int32_t integer; }; -void call(struct Thread* thread, 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 POW: - { - 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); - } - break; - case PRINT: - { - 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); - } - break; - - default: - assert(false); + callBuiltin(thread, f.value.builtin, argumentCount); + break; + + case CLOSURE: + { + assert(false); } break; @@ -158,14 +184,17 @@ void call(struct Thread* thread, Argument argument) { {% include "arithmetic_instruction.c" %} {% endwith %} +void inst_close(Thread* thread, Argument argument) { + assert(false); +} -void drop(struct Thread* thread, Argument argument) { +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, Argument argument) { +void inst_end(struct Thread* thread, Argument argument) { } {% with name='eq', operation='==' %} @@ -184,17 +213,17 @@ void end(struct Thread* thread, Argument argument) { {% include "arithmetic_instruction.c" %} {% endwith %} -void jump(Thread* thread, Argument argument) { +void inst_jump(Thread* thread, Argument argument) { thread->program_counter = argument.label - 1; // We will increment before running } -void jump_if_false(Thread* thread, Argument argument) { +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)) { - jump(thread, argument); + inst_jump(thread, argument); } } @@ -218,7 +247,7 @@ void jump_if_false(Thread* thread, Argument argument) { {% include "comparison_instruction.c" %} {% endwith %} -void neg(Thread* thread, Argument argument) { +void inst_neg(Thread* thread, Argument argument) { assert(!Stack_isEmpty(&(thread->stack))); Object result = Stack_pop(&(thread->stack)); assert(result.type == INTEGER); @@ -228,7 +257,7 @@ void neg(Thread* thread, Argument argument) { Stack_push(&(thread->stack), result); } -void pop(struct Thread* thread, Argument argument) { +void inst_pop(struct Thread* thread, Argument argument) { char* argumentString = argument.string; assert(!Stack_isEmpty(&(thread->stack))); @@ -244,7 +273,7 @@ void pop(struct Thread* thread, Argument argument) { Environment_set(thread->environment, argumentString, result); } -void push(struct Thread* thread, Argument argument) { +void inst_push(struct Thread* thread, Argument argument) { char* argumentString = argument.string; if(strcmp(argumentString, "false") == 0) { @@ -271,7 +300,7 @@ void push(struct Thread* thread, Argument argument) { } } -void push_integer(struct Thread* thread, Argument argument) { +void inst_push_integer(Thread* thread, Argument argument) { Object result; result.type = INTEGER; result.value.integer = argument.integer; @@ -279,7 +308,7 @@ void push_integer(struct Thread* thread, Argument argument) { Stack_push(&(thread->stack), result); } -void push_string(struct Thread* thread, Argument argument) { +void inst_push_string(Thread* thread, Argument argument) { Object result; result.type = STRING; result.value.string = argument.string; @@ -291,6 +320,10 @@ void push_string(struct Thread* thread, Argument argument) { {% include "arithmetic_instruction.c" %} {% endwith %} +void inst_return(Thread* thread, Argument argument) { + assert(false); +} + struct Instruction; typedef const struct Instruction Instruction; struct Instruction { @@ -304,7 +337,7 @@ 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 %} }; @@ -312,7 +345,7 @@ int main() { Thread thread; 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 -- 2.20.1