Add crossplatform IR generation up to the point of if/else statements
authorDavid Kerkeslager <kerkeslager@gmail.com>
Thu, 18 Jul 2019 01:57:16 +0000 (21:57 -0400)
committerDavid Kerkeslager <kerkeslager@gmail.com>
Thu, 18 Jul 2019 01:57:16 +0000 (21:57 -0400)
crossplatform_ir_generation.py [new file with mode: 0644]
main.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)
diff --git a/main.py b/main.py
index c649a0b..3045554 100644 (file)
--- 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)