X-Git-Url: https://code.kerkeslager.com/?p=fur;a=blobdiff_plain;f=normalization.py;h=9725b5b54e70fa84b5ff6fb290c748a26788dc3e;hp=ca6f57f755dd004c9a40892e6b79d00e0c9554fe;hb=aa339c441f43849a8cae256aa130278ca7618b7e;hpb=3297817843cd6bd087505a70d8e108f1baa35cff diff --git a/normalization.py b/normalization.py index ca6f57f..9725b5b 100644 --- a/normalization.py +++ b/normalization.py @@ -1,6 +1,6 @@ import collections -import parsing +import desugaring import util NormalVariableExpression = collections.namedtuple( @@ -17,6 +17,14 @@ NormalIntegerLiteralExpression = collections.namedtuple( ], ) +NormalLambdaExpression = collections.namedtuple( + 'NormalLambdaExpression', + ( + 'argument_name_list', + 'statement_list', + ), +) + NormalStringLiteralExpression = collections.namedtuple( 'NormalStringLiteralExpression', [ @@ -31,29 +39,19 @@ NormalSymbolExpression = collections.namedtuple( ], ) -NormalNegationExpression = collections.namedtuple( - 'NormalNegationExpression', - [ - 'internal_expression', - ], -) - -NormalInfixExpression = collections.namedtuple( - 'NormalInfixExpression', - [ - 'order', - 'operator', - 'left', - 'right', - ], +NormalPushStatement = collections.namedtuple( + 'NormalPushStatement', + ( + 'expression', + ), ) NormalFunctionCallExpression = collections.namedtuple( 'NormalFunctionCallExpression', [ + 'metadata', 'function_expression', 'argument_count', - 'argument_items', ], ) @@ -65,6 +63,14 @@ NormalArrayVariableInitializationStatement = collections.namedtuple( ], ) +NormalSymbolArrayVariableInitializationStatement = collections.namedtuple( + 'NormalSymbolArrayVariableInitializationStatement', + [ + 'variable', + 'symbol_list', + ], +) + NormalVariableInitializationStatement = collections.namedtuple( 'NormalVariableInitializationStatement', [ @@ -121,9 +127,6 @@ NormalProgram = collections.namedtuple( ], ) -def fake_normalization(counter, thing): - return (counter, (), thing) - def normalize_integer_literal_expression(counter, expression): variable = '${}'.format(counter) return ( @@ -137,6 +140,29 @@ def normalize_integer_literal_expression(counter, expression): NormalVariableExpression(variable=variable), ) +def normalize_lambda_expression(counter, expression): + variable = '${}'.format(counter) + + _, statement_list = normalize_statement_list( + 0, + expression.statement_list, + assign_result_to='result', + ) + + return ( + counter + 1, + ( + NormalVariableInitializationStatement( + variable=variable, + expression=NormalLambdaExpression( + argument_name_list=expression.argument_name_list, + statement_list=statement_list, + ), + ), + ), + NormalVariableExpression(variable=variable), + ) + NormalListConstructExpression = collections.namedtuple( 'NormalListConstructExpression', [ @@ -152,14 +178,6 @@ NormalListAppendStatement = collections.namedtuple( ], ) -NormalListGetExpression = collections.namedtuple( - 'NormalListGetExpression', - [ - 'list_expression', - 'index_expression', - ], -) - def normalize_list_literal_expression(counter, expression): list_variable = '${}'.format(counter) counter += 1 @@ -195,25 +213,6 @@ def normalize_list_literal_expression(counter, expression): list_expression, ) -def normalize_list_item_expression(counter, expression): - counter, list_prestatements, list_expression = normalize_expression(counter, expression.list_expression) - counter, index_prestatements, index_expression = normalize_expression(counter, expression.index_expression) - - result_variable = '${}'.format(counter) - result_prestatement = NormalVariableInitializationStatement( - variable=result_variable, - expression=NormalListGetExpression( - list_expression=list_expression, - index_expression=index_expression, - ), - ) - - return ( - counter + 1, - list_prestatements + index_prestatements + (result_prestatement,), - NormalVariableExpression(variable=result_variable), - ) - def normalize_string_literal_expression(counter, expression): variable = '${}'.format(counter) return ( @@ -227,6 +226,72 @@ def normalize_string_literal_expression(counter, expression): NormalVariableExpression(variable=variable), ) +NormalStructureLiteralExpression = collections.namedtuple( + 'NormalStructureLiteralExpression', + [ + 'field_count', + 'symbol_list_variable', + 'value_list_variable', + ], +) + +def normalize_structure_literal_expression(counter, expression): + prestatements = [] + field_symbol_array = [] + field_value_array = [] + + for symbol_expression_pair in expression.fields: + counter, field_prestatements, field_expression = normalize_expression( + counter, + symbol_expression_pair.expression, + ) + + for p in field_prestatements: + prestatements.append(p) + + field_symbol_array.append(symbol_expression_pair.symbol) + field_value_array.append(field_expression) + + symbol_array_variable = '${}'.format(counter) + counter += 1 + + prestatements.append( + NormalSymbolArrayVariableInitializationStatement( + variable=symbol_array_variable, + symbol_list=tuple(field_symbol_array), + ) + ) + + value_array_variable = '${}'.format(counter) + counter += 1 + + prestatements.append( + NormalArrayVariableInitializationStatement( + variable=value_array_variable, + items=tuple(field_value_array), + ) + ) + + variable = '${}'.format(counter) + + prestatements.append( + NormalVariableInitializationStatement( + variable=variable, + expression=NormalStructureLiteralExpression( + field_count=len(expression.fields), + symbol_list_variable=symbol_array_variable, + value_list_variable=value_array_variable, + ), + ) + ) + + return ( + counter + 1, + tuple(prestatements), + NormalVariableExpression(variable=variable), + ) + + def normalize_symbol_expression(counter, expression): variable = '${}'.format(counter) return ( @@ -241,12 +306,9 @@ def normalize_symbol_expression(counter, expression): ) def normalize_function_call_expression(counter, expression): - assert isinstance(expression, parsing.FurFunctionCallExpression) - prestatements = [] - arguments = [] - for argument in expression.arguments: + for argument in expression.argument_list: counter, argument_prestatements, normalized_argument = normalize_expression(counter, argument) for s in argument_prestatements: @@ -259,19 +321,15 @@ def normalize_function_call_expression(counter, expression): expression=normalized_argument, ) ) - arguments.append(NormalVariableExpression( - variable=variable, - )) + prestatements.append( + NormalPushStatement( + expression=NormalVariableExpression( + variable=variable, + ), + ), + ) counter += 1 - arguments_variable = '${}'.format(counter) - counter += 1 - - prestatements.append(NormalArrayVariableInitializationStatement( - variable=arguments_variable, - items=tuple(arguments), - )) - counter, function_prestatements, function_expression = normalize_expression( counter, expression.function, @@ -293,162 +351,25 @@ def normalize_function_call_expression(counter, expression): function_expression = NormalVariableExpression(variable=function_variable) counter += 1 - return ( - counter, - tuple(prestatements), - NormalFunctionCallExpression( - function_expression=function_expression, - argument_count=len(arguments), - argument_items=NormalVariableExpression(variable=arguments_variable), - ), - ) - -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 - center_variable = '${}'.format(counter) - counter += 1 + result_variable = '${}'.format(counter) - root_prestatements = ( - NormalVariableInitializationStatement( - variable=left_variable, - expression=left_expression, - ), + prestatements.append( NormalVariableInitializationStatement( - variable=right_variable, - expression=right_expression, - ), - NormalVariableInitializationStatement( - variable=center_variable, - expression=NormalInfixExpression( - order=expression.order, - operator=expression.operator, - left=NormalVariableExpression(variable=left_variable), - right=NormalVariableExpression(variable=right_variable), + variable=result_variable, + expression=NormalFunctionCallExpression( + metadata=expression.metadata, + function_expression=function_expression, + argument_count=len(expression.argument_list), ), - ), - ) - - return ( - counter, - left_prestatements + right_prestatements + root_prestatements, - NormalVariableExpression(variable=center_variable), - ) - -def normalize_comparison_expression(counter, expression): - stack = [] - - while isinstance(expression.left, parsing.FurInfixExpression) and expression.order == 'comparison_level': - stack.append((expression.operator, expression.order, expression.right)) - expression = expression.left - - 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 = ( - NormalVariableInitializationStatement( - variable=left_variable, - expression=left_expression, - ), - NormalVariableInitializationStatement( - variable=right_variable, - expression=right_expression, - ), - ) - - counter, result_prestatements, result_expression = ( - counter, - left_prestatements + right_prestatements + root_prestatements, - NormalInfixExpression( - order=expression.order, - operator=expression.operator, - left=NormalVariableExpression(variable=left_variable), - right=NormalVariableExpression(variable=right_variable), - ), - ) - - while len(stack) > 0: - right_operator, right_order, right_expression = stack.pop() - and_right_expression = parsing.FurInfixExpression( - operator=right_operator, - order=right_order, - left=NormalVariableExpression(variable=right_variable), - right=right_expression, - ) - - and_expression = parsing.FurInfixExpression( - operator='and', - order='and_level', - left=result_expression, - right=and_right_expression, ) - - counter, and_prestatements, result_expression = normalize_boolean_expression( - counter, - and_expression, - ) - - result_prestatements = result_prestatements + and_prestatements - - return (counter, result_prestatements, result_expression) - -def normalize_boolean_expression(counter, expression): - counter, left_prestatements, left_expression = normalize_expression(counter, expression.left) - counter, right_prestatements, right_expression = normalize_expression(counter, expression.right) - - result_variable = '${}'.format(counter) - if_else_prestatment = NormalVariableInitializationStatement( - variable=result_variable, - expression=left_expression, ) - counter += 1 - - condition_expression=NormalVariableExpression(variable=result_variable) - short_circuited_statements = right_prestatements + (NormalVariableReassignmentStatement(variable=result_variable, expression=right_expression),) - - if expression.operator == 'and': - if_else_statement = NormalIfElseStatement( - condition_expression=condition_expression, - if_statement_list=short_circuited_statements, - else_statement_list=(), - ) - - elif expression.operator == 'or': - if_else_statement = NormalIfElseStatement( - condition_expression=condition_expression, - if_statement_list=(), - else_statement_list=short_circuited_statements, - ) - - else: - raise Exception('Unable to handle operator "{}"'.format(expression.operator)) return ( - counter, - left_prestatements + (if_else_prestatment, if_else_statement), + counter + 1, + tuple(prestatements), NormalVariableExpression(variable=result_variable), ) - -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, @@ -485,36 +406,16 @@ def normalize_if_expression(counter, expression): 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, + desugaring.DesugaredFunctionCallExpression: normalize_function_call_expression, + desugaring.DesugaredIfExpression: normalize_if_expression, + desugaring.DesugaredIntegerLiteralExpression: normalize_integer_literal_expression, + desugaring.DesugaredLambdaExpression: normalize_lambda_expression, + desugaring.DesugaredListLiteralExpression: normalize_list_literal_expression, + desugaring.DesugaredStringLiteralExpression: normalize_string_literal_expression, + desugaring.DesugaredStructureLiteralExpression: normalize_structure_literal_expression, + desugaring.DesugaredSymbolExpression: normalize_symbol_expression, }[type(expression)](counter, expression) def normalize_expression_statement(counter, statement): @@ -559,9 +460,9 @@ def normalize_assignment_statement(counter, statement): def normalize_statement(counter, statement): return { - parsing.FurAssignmentStatement: normalize_assignment_statement, - parsing.FurExpressionStatement: normalize_expression_statement, - parsing.FurFunctionDefinitionStatement: normalize_function_definition_statement, + desugaring.DesugaredAssignmentStatement: normalize_assignment_statement, + desugaring.DesugaredExpressionStatement: normalize_expression_statement, + desugaring.DesugaredFunctionDefinitionStatement: normalize_function_definition_statement, }[type(statement)](counter, statement) @util.force_generator(tuple) @@ -578,12 +479,12 @@ 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): - result_expression = result_statement_list.pop().expression - if assign_result_to is not None: + result_expression = result_statement_list.pop().expression result_statement_list.append( NormalVariableReassignmentStatement( variable=assign_result_to,