Add crossplatform IR generation up to the point of if/else statements
[fur] / crossplatform_ir_generation.py
diff --git a/crossplatform_ir_generation.py b/crossplatform_ir_generation.py
new file mode 100644 (file)
index 0000000..d753103
--- /dev/null
@@ -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)