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):
42 # Environment operations
47 '__integer_divide__': 'idiv',
48 '__modular_divide__': 'mod',
49 '__multiply__': 'mul',
51 '__subtract__': 'sub',
62 '__concat__': 'concat',
66 import ipdb; ipdb.set_trace()
68 def generate_function_call_expression(counters, expression):
69 if isinstance(expression.function_expression, conversion.CPSBuiltinExpression):
74 instruction=generate_instruction_name_from_builtin(
75 expression.function_expression.symbol,
77 argument=expression.argument_count,
82 referenced_entry_list, instruction_list = generate_expression(
84 expression.function_expression,
90 argument=expression.argument_count,
94 return referenced_entry_list, instruction_list
96 def generate_integer_literal_expression(counters, expression):
97 referenced_entry_list = ()
98 instruction_list = (CIRInstruction(
99 instruction='push_integer',
100 argument=generate_integer_literal(expression.integer),
103 return referenced_entry_list, instruction_list
105 def escape_name(name):
106 return name.replace('$','$$').replace('_','$')
108 def generate_lambda_expression(counters, expression):
109 if expression.name is None:
112 name = escape_name(expression.name)
114 name_counter = counters.get(name, 0)
115 counters[expression.name] = name_counter + 1
116 label = '{}${}'.format(name, name_counter)
118 referenced_entry_list_list = []
119 instruction_list_list = []
121 for statement in expression.statement_list:
122 referenced_entry_list, instruction_list = generate_statement(counters, statement)
123 referenced_entry_list_list.append(referenced_entry_list)
124 instruction_list_list.append(instruction_list)
126 # Pop from the stack in reversed order, because arguments were pushed onto
128 argument_bindings = tuple(
129 CIRInstruction(instruction='pop', argument='sym({})'.format(arg))
130 for arg in reversed(expression.argument_name_list)
133 lambda_body = flatten(instruction_list_list)
134 assert lambda_body[-1].instruction == 'drop'
135 lambda_body = argument_bindings + lambda_body[:-1] + (CIRInstruction(instruction='return', argument=None),)
137 referenced_entry_list_list.append(
138 (CIRLabel(label=label),) + lambda_body,
142 CIRInstruction(instruction='close', argument=label),
145 return flatten(referenced_entry_list_list), instruction_list
147 def generate_list_construct_expression(counters, expression):
148 referenced_entry_list = ()
149 instruction_list = (CIRInstruction(
153 return referenced_entry_list, instruction_list
155 def generate_string_literal_expression(counters, expression):
156 referenced_entry_list = ()
157 instruction_list = (CIRInstruction(
158 instruction='push_string',
159 argument=generate_string_literal(expression.string),
162 return referenced_entry_list, instruction_list
164 def generate_structure_literal_expression(counters, expression):
165 referenced_entry_list = ()
166 instruction_list = (CIRInstruction(
167 instruction='structure',
168 argument=expression.field_count,
171 return referenced_entry_list, instruction_list
173 def generate_symbol_expression(counters, expression):
174 referenced_entry_list = ()
175 instruction_list = (CIRInstruction(
177 argument=generate_symbol_literal(expression.symbol),
180 return referenced_entry_list, instruction_list
182 def generate_symbol_literal_expression(counters, expression):
183 referenced_entry_list = ()
184 instruction_list = (CIRInstruction(
185 instruction='push_symbol',
186 argument=generate_symbol_literal(expression.symbol),
189 return referenced_entry_list, instruction_list
191 def generate_variable_expression(counters, expression):
192 referenced_entry_list = ()
193 instruction_list = (CIRInstruction(
195 argument=generate_symbol_literal(expression.variable),
198 return referenced_entry_list, instruction_list
200 def generate_expression(counters, expression):
202 conversion.CPSFunctionCallExpression: generate_function_call_expression,
203 conversion.CPSIfElseExpression: generate_if_else_expression,
204 conversion.CPSIntegerLiteralExpression: generate_integer_literal_expression,
205 conversion.CPSLambdaExpression: generate_lambda_expression,
206 conversion.CPSListConstructExpression: generate_list_construct_expression,
207 conversion.CPSStringLiteralExpression: generate_string_literal_expression,
208 conversion.CPSStructureLiteralExpression: generate_structure_literal_expression,
209 conversion.CPSSymbolExpression: generate_symbol_expression,
210 conversion.CPSSymbolLiteralExpression: generate_symbol_literal_expression,
211 conversion.CPSVariableExpression: generate_variable_expression,
212 }[type(expression)](counters, expression)
214 def generate_expression_statement(counters, statement):
215 referenced_entry_list, instruction_list = generate_expression(
217 statement.expression,
220 instruction_list += (
227 return referenced_entry_list, instruction_list
229 def generate_if_else_expression(counters, statement):
230 if_counter = counters['if']
233 referenced_entry_list_list = []
235 condition_referenced_entry_list, condition_instruction_list = generate_expression(
237 statement.condition_expression,
240 if_instruction_list_list = []
241 for if_statement in statement.if_statement_list:
242 referenced_entry_list, instruction_list = generate_statement(counters, if_statement)
243 referenced_entry_list_list.append(referenced_entry_list)
244 if_instruction_list_list.append(instruction_list)
246 if_instruction_list = flatten(if_instruction_list_list)
247 assert if_instruction_list[-1].instruction == 'drop'
248 if_instruction_list = if_instruction_list[:-1]
250 else_instruction_list_list = []
252 for else_statement in statement.else_statement_list:
253 referenced_entry_list, instruction_list = generate_statement(counters, else_statement)
254 referenced_entry_list_list.append(referenced_entry_list)
255 else_instruction_list_list.append(instruction_list)
257 else_instruction_list = flatten(else_instruction_list_list)
258 assert else_instruction_list[-1].instruction == 'drop'
259 else_instruction_list = else_instruction_list[:-1]
261 if_label = '__if${}__'.format(if_counter)
262 else_label = '__else${}__'.format(if_counter)
263 endif_label = '__endif${}__'.format(if_counter)
265 instruction_list = condition_instruction_list + (
267 instruction='jump_if_false',
274 CIRLabel(label=if_label),
275 ) + if_instruction_list + (
278 argument=endif_label,
280 CIRLabel(label=else_label),
281 ) + else_instruction_list + (
282 CIRLabel(label=endif_label),
286 condition_referenced_entry_list + flatten(referenced_entry_list_list),
290 def generate_assignment_statement(counters, statement):
291 referenced_entry_list, instruction_list = generate_expression(
293 statement.expression,
296 instruction_list += (
299 argument=generate_symbol_literal(statement.target),
303 return referenced_entry_list, instruction_list
305 def generate_push_statement(counters, statement):
306 return generate_expression(counters, statement.expression)
308 def generate_variable_initialization_statement(counters, statement):
309 referenced_entry_list, instruction_list = generate_expression(
311 statement.expression,
314 instruction_list += (
317 argument=generate_symbol_literal(statement.variable),
321 return referenced_entry_list, instruction_list
323 def generate_statement(counters, statement):
325 conversion.CPSAssignmentStatement: generate_assignment_statement,
326 conversion.CPSExpressionStatement: generate_expression_statement,
327 conversion.CPSPushStatement: generate_push_statement,
328 conversion.CPSVariableInitializationStatement: generate_variable_initialization_statement,
329 }[type(statement)](counters, statement)
331 def generate(converted):
332 referenced_entry_list_list = []
333 instruction_list_list = []
338 for statement in converted.statement_list:
339 referenced_entry_list, instruction_list = generate_statement(counters, statement)
340 referenced_entry_list_list.append(referenced_entry_list)
341 instruction_list_list.append(instruction_list)
344 entry_list=flatten(referenced_entry_list_list) + (
345 CIRLabel(label='__main__'),
346 ) + flatten(instruction_list_list) + (
347 CIRInstruction(instruction='end', argument=None),
351 NO_ARGUMENT_INSTRUCTIONS = set([
356 def format_argument(arg):
364 for entry in program.entry_list:
365 if isinstance(entry, CIRInstruction):
366 if entry.instruction in NO_ARGUMENT_INSTRUCTIONS and entry.argument is None:
367 lines.append(' {}'.format(entry.instruction))
369 lines.append(' {} {}'.format(entry.instruction, format_argument(entry.argument)))
371 if isinstance(entry, CIRLabel):
372 lines.append('\n{}:'.format(entry.label))
374 return '\n'.join(lines).lstrip()