From: David Kerkeslager Date: Thu, 18 Jul 2019 01:57:16 +0000 (-0400) Subject: Add crossplatform IR generation up to the point of if/else statements X-Git-Url: https://code.kerkeslager.com/?a=commitdiff_plain;h=6c9a12a330ef68ef17c50b12dbc99732891d23a1;p=fur Add crossplatform IR generation up to the point of if/else statements --- diff --git a/crossplatform_ir_generation.py b/crossplatform_ir_generation.py new file mode 100644 index 0000000..d753103 --- /dev/null +++ b/crossplatform_ir_generation.py @@ -0,0 +1,170 @@ +import collections + +import conversion + +CIRProgram = collections.namedtuple( + 'CIRProgram', + ( + 'entry_list', + ), +) + +CIREntry = collections.namedtuple( + 'CIREntry', + ( + 'name', + 'instruction_list', + ), +) + +CIRInstruction = collections.namedtuple( + 'CIRInstruction', + ( + 'instruction', + 'argument', + ), +) + +def generate_integer_literal(integer): + return integer + +def generate_string_literal(string): + return '"{}"'.format(string) + +def generate_symbol_literal(symbol): + return 'sym({})'.format(symbol) + +def generate_function_call_expression(expression): + return generate_expression(expression.function_expression) + ( + CIRInstruction( + instruction='call', + argument=expression.argument_count, + ), + ) + +def generate_integer_literal_expression(expression): + return (CIRInstruction( + instruction='push_value', + argument=generate_integer_literal(expression.integer), + ),) + +def generate_string_literal_expression(expression): + return (CIRInstruction( + instruction='push_value', + argument=generate_string_literal(expression.string), + ),) + +def generate_symbol_expression(expression): + return (CIRInstruction( + instruction='push', + argument=generate_symbol_literal(expression.symbol), + ),) + +def generate_variable_expression(expression): + return (CIRInstruction( + instruction='push', + argument=generate_symbol_literal(expression.variable), + ),) + +def generate_expression(expression): + return { + conversion.CPSFunctionCallExpression: generate_function_call_expression, + conversion.CPSIntegerLiteralExpression: generate_integer_literal_expression, + conversion.CPSStringLiteralExpression: generate_string_literal_expression, + conversion.CPSSymbolExpression: generate_symbol_expression, + conversion.CPSVariableExpression: generate_variable_expression, + }[type(expression)](expression) + +def generate_expression_statement(statement): + return ( + (), + generate_expression(statement.expression) + ( + CIRInstruction( + instruction='drop', + argument=None, + ), + ), + ) + +def generate_if_else_statement(statement): + import ipdb; ipdb.set_trace() + +def generate_assignment_statement(statement): + return ( + (), + generate_expression(statement.expression) + ( + CIRInstruction( + instruction='pop', + argument=generate_symbol_literal(statement.target), + ), + ), + ) + +def generate_push_statement(statement): + return ( + (), + generate_expression(statement.expression), + ) + +def generate_variable_initialization_statement(statement): + return ( + (), + generate_expression(statement.expression) + ( + CIRInstruction( + instruction='pop', + argument=generate_symbol_literal(statement.variable), + ), + ), + ) + +def generate_statement(statement): + return { + conversion.CPSAssignmentStatement: generate_assignment_statement, + conversion.CPSExpressionStatement: generate_expression_statement, + conversion.CPSIfElseStatement: generate_if_else_statement, + conversion.CPSPushStatement: generate_push_statement, + conversion.CPSVariableInitializationStatement: generate_variable_initialization_statement, + }[type(statement)](statement) + +def generate(converted): + referenced_entry_list_list = [] + instruction_list_list = [] + + for statement in converted.statement_list: + referenced_entry_list, instruction_list = generate_statement(statement) + referenced_entry_list_list.append(referenced_entry_list) + instruction_list_list.append(instruction_list) + + return CIRProgram( + entry_list=tuple( + entry + for referenced_entry_list in referenced_entry_list_list + for entry in referenced_entry_list + ) + (CIREntry( + name='__main__', + instruction_list=tuple( + instruction + for instruction_list in instruction_list_list + for instruction in instruction_list + ), + ),), + ) + +def output(program): + entry_outputs = [] + + for entry in program.entry_list: + statement_outputs = [] + + for instruction in entry.instruction_list: + statement_outputs.append(' {} {}'.format( + instruction.instruction, + instruction.argument, + )) + + entry_outputs.append('{}:\n{}'.format( + entry.name, + '\n'.join(statement_outputs), + )) + + return '\n\n'.join(entry_outputs) diff --git a/main.py b/main.py index c649a0b..3045554 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,7 @@ import sys import conversion +import crossplatform_ir_generation import desugaring import generation import normalization @@ -18,6 +19,8 @@ parsed = parsing.parse(tokens) desugared = desugaring.desugar(parsed) normalized = normalization.normalize(desugared) converted = conversion.convert(normalized) + +# This is the C generation path transformed = transformation.transform(converted) generated = generation.generate(transformed) @@ -26,3 +29,8 @@ destination_path = source_path + '.c' with open(destination_path, 'w') as f: f.write(generated) + +# This is the crossplatform IR generation path +crossplatform_ir = crossplatform_ir_generation.generate(converted) +outputted = crossplatform_ir_generation.output(crossplatform_ir) +print(outputted)