+def normalize_infix_expression(counter, expression):
+ return {
+ 'multiplication_level': normalize_basic_infix_operation,
+ 'addition_level': normalize_basic_infix_operation,
+ 'comparison_level': normalize_comparison_expression,
+ 'and_level': normalize_boolean_expression,
+ 'or_level': normalize_boolean_expression,
+ }[expression.order](counter, expression)
+
+def normalize_if_expression(counter, expression):
+ counter, condition_prestatements, condition_expression = normalize_expression(
+ counter,
+ expression.condition_expression,
+ )
+
+ result_variable = '${}'.format(counter)
+ counter += 1
+
+ counter, if_statement_list = normalize_statement_list(
+ counter,
+ expression.if_statement_list,
+ assign_result_to=result_variable,
+ )
+ counter, else_statement_list = normalize_statement_list(
+ counter,
+ expression.else_statement_list,
+ assign_result_to=result_variable,
+ )
+
+ return (
+ counter,
+ condition_prestatements + (
+ NormalVariableInitializationStatement(
+ variable=result_variable,
+ expression=NormalVariableExpression(variable='builtin$nil'),
+ ),
+ NormalIfElseStatement(
+ condition_expression=condition_expression,
+ if_statement_list=if_statement_list,
+ else_statement_list=else_statement_list,
+ ),
+ ),
+ NormalVariableExpression(variable=result_variable),
+ )
+
+def normalize_negation_expression(counter, expression):
+ counter, prestatements, internal_expression = normalize_expression(counter, expression.value)
+
+ internal_variable = '${}'.format(counter)
+ counter += 1
+
+ return (
+ counter,
+ prestatements + (
+ NormalVariableInitializationStatement(
+ variable=internal_variable,
+ expression=internal_expression,
+ ),
+ ),
+ NormalNegationExpression(internal_expression=NormalVariableExpression(variable=internal_variable)),
+ )
+
+def normalize_expression(counter, expression):
+ return {
+ NormalInfixExpression: fake_normalization,
+ NormalVariableExpression: fake_normalization,
+ parsing.FurFunctionCallExpression: normalize_function_call_expression,
+ parsing.FurIfExpression: normalize_if_expression,
+ parsing.FurInfixExpression: normalize_infix_expression,
+ parsing.FurIntegerLiteralExpression: normalize_integer_literal_expression,
+ parsing.FurListLiteralExpression: normalize_list_literal_expression,
+ parsing.FurListItemExpression: normalize_list_item_expression,
+ parsing.FurNegationExpression: normalize_negation_expression,
+ parsing.FurStringLiteralExpression: normalize_string_literal_expression,
+ parsing.FurSymbolExpression: normalize_symbol_expression,
+ }[type(expression)](counter, expression)
+
+def normalize_expression_statement(counter, statement):
+ # TODO Normalized will be a NormalVariableExpression, which will go unused
+ # for expression statements in every case except when it's a return
+ # statement. This cases warnings on C compilation. We should only generate
+ # this variable when it will be used on return.
+ counter, prestatements, normalized = normalize_expression(counter, statement.expression)
+
+ return (
+ counter,
+ prestatements,
+ NormalExpressionStatement(expression=normalized),
+ )
+
+def normalize_function_definition_statement(counter, statement):
+ _, statement_list = normalize_statement_list(
+ 0,
+ statement.statement_list,
+ assign_result_to='result',
+ )
+ return (
+ counter,
+ (),
+ NormalFunctionDefinitionStatement(
+ name=statement.name,
+ argument_name_list=statement.argument_name_list,
+ statement_list=statement_list,
+ ),
+ )
+
+def normalize_assignment_statement(counter, statement):
+ counter, prestatements, normalized_expression = normalize_expression(counter, statement.expression)
+ return (
+ counter,
+ prestatements,
+ NormalAssignmentStatement(
+ target=statement.target,
+ expression=normalized_expression,
+ ),
+ )
+
+def normalize_statement(counter, statement):
+ return {
+ parsing.FurAssignmentStatement: normalize_assignment_statement,
+ parsing.FurExpressionStatement: normalize_expression_statement,
+ parsing.FurFunctionDefinitionStatement: normalize_function_definition_statement,
+ }[type(statement)](counter, statement)
+
+@util.force_generator(tuple)
+def normalize_statement_list(counter, statement_list, **kwargs):
+ assign_result_to = kwargs.pop('assign_result_to', None)
+
+ assert len(kwargs) == 0
+
+ result_statement_list = []
+
+ for statement in statement_list: