4 import parsing # TODO Remove this import, as we should be normalizing everything before it gets here
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 CDotExpression = collections.namedtuple(
54 CNegationExpression = collections.namedtuple(
55 'CNegationExpression',
61 CFunctionCallForFurInfixOperator = collections.namedtuple(
62 'CFunctionCallForFurInfixOperator',
70 CPushStatement = collections.namedtuple(
77 CFunctionCallExpression = collections.namedtuple(
78 'CFunctionCallExpression',
80 'function_expression',
85 # TODO We are currently not changing variables, just preventing them from being accessed.
86 CSymbolAssignmentStatement = collections.namedtuple(
87 'CSymbolAssignmentStatement',
90 'target_symbol_list_index',
95 CArrayVariableInitializationStatement = collections.namedtuple(
96 'CArrayVariableInitializationStatement',
103 CSymbolArrayVariableInitializationStatement = collections.namedtuple(
104 'CSymbolArrayVariableInitializationStatement',
108 'symbol_list_indices',
112 CVariableInitializationStatement = collections.namedtuple(
113 'CVariableInitializationStatement',
120 CVariableReassignmentStatement = collections.namedtuple(
121 'CVariableReassignmentStatement',
128 CExpressionStatement = collections.namedtuple(
129 'CExpressionStatement',
135 CIfElseStatement = collections.namedtuple(
138 'condition_expression',
140 'else_statement_list',
144 CFunctionDeclaration = collections.namedtuple(
145 'CFunctionDeclaration',
151 # TODO If a function definition doesn't end with an expression, we have issues currently because we try to return statement.
152 # TODO Closures currently wrap entire defining environment, even symbols that are not used, which makes garbage collection ineffective.
153 CFunctionDefinition = collections.namedtuple(
154 'CFunctionDefinition',
157 'argument_name_list',
162 CProgram = collections.namedtuple(
166 'function_definition_list',
167 'operator_declarations',
169 'standard_libraries',
170 'string_literal_list',
179 'print': ['stdio.h'],
183 def transform_variable_expression(accumulators, expression):
184 assert isinstance(expression, normalization.NormalVariableExpression)
185 return CVariableExpression(variable=expression.variable)
187 def transform_string_literal_expression(accumulators, expression):
188 value = expression.string
191 index = accumulators.string_literal_list.index(value)
193 index = len(accumulators.string_literal_list)
194 accumulators.string_literal_list.append(value)
196 return CStringLiteral(index=index, value=value)
198 def transform_symbol_expression(accumulators, expression):
199 if expression.symbol in BUILTINS:
200 accumulators.builtin_set.add(expression.symbol)
203 symbol_list_index = accumulators.symbol_list.index(expression.symbol)
205 symbol_list_index = len(accumulators.symbol_list)
206 accumulators.symbol_list.append(expression.symbol)
208 return CSymbolExpression(
209 symbol=expression.symbol,
210 symbol_list_index=symbol_list_index,
213 CInfixDeclaration = collections.namedtuple(
223 FUR_INFIX_OPERATOR_TO_C_FUNCTION = {
227 FUR_INFIX_OPERATOR_TO_C_INFIX_OPERATOR = {
228 '+': CInfixDeclaration(name='add', in_type='integer', out_type='integer', operator='+'),
229 '-': CInfixDeclaration(name='subtract', in_type='integer', out_type='integer', operator='-'),
230 '*': CInfixDeclaration(name='multiply', in_type='integer', out_type='integer', operator='*'),
231 '//': CInfixDeclaration(name='integerDivide', in_type='integer', out_type='integer', operator='/'),
232 '%': CInfixDeclaration(name='modularDivide', in_type='integer', out_type='integer', operator='%'),
233 'and': CInfixDeclaration(name='and', in_type='boolean', out_type='boolean', operator='&&'),
234 'or': CInfixDeclaration(name='or', in_type='boolean', out_type='boolean', operator='||'),
235 '==': CInfixDeclaration(name='equals', in_type='integer', out_type='boolean', operator='=='),
236 '!=': CInfixDeclaration(name='notEquals', in_type='integer', out_type='boolean', operator='!='),
237 '<=': CInfixDeclaration(name='lessThanOrEqual', in_type='integer', out_type='boolean', operator='<='),
238 '>=': CInfixDeclaration(name='greaterThanOrEqual', in_type='integer', out_type='boolean', operator='>='),
239 '<': CInfixDeclaration(name='lessThan', in_type='integer', out_type='boolean', operator='<'),
240 '>': CInfixDeclaration(name='greaterThan', in_type='integer', out_type='boolean', operator='>'),
243 def transform_comparison_level_expression(accumulators, expression):
244 accumulators.operator_set.add(FUR_INFIX_OPERATOR_TO_C_INFIX_OPERATOR[expression.operator])
246 # Transform expressions like 1 < 2 < 3 into expressions like 1 < 2 && 2 < 3
247 if isinstance(expression.left, parsing.FurInfixExpression) and expression.left.order == 'comparison_level':
248 left = transform_comparison_level_expression(
255 right = transform_expression(
260 # TODO Don't evaluate the middle expression twice
261 return CFunctionCallForFurInfixOperator(
264 right=CFunctionCallForFurInfixOperator(
265 name=FUR_INFIX_OPERATOR_TO_C_INFIX_OPERATOR[expression.operator].name,
271 return CFunctionCallForFurInfixOperator(
272 name=FUR_INFIX_OPERATOR_TO_C_INFIX_OPERATOR[expression.operator].name,
273 left=transform_expression(accumulators, expression.left),
274 right=transform_expression(accumulators, expression.right),
277 def transform_infix_operator_without_c_equivalent(accumulators, expression):
278 return CFunctionCallForFurInfixOperator(
280 left=transform_expression(accumulators, expression.left),
281 right=transform_expression(accumulators, expression.right),
283 def transform_infix_expression(accumulators, expression):
284 if expression.operator in FUR_INFIX_OPERATOR_TO_C_FUNCTION:
285 return transform_infix_operator_without_c_equivalent(accumulators, expression)
287 if expression.order == 'comparison_level':
288 return transform_comparison_level_expression(accumulators, expression)
290 accumulators.operator_set.add(FUR_INFIX_OPERATOR_TO_C_INFIX_OPERATOR[expression.operator])
292 return CFunctionCallForFurInfixOperator(
293 name=FUR_INFIX_OPERATOR_TO_C_INFIX_OPERATOR[expression.operator].name,
294 left=transform_expression(accumulators, expression.left),
295 right=transform_expression(accumulators, expression.right),
298 def transform_integer_literal_expression(accumulators, expression):
299 return CIntegerLiteral(value=expression.integer)
301 def transform_negation_expression(accumulators, expression):
302 return CNegationExpression(
303 value=transform_expression(accumulators, expression.internal_expression),
306 CListConstructExpression = collections.namedtuple(
307 'CListConstructExpression',
313 CListAppendStatement = collections.namedtuple(
314 'CListAppendStatement',
321 CListGetExpression = collections.namedtuple(
322 'CListGetExpression',
329 def transform_structure_literal_expression(accumulators, expression):
330 return CStructureLiteralExpression(
331 field_count=expression.field_count,
332 symbol_list_variable=expression.symbol_list_variable,
333 value_list_variable=expression.value_list_variable,
336 def transform_dot_expression(accumulators, expression):
338 symbol_list_index = accumulators.symbol_list.index(expression.field)
341 symbol_list_index = len(accumulators.symbol_list)
342 accumulators.symbol_list.append(expression.field)
344 return CDotExpression(
345 instance=transform_variable_expression(accumulators, expression.instance),
346 symbol=expression.field,
347 symbol_list_index=symbol_list_index,
350 def transform_list_construct_expression(accumulators, expression):
351 return CListConstructExpression(allocate=expression.allocate)
353 def transform_list_get_expression(accumulators, expression):
354 return CListGetExpression(
355 list_expression=transform_expression(accumulators, expression.list_expression),
356 index_expression=transform_expression(accumulators, expression.index_expression),
359 def transform_list_append_statement(accumulators, expression):
360 return CListAppendStatement(
361 list_expression=transform_expression(accumulators, expression.list_expression),
362 item_expression=transform_expression(accumulators, expression.item_expression),
365 def transform_expression(accumulators, expression):
366 # TODO Clean up handlers for parsing expressions
368 parsing.FurInfixExpression: transform_infix_expression,
369 parsing.FurIntegerLiteralExpression: transform_integer_literal_expression,
370 parsing.FurNegationExpression: transform_negation_expression,
371 parsing.FurStringLiteralExpression: transform_string_literal_expression,
372 normalization.NormalDotExpression: transform_dot_expression,
373 normalization.NormalFunctionCallExpression: transform_function_call_expression,
374 normalization.NormalInfixExpression: transform_infix_expression,
375 normalization.NormalIntegerLiteralExpression: transform_integer_literal_expression,
376 normalization.NormalListConstructExpression: transform_list_construct_expression,
377 normalization.NormalListGetExpression: transform_list_get_expression,
378 normalization.NormalNegationExpression: transform_negation_expression,
379 normalization.NormalStructureLiteralExpression: transform_structure_literal_expression,
380 normalization.NormalStringLiteralExpression: transform_string_literal_expression,
381 normalization.NormalSymbolExpression: transform_symbol_expression,
382 normalization.NormalVariableExpression: transform_variable_expression,
383 }[type(expression)](accumulators, expression)
385 def transform_symbol_assignment_statement(accumulators, assignment_statement):
386 # TODO Check that target is not a builtin
388 symbol_list_index = accumulators.symbol_list.index(assignment_statement.target)
390 symbol_list_index = len(accumulators.symbol_list)
391 accumulators.symbol_list.append(assignment_statement.target)
393 return CSymbolAssignmentStatement(
394 target=assignment_statement.target,
395 target_symbol_list_index=symbol_list_index,
396 expression=transform_expression(
398 assignment_statement.expression,
402 def transform_function_call_expression(accumulators, function_call):
403 # TODO Use the symbol from SYMBOL LIST
404 return CFunctionCallExpression(
405 function_expression=transform_expression(accumulators, function_call.function_expression),
406 argument_count=function_call.argument_count,
409 def transform_expression_statement(accumulators, statement):
410 return CExpressionStatement(
411 expression=transform_expression(accumulators, statement.expression),
414 def transform_if_else_statement(accumulators, statement):
415 return CIfElseStatement(
416 condition_expression=transform_expression(accumulators, statement.condition_expression),
417 if_statement_list=tuple(transform_statement(accumulators, s) for s in statement.if_statement_list),
418 else_statement_list=tuple(transform_statement(accumulators, s) for s in statement.else_statement_list),
421 def transform_array_variable_initialization_statement(accumulators, statement):
422 return CArrayVariableInitializationStatement(
423 variable=statement.variable,
424 items=tuple(transform_expression(accumulators, i) for i in statement.items),
427 def transform_symbol_array_variable_initialization_statement(accumulators, statement):
428 symbol_list_indices = []
430 for symbol in statement.symbol_list:
432 symbol_list_index = accumulators.symbol_list.index(symbol)
434 symbol_list_index = len(accumulators.symbol_list)
435 accumulators.symbol_list.append(symbol)
437 symbol_list_indices.append(symbol_list_index)
439 return CSymbolArrayVariableInitializationStatement(
440 variable=statement.variable,
441 symbol_list=statement.symbol_list,
442 symbol_list_indices=tuple(symbol_list_indices),
445 def transform_variable_initialization_statement(accumulators, statement):
446 return CVariableInitializationStatement(
447 variable=statement.variable,
448 expression=transform_expression(accumulators, statement.expression),
451 def transform_variable_reassignment_statement(accumulators, statement):
452 return CVariableReassignmentStatement(
453 variable=statement.variable,
454 expression=transform_expression(accumulators, statement.expression),
457 def transform_function_definition_statement(accumulators, statement):
458 # TODO Allow defining the same function in different contexts
459 if any(fd.name == statement.name for fd in accumulators.function_definition_list):
460 raise Exception('A function with name "{}" already exists'.format(statement.name))
462 # TODO Add argument names to the symbol table
463 accumulators.function_definition_list.append(CFunctionDefinition(
465 argument_name_list=statement.argument_name_list,
466 statement_list=tuple(transform_statement(accumulators, s) for s in statement.statement_list)
469 return CFunctionDeclaration(name=statement.name)
471 def transform_push_statement(accumulators, statement):
472 return CPushStatement(expression=transform_expression(accumulators, statement.expression))
474 def transform_statement(accumulators, statement):
476 parsing.FurExpressionStatement: transform_expression_statement,
477 normalization.NormalArrayVariableInitializationStatement: transform_array_variable_initialization_statement,
478 normalization.NormalAssignmentStatement: transform_symbol_assignment_statement,
479 normalization.NormalExpressionStatement: transform_expression_statement,
480 normalization.NormalFunctionDefinitionStatement: transform_function_definition_statement,
481 normalization.NormalIfElseStatement: transform_if_else_statement,
482 normalization.NormalListAppendStatement: transform_list_append_statement,
483 normalization.NormalPushStatement: transform_push_statement,
484 normalization.NormalSymbolArrayVariableInitializationStatement: transform_symbol_array_variable_initialization_statement,
485 normalization.NormalVariableInitializationStatement: transform_variable_initialization_statement,
486 normalization.NormalVariableReassignmentStatement: transform_variable_reassignment_statement,
487 }[type(statement)](accumulators, statement)
490 Accumulators = collections.namedtuple(
494 'function_definition_list',
497 'string_literal_list',
501 def transform(program):
502 accumulators = Accumulators(
504 function_definition_list=[],
507 string_literal_list=[],
511 transform_statement(accumulators, statement) for statement in program.statement_list
514 standard_library_set = set()
515 for builtin in accumulators.builtin_set:
516 for standard_library in BUILTINS[builtin]:
517 standard_library_set.add(standard_library)
520 builtin_set=accumulators.builtin_set,
521 function_definition_list=accumulators.function_definition_list,
522 operator_declarations=tuple(sorted(accumulators.operator_set)),
523 statements=statement_list,
524 standard_libraries=standard_library_set,
525 string_literal_list=accumulators.string_literal_list,
526 symbol_list=accumulators.symbol_list,
530 if __name__ == '__main__':