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',
51 import ipdb; ipdb.set_trace()
53 def generate_function_call_expression(counters, expression):
54 if isinstance(expression.function_expression, conversion.CPSBuiltinExpression):
59 instruction=generate_instruction_name_from_builtin(
60 expression.function_expression.symbol,
62 argument=expression.argument_count,
67 referenced_entry_list, instruction_list = generate_expression(
69 expression.function_expression,
75 argument=expression.argument_count,
79 return referenced_entry_list, instruction_list
81 def generate_integer_literal_expression(counters, expression):
82 referenced_entry_list = ()
83 instruction_list = (CIRInstruction(
84 instruction='push_integer',
85 argument=generate_integer_literal(expression.integer),
88 return referenced_entry_list, instruction_list
90 def escape_name(name):
91 return name.replace('$','$$').replace('_','$')
93 def generate_lambda_expression(counters, expression):
94 if expression.name is None:
97 name = escape_name(expression.name)
99 name_counter = counters.get(name, 0)
100 counters[expression.name] = name_counter + 1
101 label = '{}${}'.format(name, name_counter)
103 referenced_entry_list_list = []
104 instruction_list_list = []
106 for statement in expression.statement_list:
107 referenced_entry_list, instruction_list = generate_statement(counters, statement)
108 referenced_entry_list_list.append(referenced_entry_list)
109 instruction_list_list.append(instruction_list)
111 # Pop from the stack in reversed order, because arguments were pushed onto
113 argument_bindings = tuple(
114 CIRInstruction(instruction='pop', argument='sym({})'.format(arg))
115 for arg in reversed(expression.argument_name_list)
118 lambda_body = flatten(instruction_list_list)
119 assert lambda_body[-1].instruction == 'drop'
120 lambda_body = argument_bindings + lambda_body[:-1] + (CIRInstruction(instruction='return', argument=None),)
122 referenced_entry_list_list.append(
123 (CIRLabel(label=label),) + lambda_body,
127 CIRInstruction(instruction='close', argument=label),
130 return flatten(referenced_entry_list_list), instruction_list
132 def generate_list_construct_expression(counters, expression):
133 referenced_entry_list = ()
134 instruction_list = (CIRInstruction(
138 return referenced_entry_list, instruction_list
140 def generate_string_literal_expression(counters, expression):
141 referenced_entry_list = ()
142 instruction_list = (CIRInstruction(
143 instruction='push_string',
144 argument=generate_string_literal(expression.string),
147 return referenced_entry_list, instruction_list
149 def generate_structure_literal_expression(counters, expression):
150 referenced_entry_list = ()
151 instruction_list = (CIRInstruction(
152 instruction='structure',
153 argument=expression.field_count,
156 return referenced_entry_list, instruction_list
158 def generate_symbol_expression(counters, expression):
159 referenced_entry_list = ()
160 instruction_list = (CIRInstruction(
162 argument=generate_symbol_literal(expression.symbol),
165 return referenced_entry_list, instruction_list
167 def generate_symbol_literal_expression(counters, expression):
168 referenced_entry_list = ()
169 instruction_list = (CIRInstruction(
170 instruction='push_symbol',
171 argument=generate_symbol_literal(expression.symbol),
174 return referenced_entry_list, instruction_list
176 def generate_variable_expression(counters, expression):
177 referenced_entry_list = ()
178 instruction_list = (CIRInstruction(
180 argument=generate_symbol_literal(expression.variable),
183 return referenced_entry_list, instruction_list
185 def generate_expression(counters, expression):
187 conversion.CPSFunctionCallExpression: generate_function_call_expression,
188 conversion.CPSIfElseExpression: generate_if_else_expression,
189 conversion.CPSIntegerLiteralExpression: generate_integer_literal_expression,
190 conversion.CPSLambdaExpression: generate_lambda_expression,
191 conversion.CPSListConstructExpression: generate_list_construct_expression,
192 conversion.CPSStringLiteralExpression: generate_string_literal_expression,
193 conversion.CPSStructureLiteralExpression: generate_structure_literal_expression,
194 conversion.CPSSymbolExpression: generate_symbol_expression,
195 conversion.CPSSymbolLiteralExpression: generate_symbol_literal_expression,
196 conversion.CPSVariableExpression: generate_variable_expression,
197 }[type(expression)](counters, expression)
199 def generate_expression_statement(counters, statement):
200 referenced_entry_list, instruction_list = generate_expression(
202 statement.expression,
205 instruction_list += (
212 return referenced_entry_list, instruction_list
214 def generate_if_else_expression(counters, statement):
215 if_counter = counters['if']
218 referenced_entry_list_list = []
220 condition_referenced_entry_list, condition_instruction_list = generate_expression(
222 statement.condition_expression,
225 if_instruction_list_list = []
226 for if_statement in statement.if_statement_list:
227 referenced_entry_list, instruction_list = generate_statement(counters, if_statement)
228 referenced_entry_list_list.append(referenced_entry_list)
229 if_instruction_list_list.append(instruction_list)
231 if_instruction_list = flatten(if_instruction_list_list)
232 assert if_instruction_list[-1].instruction == 'drop'
233 if_instruction_list = if_instruction_list[:-1]
235 else_instruction_list_list = []
237 for else_statement in statement.else_statement_list:
238 referenced_entry_list, instruction_list = generate_statement(counters, else_statement)
239 referenced_entry_list_list.append(referenced_entry_list)
240 else_instruction_list_list.append(instruction_list)
242 else_instruction_list = flatten(else_instruction_list_list)
243 assert else_instruction_list[-1].instruction == 'drop'
244 else_instruction_list = else_instruction_list[:-1]
246 if_label = '__if${}__'.format(if_counter)
247 else_label = '__else${}__'.format(if_counter)
248 endif_label = '__endif${}__'.format(if_counter)
250 instruction_list = condition_instruction_list + (
252 instruction='jump_if_false',
259 CIRLabel(label=if_label),
260 ) + if_instruction_list + (
263 argument=endif_label,
265 CIRLabel(label=else_label),
266 ) + else_instruction_list + (
267 CIRLabel(label=endif_label),
271 condition_referenced_entry_list + flatten(referenced_entry_list_list),
275 def generate_assignment_statement(counters, statement):
276 referenced_entry_list, instruction_list = generate_expression(
278 statement.expression,
281 instruction_list += (
284 argument=generate_symbol_literal(statement.target),
288 return referenced_entry_list, instruction_list
290 def generate_push_statement(counters, statement):
291 return generate_expression(counters, statement.expression)
293 def generate_variable_initialization_statement(counters, statement):
294 referenced_entry_list, instruction_list = generate_expression(
296 statement.expression,
299 instruction_list += (
302 argument=generate_symbol_literal(statement.variable),
306 return referenced_entry_list, instruction_list
308 def generate_statement(counters, statement):
310 conversion.CPSAssignmentStatement: generate_assignment_statement,
311 conversion.CPSExpressionStatement: generate_expression_statement,
312 conversion.CPSPushStatement: generate_push_statement,
313 conversion.CPSVariableInitializationStatement: generate_variable_initialization_statement,
314 }[type(statement)](counters, statement)
316 def generate(converted):
317 referenced_entry_list_list = []
318 instruction_list_list = []
323 for statement in converted.statement_list:
324 referenced_entry_list, instruction_list = generate_statement(counters, statement)
325 referenced_entry_list_list.append(referenced_entry_list)
326 instruction_list_list.append(instruction_list)
329 entry_list=flatten(referenced_entry_list_list) + (
330 CIRLabel(label='__main__'),
331 ) + flatten(instruction_list_list) + (
332 CIRInstruction(instruction='end', argument=None),
336 NO_ARGUMENT_INSTRUCTIONS = set([
341 def format_argument(arg):
349 for entry in program.entry_list:
350 if isinstance(entry, CIRInstruction):
351 if entry.instruction in NO_ARGUMENT_INSTRUCTIONS and entry.argument is None:
352 lines.append(' {}'.format(entry.instruction))
354 lines.append(' {} {}'.format(entry.instruction, format_argument(entry.argument)))
356 if isinstance(entry, CIRLabel):
357 lines.append('\n{}:'.format(entry.label))
359 return '\n'.join(lines).lstrip()