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 CFunctionCallForFurInfixOperator = collections.namedtuple(
42 'CFunctionCallForFurInfixOperator',
50 CFunctionCallExpression = collections.namedtuple(
51 'CFunctionCallExpression',
58 CAssignmentStatement = collections.namedtuple(
59 'CAssignmentStatement',
62 'target_symbol_list_index',
67 CProgram = collections.namedtuple(
77 EQUALITY_LEVEL_OPERATOR_TO_FUNCTION_NAME_MAPPING = {
80 '<=': 'lessThanOrEqual',
81 '>=': 'greaterThanOrEqual',
86 def transform_equality_level_expression(builtin_dependencies, symbol_list, expression):
87 # Transform expressions like 1 < 2 < 3 into expressions like 1 < 2 && 2 < 3
88 if isinstance(expression.left, parsing.FurEqualityLevelExpression):
89 left = transform_equality_level_expression(
97 right = transform_expression(
103 # TODO Don't evaluate the middle expression twice
104 return CFunctionCallForFurInfixOperator(
107 right=CFunctionCallForFurInfixOperator(
108 name=EQUALITY_LEVEL_OPERATOR_TO_FUNCTION_NAME_MAPPING[expression.operator],
114 return CFunctionCallForFurInfixOperator(
115 name=EQUALITY_LEVEL_OPERATOR_TO_FUNCTION_NAME_MAPPING[expression.operator],
116 left=transform_expression(builtin_dependencies, symbol_list, expression.left),
117 right=transform_expression(builtin_dependencies, symbol_list, expression.right),
123 'print': ['stdio.h'],
127 def transform_expression(builtin_dependencies, symbol_list, expression):
128 if isinstance(expression, parsing.FurParenthesizedExpression):
129 # Parentheses can be removed because everything in the C output is explicitly parenthesized
130 return transform_expression(builtin_dependencies, symbol_list, expression.internal)
132 if isinstance(expression, parsing.FurNegationExpression):
133 return transform_negation_expression(builtin_dependencies, symbol_list, expression)
135 if isinstance(expression, parsing.FurFunctionCallExpression):
136 return transform_function_call_expression(builtin_dependencies, symbol_list, expression)
138 if isinstance(expression, parsing.FurSymbolExpression):
139 if expression.value in ['true', 'false']:
140 return CConstantExpression(value=expression.value)
142 if expression.value not in symbol_list:
143 symbol_list.append(expression.value)
145 return CSymbolExpression(
146 symbol=expression.value,
147 symbol_list_index=symbol_list.index(expression.value),
150 LITERAL_TYPE_MAPPING = {
151 parsing.FurIntegerLiteralExpression: CIntegerLiteral,
152 parsing.FurStringLiteralExpression: CStringLiteral,
155 if type(expression) in LITERAL_TYPE_MAPPING:
156 return LITERAL_TYPE_MAPPING[type(expression)](value=expression.value)
158 if isinstance(expression, parsing.FurEqualityLevelExpression):
159 return transform_equality_level_expression(builtin_dependencies, symbol_list, expression)
161 INFIX_OPERATOR_TO_FUNCTION_NAME = {
165 '//': 'integerDivide',
166 '%': 'modularDivide',
169 return CFunctionCallForFurInfixOperator(
170 name=INFIX_OPERATOR_TO_FUNCTION_NAME[expression.operator],
171 left=transform_expression(builtin_dependencies, symbol_list, expression.left),
172 right=transform_expression(builtin_dependencies, symbol_list, expression.right),
175 def transform_assignment_statement(builtin_dependencies, symbol_list, assignment_statement):
176 # TODO Check that target is not a builtin
177 if assignment_statement.target not in symbol_list:
178 symbol_list.append(assignment_statement.target)
180 return CAssignmentStatement(
181 target=assignment_statement.target,
182 target_symbol_list_index=symbol_list.index(assignment_statement.target),
183 expression=transform_expression(
184 builtin_dependencies,
186 assignment_statement.expression,
190 def transform_negation_expression(builtin_dependencies, symbol_list, negation_expression):
191 return CNegationExpression(
192 value=transform_expression(builtin_dependencies, symbol_list, negation_expression.value),
195 def transform_function_call_expression(builtin_dependencies, symbol_list, function_call):
196 if function_call.function.value in BUILTINS.keys():
197 # TODO Check that the builtin is actually callable
198 builtin_dependencies.add(function_call.function.value)
200 return CFunctionCallExpression(
201 name='builtin$' + function_call.function.value,
203 transform_expression(builtin_dependencies, symbol_list, arg)
204 for arg in function_call.arguments
210 def transform_statement(builtin_dependencies, symbol_list, statement):
212 parsing.FurAssignmentStatement: transform_assignment_statement,
213 parsing.FurFunctionCallExpression: transform_function_call_expression,
214 }[type(statement)](builtin_dependencies, symbol_list, statement)
216 def transform(program):
221 transform_statement(builtins, symbol_list, statement) for statement in program.statement_list
224 standard_libraries = set()
225 for builtin in builtins:
226 for standard_library in BUILTINS[builtin]:
227 standard_libraries.add(standard_library)
231 statements=c_statements,
232 standard_libraries=standard_libraries,
233 symbol_list=symbol_list,
237 if __name__ == '__main__':