6 NormalVariableExpression = collections.namedtuple(
7 'NormalVariableExpression',
13 NormalNegationExpression = collections.namedtuple(
14 'NormalNegationExpression',
16 'internal_expression',
20 NormalInfixExpression = collections.namedtuple(
21 'NormalInfixExpression',
30 NormalFunctionCallExpression = collections.namedtuple(
31 'NormalFunctionCallExpression',
39 NormalArrayVariableInitializationStatement = collections.namedtuple(
40 'NormalArrayVariableInitializationStatement',
47 NormalVariableInitializationStatement = collections.namedtuple(
48 'NormalVariableInitializationStatement',
55 NormalVariableReassignmentStatement = collections.namedtuple(
56 'NormalVariableReassignmentStatement',
63 NormalExpressionStatement = collections.namedtuple(
64 'NormalExpressionStatement',
70 NormalIfElseStatement = collections.namedtuple(
71 'NormalIfElseStatement',
73 'condition_expression',
79 NormalFunctionDefinitionStatement = collections.namedtuple(
80 'NormalFunctionDefinitionStatement',
87 NormalProgram = collections.namedtuple(
94 # TODO Get rid of this
95 def fake_normalization(counter, thing):
96 return (counter, (), thing)
98 def normalize_function_call_expression(counter, expression):
99 assert isinstance(expression, parsing.FurFunctionCallExpression)
104 for argument in expression.arguments:
105 counter, argument_prestatements, normalized_argument = normalize_expression(counter, argument)
107 for s in argument_prestatements:
108 prestatements.append(s)
110 variable = '${}'.format(counter)
111 prestatements.append(NormalVariableInitializationStatement(
113 expression=normalized_argument,
115 arguments.append(NormalVariableExpression(
120 arguments_variable = '${}'.format(counter)
123 prestatements.append(NormalArrayVariableInitializationStatement(
124 variable=arguments_variable,
125 items=tuple(arguments),
130 tuple(prestatements),
131 NormalFunctionCallExpression(
132 function=expression.function, # TODO Normalize the function
133 argument_count=len(arguments),
134 argument_items=NormalVariableExpression(variable=arguments_variable),
138 def normalize_basic_infix_operation(counter, expression):
139 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
140 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
142 left_variable = '${}'.format(counter)
144 right_variable = '${}'.format(counter)
147 root_prestatements = (
148 NormalVariableInitializationStatement(
149 variable=left_variable,
150 expression=left_expression,
152 NormalVariableInitializationStatement(
153 variable=right_variable,
154 expression=right_expression,
160 left_prestatements + right_prestatements + root_prestatements,
161 NormalInfixExpression(
162 order=expression.order, # TODO Do we need this?
163 operator=expression.operator,
164 left=NormalVariableExpression(variable=left_variable),
165 right=NormalVariableExpression(variable=right_variable),
169 def normalize_comparison_expression(counter, expression):
172 while isinstance(expression.left, parsing.FurInfixExpression) and expression.order == 'comparison_level':
173 stack.append((expression.operator, expression.order, expression.right))
174 expression = expression.left
176 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
177 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
179 left_variable = '${}'.format(counter)
181 right_variable = '${}'.format(counter)
184 root_prestatements = (
185 NormalVariableInitializationStatement(
186 variable=left_variable,
187 expression=left_expression,
189 NormalVariableInitializationStatement(
190 variable=right_variable,
191 expression=right_expression,
195 counter, result_prestatements, result_expression = (
197 left_prestatements + right_prestatements + root_prestatements,
198 # TODO Implement short-circuiting
199 NormalInfixExpression(
200 order=expression.order, # TODO Do we need this?
201 operator=expression.operator,
202 left=NormalVariableExpression(variable=left_variable),
203 right=NormalVariableExpression(variable=right_variable),
207 while len(stack) > 0:
208 right_operator, right_order, right_expression = stack.pop()
209 and_right_expression = parsing.FurInfixExpression(
210 operator=right_operator,
212 left=NormalVariableExpression(variable=right_variable),
213 right=right_expression,
216 and_expression = parsing.FurInfixExpression(
219 left=result_expression,
220 right=and_right_expression,
223 counter, and_prestatements, result_expression = normalize_boolean_expression(
228 result_prestatements = result_prestatements + and_prestatements
230 return (counter, result_prestatements, result_expression)
232 def normalize_boolean_expression(counter, expression):
233 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
234 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
236 result_variable = '${}'.format(counter)
237 if_else_prestatment = NormalVariableInitializationStatement(variable=result_variable, expression=left_expression)
240 condition_expression=NormalVariableExpression(variable=result_variable)
241 short_circuited_statements = right_prestatements + (NormalVariableReassignmentStatement(variable=result_variable, expression=right_expression),)
243 if expression.operator == 'and':
244 if_else_statement = NormalIfElseStatement(
245 condition_expression=condition_expression,
246 if_statements=short_circuited_statements,
250 elif expression.operator == 'or':
251 if_else_statement = NormalIfElseStatement(
252 condition_expression=condition_expression,
254 else_statements=short_circuited_statements,
258 raise Exception('Unable to handle operator "{}"'.format(expression.operator))
262 left_prestatements + (if_else_prestatment, if_else_statement),
263 NormalVariableExpression(variable=result_variable),
267 def normalize_infix_expression(counter, expression):
269 'multiplication_level': normalize_basic_infix_operation,
270 'addition_level': normalize_basic_infix_operation,
271 'comparison_level': normalize_comparison_expression,
272 'and_level': normalize_boolean_expression,
273 'or_level': normalize_boolean_expression,
274 }[expression.order](counter, expression)
276 def normalize_negation_expression(counter, expression):
277 counter, prestatements, internal_expression = normalize_expression(counter, expression.value)
279 internal_variable = '${}'.format(counter)
284 prestatements + (NormalVariableInitializationStatement(variable=internal_variable, expression=internal_expression),),
285 NormalNegationExpression(internal_expression=NormalVariableExpression(variable=internal_variable)),
288 def normalize_parenthesized_expression(counter, expression):
289 return normalize_expression(counter, expression.internal)
291 def normalize_expression(counter, expression):
293 NormalInfixExpression: fake_normalization,
294 NormalVariableExpression: fake_normalization,
295 parsing.FurFunctionCallExpression: normalize_function_call_expression,
296 parsing.FurInfixExpression: normalize_infix_expression,
297 parsing.FurIntegerLiteralExpression: fake_normalization,
298 parsing.FurNegationExpression: normalize_negation_expression,
299 parsing.FurParenthesizedExpression: normalize_parenthesized_expression,
300 parsing.FurStringLiteralExpression: fake_normalization,
301 parsing.FurSymbolExpression: fake_normalization,
302 }[type(expression)](counter, expression)
304 def normalize_expression_statement(counter, statement):
305 # TODO Verify all expression types are supported and just call normalize_expression
306 counter, prestatements, normalized = {
307 parsing.FurFunctionCallExpression: normalize_function_call_expression,
308 parsing.FurSymbolExpression: normalize_expression,
309 parsing.FurInfixExpression: normalize_expression,
310 parsing.FurIntegerLiteralExpression: normalize_expression,
311 }[type(statement.expression)](counter, statement.expression)
316 NormalExpressionStatement(expression=normalized),
319 def normalize_function_definition_statement(counter, statement):
323 NormalFunctionDefinitionStatement(
325 statement_list=normalize_statement_list(statement.statement_list),
329 def normalize_statement(counter, statement):
331 parsing.FurAssignmentStatement: fake_normalization, # TODO unfake this
332 parsing.FurExpressionStatement: normalize_expression_statement,
333 parsing.FurFunctionDefinitionStatement: normalize_function_definition_statement,
334 }[type(statement)](counter, statement)
336 @util.force_generator(tuple)
337 def normalize_statement_list(statement_list):
340 for statement in statement_list:
341 counter, prestatements, normalized = normalize_statement(counter, statement)
342 for s in prestatements:
346 def normalize(program):
348 return NormalProgram(
349 statement_list=normalize_statement_list(program.statement_list),