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(accumulators, 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(
96 right = transform_expression(
101 # TODO Don't evaluate the middle expression twice
102 return CFunctionCallForFurInfixOperator(
105 right=CFunctionCallForFurInfixOperator(
106 name=EQUALITY_LEVEL_OPERATOR_TO_FUNCTION_NAME_MAPPING[expression.operator],
112 return CFunctionCallForFurInfixOperator(
113 name=EQUALITY_LEVEL_OPERATOR_TO_FUNCTION_NAME_MAPPING[expression.operator],
114 left=transform_expression(accumulators, expression.left),
115 right=transform_expression(accumulators, expression.right),
121 'print': ['stdio.h'],
125 def transform_expression(accumulators, expression):
126 if isinstance(expression, parsing.FurParenthesizedExpression):
127 # Parentheses can be removed because everything in the C output is explicitly parenthesized
128 return transform_expression(accumulators, expression.internal)
130 if isinstance(expression, parsing.FurNegationExpression):
131 return transform_negation_expression(accumulators, expression)
133 if isinstance(expression, parsing.FurFunctionCallExpression):
134 return transform_function_call_expression(accumulators, expression)
136 if isinstance(expression, parsing.FurSymbolExpression):
137 if expression.value in ['true', 'false']:
138 return CConstantExpression(value=expression.value)
140 if expression.value not in accumulators.symbol_list:
141 symbol_list.append(expression.value)
143 return CSymbolExpression(
144 symbol=expression.value,
145 symbol_list_index=accumulators.symbol_list.index(expression.value),
148 LITERAL_TYPE_MAPPING = {
149 parsing.FurIntegerLiteralExpression: CIntegerLiteral,
150 parsing.FurStringLiteralExpression: CStringLiteral,
153 if type(expression) in LITERAL_TYPE_MAPPING:
154 return LITERAL_TYPE_MAPPING[type(expression)](value=expression.value)
156 if isinstance(expression, parsing.FurInfixExpression):
157 if expression.order == 'equality_level':
158 return transform_equality_level_expression(accumulators, expression)
160 INFIX_OPERATOR_TO_FUNCTION_NAME = {
164 '//': 'integerDivide',
165 '%': 'modularDivide',
170 return CFunctionCallForFurInfixOperator(
171 name=INFIX_OPERATOR_TO_FUNCTION_NAME[expression.operator],
172 left=transform_expression(accumulators, expression.left),
173 right=transform_expression(accumulators, expression.right),
176 raise Exception('Could not transform expression "{}"'.format(expression))
178 def transform_assignment_statement(accumulators, assignment_statement):
179 # TODO Check that target is not a builtin
180 if assignment_statement.target not in accumulators.symbol_list:
181 accumulators.symbol_list.append(assignment_statement.target)
183 return CAssignmentStatement(
184 target=assignment_statement.target,
185 target_symbol_list_index=accumulators.symbol_list.index(assignment_statement.target),
186 expression=transform_expression(
188 assignment_statement.expression,
192 def transform_negation_expression(accumulators, negation_expression):
193 return CNegationExpression(
194 value=transform_expression(accumulators, negation_expression.value),
197 def transform_function_call_expression(accumulators, function_call):
198 if function_call.function.value in BUILTINS.keys():
199 # TODO Check that the builtin is actually callable
200 accumulators.builtin_set.add(function_call.function.value)
202 return CFunctionCallExpression(
203 name='builtin$' + function_call.function.value,
205 transform_expression(accumulators, arg)
206 for arg in function_call.arguments
212 def transform_statement(accumulators, statement):
214 parsing.FurAssignmentStatement: transform_assignment_statement,
215 parsing.FurFunctionCallExpression: transform_function_call_expression,
216 }[type(statement)](accumulators, statement)
219 Accumulators = collections.namedtuple(
227 def transform(program):
228 accumulators = Accumulators(
234 transform_statement(accumulators, statement) for statement in program.statement_list
237 standard_libraries = set()
238 for builtin in accumulators.builtin_set:
239 for standard_library in BUILTINS[builtin]:
240 standard_libraries.add(standard_library)
243 builtin_set=accumulators.builtin_set,
244 statements=c_statements,
245 standard_libraries=standard_libraries,
246 symbol_list=accumulators.symbol_list,
250 if __name__ == '__main__':