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',
170 return CFunctionCallForFurInfixOperator(
171 name=INFIX_OPERATOR_TO_FUNCTION_NAME[expression.operator],
172 left=transform_expression(builtin_dependencies, symbol_list, expression.left),
173 right=transform_expression(builtin_dependencies, symbol_list, expression.right),
176 raise Exception('Could not transform expression "{}"'.format(expression))
178 def transform_assignment_statement(builtin_dependencies, symbol_list, assignment_statement):
179 # TODO Check that target is not a builtin
180 if assignment_statement.target not in symbol_list:
181 symbol_list.append(assignment_statement.target)
183 return CAssignmentStatement(
184 target=assignment_statement.target,
185 target_symbol_list_index=symbol_list.index(assignment_statement.target),
186 expression=transform_expression(
187 builtin_dependencies,
189 assignment_statement.expression,
193 def transform_negation_expression(builtin_dependencies, symbol_list, negation_expression):
194 return CNegationExpression(
195 value=transform_expression(builtin_dependencies, symbol_list, negation_expression.value),
198 def transform_function_call_expression(builtin_dependencies, symbol_list, function_call):
199 if function_call.function.value in BUILTINS.keys():
200 # TODO Check that the builtin is actually callable
201 builtin_dependencies.add(function_call.function.value)
203 return CFunctionCallExpression(
204 name='builtin$' + function_call.function.value,
206 transform_expression(builtin_dependencies, symbol_list, arg)
207 for arg in function_call.arguments
213 def transform_statement(builtin_dependencies, symbol_list, statement):
215 parsing.FurAssignmentStatement: transform_assignment_statement,
216 parsing.FurFunctionCallExpression: transform_function_call_expression,
217 }[type(statement)](builtin_dependencies, symbol_list, statement)
219 def transform(program):
224 transform_statement(builtins, symbol_list, statement) for statement in program.statement_list
227 standard_libraries = set()
228 for builtin in builtins:
229 for standard_library in BUILTINS[builtin]:
230 standard_libraries.add(standard_library)
234 statements=c_statements,
235 standard_libraries=standard_libraries,
236 symbol_list=symbol_list,
240 if __name__ == '__main__':