6 CIntegerLiteral = collections.namedtuple(
13 CStringLiteral = collections.namedtuple(
21 CVariableExpression = collections.namedtuple(
22 'CVariableExpression',
28 CSymbolExpression = collections.namedtuple(
36 CStructureLiteralExpression = collections.namedtuple(
37 'CStructureLiteralExpression',
40 'symbol_list_variable',
41 'value_list_variable',
45 CPushStatement = collections.namedtuple(
52 CFunctionCallExpression = collections.namedtuple(
53 'CFunctionCallExpression',
56 'function_expression',
61 # TODO We are currently not changing variables, just preventing them from being accessed.
62 CSymbolAssignmentStatement = collections.namedtuple(
63 'CSymbolAssignmentStatement',
66 'target_symbol_list_index',
71 CArrayVariableInitializationStatement = collections.namedtuple(
72 'CArrayVariableInitializationStatement',
79 CSymbolArrayVariableInitializationStatement = collections.namedtuple(
80 'CSymbolArrayVariableInitializationStatement',
84 'symbol_list_indices',
88 CVariableInitializationStatement = collections.namedtuple(
89 'CVariableInitializationStatement',
96 CVariableReassignmentStatement = collections.namedtuple(
97 'CVariableReassignmentStatement',
104 CExpressionStatement = collections.namedtuple(
105 'CExpressionStatement',
111 CIfElseStatement = collections.namedtuple(
114 'condition_expression',
116 'else_statement_list',
120 CFunctionDeclaration = collections.namedtuple(
121 'CFunctionDeclaration',
127 # TODO If a function definition doesn't end with an expression, we have issues currently because we try to return statement.
128 # TODO Closures currently wrap entire defining environment, even symbols that are not used, which makes garbage collection ineffective.
129 CFunctionDefinition = collections.namedtuple(
130 'CFunctionDefinition',
133 'argument_name_list',
138 CProgram = collections.namedtuple(
142 'function_definition_list',
143 'operator_declarations',
145 'standard_libraries',
146 'string_literal_list',
155 'print': ['stdio.h'],
159 def transform_variable_expression(accumulators, expression):
160 assert isinstance(expression, conversion.CPSVariableExpression)
161 return CVariableExpression(variable=expression.variable)
163 def transform_string_literal_expression(accumulators, expression):
164 value = expression.string
167 index = accumulators.string_literal_list.index(value)
169 index = len(accumulators.string_literal_list)
170 accumulators.string_literal_list.append(value)
172 return CStringLiteral(index=index, value=value)
174 def transform_symbol_expression(accumulators, expression):
175 if expression.symbol in BUILTINS:
176 accumulators.builtin_set.add(expression.symbol)
179 symbol_list_index = accumulators.symbol_list.index(expression.symbol)
181 symbol_list_index = len(accumulators.symbol_list)
182 accumulators.symbol_list.append(expression.symbol)
184 return CSymbolExpression(
185 symbol=expression.symbol,
186 symbol_list_index=symbol_list_index,
189 def transform_integer_literal_expression(accumulators, expression):
190 return CIntegerLiteral(value=expression.integer)
192 CListConstructExpression = collections.namedtuple(
193 'CListConstructExpression',
199 CListAppendStatement = collections.namedtuple(
200 'CListAppendStatement',
207 CListGetExpression = collections.namedtuple(
208 'CListGetExpression',
215 def transform_structure_literal_expression(accumulators, expression):
216 return CStructureLiteralExpression(
217 field_count=expression.field_count,
218 symbol_list_variable=expression.symbol_list_variable,
219 value_list_variable=expression.value_list_variable,
222 def transform_list_construct_expression(accumulators, expression):
223 return CListConstructExpression(allocate=expression.allocate)
225 def transform_list_get_expression(accumulators, expression):
226 return CListGetExpression(
227 list_expression=transform_expression(accumulators, expression.list_expression),
228 index_expression=transform_expression(accumulators, expression.index_expression),
231 def transform_list_append_statement(accumulators, expression):
232 return CListAppendStatement(
233 list_expression=transform_expression(accumulators, expression.list_expression),
234 item_expression=transform_expression(accumulators, expression.item_expression),
237 def transform_expression(accumulators, expression):
239 conversion.CPSFunctionCallExpression: transform_function_call_expression,
240 conversion.CPSIntegerLiteralExpression: transform_integer_literal_expression,
241 conversion.CPSListConstructExpression: transform_list_construct_expression,
242 normalization.NormalListGetExpression: transform_list_get_expression,
243 conversion.CPSStructureLiteralExpression: transform_structure_literal_expression,
244 conversion.CPSStringLiteralExpression: transform_string_literal_expression,
245 conversion.CPSSymbolExpression: transform_symbol_expression,
246 conversion.CPSVariableExpression: transform_variable_expression,
247 }[type(expression)](accumulators, expression)
249 def transform_symbol_assignment_statement(accumulators, assignment_statement):
250 # TODO Check that target is not a builtin
252 symbol_list_index = accumulators.symbol_list.index(assignment_statement.target)
254 symbol_list_index = len(accumulators.symbol_list)
255 accumulators.symbol_list.append(assignment_statement.target)
257 return CSymbolAssignmentStatement(
258 target=assignment_statement.target,
259 target_symbol_list_index=symbol_list_index,
260 expression=transform_expression(
262 assignment_statement.expression,
266 def transform_function_call_expression(accumulators, function_call):
267 # TODO Use the symbol from SYMBOL LIST
268 return CFunctionCallExpression(
269 metadata=function_call.metadata,
270 function_expression=transform_expression(accumulators, function_call.function_expression),
271 argument_count=function_call.argument_count,
274 def transform_expression_statement(accumulators, statement):
275 return CExpressionStatement(
276 expression=transform_expression(accumulators, statement.expression),
279 def transform_if_else_statement(accumulators, statement):
280 return CIfElseStatement(
281 condition_expression=transform_expression(accumulators, statement.condition_expression),
282 if_statement_list=tuple(transform_statement(accumulators, s) for s in statement.if_statement_list),
283 else_statement_list=tuple(transform_statement(accumulators, s) for s in statement.else_statement_list),
286 def transform_array_variable_initialization_statement(accumulators, statement):
287 return CArrayVariableInitializationStatement(
288 variable=statement.variable,
289 items=tuple(transform_expression(accumulators, i) for i in statement.items),
292 def transform_symbol_array_variable_initialization_statement(accumulators, statement):
293 symbol_list_indices = []
295 for symbol in statement.symbol_list:
297 symbol_list_index = accumulators.symbol_list.index(symbol)
299 symbol_list_index = len(accumulators.symbol_list)
300 accumulators.symbol_list.append(symbol)
302 symbol_list_indices.append(symbol_list_index)
304 return CSymbolArrayVariableInitializationStatement(
305 variable=statement.variable,
306 symbol_list=statement.symbol_list,
307 symbol_list_indices=tuple(symbol_list_indices),
310 def transform_variable_initialization_statement(accumulators, statement):
311 return CVariableInitializationStatement(
312 variable=statement.variable,
313 expression=transform_expression(accumulators, statement.expression),
316 def transform_variable_reassignment_statement(accumulators, statement):
317 return CVariableReassignmentStatement(
318 variable=statement.variable,
319 expression=transform_expression(accumulators, statement.expression),
322 def transform_function_definition_statement(accumulators, statement):
323 # TODO Allow defining the same function in different contexts
324 if any(fd.name == statement.name for fd in accumulators.function_definition_list):
325 raise Exception('A function with name "{}" already exists'.format(statement.name))
327 # TODO Add argument names to the symbol table
328 accumulators.function_definition_list.append(CFunctionDefinition(
330 argument_name_list=statement.argument_name_list,
331 statement_list=tuple(transform_statement(accumulators, s) for s in statement.statement_list)
334 return CFunctionDeclaration(name=statement.name)
336 def transform_push_statement(accumulators, statement):
337 return CPushStatement(expression=transform_expression(accumulators, statement.expression))
339 def transform_statement(accumulators, statement):
341 conversion.CPSArrayVariableInitializationStatement: transform_array_variable_initialization_statement,
342 conversion.CPSAssignmentStatement: transform_symbol_assignment_statement,
343 conversion.CPSExpressionStatement: transform_expression_statement,
344 conversion.CPSFunctionDefinitionStatement: transform_function_definition_statement,
345 conversion.CPSIfElseStatement: transform_if_else_statement,
346 conversion.CPSListAppendStatement: transform_list_append_statement,
347 conversion.CPSPushStatement: transform_push_statement,
348 conversion.CPSSymbolArrayVariableInitializationStatement: transform_symbol_array_variable_initialization_statement,
349 conversion.CPSVariableInitializationStatement: transform_variable_initialization_statement,
350 conversion.CPSVariableReassignmentStatement: transform_variable_reassignment_statement,
351 }[type(statement)](accumulators, statement)
354 Accumulators = collections.namedtuple(
358 'function_definition_list',
361 'string_literal_list',
365 def transform(program):
366 accumulators = Accumulators(
368 function_definition_list=[],
371 string_literal_list=[],
375 transform_statement(accumulators, statement) for statement in program.statement_list
378 standard_library_set = set()
379 for builtin in accumulators.builtin_set:
380 for standard_library in BUILTINS[builtin]:
381 standard_library_set.add(standard_library)
384 builtin_set=accumulators.builtin_set,
385 function_definition_list=accumulators.function_definition_list,
386 operator_declarations=tuple(sorted(accumulators.operator_set)),
387 statements=statement_list,
388 standard_libraries=standard_library_set,
389 string_literal_list=accumulators.string_literal_list,
390 symbol_list=accumulators.symbol_list,
394 if __name__ == '__main__':