6 return tuple(x for xs in xses for x in xs)
8 CIRProgram = collections.namedtuple(
15 CIRLabel = collections.namedtuple(
22 CIRInstruction = collections.namedtuple(
30 def generate_integer_literal(integer):
33 def generate_string_literal(string):
34 return '"{}"'.format(string)
36 def generate_symbol_literal(symbol):
37 return 'sym({})'.format(symbol)
39 def generate_function_call_expression(counters, expression):
40 referenced_entry_list, instruction_list = generate_expression(
42 expression.function_expression,
48 argument=expression.argument_count,
52 return referenced_entry_list, instruction_list
54 def generate_integer_literal_expression(counters, expression):
55 referenced_entry_list = ()
56 instruction_list = (CIRInstruction(
57 instruction='push_value',
58 argument=generate_integer_literal(expression.integer),
61 return referenced_entry_list, instruction_list
63 def generate_lambda_expression(counters, expression):
64 if expression.name is None or 'lambda' in expression.name.lower():
65 import ipdb; ipdb.set_trace()
67 name_counter = counters.get(expression.name, 0)
68 counters[expression.name] = name_counter + 1
69 label = '{}${}'.format(expression.name, name_counter)
71 referenced_entry_list_list = []
72 instruction_list_list = []
74 for statement in expression.statement_list:
75 referenced_entry_list, instruction_list = generate_statement(counters, statement)
76 referenced_entry_list_list.append(referenced_entry_list)
77 instruction_list_list.append(instruction_list)
79 # Pop from the stack in reversed order, because arguments were pushed onto
81 argument_bindings = tuple(
82 CIRInstruction(instruction='pop', argument='sym({})'.format(arg))
83 for arg in reversed(expression.argument_name_list)
86 lambda_body = flatten(instruction_list_list)
87 assert lambda_body[-1].instruction == 'drop'
88 lambda_body = argument_bindings + lambda_body[:-1] + (CIRInstruction(instruction='return', argument=None),)
90 referenced_entry_list_list.append(
91 (CIRLabel(label=label),) + lambda_body,
95 CIRInstruction(instruction='close', argument=label),
98 return flatten(referenced_entry_list_list), instruction_list
100 def generate_list_construct_expression(counters, expression):
101 referenced_entry_list = ()
102 instruction_list = (CIRInstruction(
106 return referenced_entry_list, instruction_list
108 def generate_string_literal_expression(counters, expression):
109 referenced_entry_list = ()
110 instruction_list = (CIRInstruction(
111 instruction='push_value',
112 argument=generate_string_literal(expression.string),
115 return referenced_entry_list, instruction_list
117 def generate_structure_literal_expression(counters, expression):
118 referenced_entry_list = ()
119 instruction_list = (CIRInstruction(
120 instruction='structure',
121 argument=expression.field_count,
124 return referenced_entry_list, instruction_list
126 def generate_symbol_expression(counters, expression):
127 referenced_entry_list = ()
128 instruction_list = (CIRInstruction(
130 argument=generate_symbol_literal(expression.symbol),
133 return referenced_entry_list, instruction_list
135 def generate_symbol_literal_expression(counters, expression):
136 referenced_entry_list = ()
137 instruction_list = (CIRInstruction(
138 instruction='push_value',
139 argument=generate_symbol_literal(expression.symbol),
142 return referenced_entry_list, instruction_list
144 def generate_variable_expression(counters, expression):
145 referenced_entry_list = ()
146 instruction_list = (CIRInstruction(
148 argument=generate_symbol_literal(expression.variable),
151 return referenced_entry_list, instruction_list
153 def generate_expression(counters, expression):
155 conversion.CPSFunctionCallExpression: generate_function_call_expression,
156 conversion.CPSIfElseExpression: generate_if_else_expression,
157 conversion.CPSIntegerLiteralExpression: generate_integer_literal_expression,
158 conversion.CPSLambdaExpression: generate_lambda_expression,
159 conversion.CPSListConstructExpression: generate_list_construct_expression,
160 conversion.CPSStringLiteralExpression: generate_string_literal_expression,
161 conversion.CPSStructureLiteralExpression: generate_structure_literal_expression,
162 conversion.CPSSymbolExpression: generate_symbol_expression,
163 conversion.CPSSymbolLiteralExpression: generate_symbol_literal_expression,
164 conversion.CPSVariableExpression: generate_variable_expression,
165 }[type(expression)](counters, expression)
167 def generate_expression_statement(counters, statement):
168 referenced_entry_list, instruction_list = generate_expression(
170 statement.expression,
173 instruction_list += (
180 return referenced_entry_list, instruction_list
182 def generate_if_else_expression(counters, statement):
183 if_counter = counters['if']
186 referenced_entry_list_list = []
188 condition_referenced_entry_list, condition_instruction_list = generate_expression(
190 statement.condition_expression,
193 if_instruction_list_list = []
194 for if_statement in statement.if_statement_list:
195 referenced_entry_list, instruction_list = generate_statement(counters, if_statement)
196 referenced_entry_list_list.append(referenced_entry_list)
197 if_instruction_list_list.append(instruction_list)
199 if_instruction_list = flatten(if_instruction_list_list)
200 assert if_instruction_list[-1].instruction == 'drop'
201 if_instruction_list = if_instruction_list[:-1]
203 else_instruction_list_list = []
205 for else_statement in statement.else_statement_list:
206 referenced_entry_list, instruction_list = generate_statement(counters, else_statement)
207 referenced_entry_list_list.append(referenced_entry_list)
208 else_instruction_list_list.append(instruction_list)
210 else_instruction_list = flatten(else_instruction_list_list)
211 assert else_instruction_list[-1].instruction == 'drop'
212 else_instruction_list = else_instruction_list[:-1]
214 if_label = '__if${}__'.format(if_counter)
215 else_label = '__else${}__'.format(if_counter)
216 endif_label = '__endif${}__'.format(if_counter)
218 instruction_list = condition_instruction_list + (
220 instruction='jump_if_false',
227 CIRLabel(label=if_label),
228 ) + if_instruction_list + (
231 argument=endif_label,
233 CIRLabel(label=else_label),
234 ) + else_instruction_list + (
235 CIRLabel(label=endif_label),
239 condition_referenced_entry_list + flatten(referenced_entry_list_list),
243 def generate_assignment_statement(counters, statement):
244 referenced_entry_list, instruction_list = generate_expression(
246 statement.expression,
249 instruction_list += (
252 argument=generate_symbol_literal(statement.target),
256 return referenced_entry_list, instruction_list
258 def generate_push_statement(counters, statement):
259 return generate_expression(counters, statement.expression)
261 def generate_variable_initialization_statement(counters, statement):
262 referenced_entry_list, instruction_list = generate_expression(
264 statement.expression,
267 instruction_list += (
270 argument=generate_symbol_literal(statement.variable),
274 return referenced_entry_list, instruction_list
276 def generate_statement(counters, statement):
278 conversion.CPSAssignmentStatement: generate_assignment_statement,
279 conversion.CPSExpressionStatement: generate_expression_statement,
280 conversion.CPSPushStatement: generate_push_statement,
281 conversion.CPSVariableInitializationStatement: generate_variable_initialization_statement,
282 }[type(statement)](counters, statement)
284 def generate(converted):
285 referenced_entry_list_list = []
286 instruction_list_list = []
291 for statement in converted.statement_list:
292 referenced_entry_list, instruction_list = generate_statement(counters, statement)
293 referenced_entry_list_list.append(referenced_entry_list)
294 instruction_list_list.append(instruction_list)
297 entry_list=flatten(referenced_entry_list_list) + (
298 CIRLabel(label='__main__'),
299 ) + flatten(instruction_list_list),
302 NO_ARGUMENT_INSTRUCTIONS = set([
307 def format_argument(arg):
315 for entry in program.entry_list:
316 if isinstance(entry, CIRInstruction):
317 if entry.instruction in NO_ARGUMENT_INSTRUCTIONS and entry.argument is None:
318 lines.append(' {}'.format(entry.instruction))
320 lines.append(' {} {}'.format(entry.instruction, format_argument(entry.argument)))
322 if isinstance(entry, CIRLabel):
323 lines.append('\n{}:'.format(entry.label))
325 return '\n'.join(lines).lstrip()