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(
129 CModularDivisionExpression = collections.namedtuple(
130 'CModularDivisionExpression',
137 CFunctionCallExpression = collections.namedtuple(
138 'CFunctionCallExpression',
145 CAssignmentStatement = collections.namedtuple(
146 'CAssignmentStatement',
149 'target_symbol_list_index',
154 CProgram = collections.namedtuple(
159 'standard_libraries',
164 EQUALITY_LEVEL_OPERATOR_MAPPING = {
165 '==': CEqualityExpression,
166 '!=': CInequalityExpression,
167 '<=': CLessThanOrEqualExpression,
168 '>=': CGreaterThanOrEqualExpression,
169 '<': CLessThanExpression,
170 '>': CGreaterThanExpression,
173 def transform_equality_level_expression(builtin_dependencies, symbol_list, expression):
174 # Transform expressions like 1 < 2 < 3 into expressions like 1 < 2 && 2 < 3
175 if isinstance(expression.left, parsing.FurEqualityLevelExpression):
176 left = transform_equality_level_expression(
177 builtin_dependencies,
184 right = transform_expression(
185 builtin_dependencies,
190 # TODO Don't evaluate the middle expression twice
191 return CAndExpression(
193 right=EQUALITY_LEVEL_OPERATOR_MAPPING[expression.operator](
199 return EQUALITY_LEVEL_OPERATOR_MAPPING[expression.operator](
200 left=transform_expression(builtin_dependencies, symbol_list, expression.left),
201 right=transform_expression(builtin_dependencies, symbol_list, expression.right),
207 'print': ['stdio.h'],
211 def transform_expression(builtin_dependencies, symbol_list, expression):
212 if isinstance(expression, parsing.FurParenthesizedExpression):
213 # Parentheses can be removed because everything in the C output is explicitly parenthesized
214 return transform_expression(builtin_dependencies, symbol_list, expression.internal)
216 if isinstance(expression, parsing.FurNegationExpression):
217 return transform_negation_expression(builtin_dependencies, symbol_list, expression)
219 if isinstance(expression, parsing.FurFunctionCallExpression):
220 return transform_function_call_expression(builtin_dependencies, symbol_list, expression)
222 if isinstance(expression, parsing.FurSymbolExpression):
223 if expression.value in ['true', 'false']:
224 return CConstantExpression(value=expression.value)
226 if expression.value not in symbol_list:
227 symbol_list.append(expression.value)
229 return CSymbolExpression(
230 symbol=expression.value,
231 symbol_list_index=symbol_list.index(expression.value),
234 LITERAL_TYPE_MAPPING = {
235 parsing.FurIntegerLiteralExpression: CIntegerLiteral,
236 parsing.FurStringLiteralExpression: CStringLiteral,
239 if type(expression) in LITERAL_TYPE_MAPPING:
240 return LITERAL_TYPE_MAPPING[type(expression)](value=expression.value)
242 if isinstance(expression, parsing.FurEqualityLevelExpression):
243 return transform_equality_level_expression(builtin_dependencies, symbol_list, expression)
245 INFIX_OPERATOR_TO_TYPE_MAPPING = {
246 '+': CAdditionExpression,
247 '-': CSubtractionExpression,
248 '*': CMultiplicationExpression,
249 '//': CIntegerDivisionExpression,
250 '%': CModularDivisionExpression,
253 return INFIX_OPERATOR_TO_TYPE_MAPPING[expression.operator](
254 left=transform_expression(builtin_dependencies, symbol_list, expression.left),
255 right=transform_expression(builtin_dependencies, symbol_list, expression.right),
258 def transform_assignment_statement(builtin_dependencies, symbol_list, assignment_statement):
259 # TODO Check that target is not a builtin
260 if assignment_statement.target not in symbol_list:
261 symbol_list.append(assignment_statement.target)
263 return CAssignmentStatement(
264 target=assignment_statement.target,
265 target_symbol_list_index=symbol_list.index(assignment_statement.target),
266 expression=transform_expression(
267 builtin_dependencies,
269 assignment_statement.expression,
273 def transform_negation_expression(builtin_dependencies, symbol_list, negation_expression):
274 return CNegationExpression(
275 value=transform_expression(builtin_dependencies, symbol_list, negation_expression.value),
278 def transform_function_call_expression(builtin_dependencies, symbol_list, function_call):
279 if function_call.function.value in BUILTINS.keys():
280 # TODO Check that the builtin is actually callable
281 builtin_dependencies.add(function_call.function.value)
283 return CFunctionCallExpression(
284 name='builtin$' + function_call.function.value,
286 transform_expression(builtin_dependencies, symbol_list, arg)
287 for arg in function_call.arguments
293 def transform_statement(builtin_dependencies, symbol_list, statement):
295 parsing.FurAssignmentStatement: transform_assignment_statement,
296 parsing.FurFunctionCallExpression: transform_function_call_expression,
297 }[type(statement)](builtin_dependencies, symbol_list, statement)
299 def transform(program):
304 transform_statement(builtins, symbol_list, statement) for statement in program.statement_list
307 standard_libraries = set()
308 for builtin in builtins:
309 for standard_library in BUILTINS[builtin]:
310 standard_libraries.add(standard_library)
314 statements=c_statements,
315 standard_libraries=standard_libraries,
316 symbol_list=symbol_list,
320 if __name__ == '__main__':