X-Git-Url: https://code.kerkeslager.com/?p=fur;a=blobdiff_plain;f=normalization.py;h=8248169c9210e0a2d005bfafe5a6e6455c434877;hp=618e5d9a7d1d6e59eb8a32ed8680780963d0afc6;hb=c24be69b26aedc427c7831f150e86ca00182d8e0;hpb=204200cd277191bd0a272528b2a811cbdb7990a0 diff --git a/normalization.py b/normalization.py index 618e5d9..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,42 +42,31 @@ NormalStringLiteralExpression = collections.namedtuple( NormalSymbolExpression = collections.namedtuple( 'NormalSymbolExpression', - [ + ( 'symbol', - ], + ), ) -NormalNegationExpression = collections.namedtuple( - 'NormalNegationExpression', - [ - 'internal_expression', - ], +NormalSymbolLiteralExpression = collections.namedtuple( + 'NormalSymbolLiteralExpression', + ( + 'symbol', + ), ) -NormalInfixExpression = collections.namedtuple( - 'NormalInfixExpression', - [ - 'order', - 'operator', - 'left', - 'right', - ], +NormalPushStatement = collections.namedtuple( + 'NormalPushStatement', + ( + 'expression', + ), ) NormalFunctionCallExpression = collections.namedtuple( 'NormalFunctionCallExpression', [ - 'function', + 'metadata', + 'function_expression', 'argument_count', - 'argument_items', - ], -) - -NormalArrayVariableInitializationStatement = collections.namedtuple( - 'NormalArrayVariableInitializationStatement', - [ - 'variable', - 'items', ], ) @@ -73,14 +78,6 @@ NormalVariableInitializationStatement = collections.namedtuple( ], ) -NormalVariableReassignmentStatement = collections.namedtuple( - 'NormalVariableReassignmentStatement', - [ - 'variable', - 'expression', - ], -) - NormalExpressionStatement = collections.namedtuple( 'NormalExpressionStatement', [ @@ -96,21 +93,12 @@ NormalAssignmentStatement = collections.namedtuple( ], ) -NormalIfElseStatement = collections.namedtuple( - 'NormalIfElseStatement', +NormalIfElseExpression = collections.namedtuple( + 'NormalIfElseExpression', [ 'condition_expression', - 'if_statements', - 'else_statements', - ], -) - -NormalFunctionDefinitionStatement = collections.namedtuple( - 'NormalFunctionDefinitionStatement', - [ - 'name', - 'argument_name_list', - 'statement_list', + 'if_statement_list', + 'else_statement_list', ], ) @@ -121,62 +109,149 @@ 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): - # TODO Store this in a C variable 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=NormalLambdaExpression( + name=expression.name, + argument_name_list=expression.argument_name_list, + statement_list=statement_list, + ), + ), + ), + NormalVariableExpression(variable=variable), + ) + +NormalListConstructExpression = collections.namedtuple( + 'NormalListConstructExpression', + [ + 'allocate', + ], +) + +def normalize_list_literal_expression(counter, expression): + list_variable = '${}'.format(counter) + counter += 1 + + prestatements = [] + + for item_expression in expression.item_expression_list: + counter, item_expression_prestatements, normalized = normalize_expression( + counter, + item_expression, + ) + + for p in item_expression_prestatements: + prestatements.append(p) + + prestatements.append( + NormalPushStatement( + expression=normalized, + ) + ) + + return ( + counter, + tuple(prestatements), + NormalListConstructExpression(allocate=len(expression.item_expression_list)), + ) + def normalize_string_literal_expression(counter, expression): - # TODO Store this in a C variable return ( counter, (), NormalStringLiteralExpression(string=expression.string), ) +NormalStructureLiteralExpression = collections.namedtuple( + 'NormalStructureLiteralExpression', + ( + 'field_count', + ), +) + +def normalize_structure_literal_expression(counter, expression): + prestatements = [] + + for field in expression.fields: + counter, field_expression_prestatements, field_expression = normalize_expression( + counter, + field.expression, + ) + + for p in field_expression_prestatements: + prestatements.append(p) + + prestatements.append(NormalPushStatement( + expression=field_expression, + )) + + prestatements.append(NormalPushStatement( + expression=NormalSymbolLiteralExpression( + symbol=field.symbol, + ), + )) + + return ( + counter, + tuple(prestatements), + NormalStructureLiteralExpression( + field_count=len(expression.fields), + ), + ) + def normalize_symbol_expression(counter, expression): - # TODO Store this in a C variable return ( 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 = [] - 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: prestatements.append(s) - variable = '${}'.format(counter) - prestatements.append(NormalVariableInitializationStatement( - variable=variable, - expression=normalized_argument, - )) - arguments.append(NormalVariableExpression( - variable=variable, - )) - counter += 1 - - arguments_variable = '${}'.format(counter) - counter += 1 - - prestatements.append(NormalArrayVariableInitializationStatement( - variable=arguments_variable, - items=tuple(arguments), - )) + prestatements.append( + NormalPushStatement( + expression=normalized_argument, + ), + ) counter, function_prestatements, function_expression = normalize_expression( counter, @@ -190,174 +265,56 @@ def normalize_function_call_expression(counter, expression): counter, tuple(prestatements), NormalFunctionCallExpression( - function=function_expression, - argument_count=len(arguments), - argument_items=NormalVariableExpression(variable=arguments_variable), + metadata=expression.metadata, + function_expression=function_expression, + argument_count=len(expression.argument_list), ), ) -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 - - root_prestatements = ( - NormalVariableInitializationStatement( - variable=left_variable, - expression=left_expression, - ), - NormalVariableInitializationStatement( - variable=right_variable, - expression=right_expression, - ), - ) - - return ( +def normalize_if_expression(counter, expression): + counter, condition_prestatements, condition_expression = normalize_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), - ), + expression.condition_expression, ) -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, if_statement_list = normalize_statement_list( counter, - left_prestatements + right_prestatements + root_prestatements, - NormalInfixExpression( - order=expression.order, - operator=expression.operator, - left=NormalVariableExpression(variable=left_variable), - right=NormalVariableExpression(variable=right_variable), - ), + expression.if_statement_list, ) - - 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_statements=short_circuited_statements, - else_statements=(), - ) - - elif expression.operator == 'or': - if_else_statement = NormalIfElseStatement( - condition_expression=condition_expression, - if_statements=(), - else_statements=short_circuited_statements, - ) - - else: - raise Exception('Unable to handle operator "{}"'.format(expression.operator)) - - return ( + counter, else_statement_list = normalize_statement_list( counter, - left_prestatements + (if_else_prestatment, if_else_statement), - NormalVariableExpression(variable=result_variable), + expression.else_statement_list, ) - -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_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)), + condition_prestatements, + NormalIfElseExpression( + condition_expression=condition_expression, + if_statement_list=if_statement_list, + else_statement_list=else_statement_list, + ), ) def normalize_expression(counter, expression): return { - NormalInfixExpression: fake_normalization, - NormalVariableExpression: fake_normalization, - parsing.FurFunctionCallExpression: normalize_function_call_expression, - parsing.FurInfixExpression: normalize_infix_expression, - parsing.FurIntegerLiteralExpression: normalize_integer_literal_expression, - parsing.FurNegationExpression: normalize_negation_expression, - parsing.FurStringLiteralExpression: normalize_string_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): + # 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 ( @@ -366,17 +323,6 @@ def normalize_expression_statement(counter, statement): NormalExpressionStatement(expression=normalized), ) -def normalize_function_definition_statement(counter, statement): - return ( - counter, - (), - NormalFunctionDefinitionStatement( - name=statement.name, - argument_name_list=statement.argument_name_list, - statement_list=normalize_statement_list(statement.statement_list), - ), - ) - def normalize_assignment_statement(counter, statement): counter, prestatements, normalized_expression = normalize_expression(counter, statement.expression) return ( @@ -390,23 +336,28 @@ 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(statement_list): - counter = 0 +def normalize_statement_list(counter, statement_list): + result_statement_list = [] for statement in statement_list: counter, prestatements, normalized = normalize_statement(counter, statement) for s in prestatements: - yield s - yield normalized + result_statement_list.append(s) + result_statement_list.append(normalized) + + return ( + counter, + result_statement_list, + ) def normalize(program): + _, statement_list = normalize_statement_list(0, program.statement_list) return NormalProgram( - statement_list=normalize_statement_list(program.statement_list), + statement_list=statement_list, )