Add crossplatform IR generation up to the point of if/else statements
[fur] / crossplatform_ir_generation.py
1 import collections
2
3 import conversion
4
5 CIRProgram = collections.namedtuple(
6     'CIRProgram',
7     (
8         'entry_list',
9     ),
10 )
11
12 CIREntry = collections.namedtuple(
13     'CIREntry',
14     (
15         'name',
16         'instruction_list',
17     ),
18 )
19
20 CIRInstruction = collections.namedtuple(
21     'CIRInstruction',
22     (
23         'instruction',
24         'argument',
25     ),
26 )
27
28 def generate_integer_literal(integer):
29     return integer
30
31 def generate_string_literal(string):
32     return '"{}"'.format(string)
33
34 def generate_symbol_literal(symbol):
35     return 'sym({})'.format(symbol)
36
37 def generate_function_call_expression(expression):
38     return generate_expression(expression.function_expression) + (
39         CIRInstruction(
40             instruction='call',
41             argument=expression.argument_count,
42         ),
43     )
44
45 def generate_integer_literal_expression(expression):
46     return (CIRInstruction(
47         instruction='push_value',
48         argument=generate_integer_literal(expression.integer),
49     ),)
50
51 def generate_string_literal_expression(expression):
52     return (CIRInstruction(
53         instruction='push_value',
54         argument=generate_string_literal(expression.string),
55     ),)
56
57 def generate_symbol_expression(expression):
58     return (CIRInstruction(
59         instruction='push',
60         argument=generate_symbol_literal(expression.symbol),
61     ),)
62
63 def generate_variable_expression(expression):
64     return (CIRInstruction(
65         instruction='push',
66         argument=generate_symbol_literal(expression.variable),
67     ),)
68
69 def generate_expression(expression):
70     return {
71         conversion.CPSFunctionCallExpression: generate_function_call_expression,
72         conversion.CPSIntegerLiteralExpression: generate_integer_literal_expression,
73         conversion.CPSStringLiteralExpression: generate_string_literal_expression,
74         conversion.CPSSymbolExpression: generate_symbol_expression,
75         conversion.CPSVariableExpression: generate_variable_expression,
76     }[type(expression)](expression)
77
78 def generate_expression_statement(statement):
79     return (
80         (),
81         generate_expression(statement.expression) + (
82             CIRInstruction(
83                 instruction='drop',
84                 argument=None,
85             ),
86         ),
87     )
88
89 def generate_if_else_statement(statement):
90     import ipdb; ipdb.set_trace()
91
92 def generate_assignment_statement(statement):
93     return (
94         (),
95         generate_expression(statement.expression) + (
96             CIRInstruction(
97                 instruction='pop',
98                 argument=generate_symbol_literal(statement.target),
99             ),
100         ),
101     )
102
103 def generate_push_statement(statement):
104     return (
105         (),
106         generate_expression(statement.expression),
107     )
108
109 def generate_variable_initialization_statement(statement):
110     return (
111         (),
112         generate_expression(statement.expression) + (
113             CIRInstruction(
114                 instruction='pop',
115                 argument=generate_symbol_literal(statement.variable),
116             ),
117         ),
118     )
119
120 def generate_statement(statement):
121     return {
122         conversion.CPSAssignmentStatement: generate_assignment_statement,
123         conversion.CPSExpressionStatement: generate_expression_statement,
124         conversion.CPSIfElseStatement: generate_if_else_statement,
125         conversion.CPSPushStatement: generate_push_statement,
126         conversion.CPSVariableInitializationStatement: generate_variable_initialization_statement,
127     }[type(statement)](statement)
128
129 def generate(converted):
130     referenced_entry_list_list = []
131     instruction_list_list = []
132
133     for statement in converted.statement_list:
134         referenced_entry_list, instruction_list = generate_statement(statement)
135         referenced_entry_list_list.append(referenced_entry_list)
136         instruction_list_list.append(instruction_list)
137
138     return CIRProgram(
139         entry_list=tuple(
140             entry
141             for referenced_entry_list in referenced_entry_list_list
142             for entry in referenced_entry_list
143         ) + (CIREntry(
144             name='__main__',
145             instruction_list=tuple(
146                 instruction
147                 for instruction_list in instruction_list_list
148                 for instruction in instruction_list
149             ),
150         ),),
151     )
152
153 def output(program):
154     entry_outputs = []
155
156     for entry in program.entry_list:
157         statement_outputs = []
158
159         for instruction in entry.instruction_list:
160             statement_outputs.append('    {} {}'.format(
161                 instruction.instruction,
162                 instruction.argument,
163             ))
164
165         entry_outputs.append('{}:\n{}'.format(
166             entry.name,
167             '\n'.join(statement_outputs),
168         ))
169
170     return '\n\n'.join(entry_outputs)