6 NormalVariableExpression = collections.namedtuple(
7 'NormalVariableExpression',
13 NormalIntegerLiteralExpression = collections.namedtuple(
14 'NormalIntegerLiteralExpression',
20 NormalStringLiteralExpression = collections.namedtuple(
21 'NormalStringLiteralExpression',
27 NormalNegationExpression = collections.namedtuple(
28 'NormalNegationExpression',
30 'internal_expression',
34 NormalInfixExpression = collections.namedtuple(
35 'NormalInfixExpression',
44 NormalFunctionCallExpression = collections.namedtuple(
45 'NormalFunctionCallExpression',
53 NormalArrayVariableInitializationStatement = collections.namedtuple(
54 'NormalArrayVariableInitializationStatement',
61 NormalVariableInitializationStatement = collections.namedtuple(
62 'NormalVariableInitializationStatement',
69 NormalVariableReassignmentStatement = collections.namedtuple(
70 'NormalVariableReassignmentStatement',
77 NormalExpressionStatement = collections.namedtuple(
78 'NormalExpressionStatement',
84 NormalAssignmentStatement = collections.namedtuple(
85 'NormalAssignmentStatement',
92 NormalIfElseStatement = collections.namedtuple(
93 'NormalIfElseStatement',
95 'condition_expression',
101 NormalFunctionDefinitionStatement = collections.namedtuple(
102 'NormalFunctionDefinitionStatement',
105 'argument_name_list',
110 NormalProgram = collections.namedtuple(
117 # TODO Get rid of this
118 def fake_normalization(counter, thing):
119 return (counter, (), thing)
121 def normalize_integer_literal_expression(counter, expression):
122 return (counter, (), NormalIntegerLiteralExpression(integer=expression.integer))
124 def normalize_string_literal_expression(counter, expression):
125 return (counter, (), NormalStringLiteralExpression(string=expression.string))
127 def normalize_function_call_expression(counter, expression):
128 assert isinstance(expression, parsing.FurFunctionCallExpression)
133 for argument in expression.arguments:
134 counter, argument_prestatements, normalized_argument = normalize_expression(counter, argument)
136 for s in argument_prestatements:
137 prestatements.append(s)
139 variable = '${}'.format(counter)
140 prestatements.append(NormalVariableInitializationStatement(
142 expression=normalized_argument,
144 arguments.append(NormalVariableExpression(
149 arguments_variable = '${}'.format(counter)
152 prestatements.append(NormalArrayVariableInitializationStatement(
153 variable=arguments_variable,
154 items=tuple(arguments),
157 counter, function_prestatements, function_expression = normalize_expression(
162 for ps in function_prestatements:
163 prestatements.append(ps)
167 tuple(prestatements),
168 NormalFunctionCallExpression(
169 function=function_expression,
170 argument_count=len(arguments),
171 argument_items=NormalVariableExpression(variable=arguments_variable),
175 def normalize_basic_infix_operation(counter, expression):
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,
197 left_prestatements + right_prestatements + root_prestatements,
198 NormalInfixExpression(
199 order=expression.order, # TODO Do we need this?
200 operator=expression.operator,
201 left=NormalVariableExpression(variable=left_variable),
202 right=NormalVariableExpression(variable=right_variable),
206 def normalize_comparison_expression(counter, expression):
209 while isinstance(expression.left, parsing.FurInfixExpression) and expression.order == 'comparison_level':
210 stack.append((expression.operator, expression.order, expression.right))
211 expression = expression.left
213 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
214 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
216 left_variable = '${}'.format(counter)
218 right_variable = '${}'.format(counter)
221 root_prestatements = (
222 NormalVariableInitializationStatement(
223 variable=left_variable,
224 expression=left_expression,
226 NormalVariableInitializationStatement(
227 variable=right_variable,
228 expression=right_expression,
232 counter, result_prestatements, result_expression = (
234 left_prestatements + right_prestatements + root_prestatements,
235 # TODO Implement short-circuiting
236 NormalInfixExpression(
237 order=expression.order, # TODO Do we need this?
238 operator=expression.operator,
239 left=NormalVariableExpression(variable=left_variable),
240 right=NormalVariableExpression(variable=right_variable),
244 while len(stack) > 0:
245 right_operator, right_order, right_expression = stack.pop()
246 and_right_expression = parsing.FurInfixExpression(
247 operator=right_operator,
249 left=NormalVariableExpression(variable=right_variable),
250 right=right_expression,
253 and_expression = parsing.FurInfixExpression(
256 left=result_expression,
257 right=and_right_expression,
260 counter, and_prestatements, result_expression = normalize_boolean_expression(
265 result_prestatements = result_prestatements + and_prestatements
267 return (counter, result_prestatements, result_expression)
269 def normalize_boolean_expression(counter, expression):
270 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
271 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
273 result_variable = '${}'.format(counter)
274 if_else_prestatment = NormalVariableInitializationStatement(variable=result_variable, expression=left_expression)
277 condition_expression=NormalVariableExpression(variable=result_variable)
278 short_circuited_statements = right_prestatements + (NormalVariableReassignmentStatement(variable=result_variable, expression=right_expression),)
280 if expression.operator == 'and':
281 if_else_statement = NormalIfElseStatement(
282 condition_expression=condition_expression,
283 if_statements=short_circuited_statements,
287 elif expression.operator == 'or':
288 if_else_statement = NormalIfElseStatement(
289 condition_expression=condition_expression,
291 else_statements=short_circuited_statements,
295 raise Exception('Unable to handle operator "{}"'.format(expression.operator))
299 left_prestatements + (if_else_prestatment, if_else_statement),
300 NormalVariableExpression(variable=result_variable),
304 def normalize_infix_expression(counter, expression):
306 'multiplication_level': normalize_basic_infix_operation,
307 'addition_level': normalize_basic_infix_operation,
308 'comparison_level': normalize_comparison_expression,
309 'and_level': normalize_boolean_expression,
310 'or_level': normalize_boolean_expression,
311 }[expression.order](counter, expression)
313 def normalize_negation_expression(counter, expression):
314 counter, prestatements, internal_expression = normalize_expression(counter, expression.value)
316 internal_variable = '${}'.format(counter)
321 prestatements + (NormalVariableInitializationStatement(variable=internal_variable, expression=internal_expression),),
322 NormalNegationExpression(internal_expression=NormalVariableExpression(variable=internal_variable)),
325 def normalize_expression(counter, expression):
327 NormalInfixExpression: fake_normalization,
328 NormalVariableExpression: fake_normalization,
329 parsing.FurFunctionCallExpression: normalize_function_call_expression,
330 parsing.FurInfixExpression: normalize_infix_expression,
331 parsing.FurIntegerLiteralExpression: normalize_integer_literal_expression,
332 parsing.FurNegationExpression: normalize_negation_expression,
333 parsing.FurStringLiteralExpression: normalize_string_literal_expression,
334 parsing.FurSymbolExpression: fake_normalization,
335 }[type(expression)](counter, expression)
337 def normalize_expression_statement(counter, statement):
338 # TODO Verify all expression types are supported and just call normalize_expression
339 counter, prestatements, normalized = {
340 parsing.FurFunctionCallExpression: normalize_function_call_expression,
341 parsing.FurSymbolExpression: normalize_expression,
342 parsing.FurInfixExpression: normalize_expression,
343 parsing.FurIntegerLiteralExpression: normalize_expression,
344 }[type(statement.expression)](counter, statement.expression)
349 NormalExpressionStatement(expression=normalized),
352 def normalize_function_definition_statement(counter, statement):
356 NormalFunctionDefinitionStatement(
358 argument_name_list=statement.argument_name_list,
359 statement_list=normalize_statement_list(statement.statement_list),
363 def normalize_assignment_statement(counter, statement):
364 counter, prestatements, normalized_expression = normalize_expression(counter, statement.expression)
368 NormalAssignmentStatement(
369 target=statement.target,
370 expression=normalized_expression,
374 def normalize_statement(counter, statement):
376 parsing.FurAssignmentStatement: normalize_assignment_statement,
377 parsing.FurExpressionStatement: normalize_expression_statement,
378 parsing.FurFunctionDefinitionStatement: normalize_function_definition_statement,
379 }[type(statement)](counter, statement)
381 @util.force_generator(tuple)
382 def normalize_statement_list(statement_list):
385 for statement in statement_list:
386 counter, prestatements, normalized = normalize_statement(counter, statement)
387 for s in prestatements:
391 def normalize(program):
393 return NormalProgram(
394 statement_list=normalize_statement_list(program.statement_list),