5 CIntegerLiteral = collections.namedtuple(
12 CStringLiteral = collections.namedtuple(
19 CConstantExpression = collections.namedtuple(
20 'CConstantExpression',
26 CSymbolExpression = collections.namedtuple(
34 CNegationExpression = collections.namedtuple(
35 'CNegationExpression',
41 CAdditionExpression = collections.namedtuple(
42 'CAdditionExpression',
49 CSubtractionExpression = collections.namedtuple(
50 'CSubtractionExpression',
57 CMultiplicationExpression = collections.namedtuple(
58 'CMultiplicationExpression',
65 CIntegerDivisionExpression = collections.namedtuple(
66 'CIntegerDivisionExpression',
73 CEqualityExpression = collections.namedtuple(
74 'CEqualityExpression',
81 CInequalityExpression = collections.namedtuple(
82 'CInequalityExpression',
89 CGreaterThanOrEqualExpression = collections.namedtuple(
90 'CGreaterThanOrEqualExpression',
97 CLessThanOrEqualExpression = collections.namedtuple(
98 'CLessThanOrEqualExpression',
105 CGreaterThanExpression = collections.namedtuple(
106 'CGreaterThanExpression',
113 CLessThanExpression = collections.namedtuple(
114 'CLessThanExpression',
121 CAndExpression = collections.namedtuple(
130 CModularDivisionExpression = collections.namedtuple(
131 'CModularDivisionExpression',
138 CFunctionCallExpression = collections.namedtuple(
139 'CFunctionCallExpression',
146 CAssignmentStatement = collections.namedtuple(
147 'CAssignmentStatement',
150 'target_symbol_list_index',
155 CProgram = collections.namedtuple(
160 'standard_libraries',
165 EQUALITY_LEVEL_TYPE_MAPPING = {
166 parsing.FurEqualityExpression: CEqualityExpression,
167 parsing.FurInequalityExpression: CInequalityExpression,
168 parsing.FurLessThanOrEqualExpression: CLessThanOrEqualExpression,
169 parsing.FurGreaterThanOrEqualExpression: CGreaterThanOrEqualExpression,
170 parsing.FurLessThanExpression: CLessThanExpression,
171 parsing.FurGreaterThanExpression: CGreaterThanExpression,
174 def transform_equality_level_expression(builtin_dependencies, symbol_list, expression):
175 # Transform expressions like 1 < 2 < 3 into expressions like 1 < 2 && 2 < 3
176 if type(expression.left) in EQUALITY_LEVEL_TYPE_MAPPING:
177 left = transform_equality_level_expression(
178 builtin_dependencies,
185 right = transform_expression(
186 builtin_dependencies,
191 # TODO Don't evaluate the middle expression twice
192 return CAndExpression(
194 right=EQUALITY_LEVEL_TYPE_MAPPING[type(expression)](
200 return EQUALITY_LEVEL_TYPE_MAPPING[type(expression)](
201 left=transform_expression(builtin_dependencies, symbol_list, expression.left),
202 right=transform_expression(builtin_dependencies, symbol_list, expression.right),
208 'print': ['stdio.h'],
212 def transform_expression(builtin_dependencies, symbol_list, expression):
213 if isinstance(expression, parsing.FurParenthesizedExpression):
214 # Parentheses can be removed because everything in the C output is explicitly parenthesized
215 return transform_expression(builtin_dependencies, symbol_list, expression.internal)
217 if isinstance(expression, parsing.FurNegationExpression):
218 return transform_negation_expression(builtin_dependencies, symbol_list, expression)
220 if isinstance(expression, parsing.FurFunctionCallExpression):
221 return transform_function_call_expression(builtin_dependencies, symbol_list, expression)
223 if isinstance(expression, parsing.FurSymbolExpression):
224 if expression.value in ['true', 'false']:
225 return CConstantExpression(value=expression.value)
227 if expression.value not in symbol_list:
228 symbol_list.append(expression.value)
230 return CSymbolExpression(
231 symbol=expression.value,
232 symbol_list_index=symbol_list.index(expression.value),
235 LITERAL_TYPE_MAPPING = {
236 parsing.FurIntegerLiteralExpression: CIntegerLiteral,
237 parsing.FurStringLiteralExpression: CStringLiteral,
240 if type(expression) in LITERAL_TYPE_MAPPING:
241 return LITERAL_TYPE_MAPPING[type(expression)](value=expression.value)
243 if type(expression) in EQUALITY_LEVEL_TYPE_MAPPING:
244 return transform_equality_level_expression(builtin_dependencies, symbol_list, expression)
246 INFIX_TYPE_MAPPING = {
247 parsing.FurAdditionExpression: CAdditionExpression,
248 parsing.FurSubtractionExpression: CSubtractionExpression,
249 parsing.FurMultiplicationExpression: CMultiplicationExpression,
250 parsing.FurIntegerDivisionExpression: CIntegerDivisionExpression,
251 parsing.FurModularDivisionExpression: CModularDivisionExpression,
254 return INFIX_TYPE_MAPPING[type(expression)](
255 left=transform_expression(builtin_dependencies, symbol_list, expression.left),
256 right=transform_expression(builtin_dependencies, symbol_list, expression.right),
259 def transform_assignment_statement(builtin_dependencies, symbol_list, assignment_statement):
260 # TODO Check that target is not a builtin
261 if assignment_statement.target not in symbol_list:
262 symbol_list.append(assignment_statement.target)
264 return CAssignmentStatement(
265 target=assignment_statement.target,
266 target_symbol_list_index=symbol_list.index(assignment_statement.target),
267 expression=transform_expression(
268 builtin_dependencies,
270 assignment_statement.expression,
274 def transform_negation_expression(builtin_dependencies, symbol_list, negation_expression):
275 return CNegationExpression(
276 value=transform_expression(builtin_dependencies, symbol_list, negation_expression.value),
279 def transform_function_call_expression(builtin_dependencies, symbol_list, function_call):
280 if function_call.function.value in BUILTINS.keys():
281 # TODO Check that the builtin is actually callable
282 builtin_dependencies.add(function_call.function.value)
284 return CFunctionCallExpression(
285 name='builtin$' + function_call.function.value,
287 transform_expression(builtin_dependencies, symbol_list, arg)
288 for arg in function_call.arguments
294 def transform_statement(builtin_dependencies, symbol_list, statement):
296 parsing.FurAssignmentStatement: transform_assignment_statement,
297 parsing.FurFunctionCallExpression: transform_function_call_expression,
298 }[type(statement)](builtin_dependencies, symbol_list, statement)
300 def transform(program):
305 transform_statement(builtins, symbol_list, statement) for statement in program.statement_list
308 standard_libraries = set()
309 for builtin in builtins:
310 for standard_library in BUILTINS[builtin]:
311 standard_libraries.add(standard_library)
315 statements=c_statements,
316 standard_libraries=standard_libraries,
317 symbol_list=symbol_list,
321 if __name__ == '__main__':