6 NormalVariableExpression = collections.namedtuple(
7 'NormalVariableExpression',
13 NormalIntegerLiteralExpression = collections.namedtuple(
14 'NormalIntegerLiteralExpression',
20 NormalStringLiteralExpression = collections.namedtuple(
21 'NormalStringLiteralExpression',
27 NormalSymbolExpression = collections.namedtuple(
28 'NormalSymbolExpression',
34 NormalNegationExpression = collections.namedtuple(
35 'NormalNegationExpression',
37 'internal_expression',
41 NormalInfixExpression = collections.namedtuple(
42 'NormalInfixExpression',
51 NormalFunctionCallExpression = collections.namedtuple(
52 'NormalFunctionCallExpression',
54 'function_expression',
60 NormalArrayVariableInitializationStatement = collections.namedtuple(
61 'NormalArrayVariableInitializationStatement',
68 NormalVariableInitializationStatement = collections.namedtuple(
69 'NormalVariableInitializationStatement',
76 NormalVariableReassignmentStatement = collections.namedtuple(
77 'NormalVariableReassignmentStatement',
84 NormalExpressionStatement = collections.namedtuple(
85 'NormalExpressionStatement',
91 NormalAssignmentStatement = collections.namedtuple(
92 'NormalAssignmentStatement',
99 NormalIfElseStatement = collections.namedtuple(
100 'NormalIfElseStatement',
102 'condition_expression',
104 'else_statement_list',
108 NormalFunctionDefinitionStatement = collections.namedtuple(
109 'NormalFunctionDefinitionStatement',
112 'argument_name_list',
117 NormalProgram = collections.namedtuple(
124 def fake_normalization(counter, thing):
125 return (counter, (), thing)
127 def normalize_integer_literal_expression(counter, expression):
128 variable = '${}'.format(counter)
132 NormalVariableInitializationStatement(
134 expression=NormalIntegerLiteralExpression(integer=expression.integer),
137 NormalVariableExpression(variable=variable),
140 def normalize_string_literal_expression(counter, expression):
141 variable = '${}'.format(counter)
145 NormalVariableInitializationStatement(
147 expression=NormalStringLiteralExpression(string=expression.string),
150 NormalVariableExpression(variable=variable),
153 def normalize_symbol_expression(counter, expression):
154 variable = '${}'.format(counter)
158 NormalVariableInitializationStatement(
160 expression=NormalSymbolExpression(symbol=expression.symbol),
163 NormalVariableExpression(variable=variable),
166 def normalize_function_call_expression(counter, expression):
167 assert isinstance(expression, parsing.FurFunctionCallExpression)
172 for argument in expression.arguments:
173 counter, argument_prestatements, normalized_argument = normalize_expression(counter, argument)
175 for s in argument_prestatements:
176 prestatements.append(s)
178 variable = '${}'.format(counter)
179 prestatements.append(
180 NormalVariableInitializationStatement(
182 expression=normalized_argument,
185 arguments.append(NormalVariableExpression(
190 arguments_variable = '${}'.format(counter)
193 prestatements.append(NormalArrayVariableInitializationStatement(
194 variable=arguments_variable,
195 items=tuple(arguments),
198 counter, function_prestatements, function_expression = normalize_expression(
203 for ps in function_prestatements:
204 prestatements.append(ps)
206 if not isinstance(function_expression, NormalVariableExpression):
207 function_variable = '${}'.format(counter)
209 prestatements.append(
210 NormalVariableInitializationStatement(
211 variable=function_variable,
212 expression=function_expression,
216 function_expression = NormalVariableExpression(variable=function_variable)
221 tuple(prestatements),
222 NormalFunctionCallExpression(
223 function_expression=function_expression,
224 argument_count=len(arguments),
225 argument_items=NormalVariableExpression(variable=arguments_variable),
229 def normalize_basic_infix_operation(counter, expression):
230 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
231 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
233 left_variable = '${}'.format(counter)
235 right_variable = '${}'.format(counter)
237 center_variable = '${}'.format(counter)
240 root_prestatements = (
241 NormalVariableInitializationStatement(
242 variable=left_variable,
243 expression=left_expression,
245 NormalVariableInitializationStatement(
246 variable=right_variable,
247 expression=right_expression,
249 NormalVariableInitializationStatement(
250 variable=center_variable,
251 expression=NormalInfixExpression(
252 order=expression.order,
253 operator=expression.operator,
254 left=NormalVariableExpression(variable=left_variable),
255 right=NormalVariableExpression(variable=right_variable),
262 left_prestatements + right_prestatements + root_prestatements,
263 NormalVariableExpression(variable=center_variable),
266 def normalize_comparison_expression(counter, expression):
269 while isinstance(expression.left, parsing.FurInfixExpression) and expression.order == 'comparison_level':
270 stack.append((expression.operator, expression.order, expression.right))
271 expression = expression.left
273 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
274 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
276 left_variable = '${}'.format(counter)
278 right_variable = '${}'.format(counter)
281 root_prestatements = (
282 NormalVariableInitializationStatement(
283 variable=left_variable,
284 expression=left_expression,
286 NormalVariableInitializationStatement(
287 variable=right_variable,
288 expression=right_expression,
292 counter, result_prestatements, result_expression = (
294 left_prestatements + right_prestatements + root_prestatements,
295 NormalInfixExpression(
296 order=expression.order,
297 operator=expression.operator,
298 left=NormalVariableExpression(variable=left_variable),
299 right=NormalVariableExpression(variable=right_variable),
303 while len(stack) > 0:
304 right_operator, right_order, right_expression = stack.pop()
305 and_right_expression = parsing.FurInfixExpression(
306 operator=right_operator,
308 left=NormalVariableExpression(variable=right_variable),
309 right=right_expression,
312 and_expression = parsing.FurInfixExpression(
315 left=result_expression,
316 right=and_right_expression,
319 counter, and_prestatements, result_expression = normalize_boolean_expression(
324 result_prestatements = result_prestatements + and_prestatements
326 return (counter, result_prestatements, result_expression)
328 def normalize_boolean_expression(counter, expression):
329 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
330 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
332 result_variable = '${}'.format(counter)
333 if_else_prestatment = NormalVariableInitializationStatement(
334 variable=result_variable,
335 expression=left_expression,
339 condition_expression=NormalVariableExpression(variable=result_variable)
340 short_circuited_statements = right_prestatements + (NormalVariableReassignmentStatement(variable=result_variable, expression=right_expression),)
342 if expression.operator == 'and':
343 if_else_statement = NormalIfElseStatement(
344 condition_expression=condition_expression,
345 if_statement_list=short_circuited_statements,
346 else_statement_list=(),
349 elif expression.operator == 'or':
350 if_else_statement = NormalIfElseStatement(
351 condition_expression=condition_expression,
352 if_statement_list=(),
353 else_statement_list=short_circuited_statements,
357 raise Exception('Unable to handle operator "{}"'.format(expression.operator))
361 left_prestatements + (if_else_prestatment, if_else_statement),
362 NormalVariableExpression(variable=result_variable),
366 def normalize_infix_expression(counter, expression):
368 'multiplication_level': normalize_basic_infix_operation,
369 'addition_level': normalize_basic_infix_operation,
370 'comparison_level': normalize_comparison_expression,
371 'and_level': normalize_boolean_expression,
372 'or_level': normalize_boolean_expression,
373 }[expression.order](counter, expression)
375 def normalize_if_expression(counter, expression):
376 counter, condition_prestatements, condition_expression = normalize_expression(
378 expression.condition_expression,
381 result_variable = '${}'.format(counter)
384 counter, if_statement_list = normalize_statement_list(
386 expression.if_statement_list,
387 assign_result_to=result_variable,
389 counter, else_statement_list = normalize_statement_list(
391 expression.else_statement_list,
392 assign_result_to=result_variable,
397 condition_prestatements + (
398 NormalVariableInitializationStatement(
399 variable=result_variable,
400 expression=NormalVariableExpression(variable='builtin$nil'),
402 NormalIfElseStatement(
403 condition_expression=condition_expression,
404 if_statement_list=if_statement_list,
405 else_statement_list=else_statement_list,
408 NormalVariableExpression(variable=result_variable),
414 def normalize_negation_expression(counter, expression):
415 counter, prestatements, internal_expression = normalize_expression(counter, expression.value)
417 internal_variable = '${}'.format(counter)
423 NormalVariableInitializationStatement(
424 variable=internal_variable,
425 expression=internal_expression,
428 NormalNegationExpression(internal_expression=NormalVariableExpression(variable=internal_variable)),
431 def normalize_expression(counter, expression):
433 NormalInfixExpression: fake_normalization,
434 NormalVariableExpression: fake_normalization,
435 parsing.FurFunctionCallExpression: normalize_function_call_expression,
436 parsing.FurIfExpression: normalize_if_expression,
437 parsing.FurInfixExpression: normalize_infix_expression,
438 parsing.FurIntegerLiteralExpression: normalize_integer_literal_expression,
439 parsing.FurNegationExpression: normalize_negation_expression,
440 parsing.FurStringLiteralExpression: normalize_string_literal_expression,
441 parsing.FurSymbolExpression: normalize_symbol_expression,
442 }[type(expression)](counter, expression)
444 def normalize_expression_statement(counter, statement):
445 # TODO Normalized will be a NormalVariableExpression, which will go unused
446 # for expression statements in every case except when it's a return
447 # statement. This cases warnings on C compilation. We should only generate
448 # this variable when it will be used on return.
449 counter, prestatements, normalized = normalize_expression(counter, statement.expression)
454 NormalExpressionStatement(expression=normalized),
457 def normalize_function_definition_statement(counter, statement):
458 _, statement_list = normalize_statement_list(
460 statement.statement_list,
461 assign_result_to='result',
466 NormalFunctionDefinitionStatement(
468 argument_name_list=statement.argument_name_list,
469 statement_list=statement_list,
473 def normalize_assignment_statement(counter, statement):
474 counter, prestatements, normalized_expression = normalize_expression(counter, statement.expression)
478 NormalAssignmentStatement(
479 target=statement.target,
480 expression=normalized_expression,
484 def normalize_statement(counter, statement):
486 parsing.FurAssignmentStatement: normalize_assignment_statement,
487 parsing.FurExpressionStatement: normalize_expression_statement,
488 parsing.FurFunctionDefinitionStatement: normalize_function_definition_statement,
489 }[type(statement)](counter, statement)
491 @util.force_generator(tuple)
492 def normalize_statement_list(counter, statement_list, **kwargs):
493 assign_result_to = kwargs.pop('assign_result_to', None)
495 assert len(kwargs) == 0
497 result_statement_list = []
499 for statement in statement_list:
500 counter, prestatements, normalized = normalize_statement(counter, statement)
501 for s in prestatements:
502 result_statement_list.append(s)
503 result_statement_list.append(normalized)
505 last_statement = result_statement_list[-1]
507 if isinstance(last_statement, NormalExpressionStatement) and isinstance(last_statement.expression, NormalVariableExpression):
508 result_expression = result_statement_list.pop().expression
510 if assign_result_to is not None:
511 result_statement_list.append(
512 NormalVariableReassignmentStatement(
513 variable=assign_result_to,
514 expression=result_expression,
520 result_statement_list,
523 def normalize(program):
524 _, statement_list = normalize_statement_list(0, program.statement_list)
526 return NormalProgram(
527 statement_list=statement_list,