X-Git-Url: https://code.kerkeslager.com/?p=fur;a=blobdiff_plain;f=crossplatform_ir_generation.py;h=54b296eebc4680e9ede70195072e4b71b639c49b;hp=d75310334430fe1ea9a555e5fc33951c67d12a3a;hb=64ef22e135f7c790f0cd80956d8bdf7fa0268148;hpb=6c9a12a330ef68ef17c50b12dbc99732891d23a1 diff --git a/crossplatform_ir_generation.py b/crossplatform_ir_generation.py index d753103..54b296e 100644 --- a/crossplatform_ir_generation.py +++ b/crossplatform_ir_generation.py @@ -2,6 +2,9 @@ import collections import conversion +def flatten(xses): + return tuple(x for xs in xses for x in xs) + CIRProgram = collections.namedtuple( 'CIRProgram', ( @@ -9,11 +12,10 @@ CIRProgram = collections.namedtuple( ), ) -CIREntry = collections.namedtuple( - 'CIREntry', +CIRLabel = collections.namedtuple( + 'CIRLabel', ( - 'name', - 'instruction_list', + 'label', ), ) @@ -34,137 +36,239 @@ def generate_string_literal(string): def generate_symbol_literal(symbol): return 'sym({})'.format(symbol) -def generate_function_call_expression(expression): - return generate_expression(expression.function_expression) + ( +def generate_function_call_expression(counters, expression): + referenced_entry_list, instruction_list = generate_expression( + counters, + expression.function_expression, + ) + + instruction_list += ( CIRInstruction( instruction='call', argument=expression.argument_count, ), ) -def generate_integer_literal_expression(expression): - return (CIRInstruction( + return referenced_entry_list, instruction_list + +def generate_integer_literal_expression(counters, expression): + referenced_entry_list = () + instruction_list = (CIRInstruction( instruction='push_value', argument=generate_integer_literal(expression.integer), ),) -def generate_string_literal_expression(expression): - return (CIRInstruction( + return referenced_entry_list, instruction_list + +def generate_lambda_expression(counters, expression): + if expression.name is None or 'lambda' in expression.name.lower(): + import ipdb; ipdb.set_trace() + + name_counter = counters.get(expression.name, 0) + counters[expression.name] = name_counter + 1 + label = '{}${}'.format(expression.name, name_counter) + + for argument_name in expression.argument_name_list: + import ipdb; ipdb.set_trace() + + referenced_entry_list_list = [] + instruction_list_list = [] + + for statement in expression.statement_list: + referenced_entry_list, instruction_list = generate_statement(counters, statement) + referenced_entry_list_list.append(referenced_entry_list) + instruction_list_list.append(instruction_list) + + referenced_entry_list_list.append( + (CIRLabel(label=label),) + flatten(instruction_list_list), + ) + + instruction_list = ( + CIRInstruction(instruction='close', argument=label), + ) + + return flatten(referenced_entry_list_list), instruction_list + +def generate_string_literal_expression(counters, expression): + referenced_entry_list = () + instruction_list = (CIRInstruction( instruction='push_value', argument=generate_string_literal(expression.string), ),) -def generate_symbol_expression(expression): - return (CIRInstruction( + return referenced_entry_list, instruction_list + +def generate_symbol_expression(counters, expression): + referenced_entry_list = () + instruction_list = (CIRInstruction( instruction='push', argument=generate_symbol_literal(expression.symbol), ),) -def generate_variable_expression(expression): - return (CIRInstruction( + return referenced_entry_list, instruction_list + +def generate_variable_expression(counters, expression): + referenced_entry_list = () + instruction_list = (CIRInstruction( instruction='push', argument=generate_symbol_literal(expression.variable), ),) -def generate_expression(expression): + return referenced_entry_list, instruction_list + +def generate_expression(counters, expression): return { conversion.CPSFunctionCallExpression: generate_function_call_expression, conversion.CPSIntegerLiteralExpression: generate_integer_literal_expression, + conversion.CPSLambdaExpression: generate_lambda_expression, conversion.CPSStringLiteralExpression: generate_string_literal_expression, conversion.CPSSymbolExpression: generate_symbol_expression, conversion.CPSVariableExpression: generate_variable_expression, - }[type(expression)](expression) + }[type(expression)](counters, expression) -def generate_expression_statement(statement): - return ( - (), - generate_expression(statement.expression) + ( - CIRInstruction( - instruction='drop', - argument=None, - ), +def generate_expression_statement(counters, statement): + referenced_entry_list, instruction_list = generate_expression( + counters, + statement.expression, + ) + + instruction_list += ( + CIRInstruction( + instruction='drop', + argument=None, ), ) -def generate_if_else_statement(statement): - import ipdb; ipdb.set_trace() + return referenced_entry_list, instruction_list + +def generate_if_else_statement(counters, statement): + if_counter = counters['if'] + counters['if'] += 1 + + referenced_entry_list_list = [] + + if_instruction_list_list = [] + for if_statement in statement.if_statement_list: + referenced_entry_list, instruction_list = generate_statement(counters, if_statement) + referenced_entry_list_list.append(referenced_entry_list) + if_instruction_list_list.append(instruction_list) + + else_instruction_list_list = [] + + for else_statement in statement.else_statement_list: + referenced_entry_list, instruction_list = generate_statement(counters, else_statement) + referenced_entry_list_list.append(referenced_entry_list) + else_instruction_list_list.append(instruction_list) + + if_label = '__if${}__'.format(if_counter) + else_label = '__else${}__'.format(if_counter) + endif_label = '__endif${}__'.format(if_counter) -def generate_assignment_statement(statement): - return ( - (), - generate_expression(statement.expression) + ( + instruction_list = ( + referenced_entry_list_list, + generate_expression(counters, statement.condition_expression) + ( + CIRInstruction( + instruction='jump_if_false', + argument=else_label, + ), + CIRLabel(label=if_label), + ) + flatten(if_instruction_list_list) + ( CIRInstruction( - instruction='pop', - argument=generate_symbol_literal(statement.target), + instruction='jump', + argument=endif_label, ), + CIRLabel(label=else_label), + ) + flatten(else_instruction_list_list) + ( + CIRLabel(label=endif_label), ), ) -def generate_push_statement(statement): - return ( - (), - generate_expression(statement.expression), + return flatten(referenced_entry_list_list), instruction_list + +def generate_assignment_statement(counters, statement): + referenced_entry_list, instruction_list = generate_expression( + counters, + statement.expression, ) -def generate_variable_initialization_statement(statement): - return ( - (), - generate_expression(statement.expression) + ( - CIRInstruction( - instruction='pop', - argument=generate_symbol_literal(statement.variable), - ), + instruction_list += ( + CIRInstruction( + instruction='pop', + argument=generate_symbol_literal(statement.target), + ), + ) + + return referenced_entry_list, instruction_list + +def generate_push_statement(counters, statement): + return generate_expression(counters, statement.expression) + +def generate_variable_initialization_statement(counters, statement): + referenced_entry_list, instruction_list = generate_expression( + counters, + statement.expression, + ) + + instruction_list += ( + CIRInstruction( + instruction='pop', + argument=generate_symbol_literal(statement.variable), ), ) -def generate_statement(statement): + return referenced_entry_list, instruction_list + +def generate_variable_reassignment_statement(counters, statement): + referenced_entry_list, instruction_list = generate_expression( + counters, + statement.expression, + ) + + instruction_list += ( + CIRInstruction( + instruction='pop', + argument=generate_symbol_literal(statement.variable), + ), + ) + + return referenced_entry_list, instruction_list + +def generate_statement(counters, 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) + conversion.CPSVariableReassignmentStatement: generate_variable_reassignment_statement, + }[type(statement)](counters, statement) def generate(converted): referenced_entry_list_list = [] instruction_list_list = [] + counters = { + 'if': 0, + } for statement in converted.statement_list: - referenced_entry_list, instruction_list = generate_statement(statement) + referenced_entry_list, instruction_list = generate_statement(counters, 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 - ), - ),), + entry_list=( + CIRLabel(label='__main__'), + ) + flatten(referenced_entry_list_list) + flatten(instruction_list_list), ) def output(program): - entry_outputs = [] + lines = [] for entry in program.entry_list: - statement_outputs = [] - - for instruction in entry.instruction_list: - statement_outputs.append(' {} {}'.format( - instruction.instruction, - instruction.argument, - )) + if isinstance(entry, CIRInstruction): + lines.append(' {} {}'.format(entry.instruction, entry.argument)) - entry_outputs.append('{}:\n{}'.format( - entry.name, - '\n'.join(statement_outputs), - )) + if isinstance(entry, CIRLabel): + lines.append('\n{}:'.format(entry.label)) - return '\n\n'.join(entry_outputs) + return '\n'.join(lines).lstrip()