From c40954b865b48ffa4993f735d56213fb91c3e90e Mon Sep 17 00:00:00 2001 From: David Kerkeslager Date: Fri, 4 Aug 2017 11:26:32 -0400 Subject: [PATCH] Added support for integers --- ...02_the_answer_to_the_ultimate_question.fur | 1 + ...er_to_the_ultimate_question.fur.output.txt | 1 + generation.py | 13 +++- parsing.py | 30 +++++++- templates/program.c | 69 ++++++++++++++++--- tokenization.py | 1 + transformation.py | 15 ++-- 7 files changed, 115 insertions(+), 15 deletions(-) create mode 100644 examples/02_the_answer_to_the_ultimate_question.fur create mode 100644 examples/02_the_answer_to_the_ultimate_question.fur.output.txt diff --git a/examples/02_the_answer_to_the_ultimate_question.fur b/examples/02_the_answer_to_the_ultimate_question.fur new file mode 100644 index 0000000..517b47d --- /dev/null +++ b/examples/02_the_answer_to_the_ultimate_question.fur @@ -0,0 +1 @@ +print(42) diff --git a/examples/02_the_answer_to_the_ultimate_question.fur.output.txt b/examples/02_the_answer_to_the_ultimate_question.fur.output.txt new file mode 100644 index 0000000..f70d7bb --- /dev/null +++ b/examples/02_the_answer_to_the_ultimate_question.fur.output.txt @@ -0,0 +1 @@ +42 \ No newline at end of file diff --git a/generation.py b/generation.py index 9962bf3..56bd0a5 100644 --- a/generation.py +++ b/generation.py @@ -1,12 +1,17 @@ import jinja2 +import transformation + ENV = jinja2.Environment( autoescape=jinja2.select_autoescape([]), loader=jinja2.FileSystemLoader('templates'), trim_blocks=True, ) -def generate_argument(c_string_literal): +def generate_integer_literal(c_integer_literal): + return 'integerLiteral({})'.format(c_integer_literal.value) + +def generate_string_literal(c_string_literal): def c_escape(ch): return { '\n': r'\n', @@ -18,6 +23,12 @@ def generate_argument(c_string_literal): ''.join(c_escape(ch for ch in c_string_literal.value)), ) +def generate_argument(c_argument): + return { + transformation.CIntegerLiteral: generate_integer_literal, + transformation.CStringLiteral: generate_string_literal, + }[type(c_argument)](c_argument) + def generate_statement(c_function_call_statement): return '{}({});'.format( c_function_call_statement.name, diff --git a/parsing.py b/parsing.py index 62ac92f..6b11745 100644 --- a/parsing.py +++ b/parsing.py @@ -1,5 +1,12 @@ import collections +IntegerLiteral = collections.namedtuple( + 'IntegerLiteral', + [ + 'value', + ], +) + StringLiteral = collections.namedtuple( 'StringLiteral', [ @@ -7,6 +14,16 @@ StringLiteral = collections.namedtuple( ], ) +def _integer_literal_parser(index, tokens): + failure = (False, index, None) + + if tokens[index].type != 'integer_literal': + return failure + value = int(tokens[index].match) + index += 1 + + return True, index, IntegerLiteral(value=value) + def _string_literal_parser(index, tokens): failure = (False, index, None) @@ -17,6 +34,17 @@ def _string_literal_parser(index, tokens): return True, index, StringLiteral(value=value) +def _argument_parser(index, tokens): + failure = (False, index, None) + + for parser in [_integer_literal_parser, _string_literal_parser]: + success, index, value = parser(index, tokens) + + if success: + return (success, index, value) + + return failure + FunctionCall = collections.namedtuple( 'FunctionCall', @@ -38,7 +66,7 @@ def _function_call_parser(index, tokens): return failure index += 1 - success, index, argument = _string_literal_parser(index, tokens) + success, index, argument = _argument_parser(index, tokens) if not success: return failure diff --git a/templates/program.c b/templates/program.c index d027c52..ecabb17 100644 --- a/templates/program.c +++ b/templates/program.c @@ -1,3 +1,6 @@ +#include +#include +#include #include #include @@ -7,6 +10,12 @@ struct String; typedef struct String String; +enum Type; +typedef enum Type Type; +union Instance; +typedef union Instance Instance; +struct Object; +typedef struct Object Object; struct Runtime; typedef struct Runtime Runtime; @@ -16,6 +25,24 @@ struct String char* characters; }; +enum Type +{ + INTEGER, + STRING +}; + +union Instance +{ + int32_t integer; + String* string; +}; + +struct Object +{ + Type type; + Instance instance; +}; + struct Runtime { size_t permanentStringsLength; @@ -64,21 +91,45 @@ void Runtime_addPermanentString(Runtime* self, String* string) self->permanentStringsLength++; } -String* stringLiteral(Runtime* runtime, const char* literal) +Object integerLiteral(int32_t literal) { - String* result = malloc(sizeof(String)); - result->length = strlen(literal); - result->characters = malloc(result->length); - memcpy(result->characters, literal, result->length); - Runtime_addPermanentString(runtime, result); + Object result; + result.type = INTEGER; + result.instance.integer = literal; + return result; +} + +Object stringLiteral(Runtime* runtime, const char* literal) +{ + String* resultString = malloc(sizeof(String)); + resultString->length = strlen(literal); + resultString->characters = malloc(resultString->length); + memcpy(resultString->characters, literal, resultString->length); + Runtime_addPermanentString(runtime, resultString); + + Object result; + result.type = STRING; + result.instance.string = resultString; return result; } {% if 'print' in builtins %} -void builtin$print(String* output) +void builtin$print(Object output) { - // Using fwrite instead of printf to handle size_t length - fwrite(output->characters, 1, output->length, stdout); + switch(output.type) + { + case INTEGER: + printf("%" PRId32, output.instance.integer); + break; + + case STRING: + // Using fwrite instead of printf to handle size_t length + fwrite(output.instance.string->characters, 1, output.instance.string->length, stdout); + break; + + default: + assert(false); + } } {% endif %} diff --git a/tokenization.py b/tokenization.py index c1b30df..10ed80f 100644 --- a/tokenization.py +++ b/tokenization.py @@ -29,6 +29,7 @@ def _make_token_matcher(definition): _TOKEN_MATCHERS = [ ('open_parenthese', r'\('), ('close_parenthese', r'\)'), + ('integer_literal', r'-?\s*\d+'), ('symbol', r'[a-z]+'), ('single_quoted_string_literal', r"'.*?'"), ] diff --git a/transformation.py b/transformation.py index 9ba0c0a..ef4e9bf 100644 --- a/transformation.py +++ b/transformation.py @@ -2,6 +2,13 @@ import collections import parsing +CIntegerLiteral = collections.namedtuple( + 'CIntegerLiteral', + [ + 'value', + ], +) + CStringLiteral = collections.namedtuple( 'CStringLiteral', [ @@ -31,10 +38,10 @@ BUILTINS = { } def transform_argument(builtin_dependencies, argument): - if isinstance(argument, parsing.StringLiteral): - return CStringLiteral(value=argument.value) - - raise Exception() + return { + parsing.IntegerLiteral: CIntegerLiteral, + parsing.StringLiteral: CStringLiteral, + }[type(argument)](value=argument.value) def transform_function_call_statement(builtin_dependencies, function_call): if function_call.name in BUILTINS.keys(): -- 2.20.1