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 '__integer_divide__': 'idiv',
44 '__modular_divide__': 'mod',
45 '__multiply__': 'mul',
47 '__subtract__': 'sub',
58 import ipdb; ipdb.set_trace()
60 def generate_function_call_expression(counters, expression):
61 if isinstance(expression.function_expression, conversion.CPSBuiltinExpression):
66 instruction=generate_instruction_name_from_builtin(
67 expression.function_expression.symbol,
69 argument=expression.argument_count,
74 referenced_entry_list, instruction_list = generate_expression(
76 expression.function_expression,
82 argument=expression.argument_count,
86 return referenced_entry_list, instruction_list
88 def generate_integer_literal_expression(counters, expression):
89 referenced_entry_list = ()
90 instruction_list = (CIRInstruction(
91 instruction='push_integer',
92 argument=generate_integer_literal(expression.integer),
95 return referenced_entry_list, instruction_list
97 def escape_name(name):
98 return name.replace('$','$$').replace('_','$')
100 def generate_lambda_expression(counters, expression):
101 if expression.name is None:
104 name = escape_name(expression.name)
106 name_counter = counters.get(name, 0)
107 counters[expression.name] = name_counter + 1
108 label = '{}${}'.format(name, name_counter)
110 referenced_entry_list_list = []
111 instruction_list_list = []
113 for statement in expression.statement_list:
114 referenced_entry_list, instruction_list = generate_statement(counters, statement)
115 referenced_entry_list_list.append(referenced_entry_list)
116 instruction_list_list.append(instruction_list)
118 # Pop from the stack in reversed order, because arguments were pushed onto
120 argument_bindings = tuple(
121 CIRInstruction(instruction='pop', argument='sym({})'.format(arg))
122 for arg in reversed(expression.argument_name_list)
125 lambda_body = flatten(instruction_list_list)
126 assert lambda_body[-1].instruction == 'drop'
127 lambda_body = argument_bindings + lambda_body[:-1] + (CIRInstruction(instruction='return', argument=None),)
129 referenced_entry_list_list.append(
130 (CIRLabel(label=label),) + lambda_body,
134 CIRInstruction(instruction='close', argument=label),
137 return flatten(referenced_entry_list_list), instruction_list
139 def generate_list_construct_expression(counters, expression):
140 referenced_entry_list = ()
141 instruction_list = (CIRInstruction(
145 return referenced_entry_list, instruction_list
147 def generate_string_literal_expression(counters, expression):
148 referenced_entry_list = ()
149 instruction_list = (CIRInstruction(
150 instruction='push_string',
151 argument=generate_string_literal(expression.string),
154 return referenced_entry_list, instruction_list
156 def generate_structure_literal_expression(counters, expression):
157 referenced_entry_list = ()
158 instruction_list = (CIRInstruction(
159 instruction='structure',
160 argument=expression.field_count,
163 return referenced_entry_list, instruction_list
165 def generate_symbol_expression(counters, expression):
166 referenced_entry_list = ()
167 instruction_list = (CIRInstruction(
169 argument=generate_symbol_literal(expression.symbol),
172 return referenced_entry_list, instruction_list
174 def generate_symbol_literal_expression(counters, expression):
175 referenced_entry_list = ()
176 instruction_list = (CIRInstruction(
177 instruction='push_symbol',
178 argument=generate_symbol_literal(expression.symbol),
181 return referenced_entry_list, instruction_list
183 def generate_variable_expression(counters, expression):
184 referenced_entry_list = ()
185 instruction_list = (CIRInstruction(
187 argument=generate_symbol_literal(expression.variable),
190 return referenced_entry_list, instruction_list
192 def generate_expression(counters, expression):
194 conversion.CPSFunctionCallExpression: generate_function_call_expression,
195 conversion.CPSIfElseExpression: generate_if_else_expression,
196 conversion.CPSIntegerLiteralExpression: generate_integer_literal_expression,
197 conversion.CPSLambdaExpression: generate_lambda_expression,
198 conversion.CPSListConstructExpression: generate_list_construct_expression,
199 conversion.CPSStringLiteralExpression: generate_string_literal_expression,
200 conversion.CPSStructureLiteralExpression: generate_structure_literal_expression,
201 conversion.CPSSymbolExpression: generate_symbol_expression,
202 conversion.CPSSymbolLiteralExpression: generate_symbol_literal_expression,
203 conversion.CPSVariableExpression: generate_variable_expression,
204 }[type(expression)](counters, expression)
206 def generate_expression_statement(counters, statement):
207 referenced_entry_list, instruction_list = generate_expression(
209 statement.expression,
212 instruction_list += (
219 return referenced_entry_list, instruction_list
221 def generate_if_else_expression(counters, statement):
222 if_counter = counters['if']
225 referenced_entry_list_list = []
227 condition_referenced_entry_list, condition_instruction_list = generate_expression(
229 statement.condition_expression,
232 if_instruction_list_list = []
233 for if_statement in statement.if_statement_list:
234 referenced_entry_list, instruction_list = generate_statement(counters, if_statement)
235 referenced_entry_list_list.append(referenced_entry_list)
236 if_instruction_list_list.append(instruction_list)
238 if_instruction_list = flatten(if_instruction_list_list)
239 assert if_instruction_list[-1].instruction == 'drop'
240 if_instruction_list = if_instruction_list[:-1]
242 else_instruction_list_list = []
244 for else_statement in statement.else_statement_list:
245 referenced_entry_list, instruction_list = generate_statement(counters, else_statement)
246 referenced_entry_list_list.append(referenced_entry_list)
247 else_instruction_list_list.append(instruction_list)
249 else_instruction_list = flatten(else_instruction_list_list)
250 assert else_instruction_list[-1].instruction == 'drop'
251 else_instruction_list = else_instruction_list[:-1]
253 if_label = '__if${}__'.format(if_counter)
254 else_label = '__else${}__'.format(if_counter)
255 endif_label = '__endif${}__'.format(if_counter)
257 instruction_list = condition_instruction_list + (
259 instruction='jump_if_false',
266 CIRLabel(label=if_label),
267 ) + if_instruction_list + (
270 argument=endif_label,
272 CIRLabel(label=else_label),
273 ) + else_instruction_list + (
274 CIRLabel(label=endif_label),
278 condition_referenced_entry_list + flatten(referenced_entry_list_list),
282 def generate_assignment_statement(counters, statement):
283 referenced_entry_list, instruction_list = generate_expression(
285 statement.expression,
288 instruction_list += (
291 argument=generate_symbol_literal(statement.target),
295 return referenced_entry_list, instruction_list
297 def generate_push_statement(counters, statement):
298 return generate_expression(counters, statement.expression)
300 def generate_variable_initialization_statement(counters, statement):
301 referenced_entry_list, instruction_list = generate_expression(
303 statement.expression,
306 instruction_list += (
309 argument=generate_symbol_literal(statement.variable),
313 return referenced_entry_list, instruction_list
315 def generate_statement(counters, statement):
317 conversion.CPSAssignmentStatement: generate_assignment_statement,
318 conversion.CPSExpressionStatement: generate_expression_statement,
319 conversion.CPSPushStatement: generate_push_statement,
320 conversion.CPSVariableInitializationStatement: generate_variable_initialization_statement,
321 }[type(statement)](counters, statement)
323 def generate(converted):
324 referenced_entry_list_list = []
325 instruction_list_list = []
330 for statement in converted.statement_list:
331 referenced_entry_list, instruction_list = generate_statement(counters, statement)
332 referenced_entry_list_list.append(referenced_entry_list)
333 instruction_list_list.append(instruction_list)
336 entry_list=flatten(referenced_entry_list_list) + (
337 CIRLabel(label='__main__'),
338 ) + flatten(instruction_list_list) + (
339 CIRInstruction(instruction='end', argument=None),
343 NO_ARGUMENT_INSTRUCTIONS = set([
348 def format_argument(arg):
356 for entry in program.entry_list:
357 if isinstance(entry, CIRInstruction):
358 if entry.instruction in NO_ARGUMENT_INSTRUCTIONS and entry.argument is None:
359 lines.append(' {}'.format(entry.instruction))
361 lines.append(' {} {}'.format(entry.instruction, format_argument(entry.argument)))
363 if isinstance(entry, CIRLabel):
364 lines.append('\n{}:'.format(entry.label))
366 return '\n'.join(lines).lstrip()