Normalize infix operators
authorDavid Kerkeslager <kerkeslager@gmail.com>
Tue, 8 Aug 2017 08:03:35 +0000 (04:03 -0400)
committerDavid Kerkeslager <kerkeslager@gmail.com>
Tue, 8 Aug 2017 08:03:35 +0000 (04:03 -0400)
normalization.py
transformation.py

index c48c3e9..3ece2bb 100644 (file)
@@ -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)
index 3309b9c..5de9bbf 100644 (file)
@@ -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):