X-Git-Url: https://code.kerkeslager.com/?p=fur;a=blobdiff_plain;f=normalization.py;h=8248169c9210e0a2d005bfafe5a6e6455c434877;hp=f2b7b138a6a8dbe9db3ce5cad5e8c5b280b454cb;hb=c24be69b26aedc427c7831f150e86ca00182d8e0;hpb=328947882d63d9d4f2ead0dbc54bee33bef6c33b diff --git a/normalization.py b/normalization.py index f2b7b13..8248169 100644 --- a/normalization.py +++ b/normalization.py @@ -1,8 +1,15 @@ import collections -import parsing +import desugaring import util +NormalBuiltinExpression = collections.namedtuple( + 'NormalBuiltinExpression', + ( + 'symbol', + ), +) + NormalVariableExpression = collections.namedtuple( 'NormalVariableExpression', [ @@ -17,6 +24,15 @@ NormalIntegerLiteralExpression = collections.namedtuple( ], ) +NormalLambdaExpression = collections.namedtuple( + 'NormalLambdaExpression', + ( + 'name', + 'argument_name_list', + 'statement_list', + ), +) + NormalStringLiteralExpression = collections.namedtuple( 'NormalStringLiteralExpression', [ @@ -26,33 +42,16 @@ NormalStringLiteralExpression = collections.namedtuple( NormalSymbolExpression = collections.namedtuple( 'NormalSymbolExpression', - [ + ( 'symbol', - ], -) - -NormalNegationExpression = collections.namedtuple( - 'NormalNegationExpression', - [ - 'internal_expression', - ], -) - -NormalDotExpression = collections.namedtuple( - 'NormalDotExpression', - [ - 'instance', - 'field', - ], + ), ) -NormalInfixExpression = collections.namedtuple( - 'NormalInfixExpression', - [ - 'metadata', - 'order', - 'operator', - ], +NormalSymbolLiteralExpression = collections.namedtuple( + 'NormalSymbolLiteralExpression', + ( + 'symbol', + ), ) NormalPushStatement = collections.namedtuple( @@ -65,27 +64,12 @@ NormalPushStatement = collections.namedtuple( NormalFunctionCallExpression = collections.namedtuple( 'NormalFunctionCallExpression', [ + 'metadata', 'function_expression', 'argument_count', ], ) -NormalArrayVariableInitializationStatement = collections.namedtuple( - 'NormalArrayVariableInitializationStatement', - [ - 'variable', - 'items', - ], -) - -NormalSymbolArrayVariableInitializationStatement = collections.namedtuple( - 'NormalSymbolArrayVariableInitializationStatement', - [ - 'variable', - 'symbol_list', - ], -) - NormalVariableInitializationStatement = collections.namedtuple( 'NormalVariableInitializationStatement', [ @@ -94,14 +78,6 @@ NormalVariableInitializationStatement = collections.namedtuple( ], ) -NormalVariableReassignmentStatement = collections.namedtuple( - 'NormalVariableReassignmentStatement', - [ - 'variable', - 'expression', - ], -) - NormalExpressionStatement = collections.namedtuple( 'NormalExpressionStatement', [ @@ -117,8 +93,8 @@ NormalAssignmentStatement = collections.namedtuple( ], ) -NormalIfElseStatement = collections.namedtuple( - 'NormalIfElseStatement', +NormalIfElseExpression = collections.namedtuple( + 'NormalIfElseExpression', [ 'condition_expression', 'if_statement_list', @@ -126,15 +102,6 @@ NormalIfElseStatement = collections.namedtuple( ], ) -NormalFunctionDefinitionStatement = collections.namedtuple( - 'NormalFunctionDefinitionStatement', - [ - 'name', - 'argument_name_list', - 'statement_list', - ], -) - NormalProgram = collections.namedtuple( 'NormalProgram', [ @@ -142,17 +109,38 @@ NormalProgram = collections.namedtuple( ], ) -def fake_normalization(counter, thing): - return (counter, (), thing) +def normalize_builtin_expression(counter, expression): + return ( + counter, + (), + NormalBuiltinExpression(symbol=expression.symbol), + ) def normalize_integer_literal_expression(counter, expression): + return ( + counter, + (), + NormalIntegerLiteralExpression(integer=expression.integer), + ) + +def normalize_lambda_expression(counter, expression): variable = '${}'.format(counter) + + _, statement_list = normalize_statement_list( + 0, + expression.statement_list, + ) + return ( counter + 1, ( NormalVariableInitializationStatement( variable=variable, - expression=NormalIntegerLiteralExpression(integer=expression.integer), + expression=NormalLambdaExpression( + name=expression.name, + argument_name_list=expression.argument_name_list, + statement_list=statement_list, + ), ), ), NormalVariableExpression(variable=variable), @@ -165,34 +153,11 @@ NormalListConstructExpression = collections.namedtuple( ], ) -NormalListAppendStatement = collections.namedtuple( - 'NormalListAppendStatement', - [ - 'list_expression', - 'item_expression', - ], -) - -NormalListGetExpression = collections.namedtuple( - 'NormalListGetExpression', - [ - 'list_expression', - 'index_expression', - ], -) - def normalize_list_literal_expression(counter, expression): list_variable = '${}'.format(counter) counter += 1 - prestatements = [ - NormalVariableInitializationStatement( - variable=list_variable, - expression=NormalListConstructExpression(allocate=len(expression.item_expression_list)), - ), - ] - - list_expression = NormalVariableExpression(variable=list_variable) + prestatements = [] for item_expression in expression.item_expression_list: counter, item_expression_prestatements, normalized = normalize_expression( @@ -204,155 +169,89 @@ def normalize_list_literal_expression(counter, expression): prestatements.append(p) prestatements.append( - NormalListAppendStatement( - list_expression=list_expression, - item_expression=normalized, + NormalPushStatement( + expression=normalized, ) ) return ( counter, tuple(prestatements), - 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), + NormalListConstructExpression(allocate=len(expression.item_expression_list)), ) def normalize_string_literal_expression(counter, expression): - variable = '${}'.format(counter) return ( - counter + 1, - ( - NormalVariableInitializationStatement( - variable=variable, - expression=NormalStringLiteralExpression(string=expression.string), - ), - ), - NormalVariableExpression(variable=variable), + counter, + (), + NormalStringLiteralExpression(string=expression.string), ) 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( + for field in expression.fields: + counter, field_expression_prestatements, field_expression = normalize_expression( counter, - symbol_expression_pair.expression, + field.expression, ) - for p in field_prestatements: + for p in field_expression_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(NormalPushStatement( + expression=field_expression, + )) - 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, + prestatements.append(NormalPushStatement( + expression=NormalSymbolLiteralExpression( + symbol=field.symbol, ), - ) - ) + )) return ( - counter + 1, + counter, tuple(prestatements), - NormalVariableExpression(variable=variable), + NormalStructureLiteralExpression( + field_count=len(expression.fields), + ), ) - def normalize_symbol_expression(counter, expression): - variable = '${}'.format(counter) return ( - counter + 1, - ( - NormalVariableInitializationStatement( - variable=variable, - expression=NormalSymbolExpression(symbol=expression.symbol), - ), - ), - NormalVariableExpression(variable=variable), + counter, + (), + NormalSymbolExpression(symbol=expression.symbol), ) -def normalize_function_call_expression(counter, expression): - assert isinstance(expression, parsing.FurFunctionCallExpression) +def normalize_symbol_literal_expression(counter, expression): + return ( + counter, + (), + NormalSymbolLiteralExpression(symbol=expression.symbol), + ) +def normalize_function_call_expression(counter, expression): prestatements = [] - 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: prestatements.append(s) - variable = '${}'.format(counter) - prestatements.append( - NormalVariableInitializationStatement( - variable=variable, - expression=normalized_argument, - ) - ) prestatements.append( NormalPushStatement( - expression=NormalVariableExpression( - variable=variable, - ), + expression=normalized_argument, ), ) - counter += 1 counter, function_prestatements, function_expression = normalize_expression( counter, @@ -362,254 +261,53 @@ def normalize_function_call_expression(counter, expression): for ps in function_prestatements: prestatements.append(ps) - if not isinstance(function_expression, NormalVariableExpression): - function_variable = '${}'.format(counter) - - prestatements.append( - NormalVariableInitializationStatement( - variable=function_variable, - expression=function_expression, - ) - ) - - function_expression = NormalVariableExpression(variable=function_variable) - counter += 1 - - result_variable = '${}'.format(counter) - - prestatements.append( - NormalVariableInitializationStatement( - variable=result_variable, - expression=NormalFunctionCallExpression( - function_expression=function_expression, - argument_count=len(expression.arguments), - ), - ) - ) - - return ( - counter + 1, - tuple(prestatements), - NormalVariableExpression(variable=result_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) - - center_variable = '${}'.format(counter) - counter += 1 - - root_prestatements = ( - NormalPushStatement(expression=left_expression), - NormalPushStatement(expression=right_expression), - NormalVariableInitializationStatement( - variable=center_variable, - expression=NormalInfixExpression( - metadata=expression.metadata, - order=expression.order, - operator=expression.operator, - ), - ), - ) - - return ( - counter, - left_prestatements + right_prestatements + root_prestatements, - NormalVariableExpression(variable=center_variable), - ) - -def desugar_ternary_comparison(counter, expression): - counter, left_prestatements, left_expression = normalize_expression(counter, expression.left.left) - counter, middle_prestatements, middle_expression = normalize_expression(counter, expression.left.right) - - left_variable = '${}'.format(counter) - counter += 1 - middle_variable = '${}'.format(counter) - counter += 1 - - # TODO Is there a memory leak if the middle expression throws an exception because the first expression result hasn't been added to the stack? - juncture_prestatements = ( - NormalVariableInitializationStatement( - variable=left_variable, - expression=left_expression, - ), - NormalVariableInitializationStatement( - variable=middle_variable, - expression=middle_expression, - ) - ) - - counter, boolean_expression_prestatements, boolean_expression = normalize_boolean_expression( - counter, - parsing.FurInfixExpression( - metadata=expression.left.metadata, - order='and_level', - operator='and', - left=parsing.FurInfixExpression( - metadata=expression.left.metadata, - order='comparison_level', - operator=expression.left.operator, - left=NormalVariableExpression(variable=left_variable), - right=NormalVariableExpression(variable=middle_variable), - ), - right=parsing.FurInfixExpression( - metadata=expression.metadata, - order='comparison_level', - operator=expression.operator, - left=NormalVariableExpression(variable=middle_variable), - right=expression.right, - ), - ) - ) - return ( counter, - left_prestatements + middle_prestatements + juncture_prestatements + boolean_expression_prestatements, - boolean_expression, - ) - -def normalize_comparison_expression(counter, expression): - if isinstance(expression.left, parsing.FurInfixExpression) and expression.order == 'comparison_level': - return desugar_ternary_comparison(counter, expression) - - return normalize_basic_infix_operation(counter, 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), - NormalVariableExpression(variable=result_variable), - ) - -def normalize_dot_expression(counter, expression): - assert isinstance(expression.right, parsing.FurSymbolExpression) - - counter, prestatements, left_expression = normalize_expression(counter, expression.left) - - variable = '${}'.format(counter) - - dot_expression_prestatement = NormalVariableInitializationStatement( - variable=variable, - expression=NormalDotExpression( - instance=left_expression, - field=expression.right.symbol, + tuple(prestatements), + NormalFunctionCallExpression( + metadata=expression.metadata, + function_expression=function_expression, + argument_count=len(expression.argument_list), ), ) - return ( - counter + 1, - prestatements + (dot_expression_prestatement,), - NormalVariableExpression(variable=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, - 'dot_level': normalize_dot_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, - ), + condition_prestatements, + NormalIfElseExpression( + condition_expression=condition_expression, + if_statement_list=if_statement_list, + else_statement_list=else_statement_list, ), - 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.FurStructureLiteralExpression: normalize_structure_literal_expression, - parsing.FurSymbolExpression: normalize_symbol_expression, + desugaring.DesugaredBuiltinExpression: normalize_builtin_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, + desugaring.DesugaredSymbolLiteralExpression: normalize_symbol_literal_expression, }[type(expression)](counter, expression) def normalize_expression_statement(counter, statement): @@ -625,22 +323,6 @@ def normalize_expression_statement(counter, statement): 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 ( @@ -654,17 +336,12 @@ 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, }[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: @@ -673,19 +350,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,