From aefed436c89745b3516e2e84d4d43a2bb2c0ed5d Mon Sep 17 00:00:00 2001 From: David Kerkeslager Date: Tue, 8 Aug 2017 02:53:25 -0400 Subject: [PATCH] Add a CExpressionStatement to wrap expressions instead of passing them into statement functions --- generation.py | 28 +++++++++++----- normalization.py | 83 ++++++++++++++++++++++++++++++++++++++++++++--- transformation.py | 56 ++++++++++++++++++++++++++++---- 3 files changed, 147 insertions(+), 20 deletions(-) diff --git a/generation.py b/generation.py index 816ebc9..92d07be 100644 --- a/generation.py +++ b/generation.py @@ -28,6 +28,9 @@ def generate_symbol_expression(c_symbol_expression): c_symbol_expression.symbol, ) +def generate_variable_expression(expression): + return expression.variable + def generate_expression(expression): if isinstance(expression, transformation.CNegationExpression): return generate_negation_expression(expression) @@ -52,7 +55,9 @@ def generate_expression(expression): generate_expression(expression.right), ) - raise Exception('Could not handle expresssion "{}"'.format(expression)) + return { + transformation.CVariableExpression: generate_variable_expression, + }[type(expression)](expression) def generate_negation_expression(c_negation_expression): return 'builtin$negate({})'.format( @@ -65,22 +70,29 @@ def generate_function_call(c_function_call): ', '.join(generate_expression(argument) for argument in c_function_call.arguments), ) -def generate_expression_statement(c_function_call_statement): +def generate_expression_statement(statement): # TODO Do we need to garbage collect the results of arbitrary statements? - return '{};'.format(generate_expression(c_function_call_statement)) + return '{};'.format(generate_expression(statement.expression)) -def generate_assignment_statement(c_assignment_statement): +def generate_symbol_assignment_statement(c_assignment_statement): return 'Environment_set(environment, SYMBOL_LIST[{}] /* symbol: {} */, {});'.format( c_assignment_statement.target_symbol_list_index, c_assignment_statement.target, generate_expression(c_assignment_statement.expression), ) -def generate_statement(statement): - if isinstance(statement, transformation.CAssignmentStatement): - return generate_assignment_statement(statement) +def generate_variable_assignment_statement(statement): + return 'Object {} = {};'.format( + statement.variable, + generate_expression(statement.expression), + ) - return generate_expression_statement(statement) +def generate_statement(statement): + return { + transformation.CSymbolAssignmentStatement: generate_symbol_assignment_statement, + transformation.CExpressionStatement: generate_expression_statement, + transformation.CVariableAssignmentStatement: generate_variable_assignment_statement, + }[type(statement)](statement) def generate(program): template = ENV.get_template('program.c') diff --git a/normalization.py b/normalization.py index 1cddaed..8582bc5 100644 --- a/normalization.py +++ b/normalization.py @@ -1,5 +1,37 @@ import collections +import parsing + +NormalVariableExpression = collections.namedtuple( + 'NormalVariableExpression', + [ + 'variable', + ], +) + +NormalVariableAssignmentStatement = collections.namedtuple( + 'NormalVariableAssignmentStatement', + [ + 'variable', + 'expression', + ], +) + +NormalFunctionCallExpression = collections.namedtuple( + 'NormalFunctionCallExpression', + [ + 'function', + 'arguments', + ], +) + +NormalExpressionStatement = collections.namedtuple( + 'NormalExpressionStatement', + [ + 'expression', + ], +) + NormalProgram = collections.namedtuple( 'NormalProgram', [ @@ -7,13 +39,54 @@ NormalProgram = collections.namedtuple( ], ) -def flatten(iterable): - return tuple(item for internal in iterable for item in internal) +def normalize_function_call_expression(counter, expression): + prestatements = [] + arguments = [] + + for argument in expression.arguments: + variable = '${}'.format(counter) + prestatements.append(NormalVariableAssignmentStatement( + variable=variable, + expression=argument, # TODO Normalize each argument + )) + arguments.append(NormalVariableExpression( + variable=variable, + )) + counter += 1 -def normalize_statement(statement): - return (statement,) + return ( + counter, + tuple(prestatements), + NormalFunctionCallExpression( + expression.function, # TODO Normalize the function + arguments=tuple(arguments), + ), + ) + +def normalize_statement(counter, statement): + if isinstance(statement, parsing.FurExpressionStatement): + counter, prestatements, normalized = { + parsing.FurFunctionCallExpression: normalize_function_call_expression, + }[type(statement.expression)](counter, statement.expression) + + return ( + counter, + prestatements, + NormalExpressionStatement(expression=normalized), + ) + + return (counter, (), statement) def normalize(program): + counter = 0 + statement_list = [] + + for statement in program.statement_list: + counter, prestatements, normalized = normalize_statement(counter, statement) + for s in prestatements: + statement_list.append(s) + statement_list.append(normalized) + return NormalProgram( - statement_list=flatten(normalize_statement(s) for s in program.statement_list), + statement_list=statement_list, ) diff --git a/transformation.py b/transformation.py index 98398f8..c3ced00 100644 --- a/transformation.py +++ b/transformation.py @@ -1,5 +1,6 @@ import collections +import normalization import parsing CIntegerLiteral = collections.namedtuple( @@ -24,6 +25,13 @@ CConstantExpression = collections.namedtuple( ], ) +CVariableExpression = collections.namedtuple( + 'CVariableExpression', + [ + 'variable', + ], +) + CSymbolExpression = collections.namedtuple( 'CSymbolExpression', [ @@ -56,8 +64,8 @@ CFunctionCallExpression = collections.namedtuple( ], ) -CAssignmentStatement = collections.namedtuple( - 'CAssignmentStatement', +CSymbolAssignmentStatement = collections.namedtuple( + 'CSymbolAssignmentStatement', [ 'target', 'target_symbol_list_index', @@ -65,6 +73,21 @@ CAssignmentStatement = collections.namedtuple( ], ) +CVariableAssignmentStatement = collections.namedtuple( + 'CVariableAssignmentStatement', + [ + 'variable', + 'expression', + ], +) + +CExpressionStatement = collections.namedtuple( + 'CExpressionStatement', + [ + 'expression', + ], +) + CProgram = collections.namedtuple( 'CProgram', [ @@ -124,6 +147,9 @@ BUILTINS = { 'true': [], } +def transform_variable_expression(accumulators, expression): + return CVariableExpression(variable=expression.variable) + def transform_expression(accumulators, expression): if isinstance(expression, parsing.FurParenthesizedExpression): # Parentheses can be removed because everything in the C output is explicitly parenthesized @@ -185,14 +211,17 @@ def transform_expression(accumulators, expression): right=transform_expression(accumulators, expression.right), ) - raise Exception('Could not transform expression "{}"'.format(expression)) + # TODO Handle all possible types in this form + return { + normalization.NormalVariableExpression: transform_variable_expression, + }[type(expression)](accumulators, expression) -def transform_assignment_statement(accumulators, assignment_statement): +def transform_symbol_assignment_statement(accumulators, assignment_statement): # TODO Check that target is not a builtin if assignment_statement.target not in accumulators.symbol_list: accumulators.symbol_list.append(assignment_statement.target) - return CAssignmentStatement( + return CSymbolAssignmentStatement( target=assignment_statement.target, target_symbol_list_index=accumulators.symbol_list.index(assignment_statement.target), expression=transform_expression( @@ -222,14 +251,27 @@ def transform_function_call_expression(accumulators, function_call): raise Exception() def transform_expression_statement(accumulators, statement): - return { + expression = { parsing.FurFunctionCallExpression: transform_function_call_expression, + normalization.NormalFunctionCallExpression: transform_function_call_expression, }[type(statement.expression)](accumulators, statement.expression) + return CExpressionStatement( + expression=expression, + ) + +def transform_variable_assignment_statement(accumulators, statement): + return CVariableAssignmentStatement( + variable=statement.variable, + expression=transform_expression(accumulators, statement.expression), + ) + def transform_statement(accumulators, statement): return { - parsing.FurAssignmentStatement: transform_assignment_statement, + parsing.FurAssignmentStatement: transform_symbol_assignment_statement, parsing.FurExpressionStatement: transform_expression_statement, + normalization.NormalVariableAssignmentStatement: transform_variable_assignment_statement, + normalization.NormalExpressionStatement: transform_expression_statement, }[type(statement)](accumulators, statement) -- 2.20.1