From fb83d523f8eb241d5ccafe8d391a9edd62150b48 Mon Sep 17 00:00:00 2001 From: David Kerkeslager Date: Sat, 5 Aug 2017 16:33:35 -0400 Subject: [PATCH] Add a negation operator --- examples/08_negativity.fur | 1 + examples/08_negativity.fur.output.txt | 1 + generation.py | 16 ++++++++++++---- parsing.py | 21 +++++++++++++++++++++ templates/program.c | 10 ++++++++++ transformation.py | 13 +++++++++++++ 6 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 examples/08_negativity.fur create mode 100644 examples/08_negativity.fur.output.txt diff --git a/examples/08_negativity.fur b/examples/08_negativity.fur new file mode 100644 index 0000000..7da32ad --- /dev/null +++ b/examples/08_negativity.fur @@ -0,0 +1 @@ +print(-1) diff --git a/examples/08_negativity.fur.output.txt b/examples/08_negativity.fur.output.txt new file mode 100644 index 0000000..d7d17fc --- /dev/null +++ b/examples/08_negativity.fur.output.txt @@ -0,0 +1 @@ +-1 \ No newline at end of file diff --git a/generation.py b/generation.py index 808b0d8..cefae7b 100644 --- a/generation.py +++ b/generation.py @@ -23,7 +23,10 @@ def generate_string_literal(c_string_literal): ''.join(c_escape(ch for ch in c_string_literal.value)), ) -def generate_argument(c_argument): +def generate_expression(c_argument): + if isinstance(c_argument, transformation.CNegationExpression): + return generate_negation_expression(c_argument) + if isinstance(c_argument, transformation.CFunctionCallExpression): return generate_function_call(c_argument) @@ -45,14 +48,19 @@ def generate_argument(c_argument): return 'builtin${}({}, {})'.format( INFIX_TYPE_MAPPING[type(c_argument)], - generate_argument(c_argument.left), - generate_argument(c_argument.right), + generate_expression(c_argument.left), + generate_expression(c_argument.right), + ) + +def generate_negation_expression(c_negation_expression): + return 'builtin$negate({})'.format( + generate_expression(c_negation_expression.value) ) def generate_function_call(c_function_call): return '{}({})'.format( c_function_call.name, - ', '.join(generate_argument(argument) for argument in c_function_call.arguments), + ', '.join(generate_expression(argument) for argument in c_function_call.arguments), ) def generate_statement(c_function_call_statement): diff --git a/parsing.py b/parsing.py index 1ab6df4..0d7caa6 100644 --- a/parsing.py +++ b/parsing.py @@ -44,6 +44,13 @@ FurStringLiteralExpression = collections.namedtuple( ], ) +FurNegationExpression = collections.namedtuple( + 'FurNegationExpression', + [ + 'value', + ], +) + FurAdditionExpression = collections.namedtuple( 'FurAdditionExpression', [ @@ -104,8 +111,22 @@ def _string_literal_expression_parser(index, tokens): return True, index, FurStringLiteralExpression(value=value) +def _negation_expression_parser(index, tokens): + failure = (False, index, None) + + if tokens[index].match != '-': + return failure + + success, index, value = _literal_level_expression_parser(index + 1, tokens) + + if not success: + return failure + + return (True, index, FurNegationExpression(value=value)) + def _literal_level_expression_parser(index, tokens): return _or_parser( + _negation_expression_parser, _function_call_expression_parser, _integer_literal_expression_parser, _string_literal_expression_parser, diff --git a/templates/program.c b/templates/program.c index 063587d..64e0152 100644 --- a/templates/program.c +++ b/templates/program.c @@ -114,6 +114,16 @@ Object stringLiteral(Runtime* runtime, const char* literal) } // TODO Make this conditionally added +Object builtin$negate(Object input) +{ + assert(input.type == INTEGER); + + Object result; + result.type = INTEGER; + result.instance.integer = -input.instance.integer; + return result; +} + Object builtin$add(Object left, Object right) { assert(left.type == INTEGER); diff --git a/transformation.py b/transformation.py index 1fe7dc9..d680145 100644 --- a/transformation.py +++ b/transformation.py @@ -16,6 +16,13 @@ CStringLiteral = collections.namedtuple( ], ) +CNegationExpression = collections.namedtuple( + 'CNegationExpression', + [ + 'value', + ], +) + CAdditionExpression = collections.namedtuple( 'CAdditionExpression', [ @@ -79,6 +86,9 @@ BUILTINS = { } def transform_expression(builtin_dependencies, expression): + if isinstance(expression, parsing.FurNegationExpression): + return transform_negation_expression(builtin_dependencies, expression) + if isinstance(expression, parsing.FurFunctionCallExpression): return transform_function_call_expression(builtin_dependencies, expression) @@ -103,6 +113,9 @@ def transform_expression(builtin_dependencies, expression): right=transform_expression(builtin_dependencies, expression.right), ) +def transform_negation_expression(builtin_dependencies, negation_expression): + return CNegationExpression(value=transform_expression(builtin_dependencies, negation_expression.value)) + def transform_function_call_expression(builtin_dependencies, function_call): if function_call.name in BUILTINS.keys(): builtin_dependencies.add(function_call.name) -- 2.20.1