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.FurInfixExpression) and expression.left.order == 'equality_level':
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.FurInfixExpression):
159 if expression.order == 'equality_level':
160 return transform_equality_level_expression(builtin_dependencies, symbol_list, expression)
162 INFIX_OPERATOR_TO_FUNCTION_NAME = {
166 '//': 'integerDivide',
167 '%': 'modularDivide',
172 return CFunctionCallForFurInfixOperator(
173 name=INFIX_OPERATOR_TO_FUNCTION_NAME[expression.operator],
174 left=transform_expression(builtin_dependencies, symbol_list, expression.left),
175 right=transform_expression(builtin_dependencies, symbol_list, expression.right),
178 raise Exception('Could not transform expression "{}"'.format(expression))
180 def transform_assignment_statement(builtin_dependencies, symbol_list, assignment_statement):
181 # TODO Check that target is not a builtin
182 if assignment_statement.target not in symbol_list:
183 symbol_list.append(assignment_statement.target)
185 return CAssignmentStatement(
186 target=assignment_statement.target,
187 target_symbol_list_index=symbol_list.index(assignment_statement.target),
188 expression=transform_expression(
189 builtin_dependencies,
191 assignment_statement.expression,
195 def transform_negation_expression(builtin_dependencies, symbol_list, negation_expression):
196 return CNegationExpression(
197 value=transform_expression(builtin_dependencies, symbol_list, negation_expression.value),
200 def transform_function_call_expression(builtin_dependencies, symbol_list, function_call):
201 if function_call.function.value in BUILTINS.keys():
202 # TODO Check that the builtin is actually callable
203 builtin_dependencies.add(function_call.function.value)
205 return CFunctionCallExpression(
206 name='builtin$' + function_call.function.value,
208 transform_expression(builtin_dependencies, symbol_list, arg)
209 for arg in function_call.arguments
215 def transform_statement(builtin_dependencies, symbol_list, statement):
217 parsing.FurAssignmentStatement: transform_assignment_statement,
218 parsing.FurFunctionCallExpression: transform_function_call_expression,
219 }[type(statement)](builtin_dependencies, symbol_list, statement)
221 def transform(program):
226 transform_statement(builtins, symbol_list, statement) for statement in program.statement_list
229 standard_libraries = set()
230 for builtin in builtins:
231 for standard_library in BUILTINS[builtin]:
232 standard_libraries.add(standard_library)
236 statements=c_statements,
237 standard_libraries=standard_libraries,
238 symbol_list=symbol_list,
242 if __name__ == '__main__':