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 NormalAssignmentStatement = collections.namedtuple(
71 'NormalAssignmentStatement',
78 NormalIfElseStatement = collections.namedtuple(
79 'NormalIfElseStatement',
81 'condition_expression',
87 NormalFunctionDefinitionStatement = collections.namedtuple(
88 'NormalFunctionDefinitionStatement',
96 NormalProgram = collections.namedtuple(
103 # TODO Get rid of this
104 def fake_normalization(counter, thing):
105 return (counter, (), thing)
107 def normalize_function_call_expression(counter, expression):
108 assert isinstance(expression, parsing.FurFunctionCallExpression)
113 for argument in expression.arguments:
114 counter, argument_prestatements, normalized_argument = normalize_expression(counter, argument)
116 for s in argument_prestatements:
117 prestatements.append(s)
119 variable = '${}'.format(counter)
120 prestatements.append(NormalVariableInitializationStatement(
122 expression=normalized_argument,
124 arguments.append(NormalVariableExpression(
129 arguments_variable = '${}'.format(counter)
132 prestatements.append(NormalArrayVariableInitializationStatement(
133 variable=arguments_variable,
134 items=tuple(arguments),
137 counter, function_prestatements, function_expression = normalize_expression(
142 for ps in function_prestatements:
143 prestatements.append(ps)
147 tuple(prestatements),
148 NormalFunctionCallExpression(
149 function=function_expression,
150 argument_count=len(arguments),
151 argument_items=NormalVariableExpression(variable=arguments_variable),
155 def normalize_basic_infix_operation(counter, expression):
156 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
157 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
159 left_variable = '${}'.format(counter)
161 right_variable = '${}'.format(counter)
164 root_prestatements = (
165 NormalVariableInitializationStatement(
166 variable=left_variable,
167 expression=left_expression,
169 NormalVariableInitializationStatement(
170 variable=right_variable,
171 expression=right_expression,
177 left_prestatements + right_prestatements + root_prestatements,
178 NormalInfixExpression(
179 order=expression.order, # TODO Do we need this?
180 operator=expression.operator,
181 left=NormalVariableExpression(variable=left_variable),
182 right=NormalVariableExpression(variable=right_variable),
186 def normalize_comparison_expression(counter, expression):
189 while isinstance(expression.left, parsing.FurInfixExpression) and expression.order == 'comparison_level':
190 stack.append((expression.operator, expression.order, expression.right))
191 expression = expression.left
193 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
194 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
196 left_variable = '${}'.format(counter)
198 right_variable = '${}'.format(counter)
201 root_prestatements = (
202 NormalVariableInitializationStatement(
203 variable=left_variable,
204 expression=left_expression,
206 NormalVariableInitializationStatement(
207 variable=right_variable,
208 expression=right_expression,
212 counter, result_prestatements, result_expression = (
214 left_prestatements + right_prestatements + root_prestatements,
215 # TODO Implement short-circuiting
216 NormalInfixExpression(
217 order=expression.order, # TODO Do we need this?
218 operator=expression.operator,
219 left=NormalVariableExpression(variable=left_variable),
220 right=NormalVariableExpression(variable=right_variable),
224 while len(stack) > 0:
225 right_operator, right_order, right_expression = stack.pop()
226 and_right_expression = parsing.FurInfixExpression(
227 operator=right_operator,
229 left=NormalVariableExpression(variable=right_variable),
230 right=right_expression,
233 and_expression = parsing.FurInfixExpression(
236 left=result_expression,
237 right=and_right_expression,
240 counter, and_prestatements, result_expression = normalize_boolean_expression(
245 result_prestatements = result_prestatements + and_prestatements
247 return (counter, result_prestatements, result_expression)
249 def normalize_boolean_expression(counter, expression):
250 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
251 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
253 result_variable = '${}'.format(counter)
254 if_else_prestatment = NormalVariableInitializationStatement(variable=result_variable, expression=left_expression)
257 condition_expression=NormalVariableExpression(variable=result_variable)
258 short_circuited_statements = right_prestatements + (NormalVariableReassignmentStatement(variable=result_variable, expression=right_expression),)
260 if expression.operator == 'and':
261 if_else_statement = NormalIfElseStatement(
262 condition_expression=condition_expression,
263 if_statements=short_circuited_statements,
267 elif expression.operator == 'or':
268 if_else_statement = NormalIfElseStatement(
269 condition_expression=condition_expression,
271 else_statements=short_circuited_statements,
275 raise Exception('Unable to handle operator "{}"'.format(expression.operator))
279 left_prestatements + (if_else_prestatment, if_else_statement),
280 NormalVariableExpression(variable=result_variable),
284 def normalize_infix_expression(counter, expression):
286 'multiplication_level': normalize_basic_infix_operation,
287 'addition_level': normalize_basic_infix_operation,
288 'comparison_level': normalize_comparison_expression,
289 'and_level': normalize_boolean_expression,
290 'or_level': normalize_boolean_expression,
291 }[expression.order](counter, expression)
293 def normalize_negation_expression(counter, expression):
294 counter, prestatements, internal_expression = normalize_expression(counter, expression.value)
296 internal_variable = '${}'.format(counter)
301 prestatements + (NormalVariableInitializationStatement(variable=internal_variable, expression=internal_expression),),
302 NormalNegationExpression(internal_expression=NormalVariableExpression(variable=internal_variable)),
305 def normalize_expression(counter, expression):
307 NormalInfixExpression: fake_normalization,
308 NormalVariableExpression: fake_normalization,
309 parsing.FurFunctionCallExpression: normalize_function_call_expression,
310 parsing.FurInfixExpression: normalize_infix_expression,
311 parsing.FurIntegerLiteralExpression: fake_normalization,
312 parsing.FurNegationExpression: normalize_negation_expression,
313 parsing.FurStringLiteralExpression: fake_normalization,
314 parsing.FurSymbolExpression: fake_normalization,
315 }[type(expression)](counter, expression)
317 def normalize_expression_statement(counter, statement):
318 # TODO Verify all expression types are supported and just call normalize_expression
319 counter, prestatements, normalized = {
320 parsing.FurFunctionCallExpression: normalize_function_call_expression,
321 parsing.FurSymbolExpression: normalize_expression,
322 parsing.FurInfixExpression: normalize_expression,
323 parsing.FurIntegerLiteralExpression: normalize_expression,
324 }[type(statement.expression)](counter, statement.expression)
329 NormalExpressionStatement(expression=normalized),
332 def normalize_function_definition_statement(counter, statement):
336 NormalFunctionDefinitionStatement(
338 argument_name_list=statement.argument_name_list,
339 statement_list=normalize_statement_list(statement.statement_list),
343 def normalize_assignment_statement(counter, statement):
344 counter, prestatements, normalized_expression = normalize_expression(counter, statement.expression)
348 NormalAssignmentStatement(
349 target=statement.target,
350 expression=normalized_expression,
354 def normalize_statement(counter, statement):
356 parsing.FurAssignmentStatement: normalize_assignment_statement,
357 parsing.FurExpressionStatement: normalize_expression_statement,
358 parsing.FurFunctionDefinitionStatement: normalize_function_definition_statement,
359 }[type(statement)](counter, statement)
361 @util.force_generator(tuple)
362 def normalize_statement_list(statement_list):
365 for statement in statement_list:
366 counter, prestatements, normalized = normalize_statement(counter, statement)
367 for s in prestatements:
371 def normalize(program):
373 return NormalProgram(
374 statement_list=normalize_statement_list(program.statement_list),