From 11018d3ac01dd8244ea924f2f03b735dfec4c822 Mon Sep 17 00:00:00 2001 From: David Kerkeslager Date: Tue, 8 Aug 2017 04:03:35 -0400 Subject: [PATCH] Normalize infix operators --- normalization.py | 72 +++++++++++++++++++++++++++++++++++++++++++---- transformation.py | 44 +++++++++++++++-------------- 2 files changed, 89 insertions(+), 27 deletions(-) diff --git a/normalization.py b/normalization.py index c48c3e9..3ece2bb 100644 --- a/normalization.py +++ b/normalization.py @@ -9,11 +9,13 @@ NormalVariableExpression = collections.namedtuple( ], ) -NormalVariableAssignmentStatement = collections.namedtuple( - 'NormalVariableAssignmentStatement', +NormalInfixExpression = collections.namedtuple( + 'NormalInfixExpression', [ - 'variable', - 'expression', + 'order', + 'operator', + 'left', + 'right', ], ) @@ -25,6 +27,14 @@ NormalFunctionCallExpression = collections.namedtuple( ], ) +NormalVariableAssignmentStatement = collections.namedtuple( + 'NormalVariableAssignmentStatement', + [ + 'variable', + 'expression', + ], +) + NormalExpressionStatement = collections.namedtuple( 'NormalExpressionStatement', [ @@ -73,12 +83,62 @@ def normalize_function_call_expression(counter, expression): ), ) +def normalize_basic_infix_operation(counter, expression): + counter, left_prestatements, left_expression = normalize_expression(counter, expression.left) + counter, right_prestatements, right_expression = normalize_expression(counter, expression.right) + + left_variable = '${}'.format(counter) + counter += 1 + right_variable = '${}'.format(counter) + counter += 1 + + root_prestatements = ( + NormalVariableAssignmentStatement( + variable=left_variable, + expression=left_expression, + ), + NormalVariableAssignmentStatement( + variable=right_variable, + expression=right_expression, + ), + ) + + return ( + counter, + left_prestatements + right_prestatements + root_prestatements, + NormalInfixExpression( + order=expression.order, # TODO Do we need this? + operator=expression.operator, + left=NormalVariableExpression(variable=left_variable), + right=NormalVariableExpression(variable=right_variable), + ), + ) + +def normalize_infix_expression(counter, expression): + # TODO Unfake this normalization + return { + '+': normalize_basic_infix_operation, + '-': normalize_basic_infix_operation, + '*': normalize_basic_infix_operation, + '//': normalize_basic_infix_operation, + '%': normalize_basic_infix_operation, + '==': fake_normalization, + '<=': fake_normalization, + '>=': fake_normalization, + '!=': fake_normalization, + '<': fake_normalization, + '>': fake_normalization, + 'and': fake_normalization, + 'or': fake_normalization, + }[expression.operator](counter, expression) + def normalize_expression(counter, expression): return { parsing.FurFunctionCallExpression: normalize_function_call_expression, - parsing.FurInfixExpression: fake_normalization, # TODO This should not be faked + parsing.FurInfixExpression: normalize_infix_expression, parsing.FurIntegerLiteralExpression: fake_normalization, - parsing.FurNegationExpression: fake_normalization, + parsing.FurNegationExpression: fake_normalization, # TODO Don't fake this + parsing.FurParenthesizedExpression: fake_normalization, # TODO Don't fake this parsing.FurStringLiteralExpression: fake_normalization, parsing.FurSymbolExpression: fake_normalization, }[type(expression)](counter, expression) diff --git a/transformation.py b/transformation.py index 3309b9c..5de9bbf 100644 --- a/transformation.py +++ b/transformation.py @@ -150,6 +150,26 @@ BUILTINS = { def transform_variable_expression(accumulators, expression): return CVariableExpression(variable=expression.variable) +def transform_infix_expression(accumulators, expression): + if expression.order == 'equality_level': + return transform_equality_level_expression(accumulators, expression) + + INFIX_OPERATOR_TO_FUNCTION_NAME = { + '+': 'add', + '-': 'subtract', + '*': 'multiply', + '//': 'integerDivide', + '%': 'modularDivide', + 'and': 'and', + 'or': 'or', + } + + return CFunctionCallForFurInfixOperator( + name=INFIX_OPERATOR_TO_FUNCTION_NAME[expression.operator], + left=transform_expression(accumulators, expression.left), + right=transform_expression(accumulators, expression.right), + ) + def transform_expression(accumulators, expression): if isinstance(expression, parsing.FurParenthesizedExpression): # Parentheses can be removed because everything in the C output is explicitly parenthesized @@ -191,30 +211,12 @@ def transform_expression(accumulators, expression): if type(expression) in LITERAL_TYPE_MAPPING: return LITERAL_TYPE_MAPPING[type(expression)](value=expression.value) - if isinstance(expression, parsing.FurInfixExpression): - if expression.order == 'equality_level': - return transform_equality_level_expression(accumulators, expression) - - INFIX_OPERATOR_TO_FUNCTION_NAME = { - '+': 'add', - '-': 'subtract', - '*': 'multiply', - '//': 'integerDivide', - '%': 'modularDivide', - 'and': 'and', - 'or': 'or', - } - - return CFunctionCallForFurInfixOperator( - name=INFIX_OPERATOR_TO_FUNCTION_NAME[expression.operator], - left=transform_expression(accumulators, expression.left), - right=transform_expression(accumulators, expression.right), - ) - # TODO Handle all possible types in this form return { - normalization.NormalVariableExpression: transform_variable_expression, + parsing.FurInfixExpression: transform_infix_expression, # TODO Shouldn't need this normalization.NormalFunctionCallExpression: transform_function_call_expression, + normalization.NormalInfixExpression: transform_infix_expression, + normalization.NormalVariableExpression: transform_variable_expression, }[type(expression)](accumulators, expression) def transform_symbol_assignment_statement(accumulators, assignment_statement): -- 2.20.1