From: David Kerkeslager Date: Fri, 23 Aug 2019 05:40:00 +0000 (-0400) Subject: Fix/simplify the generation of if/else statements X-Git-Url: https://code.kerkeslager.com/?a=commitdiff_plain;h=ecbec68813b8dbd559354d9f0fe023a01d351fe9;p=fur Fix/simplify the generation of if/else statements --- diff --git a/conversion.py b/conversion.py index 49e27fd..b71e834 100644 --- a/conversion.py +++ b/conversion.py @@ -87,8 +87,8 @@ CPSExpressionStatement = collections.namedtuple( ), ) -CPSIfElseStatement = collections.namedtuple( - 'CPSIfElseStatement', +CPSIfElseExpression = collections.namedtuple( + 'CPSIfElseExpression', ( 'condition_expression', 'if_statement_list', @@ -127,14 +127,6 @@ CPSSymbolArrayVariableInitializationStatement = collections.namedtuple( ), ) -CPSVariableReassignmentStatement = collections.namedtuple( - 'CPSVariableReassignmentStatement', - ( - 'variable', - 'expression', - ), -) - CPSProgram = collections.namedtuple( 'CPSProgram', ( @@ -181,6 +173,7 @@ def convert_variable_expression(expression): def convert_expression(expression): return { normalization.NormalFunctionCallExpression: convert_function_call_expression, + normalization.NormalIfElseExpression: convert_if_else_expression, normalization.NormalIntegerLiteralExpression: convert_integer_literal_expression, normalization.NormalLambdaExpression: convert_lambda_expression, normalization.NormalListConstructExpression: convert_list_construct_expression, @@ -207,11 +200,14 @@ def convert_expression_statement(statement): expression=convert_expression(statement.expression), ) -def convert_if_else_statement(statement): - return CPSIfElseStatement( +def convert_if_else_expression(statement): + if_statement_list=tuple(convert_statement(s) for s in statement.if_statement_list) + else_statement_list=tuple(convert_statement(s) for s in statement.else_statement_list) + + return CPSIfElseExpression( condition_expression=convert_expression(statement.condition_expression), - if_statement_list=tuple(convert_statement(s) for s in statement.if_statement_list), - else_statement_list=tuple(convert_statement(s) for s in statement.else_statement_list), + if_statement_list=if_statement_list, + else_statement_list=else_statement_list, ) def convert_list_append_statement(statement): @@ -232,12 +228,6 @@ def convert_variable_initialization_statement(statement): expression=convert_expression(statement.expression), ) -def convert_variable_reassignment_statement(statement): - return CPSVariableReassignmentStatement( - variable=statement.variable, - expression=convert_expression(statement.expression), - ) - def convert_symbol_array_variable_initialization_statement(statement): return CPSSymbolArrayVariableInitializationStatement( variable=statement.variable, @@ -249,15 +239,17 @@ def convert_statement(statement): normalization.NormalArrayVariableInitializationStatement: convert_array_variable_initialization_statement, normalization.NormalAssignmentStatement: convert_assignment_statement, normalization.NormalExpressionStatement: convert_expression_statement, - normalization.NormalIfElseStatement: convert_if_else_statement, normalization.NormalListAppendStatement: convert_list_append_statement, normalization.NormalPushStatement: convert_push_statement, normalization.NormalVariableInitializationStatement: convert_variable_initialization_statement, - normalization.NormalVariableReassignmentStatement: convert_variable_reassignment_statement, normalization.NormalSymbolArrayVariableInitializationStatement: convert_symbol_array_variable_initialization_statement, }[type(statement)](statement) +def convert_statement_list(statement_list): + return tuple(convert_statement(s) for s in statement_list) + + def convert(program): return CPSProgram( - statement_list=tuple(convert_statement(s) for s in program.statement_list), + statement_list=convert_statement_list(program.statement_list), ) diff --git a/crossplatform_ir_generation.py b/crossplatform_ir_generation.py index c7d855f..332a74f 100644 --- a/crossplatform_ir_generation.py +++ b/crossplatform_ir_generation.py @@ -123,6 +123,7 @@ def generate_variable_expression(counters, expression): def generate_expression(counters, expression): return { conversion.CPSFunctionCallExpression: generate_function_call_expression, + conversion.CPSIfElseExpression: generate_if_else_expression, conversion.CPSIntegerLiteralExpression: generate_integer_literal_expression, conversion.CPSLambdaExpression: generate_lambda_expression, conversion.CPSStringLiteralExpression: generate_string_literal_expression, @@ -145,18 +146,27 @@ def generate_expression_statement(counters, statement): return referenced_entry_list, instruction_list -def generate_if_else_statement(counters, statement): +def generate_if_else_expression(counters, statement): if_counter = counters['if'] counters['if'] += 1 referenced_entry_list_list = [] + condition_referenced_entry_list, condition_instruction_list = generate_expression( + counters, + statement.condition_expression, + ) + if_instruction_list_list = [] for if_statement in statement.if_statement_list: referenced_entry_list, instruction_list = generate_statement(counters, if_statement) referenced_entry_list_list.append(referenced_entry_list) if_instruction_list_list.append(instruction_list) + if_instruction_list = flatten(if_instruction_list_list) + assert if_instruction_list[-1].instruction == 'drop' + if_instruction_list = if_instruction_list[:-1] + else_instruction_list_list = [] for else_statement in statement.else_statement_list: @@ -164,30 +174,38 @@ def generate_if_else_statement(counters, statement): referenced_entry_list_list.append(referenced_entry_list) else_instruction_list_list.append(instruction_list) + else_instruction_list = flatten(else_instruction_list_list) + assert else_instruction_list[-1].instruction == 'drop' + else_instruction_list = else_instruction_list[:-1] + if_label = '__if${}__'.format(if_counter) else_label = '__else${}__'.format(if_counter) endif_label = '__endif${}__'.format(if_counter) - instruction_list = ( - referenced_entry_list_list, - generate_expression(counters, statement.condition_expression) + ( - CIRInstruction( - instruction='jump_if_false', - argument=else_label, - ), - CIRLabel(label=if_label), - ) + flatten(if_instruction_list_list) + ( - CIRInstruction( - instruction='jump', - argument=endif_label, - ), - CIRLabel(label=else_label), - ) + flatten(else_instruction_list_list) + ( - CIRLabel(label=endif_label), + instruction_list = condition_instruction_list + ( + CIRInstruction( + instruction='jump_if_false', + argument=else_label, ), + CIRInstruction( + instruction='jump', + argument=if_label, + ), + CIRLabel(label=if_label), + ) + if_instruction_list + ( + CIRInstruction( + instruction='jump', + argument=endif_label, + ), + CIRLabel(label=else_label), + ) + else_instruction_list + ( + CIRLabel(label=endif_label), ) - return flatten(referenced_entry_list_list), instruction_list + return ( + condition_referenced_entry_list + flatten(referenced_entry_list_list), + instruction_list, + ) def generate_assignment_statement(counters, statement): referenced_entry_list, instruction_list = generate_expression( @@ -222,29 +240,12 @@ def generate_variable_initialization_statement(counters, statement): return referenced_entry_list, instruction_list -def generate_variable_reassignment_statement(counters, statement): - referenced_entry_list, instruction_list = generate_expression( - counters, - statement.expression, - ) - - instruction_list += ( - CIRInstruction( - instruction='pop', - argument=generate_symbol_literal(statement.variable), - ), - ) - - return referenced_entry_list, instruction_list - def generate_statement(counters, statement): return { conversion.CPSAssignmentStatement: generate_assignment_statement, conversion.CPSExpressionStatement: generate_expression_statement, - conversion.CPSIfElseStatement: generate_if_else_statement, conversion.CPSPushStatement: generate_push_statement, conversion.CPSVariableInitializationStatement: generate_variable_initialization_statement, - conversion.CPSVariableReassignmentStatement: generate_variable_reassignment_statement, }[type(statement)](counters, statement) def generate(converted): diff --git a/generation.py b/generation.py index d855d07..645441f 100644 --- a/generation.py +++ b/generation.py @@ -45,6 +45,7 @@ def generate_list_construct_expression(expression): def generate_expression(expression): return { transformation.CFunctionCallExpression: generate_function_call, + transformation.CIfElseExpression: generate_if_else_expression, transformation.CIntegerLiteral: generate_integer_literal, transformation.CLambdaExpression: generate_lambda_expression, transformation.CListConstructExpression: generate_list_construct_expression, @@ -98,17 +99,10 @@ def generate_variable_initialization_statement(statement): generate_expression(statement.expression), ) -def generate_variable_reassignment_statement(statement): - return '{} = {};'.format( - statement.variable, - generate_expression(statement.expression), - ) - - def indent(s): return '\n'.join(' ' * 2 + l for l in s.split('\n')) -def generate_if_else_statement(statement): +def generate_if_else_expression(statement): # TODO Check that the argument is boolean condition_expression = '{}.instance.boolean'.format( generate_expression(statement.condition_expression), @@ -153,13 +147,11 @@ def generate_statement(statement): return { transformation.CArrayVariableInitializationStatement: generate_array_variable_initialization_statement, transformation.CExpressionStatement: generate_expression_statement, - transformation.CIfElseStatement: generate_if_else_statement, transformation.CListAppendStatement: generate_list_append_statement, transformation.CPushStatement: generate_push_statement, transformation.CSymbolAssignmentStatement: generate_symbol_assignment_statement, transformation.CSymbolArrayVariableInitializationStatement: generate_symbol_array_variable_initialization_statement, transformation.CVariableInitializationStatement: generate_variable_initialization_statement, - transformation.CVariableReassignmentStatement: generate_variable_reassignment_statement, }[type(statement)](statement) def generate_function_definition(definition): diff --git a/normalization.py b/normalization.py index 71f1fba..7ce7488 100644 --- a/normalization.py +++ b/normalization.py @@ -80,14 +80,6 @@ NormalVariableInitializationStatement = collections.namedtuple( ], ) -NormalVariableReassignmentStatement = collections.namedtuple( - 'NormalVariableReassignmentStatement', - [ - 'variable', - 'expression', - ], -) - NormalExpressionStatement = collections.namedtuple( 'NormalExpressionStatement', [ @@ -103,8 +95,8 @@ NormalAssignmentStatement = collections.namedtuple( ], ) -NormalIfElseStatement = collections.namedtuple( - 'NormalIfElseStatement', +NormalIfElseExpression = collections.namedtuple( + 'NormalIfElseExpression', [ 'condition_expression', 'if_statement_list', @@ -132,7 +124,6 @@ def normalize_lambda_expression(counter, expression): _, statement_list = normalize_statement_list( 0, expression.statement_list, - assign_result_to='result', ) return ( @@ -328,34 +319,23 @@ def normalize_if_expression(counter, expression): 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, - ), + condition_prestatements, + NormalIfElseExpression( + condition_expression=condition_expression, + if_statement_list=if_statement_list, + else_statement_list=else_statement_list, ), - NormalVariableExpression(variable=result_variable), ) def normalize_expression(counter, expression): @@ -401,11 +381,7 @@ def normalize_statement(counter, 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 - +def normalize_statement_list(counter, statement_list): result_statement_list = [] for statement in statement_list: @@ -414,19 +390,6 @@ def normalize_statement_list(counter, statement_list, **kwargs): result_statement_list.append(s) result_statement_list.append(normalized) - # TODO The way we fix the last statement is really confusing - last_statement = result_statement_list[-1] - - if isinstance(last_statement, NormalExpressionStatement) and isinstance(last_statement.expression, NormalVariableExpression): - if assign_result_to is not None: - result_expression = result_statement_list.pop().expression - result_statement_list.append( - NormalVariableReassignmentStatement( - variable=assign_result_to, - expression=result_expression, - ) - ) - return ( counter, result_statement_list, diff --git a/transformation.py b/transformation.py index a9cad95..6aa7080 100644 --- a/transformation.py +++ b/transformation.py @@ -92,14 +92,6 @@ CVariableInitializationStatement = collections.namedtuple( ], ) -CVariableReassignmentStatement = collections.namedtuple( - 'CVariableReassignmentStatement', - [ - 'variable', - 'expression', - ], -) - CExpressionStatement = collections.namedtuple( 'CExpressionStatement', [ @@ -107,8 +99,8 @@ CExpressionStatement = collections.namedtuple( ], ) -CIfElseStatement = collections.namedtuple( - 'CIfElseStatement', +CIfElseExpression = collections.namedtuple( + 'CIfElseExpression', [ 'condition_expression', 'if_statement_list', @@ -246,6 +238,7 @@ def transform_list_append_statement(accumulators, expression): def transform_expression(accumulators, expression): return { conversion.CPSFunctionCallExpression: transform_function_call_expression, + conversion.CPSIfElseExpression: transform_if_else_expression, conversion.CPSIntegerLiteralExpression: transform_integer_literal_expression, conversion.CPSLambdaExpression: transform_lambda_expression, conversion.CPSListConstructExpression: transform_list_construct_expression, @@ -285,8 +278,8 @@ def transform_expression_statement(accumulators, statement): expression=transform_expression(accumulators, statement.expression), ) -def transform_if_else_statement(accumulators, statement): - return CIfElseStatement( +def transform_if_else_expression(accumulators, statement): + return CIfElseExpression( condition_expression=transform_expression(accumulators, statement.condition_expression), if_statement_list=tuple(transform_statement(accumulators, s) for s in statement.if_statement_list), else_statement_list=tuple(transform_statement(accumulators, s) for s in statement.else_statement_list), @@ -322,12 +315,6 @@ def transform_variable_initialization_statement(accumulators, statement): expression=transform_expression(accumulators, statement.expression), ) -def transform_variable_reassignment_statement(accumulators, statement): - return CVariableReassignmentStatement( - variable=statement.variable, - expression=transform_expression(accumulators, statement.expression), - ) - def transform_push_statement(accumulators, statement): return CPushStatement(expression=transform_expression(accumulators, statement.expression)) @@ -336,12 +323,10 @@ def transform_statement(accumulators, statement): conversion.CPSArrayVariableInitializationStatement: transform_array_variable_initialization_statement, conversion.CPSAssignmentStatement: transform_symbol_assignment_statement, conversion.CPSExpressionStatement: transform_expression_statement, - conversion.CPSIfElseStatement: transform_if_else_statement, conversion.CPSListAppendStatement: transform_list_append_statement, conversion.CPSPushStatement: transform_push_statement, conversion.CPSSymbolArrayVariableInitializationStatement: transform_symbol_array_variable_initialization_statement, conversion.CPSVariableInitializationStatement: transform_variable_initialization_statement, - conversion.CPSVariableReassignmentStatement: transform_variable_reassignment_statement, }[type(statement)](accumulators, statement)