5 NormalVariableExpression = collections.namedtuple(
6 'NormalVariableExpression',
12 NormalNegationExpression = collections.namedtuple(
13 'NormalNegationExpression',
15 'internal_expression',
19 NormalInfixExpression = collections.namedtuple(
20 'NormalInfixExpression',
29 NormalFunctionCallExpression = collections.namedtuple(
30 'NormalFunctionCallExpression',
37 NormalVariableInitializationStatement = collections.namedtuple(
38 'NormalVariableInitializationStatement',
45 NormalVariableReassignmentStatement = collections.namedtuple(
46 'NormalVariableReassignmentStatement',
53 NormalExpressionStatement = collections.namedtuple(
54 'NormalExpressionStatement',
60 NormalIfElseStatement = collections.namedtuple(
61 'NormalIfElseStatement',
63 'condition_expression',
69 NormalProgram = collections.namedtuple(
76 def fake_normalization(counter, thing):
77 return (counter, (), thing)
79 def normalize_function_call_expression(counter, expression):
80 assert isinstance(expression, parsing.FurFunctionCallExpression)
85 for argument in expression.arguments:
86 counter, argument_prestatements, normalized_argument = normalize_expression(counter, argument)
88 for s in argument_prestatements:
89 prestatements.append(s)
91 variable = '${}'.format(counter)
92 prestatements.append(NormalVariableInitializationStatement(
94 expression=normalized_argument,
96 arguments.append(NormalVariableExpression(
103 tuple(prestatements),
104 NormalFunctionCallExpression(
105 expression.function, # TODO Normalize the function
106 arguments=tuple(arguments),
110 def normalize_basic_infix_operation(counter, expression):
111 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
112 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
114 left_variable = '${}'.format(counter)
116 right_variable = '${}'.format(counter)
119 root_prestatements = (
120 NormalVariableInitializationStatement(
121 variable=left_variable,
122 expression=left_expression,
124 NormalVariableInitializationStatement(
125 variable=right_variable,
126 expression=right_expression,
132 left_prestatements + right_prestatements + root_prestatements,
133 NormalInfixExpression(
134 order=expression.order, # TODO Do we need this?
135 operator=expression.operator,
136 left=NormalVariableExpression(variable=left_variable),
137 right=NormalVariableExpression(variable=right_variable),
141 def normalize_comparison_expression(counter, expression):
144 while isinstance(expression.left, parsing.FurInfixExpression) and expression.order == 'comparison_level':
145 stack.append((expression.operator, expression.order, expression.right))
146 expression = expression.left
148 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
149 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
151 left_variable = '${}'.format(counter)
153 right_variable = '${}'.format(counter)
156 root_prestatements = (
157 NormalVariableInitializationStatement(
158 variable=left_variable,
159 expression=left_expression,
161 NormalVariableInitializationStatement(
162 variable=right_variable,
163 expression=right_expression,
167 counter, result_prestatements, result_expression = (
169 left_prestatements + right_prestatements + root_prestatements,
170 # TODO Implement short-circuiting
171 NormalInfixExpression(
172 order=expression.order, # TODO Do we need this?
173 operator=expression.operator,
174 left=NormalVariableExpression(variable=left_variable),
175 right=NormalVariableExpression(variable=right_variable),
179 while len(stack) > 0:
180 right_operator, right_order, right_expression = stack.pop()
181 and_right_expression = parsing.FurInfixExpression(
182 operator=right_operator,
184 left=NormalVariableExpression(variable=right_variable),
185 right=right_expression,
188 and_expression = parsing.FurInfixExpression(
191 left=result_expression,
192 right=and_right_expression,
195 counter, and_prestatements, result_expression = normalize_boolean_expression(
200 result_prestatements = result_prestatements + and_prestatements
202 return (counter, result_prestatements, result_expression)
204 def normalize_boolean_expression(counter, expression):
205 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
206 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
208 result_variable = '${}'.format(counter)
209 if_else_prestatment = NormalVariableInitializationStatement(variable=result_variable, expression=left_expression)
212 condition_expression=NormalVariableExpression(variable=result_variable)
213 short_circuited_statements = right_prestatements + (NormalVariableReassignmentStatement(variable=result_variable, expression=right_expression),)
215 if expression.operator == 'and':
216 if_else_statement = NormalIfElseStatement(
217 condition_expression=condition_expression,
218 if_statements=short_circuited_statements,
222 elif expression.operator == 'or':
223 if_else_statement = NormalIfElseStatement(
224 condition_expression=condition_expression,
226 else_statements=short_circuited_statements,
230 raise Exception('Unable to handle operator "{}"'.format(expression.operator))
234 left_prestatements + (if_else_prestatment, if_else_statement),
235 NormalVariableExpression(variable=result_variable),
239 def normalize_infix_expression(counter, expression):
241 'multiplication_level': normalize_basic_infix_operation,
242 'addition_level': normalize_basic_infix_operation,
243 'comparison_level': normalize_comparison_expression,
244 'and_level': normalize_boolean_expression,
245 'or_level': normalize_boolean_expression,
246 }[expression.order](counter, expression)
248 def normalize_negation_expression(counter, expression):
249 counter, prestatements, internal_expression = normalize_expression(counter, expression.value)
251 internal_variable = '${}'.format(counter)
256 prestatements + (NormalVariableInitializationStatement(variable=internal_variable, expression=internal_expression),),
257 NormalNegationExpression(internal_expression=NormalVariableExpression(variable=internal_variable)),
260 def normalize_parenthesized_expression(counter, expression):
261 return normalize_expression(counter, expression.internal)
263 def normalize_expression(counter, expression):
265 NormalInfixExpression: fake_normalization,
266 NormalVariableExpression: fake_normalization,
267 parsing.FurFunctionCallExpression: normalize_function_call_expression,
268 parsing.FurInfixExpression: normalize_infix_expression,
269 parsing.FurIntegerLiteralExpression: fake_normalization,
270 parsing.FurNegationExpression: normalize_negation_expression,
271 parsing.FurParenthesizedExpression: normalize_parenthesized_expression,
272 parsing.FurStringLiteralExpression: fake_normalization,
273 parsing.FurSymbolExpression: fake_normalization,
274 }[type(expression)](counter, expression)
276 def normalize_expression_statement(counter, statement):
277 counter, prestatements, normalized = {
278 parsing.FurFunctionCallExpression: normalize_function_call_expression,
279 }[type(statement.expression)](counter, statement.expression)
284 NormalExpressionStatement(expression=normalized),
287 def normalize_statement(counter, statement):
289 parsing.FurExpressionStatement: normalize_expression_statement,
290 parsing.FurAssignmentStatement: fake_normalization,
291 }[type(statement)](counter, statement)
293 def normalize(program):
297 for statement in program.statement_list:
298 counter, prestatements, normalized = normalize_statement(counter, statement)
299 for s in prestatements:
300 statement_list.append(s)
301 statement_list.append(normalized)
303 return NormalProgram(
304 statement_list=statement_list,