From: David Kerkeslager Date: Tue, 8 Aug 2017 05:29:14 +0000 (-0400) Subject: Some minor refactoring and added a (currently trivial) normalization step X-Git-Url: https://code.kerkeslager.com/?p=fur;a=commitdiff_plain;h=ce4ef136c1e6585c3e780932f3411b71a78c272b Some minor refactoring and added a (currently trivial) normalization step --- diff --git a/generation.py b/generation.py index 26945a2..816ebc9 100644 --- a/generation.py +++ b/generation.py @@ -28,12 +28,12 @@ def generate_symbol_expression(c_symbol_expression): c_symbol_expression.symbol, ) -def generate_expression(c_argument): - if isinstance(c_argument, transformation.CNegationExpression): - return generate_negation_expression(c_argument) +def generate_expression(expression): + if isinstance(expression, transformation.CNegationExpression): + return generate_negation_expression(expression) - if isinstance(c_argument, transformation.CFunctionCallExpression): - return generate_function_call(c_argument) + if isinstance(expression, transformation.CFunctionCallExpression): + return generate_function_call(expression) LITERAL_TYPE_MAPPING = { transformation.CIntegerLiteral: generate_integer_literal, @@ -42,17 +42,17 @@ def generate_expression(c_argument): transformation.CSymbolExpression: generate_symbol_expression, } - if type(c_argument) in LITERAL_TYPE_MAPPING: - return LITERAL_TYPE_MAPPING[type(c_argument)](c_argument) + if type(expression) in LITERAL_TYPE_MAPPING: + return LITERAL_TYPE_MAPPING[type(expression)](expression) - if isinstance(c_argument, transformation.CFunctionCallForFurInfixOperator): + if isinstance(expression, transformation.CFunctionCallForFurInfixOperator): return 'builtin${}({}, {})'.format( - c_argument.name, - generate_expression(c_argument.left), - generate_expression(c_argument.right), + expression.name, + generate_expression(expression.left), + generate_expression(expression.right), ) - raise Exception('Could not handle expresssion "{}"'.format(c_argument)) + raise Exception('Could not handle expresssion "{}"'.format(expression)) def generate_negation_expression(c_negation_expression): return 'builtin$negate({})'.format( @@ -82,14 +82,14 @@ def generate_statement(statement): return generate_expression_statement(statement) -def generate(c_program): +def generate(program): template = ENV.get_template('program.c') return template.render( - builtins=list(sorted(c_program.builtin_set)), - statements=[generate_statement(statement) for statement in c_program.statements], - standard_libraries=list(sorted(c_program.standard_libraries)), - string_literal_list=c_program.string_literal_list, - symbol_list=c_program.symbol_list, + builtins=list(sorted(program.builtin_set)), + statements=[generate_statement(statement) for statement in program.statements], + standard_libraries=list(sorted(program.standard_libraries)), + string_literal_list=program.string_literal_list, + symbol_list=program.symbol_list, ) if __name__ == '__main__': diff --git a/main.py b/main.py index c2592c6..be48e78 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,7 @@ import sys import generation +import normalization import parsing import tokenization import transformation @@ -12,7 +13,8 @@ with open(source_path, 'r') as f: tokens = tokenization.tokenize(source) parsed = parsing.parse(tokens) -transformed = transformation.transform(parsed) +normalized = normalization.normalize(parsed) +transformed = transformation.transform(normalized) generated = generation.generate(transformed) assert source_path.endswith('.fur') diff --git a/normalization.py b/normalization.py new file mode 100644 index 0000000..1cddaed --- /dev/null +++ b/normalization.py @@ -0,0 +1,19 @@ +import collections + +NormalProgram = collections.namedtuple( + 'NormalProgram', + [ + 'statement_list', + ], +) + +def flatten(iterable): + return tuple(item for internal in iterable for item in internal) + +def normalize_statement(statement): + return (statement,) + +def normalize(program): + return NormalProgram( + statement_list=flatten(normalize_statement(s) for s in program.statement_list), + ) diff --git a/parsing.py b/parsing.py index a7dd838..aa4f427 100644 --- a/parsing.py +++ b/parsing.py @@ -244,6 +244,13 @@ FurFunctionCallExpression = collections.namedtuple( ], ) +FurExpressionStatement = collections.namedtuple( + 'FurExpressionStatement', + [ + 'expression', + ], +) + FurAssignmentStatement = collections.namedtuple( 'FurAssignmentStatement', [ @@ -288,6 +295,16 @@ def _function_call_expression_parser(index, tokens): _expression_parser = _or_level_expression_parser +def _expression_statement_parser(index, tokens): + failure = (False, index, None) + + success, index, expression = _expression_parser(index, tokens) + + if not success: + return failure + + return (True, index, FurExpressionStatement(expression=expression)) + def _assignment_statement_parser(index, tokens): # TODO Use a FurSymbolExpression for the target? Maybe this is actually not a good idea failure = (False, index, None) @@ -320,7 +337,7 @@ def _statement_parser(index, tokens): return _or_parser( _assignment_statement_parser, - _expression_parser, + _expression_statement_parser, )(index, tokens) def _program_formatter(statement_list): diff --git a/transformation.py b/transformation.py index b75b3a0..98398f8 100644 --- a/transformation.py +++ b/transformation.py @@ -221,10 +221,15 @@ def transform_function_call_expression(accumulators, function_call): raise Exception() +def transform_expression_statement(accumulators, statement): + return { + parsing.FurFunctionCallExpression: transform_function_call_expression, + }[type(statement.expression)](accumulators, statement.expression) + def transform_statement(accumulators, statement): return { parsing.FurAssignmentStatement: transform_assignment_statement, - parsing.FurFunctionCallExpression: transform_function_call_expression, + parsing.FurExpressionStatement: transform_expression_statement, }[type(statement)](accumulators, statement) @@ -244,19 +249,19 @@ def transform(program): string_literal_list=[], ) - c_statements = [ + statement_list = [ transform_statement(accumulators, statement) for statement in program.statement_list ] - standard_libraries = set() + standard_library_set = set() for builtin in accumulators.builtin_set: for standard_library in BUILTINS[builtin]: - standard_libraries.add(standard_library) + standard_library_set.add(standard_library) return CProgram( builtin_set=accumulators.builtin_set, - statements=c_statements, - standard_libraries=standard_libraries, + statements=statement_list, + standard_libraries=standard_library_set, string_literal_list=accumulators.string_literal_list, symbol_list=accumulators.symbol_list, )