From edc05c8d2d465653c02c350592eff62c542a37ed Mon Sep 17 00:00:00 2001 From: David Kerkeslager Date: Tue, 1 Oct 2019 02:09:09 -0400 Subject: [PATCH] Implemented integer comparison --- c_generation.py | 27 ++++++++++++++++++++------- crossplatform_ir_generation.py | 7 +++++++ templates/arithmetic_instruction.c | 4 ++-- templates/comparison_instruction.c | 15 +++++++++++++++ templates/program2.c | 25 +++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 templates/comparison_instruction.c diff --git a/c_generation.py b/c_generation.py index fba8f50..a1e4e59 100644 --- a/c_generation.py +++ b/c_generation.py @@ -26,6 +26,13 @@ def generate_null_argument(argument): assert argument is None return 'NULL' +def generate_null_argument_from(argument_count): + def generator(argument): + assert isinstance(argument, int) + assert argument == argument_count + return 'NULL' + return generator + def generate_size_t_argument(argument): assert isinstance(argument, int) return '(size_t){}'.format(argument) @@ -40,19 +47,25 @@ def generate_symbol_argument(argument): def generate_argument(instruction): try: return { - 'add': generate_size_t_argument, + 'add': generate_null_argument_from(2), + 'call': generate_size_t_argument, 'drop': generate_null_argument, 'end': generate_null_argument, - 'call': generate_size_t_argument, - 'idiv': generate_size_t_argument, - 'mod': generate_size_t_argument, - 'mul': generate_size_t_argument, - 'neg': generate_size_t_argument, + 'eq': generate_null_argument_from(2), + 'gt': generate_null_argument_from(2), + 'gte': generate_null_argument_from(2), + 'idiv': generate_null_argument_from(2), + 'lt': generate_null_argument_from(2), + 'lte': generate_null_argument_from(2), + 'mod': generate_null_argument_from(2), + 'mul': generate_null_argument_from(2), + 'neg': generate_null_argument_from(1), + 'neq': generate_null_argument_from(2), 'pop': generate_symbol_argument, 'push': generate_symbol_argument, 'push_integer': generate_integer_argument, 'push_string': generate_string_argument, - 'sub': generate_size_t_argument, + 'sub': generate_null_argument_from(2), }[instruction.instruction](instruction.argument) except KeyError: diff --git a/crossplatform_ir_generation.py b/crossplatform_ir_generation.py index c452126..49e7408 100644 --- a/crossplatform_ir_generation.py +++ b/crossplatform_ir_generation.py @@ -45,6 +45,13 @@ def generate_instruction_name_from_builtin(builtin): '__multiply__': 'mul', '__negate__': 'neg', '__subtract__': 'sub', + + '__eq__': 'eq', + '__neq__': 'neq', + '__lt__': 'lt', + '__lte__': 'lte', + '__gt__': 'gt', + '__gte__': 'gte', }[builtin] except KeyError: diff --git a/templates/arithmetic_instruction.c b/templates/arithmetic_instruction.c index a78a579..5b68efd 100644 --- a/templates/arithmetic_instruction.c +++ b/templates/arithmetic_instruction.c @@ -1,12 +1,12 @@ void {{ name }}(struct Thread* thread, const union Argument argument) { - // We're going to reuse result as both the addend and the sum + // 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)); assert(result.type == INTEGER); assert(!Stack_isEmpty(&(thread->stack))); Object other = Stack_pop(&(thread->stack)); - assert(result.type == INTEGER); + assert(other.type == INTEGER); result.value.integer = other.value.integer {{ operation }} result.value.integer; diff --git a/templates/comparison_instruction.c b/templates/comparison_instruction.c new file mode 100644 index 0000000..dabd905 --- /dev/null +++ b/templates/comparison_instruction.c @@ -0,0 +1,15 @@ +void {{ 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)); + assert(result.type == INTEGER); + + assert(!Stack_isEmpty(&(thread->stack))); + Object other = Stack_pop(&(thread->stack)); + assert(other.type == INTEGER); + + result.type = BOOLEAN; + result.value.boolean = other.value.integer {{ operation }} result.value.integer; + + Stack_push(&(thread->stack), result); +} diff --git a/templates/program2.c b/templates/program2.c index 1610a54..ffd014c 100644 --- a/templates/program2.c +++ b/templates/program2.c @@ -117,6 +117,7 @@ void call(struct Thread* thread, Argument argument) { if(arg.value.boolean) printf("true"); else printf("false"); break; + case INTEGER: printf("%i", arg.value.integer); break; @@ -157,10 +158,30 @@ void drop(struct Thread* thread, Argument argument) { void 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 %} +{% 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 %} @@ -169,6 +190,10 @@ void end(struct Thread* thread, Argument argument) { {% include "arithmetic_instruction.c" %} {% endwith %} +{% with name='neq', operation='!=' %} + {% include "comparison_instruction.c" %} +{% endwith %} + void neg(struct Thread* thread, Argument argument) { assert(!Stack_isEmpty(&(thread->stack))); Object result = Stack_pop(&(thread->stack)); -- 2.20.1