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_instruction_name_from_builtin(builtin):
43 '__subtract__': 'sub',
44 '__multiply__': 'mul',
45 '__integer_divide__': 'idiv',
46 '__modular_divide__': 'mod',
50 import ipdb; ipdb.set_trace()
52 def generate_function_call_expression(counters, expression):
53 if isinstance(expression.function_expression, conversion.CPSBuiltinExpression):
58 instruction=generate_instruction_name_from_builtin(
59 expression.function_expression.symbol,
61 argument=expression.argument_count,
66 referenced_entry_list, instruction_list = generate_expression(
68 expression.function_expression,
74 argument=expression.argument_count,
78 return referenced_entry_list, instruction_list
80 def generate_integer_literal_expression(counters, expression):
81 referenced_entry_list = ()
82 instruction_list = (CIRInstruction(
83 instruction='push_integer',
84 argument=generate_integer_literal(expression.integer),
87 return referenced_entry_list, instruction_list
89 def escape_name(name):
90 return name.replace('$','$$').replace('_','$')
92 def generate_lambda_expression(counters, expression):
93 if expression.name is None:
96 name = escape_name(expression.name)
98 name_counter = counters.get(name, 0)
99 counters[expression.name] = name_counter + 1
100 label = '{}${}'.format(name, name_counter)
102 referenced_entry_list_list = []
103 instruction_list_list = []
105 for statement in expression.statement_list:
106 referenced_entry_list, instruction_list = generate_statement(counters, statement)
107 referenced_entry_list_list.append(referenced_entry_list)
108 instruction_list_list.append(instruction_list)
110 # Pop from the stack in reversed order, because arguments were pushed onto
112 argument_bindings = tuple(
113 CIRInstruction(instruction='pop', argument='sym({})'.format(arg))
114 for arg in reversed(expression.argument_name_list)
117 lambda_body = flatten(instruction_list_list)
118 assert lambda_body[-1].instruction == 'drop'
119 lambda_body = argument_bindings + lambda_body[:-1] + (CIRInstruction(instruction='return', argument=None),)
121 referenced_entry_list_list.append(
122 (CIRLabel(label=label),) + lambda_body,
126 CIRInstruction(instruction='close', argument=label),
129 return flatten(referenced_entry_list_list), instruction_list
131 def generate_list_construct_expression(counters, expression):
132 referenced_entry_list = ()
133 instruction_list = (CIRInstruction(
137 return referenced_entry_list, instruction_list
139 def generate_string_literal_expression(counters, expression):
140 referenced_entry_list = ()
141 instruction_list = (CIRInstruction(
142 instruction='push_string',
143 argument=generate_string_literal(expression.string),
146 return referenced_entry_list, instruction_list
148 def generate_structure_literal_expression(counters, expression):
149 referenced_entry_list = ()
150 instruction_list = (CIRInstruction(
151 instruction='structure',
152 argument=expression.field_count,
155 return referenced_entry_list, instruction_list
157 def generate_symbol_expression(counters, expression):
158 referenced_entry_list = ()
159 instruction_list = (CIRInstruction(
161 argument=generate_symbol_literal(expression.symbol),
164 return referenced_entry_list, instruction_list
166 def generate_symbol_literal_expression(counters, expression):
167 referenced_entry_list = ()
168 instruction_list = (CIRInstruction(
169 instruction='push_symbol',
170 argument=generate_symbol_literal(expression.symbol),
173 return referenced_entry_list, instruction_list
175 def generate_variable_expression(counters, expression):
176 referenced_entry_list = ()
177 instruction_list = (CIRInstruction(
179 argument=generate_symbol_literal(expression.variable),
182 return referenced_entry_list, instruction_list
184 def generate_expression(counters, expression):
186 conversion.CPSFunctionCallExpression: generate_function_call_expression,
187 conversion.CPSIfElseExpression: generate_if_else_expression,
188 conversion.CPSIntegerLiteralExpression: generate_integer_literal_expression,
189 conversion.CPSLambdaExpression: generate_lambda_expression,
190 conversion.CPSListConstructExpression: generate_list_construct_expression,
191 conversion.CPSStringLiteralExpression: generate_string_literal_expression,
192 conversion.CPSStructureLiteralExpression: generate_structure_literal_expression,
193 conversion.CPSSymbolExpression: generate_symbol_expression,
194 conversion.CPSSymbolLiteralExpression: generate_symbol_literal_expression,
195 conversion.CPSVariableExpression: generate_variable_expression,
196 }[type(expression)](counters, expression)
198 def generate_expression_statement(counters, statement):
199 referenced_entry_list, instruction_list = generate_expression(
201 statement.expression,
204 instruction_list += (
211 return referenced_entry_list, instruction_list
213 def generate_if_else_expression(counters, statement):
214 if_counter = counters['if']
217 referenced_entry_list_list = []
219 condition_referenced_entry_list, condition_instruction_list = generate_expression(
221 statement.condition_expression,
224 if_instruction_list_list = []
225 for if_statement in statement.if_statement_list:
226 referenced_entry_list, instruction_list = generate_statement(counters, if_statement)
227 referenced_entry_list_list.append(referenced_entry_list)
228 if_instruction_list_list.append(instruction_list)
230 if_instruction_list = flatten(if_instruction_list_list)
231 assert if_instruction_list[-1].instruction == 'drop'
232 if_instruction_list = if_instruction_list[:-1]
234 else_instruction_list_list = []
236 for else_statement in statement.else_statement_list:
237 referenced_entry_list, instruction_list = generate_statement(counters, else_statement)
238 referenced_entry_list_list.append(referenced_entry_list)
239 else_instruction_list_list.append(instruction_list)
241 else_instruction_list = flatten(else_instruction_list_list)
242 assert else_instruction_list[-1].instruction == 'drop'
243 else_instruction_list = else_instruction_list[:-1]
245 if_label = '__if${}__'.format(if_counter)
246 else_label = '__else${}__'.format(if_counter)
247 endif_label = '__endif${}__'.format(if_counter)
249 instruction_list = condition_instruction_list + (
251 instruction='jump_if_false',
258 CIRLabel(label=if_label),
259 ) + if_instruction_list + (
262 argument=endif_label,
264 CIRLabel(label=else_label),
265 ) + else_instruction_list + (
266 CIRLabel(label=endif_label),
270 condition_referenced_entry_list + flatten(referenced_entry_list_list),
274 def generate_assignment_statement(counters, statement):
275 referenced_entry_list, instruction_list = generate_expression(
277 statement.expression,
280 instruction_list += (
283 argument=generate_symbol_literal(statement.target),
287 return referenced_entry_list, instruction_list
289 def generate_push_statement(counters, statement):
290 return generate_expression(counters, statement.expression)
292 def generate_variable_initialization_statement(counters, statement):
293 referenced_entry_list, instruction_list = generate_expression(
295 statement.expression,
298 instruction_list += (
301 argument=generate_symbol_literal(statement.variable),
305 return referenced_entry_list, instruction_list
307 def generate_statement(counters, statement):
309 conversion.CPSAssignmentStatement: generate_assignment_statement,
310 conversion.CPSExpressionStatement: generate_expression_statement,
311 conversion.CPSPushStatement: generate_push_statement,
312 conversion.CPSVariableInitializationStatement: generate_variable_initialization_statement,
313 }[type(statement)](counters, statement)
315 def generate(converted):
316 referenced_entry_list_list = []
317 instruction_list_list = []
322 for statement in converted.statement_list:
323 referenced_entry_list, instruction_list = generate_statement(counters, statement)
324 referenced_entry_list_list.append(referenced_entry_list)
325 instruction_list_list.append(instruction_list)
328 entry_list=flatten(referenced_entry_list_list) + (
329 CIRLabel(label='__main__'),
330 ) + flatten(instruction_list_list) + (
331 CIRInstruction(instruction='end', argument=None),
335 NO_ARGUMENT_INSTRUCTIONS = set([
340 def format_argument(arg):
348 for entry in program.entry_list:
349 if isinstance(entry, CIRInstruction):
350 if entry.instruction in NO_ARGUMENT_INSTRUCTIONS and entry.argument is None:
351 lines.append(' {}'.format(entry.instruction))
353 lines.append(' {} {}'.format(entry.instruction, format_argument(entry.argument)))
355 if isinstance(entry, CIRLabel):
356 lines.append('\n{}:'.format(entry.label))
358 return '\n'.join(lines).lstrip()