X-Git-Url: https://code.kerkeslager.com/?a=blobdiff_plain;f=normalization.py;h=51c1d7bd2b9dbe614c6a63d2283690aa84b991fe;hb=51b6cd6152e6311805b55e847ae9eb60f5c7c471;hp=0d967d7af107c41024223264d5ec3233bac1fc08;hpb=8be4bc7974ca10fb7fe247748c95c5c240bf11f4;p=fur diff --git a/normalization.py b/normalization.py index 0d967d7..51c1d7b 100644 --- a/normalization.py +++ b/normalization.py @@ -1,6 +1,7 @@ import collections import parsing +import util NormalVariableExpression = collections.namedtuple( 'NormalVariableExpression', @@ -9,6 +10,34 @@ NormalVariableExpression = collections.namedtuple( ], ) +NormalIntegerLiteralExpression = collections.namedtuple( + 'NormalIntegerLiteralExpression', + [ + 'integer', + ], +) + +NormalStringLiteralExpression = collections.namedtuple( + 'NormalStringLiteralExpression', + [ + 'string', + ], +) + +NormalSymbolExpression = collections.namedtuple( + 'NormalSymbolExpression', + [ + 'symbol', + ], +) + +NormalNegationExpression = collections.namedtuple( + 'NormalNegationExpression', + [ + 'internal_expression', + ], +) + NormalInfixExpression = collections.namedtuple( 'NormalInfixExpression', [ @@ -23,12 +52,29 @@ NormalFunctionCallExpression = collections.namedtuple( 'NormalFunctionCallExpression', [ 'function', - 'arguments', + 'argument_count', + 'argument_items', + ], +) + +NormalArrayVariableInitializationStatement = collections.namedtuple( + 'NormalArrayVariableInitializationStatement', + [ + 'variable', + 'items', + ], +) + +NormalVariableInitializationStatement = collections.namedtuple( + 'NormalVariableInitializationStatement', + [ + 'variable', + 'expression', ], ) -NormalVariableAssignmentStatement = collections.namedtuple( - 'NormalVariableAssignmentStatement', +NormalVariableReassignmentStatement = collections.namedtuple( + 'NormalVariableReassignmentStatement', [ 'variable', 'expression', @@ -42,6 +88,32 @@ NormalExpressionStatement = collections.namedtuple( ], ) +NormalAssignmentStatement = collections.namedtuple( + 'NormalAssignmentStatement', + [ + 'target', + 'expression', + ], +) + +NormalIfElseStatement = collections.namedtuple( + 'NormalIfElseStatement', + [ + 'condition_expression', + 'if_statements', + 'else_statements', + ], +) + +NormalFunctionDefinitionStatement = collections.namedtuple( + 'NormalFunctionDefinitionStatement', + [ + 'name', + 'argument_name_list', + 'statement_list', + ], +) + NormalProgram = collections.namedtuple( 'NormalProgram', [ @@ -52,6 +124,18 @@ NormalProgram = collections.namedtuple( def fake_normalization(counter, thing): return (counter, (), thing) +def normalize_integer_literal_expression(counter, expression): + # TODO Store this in a C variable + return (counter, (), NormalIntegerLiteralExpression(integer=expression.integer)) + +def normalize_string_literal_expression(counter, expression): + # TODO Store this in a C variable + return (counter, (), NormalStringLiteralExpression(string=expression.string)) + +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) @@ -65,7 +149,7 @@ def normalize_function_call_expression(counter, expression): prestatements.append(s) variable = '${}'.format(counter) - prestatements.append(NormalVariableAssignmentStatement( + prestatements.append(NormalVariableInitializationStatement( variable=variable, expression=normalized_argument, )) @@ -74,12 +158,29 @@ def normalize_function_call_expression(counter, expression): )) 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, + ) + + for ps in function_prestatements: + prestatements.append(ps) + return ( counter, tuple(prestatements), NormalFunctionCallExpression( - expression.function, # TODO Normalize the function - arguments=tuple(arguments), + function=function_expression, + argument_count=len(arguments), + argument_items=NormalVariableExpression(variable=arguments_variable), ), ) @@ -93,11 +194,11 @@ def normalize_basic_infix_operation(counter, expression): counter += 1 root_prestatements = ( - NormalVariableAssignmentStatement( + NormalVariableInitializationStatement( variable=left_variable, expression=left_expression, ), - NormalVariableAssignmentStatement( + NormalVariableInitializationStatement( variable=right_variable, expression=right_expression, ), @@ -130,11 +231,11 @@ def normalize_comparison_expression(counter, expression): counter += 1 root_prestatements = ( - NormalVariableAssignmentStatement( + NormalVariableInitializationStatement( variable=left_variable, expression=left_expression, ), - NormalVariableAssignmentStatement( + NormalVariableInitializationStatement( variable=right_variable, expression=right_expression, ), @@ -178,8 +279,39 @@ def normalize_comparison_expression(counter, expression): return (counter, result_prestatements, result_expression) def normalize_boolean_expression(counter, expression): - # TODO Unfake this - return fake_normalization(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, + left_prestatements + (if_else_prestatment, if_else_statement), + NormalVariableExpression(variable=result_variable), + ) + def normalize_infix_expression(counter, expression): return { @@ -190,20 +322,37 @@ def normalize_infix_expression(counter, 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)), + ) + 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: fake_normalization, - parsing.FurNegationExpression: fake_normalization, # TODO Don't fake this - parsing.FurParenthesizedExpression: fake_normalization, # TODO Don't fake this - parsing.FurStringLiteralExpression: fake_normalization, - parsing.FurSymbolExpression: fake_normalization, + parsing.FurIntegerLiteralExpression: normalize_integer_literal_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 Verify all expression types are supported and just call normalize_expression counter, prestatements, normalized = { parsing.FurFunctionCallExpression: normalize_function_call_expression, + parsing.FurSymbolExpression: normalize_expression, + parsing.FurInfixExpression: normalize_expression, + parsing.FurIntegerLiteralExpression: normalize_expression, }[type(statement.expression)](counter, statement.expression) return ( @@ -212,22 +361,47 @@ 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 ( + 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.FurAssignmentStatement: fake_normalization, + parsing.FurFunctionDefinitionStatement: normalize_function_definition_statement, }[type(statement)](counter, statement) -def normalize(program): +@util.force_generator(tuple) +def normalize_statement_list(statement_list): counter = 0 - statement_list = [] - for statement in program.statement_list: + for statement in statement_list: counter, prestatements, normalized = normalize_statement(counter, statement) for s in prestatements: - statement_list.append(s) - statement_list.append(normalized) + yield s + yield normalized + +def normalize(program): return NormalProgram( - statement_list=statement_list, + statement_list=normalize_statement_list(program.statement_list), )