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 escape_name(name):
64 return name.replace('$','$$').replace('_','$')
66 def generate_lambda_expression(counters, expression):
67 if expression.name is None:
70 name = escape_name(expression.name)
72 name_counter = counters.get(name, 0)
73 counters[expression.name] = name_counter + 1
74 label = '{}${}'.format(name, name_counter)
76 referenced_entry_list_list = []
77 instruction_list_list = []
79 for statement in expression.statement_list:
80 referenced_entry_list, instruction_list = generate_statement(counters, statement)
81 referenced_entry_list_list.append(referenced_entry_list)
82 instruction_list_list.append(instruction_list)
84 # Pop from the stack in reversed order, because arguments were pushed onto
86 argument_bindings = tuple(
87 CIRInstruction(instruction='pop', argument='sym({})'.format(arg))
88 for arg in reversed(expression.argument_name_list)
91 lambda_body = flatten(instruction_list_list)
92 assert lambda_body[-1].instruction == 'drop'
93 lambda_body = argument_bindings + lambda_body[:-1] + (CIRInstruction(instruction='return', argument=None),)
95 referenced_entry_list_list.append(
96 (CIRLabel(label=label),) + lambda_body,
100 CIRInstruction(instruction='close', argument=label),
103 return flatten(referenced_entry_list_list), instruction_list
105 def generate_list_construct_expression(counters, expression):
106 referenced_entry_list = ()
107 instruction_list = (CIRInstruction(
111 return referenced_entry_list, instruction_list
113 def generate_string_literal_expression(counters, expression):
114 referenced_entry_list = ()
115 instruction_list = (CIRInstruction(
116 instruction='push_value',
117 argument=generate_string_literal(expression.string),
120 return referenced_entry_list, instruction_list
122 def generate_structure_literal_expression(counters, expression):
123 referenced_entry_list = ()
124 instruction_list = (CIRInstruction(
125 instruction='structure',
126 argument=expression.field_count,
129 return referenced_entry_list, instruction_list
131 def generate_symbol_expression(counters, expression):
132 referenced_entry_list = ()
133 instruction_list = (CIRInstruction(
135 argument=generate_symbol_literal(expression.symbol),
138 return referenced_entry_list, instruction_list
140 def generate_symbol_literal_expression(counters, expression):
141 referenced_entry_list = ()
142 instruction_list = (CIRInstruction(
143 instruction='push_value',
144 argument=generate_symbol_literal(expression.symbol),
147 return referenced_entry_list, instruction_list
149 def generate_variable_expression(counters, expression):
150 referenced_entry_list = ()
151 instruction_list = (CIRInstruction(
153 argument=generate_symbol_literal(expression.variable),
156 return referenced_entry_list, instruction_list
158 def generate_expression(counters, expression):
160 conversion.CPSFunctionCallExpression: generate_function_call_expression,
161 conversion.CPSIfElseExpression: generate_if_else_expression,
162 conversion.CPSIntegerLiteralExpression: generate_integer_literal_expression,
163 conversion.CPSLambdaExpression: generate_lambda_expression,
164 conversion.CPSListConstructExpression: generate_list_construct_expression,
165 conversion.CPSStringLiteralExpression: generate_string_literal_expression,
166 conversion.CPSStructureLiteralExpression: generate_structure_literal_expression,
167 conversion.CPSSymbolExpression: generate_symbol_expression,
168 conversion.CPSSymbolLiteralExpression: generate_symbol_literal_expression,
169 conversion.CPSVariableExpression: generate_variable_expression,
170 }[type(expression)](counters, expression)
172 def generate_expression_statement(counters, statement):
173 referenced_entry_list, instruction_list = generate_expression(
175 statement.expression,
178 instruction_list += (
185 return referenced_entry_list, instruction_list
187 def generate_if_else_expression(counters, statement):
188 if_counter = counters['if']
191 referenced_entry_list_list = []
193 condition_referenced_entry_list, condition_instruction_list = generate_expression(
195 statement.condition_expression,
198 if_instruction_list_list = []
199 for if_statement in statement.if_statement_list:
200 referenced_entry_list, instruction_list = generate_statement(counters, if_statement)
201 referenced_entry_list_list.append(referenced_entry_list)
202 if_instruction_list_list.append(instruction_list)
204 if_instruction_list = flatten(if_instruction_list_list)
205 assert if_instruction_list[-1].instruction == 'drop'
206 if_instruction_list = if_instruction_list[:-1]
208 else_instruction_list_list = []
210 for else_statement in statement.else_statement_list:
211 referenced_entry_list, instruction_list = generate_statement(counters, else_statement)
212 referenced_entry_list_list.append(referenced_entry_list)
213 else_instruction_list_list.append(instruction_list)
215 else_instruction_list = flatten(else_instruction_list_list)
216 assert else_instruction_list[-1].instruction == 'drop'
217 else_instruction_list = else_instruction_list[:-1]
219 if_label = '__if${}__'.format(if_counter)
220 else_label = '__else${}__'.format(if_counter)
221 endif_label = '__endif${}__'.format(if_counter)
223 instruction_list = condition_instruction_list + (
225 instruction='jump_if_false',
232 CIRLabel(label=if_label),
233 ) + if_instruction_list + (
236 argument=endif_label,
238 CIRLabel(label=else_label),
239 ) + else_instruction_list + (
240 CIRLabel(label=endif_label),
244 condition_referenced_entry_list + flatten(referenced_entry_list_list),
248 def generate_assignment_statement(counters, statement):
249 referenced_entry_list, instruction_list = generate_expression(
251 statement.expression,
254 instruction_list += (
257 argument=generate_symbol_literal(statement.target),
261 return referenced_entry_list, instruction_list
263 def generate_push_statement(counters, statement):
264 return generate_expression(counters, statement.expression)
266 def generate_variable_initialization_statement(counters, statement):
267 referenced_entry_list, instruction_list = generate_expression(
269 statement.expression,
272 instruction_list += (
275 argument=generate_symbol_literal(statement.variable),
279 return referenced_entry_list, instruction_list
281 def generate_statement(counters, statement):
283 conversion.CPSAssignmentStatement: generate_assignment_statement,
284 conversion.CPSExpressionStatement: generate_expression_statement,
285 conversion.CPSPushStatement: generate_push_statement,
286 conversion.CPSVariableInitializationStatement: generate_variable_initialization_statement,
287 }[type(statement)](counters, statement)
289 def generate(converted):
290 referenced_entry_list_list = []
291 instruction_list_list = []
296 for statement in converted.statement_list:
297 referenced_entry_list, instruction_list = generate_statement(counters, statement)
298 referenced_entry_list_list.append(referenced_entry_list)
299 instruction_list_list.append(instruction_list)
302 entry_list=flatten(referenced_entry_list_list) + (
303 CIRLabel(label='__main__'),
304 ) + flatten(instruction_list_list),
307 NO_ARGUMENT_INSTRUCTIONS = set([
312 def format_argument(arg):
320 for entry in program.entry_list:
321 if isinstance(entry, CIRInstruction):
322 if entry.instruction in NO_ARGUMENT_INSTRUCTIONS and entry.argument is None:
323 lines.append(' {}'.format(entry.instruction))
325 lines.append(' {} {}'.format(entry.instruction, format_argument(entry.argument)))
327 if isinstance(entry, CIRLabel):
328 lines.append('\n{}:'.format(entry.label))
330 return '\n'.join(lines).lstrip()