+CInfixDeclaration = collections.namedtuple(
+ 'CInfixDeclaration',
+ [
+ 'name',
+ 'in_type',
+ 'out_type',
+ 'operator',
+ ],
+)
+
+INFIX_OPERATOR_TO_DECLARATION = {
+ '+': CInfixDeclaration(name='add', in_type='integer', out_type='integer', operator='+'),
+ '-': CInfixDeclaration(name='subtract', in_type='integer', out_type='integer', operator='-'),
+ '*': CInfixDeclaration(name='multiply', in_type='integer', out_type='integer', operator='*'),
+ '//': CInfixDeclaration(name='integerDivide', in_type='integer', out_type='integer', operator='/'),
+ '%': CInfixDeclaration(name='modularDivide', in_type='integer', out_type='integer', operator='%'),
+ 'and': CInfixDeclaration(name='and', in_type='boolean', out_type='boolean', operator='&&'),
+ 'or': CInfixDeclaration(name='or', in_type='boolean', out_type='boolean', operator='||'),
+ '==': CInfixDeclaration(name='equals', in_type='integer', out_type='boolean', operator='=='),
+ '!=': CInfixDeclaration(name='notEquals', in_type='integer', out_type='boolean', operator='!='),
+ '<=': CInfixDeclaration(name='lessThanOrEqual', in_type='integer', out_type='boolean', operator='<='),
+ '>=': CInfixDeclaration(name='greaterThanOrEqual', in_type='integer', out_type='boolean', operator='>='),
+ '<': CInfixDeclaration(name='lessThan', in_type='integer', out_type='boolean', operator='<'),
+ '>': CInfixDeclaration(name='greaterThan', in_type='integer', out_type='boolean', operator='>'),
+}
+
+def transform_comparison_level_expression(accumulators, expression):
+ accumulators.operator_set.add(INFIX_OPERATOR_TO_DECLARATION[expression.operator])
+
+ # Transform expressions like 1 < 2 < 3 into expressions like 1 < 2 && 2 < 3
+ if isinstance(expression.left, parsing.FurInfixExpression) and expression.left.order == 'comparison_level':
+ left = transform_comparison_level_expression(
+ accumulators,
+ expression.left
+ )
+
+ middle = left.right
+
+ right = transform_expression(
+ accumulators,
+ expression.right,
+ )
+
+ # TODO Don't evaluate the middle expression twice
+ return CFunctionCallForFurInfixOperator(
+ name='and',
+ left=left,
+ right=CFunctionCallForFurInfixOperator(
+ name=INFIX_OPERATOR_TO_DECLARATION[expression.operator].name,
+ left=middle,
+ right=right,
+ ),
+ )
+
+ return CFunctionCallForFurInfixOperator(
+ name=INFIX_OPERATOR_TO_DECLARATION[expression.operator].name,
+ left=transform_expression(accumulators, expression.left),
+ right=transform_expression(accumulators, expression.right),
+ )
+
+def transform_infix_expression(accumulators, expression):
+ if expression.order == 'comparison_level':
+ return transform_comparison_level_expression(accumulators, expression)
+
+ accumulators.operator_set.add(INFIX_OPERATOR_TO_DECLARATION[expression.operator])
+
+ return CFunctionCallForFurInfixOperator(
+ name=INFIX_OPERATOR_TO_DECLARATION[expression.operator].name,
+ left=transform_expression(accumulators, expression.left),
+ right=transform_expression(accumulators, expression.right),
+ )
+
+def transform_integer_literal_expression(accumulators, expression):
+ return CIntegerLiteral(value=expression.integer)
+
+def transform_negation_expression(accumulators, expression):
+ return CNegationExpression(
+ value=transform_expression(accumulators, expression.internal_expression),
+ )
+
+def transform_expression(accumulators, expression):
+ # TODO Clean up handlers for parsing expressions
+ return {
+ parsing.FurInfixExpression: transform_infix_expression,
+ parsing.FurIntegerLiteralExpression: transform_integer_literal_expression,
+ parsing.FurNegationExpression: transform_negation_expression,
+ parsing.FurStringLiteralExpression: transform_string_literal_expression,
+ normalization.NormalFunctionCallExpression: transform_function_call_expression,
+ normalization.NormalInfixExpression: transform_infix_expression,
+ normalization.NormalIntegerLiteralExpression: transform_integer_literal_expression,
+ normalization.NormalNegationExpression: transform_negation_expression,
+ normalization.NormalStringLiteralExpression: transform_string_literal_expression,
+ normalization.NormalSymbolExpression: transform_symbol_expression,
+ normalization.NormalVariableExpression: transform_variable_expression,
+ }[type(expression)](accumulators, expression)
+
+def transform_symbol_assignment_statement(accumulators, assignment_statement):