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 NormalDotExpression = collections.namedtuple(
42 'NormalDotExpression',
49 NormalInfixExpression = collections.namedtuple(
50 'NormalInfixExpression',
59 NormalFunctionCallExpression = collections.namedtuple(
60 'NormalFunctionCallExpression',
62 'function_expression',
68 NormalArrayVariableInitializationStatement = collections.namedtuple(
69 'NormalArrayVariableInitializationStatement',
76 NormalSymbolArrayVariableInitializationStatement = collections.namedtuple(
77 'NormalSymbolArrayVariableInitializationStatement',
84 NormalVariableInitializationStatement = collections.namedtuple(
85 'NormalVariableInitializationStatement',
92 NormalVariableReassignmentStatement = collections.namedtuple(
93 'NormalVariableReassignmentStatement',
100 NormalExpressionStatement = collections.namedtuple(
101 'NormalExpressionStatement',
107 NormalAssignmentStatement = collections.namedtuple(
108 'NormalAssignmentStatement',
115 NormalIfElseStatement = collections.namedtuple(
116 'NormalIfElseStatement',
118 'condition_expression',
120 'else_statement_list',
124 NormalFunctionDefinitionStatement = collections.namedtuple(
125 'NormalFunctionDefinitionStatement',
128 'argument_name_list',
133 NormalProgram = collections.namedtuple(
140 def fake_normalization(counter, thing):
141 return (counter, (), thing)
143 def normalize_integer_literal_expression(counter, expression):
144 variable = '${}'.format(counter)
148 NormalVariableInitializationStatement(
150 expression=NormalIntegerLiteralExpression(integer=expression.integer),
153 NormalVariableExpression(variable=variable),
156 NormalListConstructExpression = collections.namedtuple(
157 'NormalListConstructExpression',
163 NormalListAppendStatement = collections.namedtuple(
164 'NormalListAppendStatement',
171 NormalListGetExpression = collections.namedtuple(
172 'NormalListGetExpression',
179 def normalize_list_literal_expression(counter, expression):
180 list_variable = '${}'.format(counter)
184 NormalVariableInitializationStatement(
185 variable=list_variable,
186 expression=NormalListConstructExpression(allocate=len(expression.item_expression_list)),
190 list_expression = NormalVariableExpression(variable=list_variable)
192 for item_expression in expression.item_expression_list:
193 counter, item_expression_prestatements, normalized = normalize_expression(
198 for p in item_expression_prestatements:
199 prestatements.append(p)
201 prestatements.append(
202 NormalListAppendStatement(
203 list_expression=list_expression,
204 item_expression=normalized,
210 tuple(prestatements),
214 def normalize_list_item_expression(counter, expression):
215 counter, list_prestatements, list_expression = normalize_expression(counter, expression.list_expression)
216 counter, index_prestatements, index_expression = normalize_expression(counter, expression.index_expression)
218 result_variable = '${}'.format(counter)
219 result_prestatement = NormalVariableInitializationStatement(
220 variable=result_variable,
221 expression=NormalListGetExpression(
222 list_expression=list_expression,
223 index_expression=index_expression,
229 list_prestatements + index_prestatements + (result_prestatement,),
230 NormalVariableExpression(variable=result_variable),
233 def normalize_string_literal_expression(counter, expression):
234 variable = '${}'.format(counter)
238 NormalVariableInitializationStatement(
240 expression=NormalStringLiteralExpression(string=expression.string),
243 NormalVariableExpression(variable=variable),
246 NormalStructureLiteralExpression = collections.namedtuple(
247 'NormalStructureLiteralExpression',
250 'symbol_list_variable',
251 'value_list_variable',
255 def normalize_structure_literal_expression(counter, expression):
257 field_symbol_array = []
258 field_value_array = []
260 for symbol_expression_pair in expression.fields:
261 counter, field_prestatements, field_expression = normalize_expression(
263 symbol_expression_pair.expression,
266 for p in field_prestatements:
267 prestatements.append(p)
269 field_symbol_array.append(symbol_expression_pair.symbol)
270 field_value_array.append(field_expression)
272 symbol_array_variable = '${}'.format(counter)
275 prestatements.append(
276 NormalSymbolArrayVariableInitializationStatement(
277 variable=symbol_array_variable,
278 symbol_list=tuple(field_symbol_array),
282 value_array_variable = '${}'.format(counter)
285 prestatements.append(
286 NormalArrayVariableInitializationStatement(
287 variable=value_array_variable,
288 items=tuple(field_value_array),
292 variable = '${}'.format(counter)
294 prestatements.append(
295 NormalVariableInitializationStatement(
297 expression=NormalStructureLiteralExpression(
298 field_count=len(expression.fields),
299 symbol_list_variable=symbol_array_variable,
300 value_list_variable=value_array_variable,
307 tuple(prestatements),
308 NormalVariableExpression(variable=variable),
312 def normalize_symbol_expression(counter, expression):
313 variable = '${}'.format(counter)
317 NormalVariableInitializationStatement(
319 expression=NormalSymbolExpression(symbol=expression.symbol),
322 NormalVariableExpression(variable=variable),
325 def normalize_function_call_expression(counter, expression):
326 assert isinstance(expression, parsing.FurFunctionCallExpression)
331 for argument in expression.arguments:
332 counter, argument_prestatements, normalized_argument = normalize_expression(counter, argument)
334 for s in argument_prestatements:
335 prestatements.append(s)
337 variable = '${}'.format(counter)
338 prestatements.append(
339 NormalVariableInitializationStatement(
341 expression=normalized_argument,
344 arguments.append(NormalVariableExpression(
349 arguments_variable = '${}'.format(counter)
352 prestatements.append(NormalArrayVariableInitializationStatement(
353 variable=arguments_variable,
354 items=tuple(arguments),
357 counter, function_prestatements, function_expression = normalize_expression(
362 for ps in function_prestatements:
363 prestatements.append(ps)
365 if not isinstance(function_expression, NormalVariableExpression):
366 function_variable = '${}'.format(counter)
368 prestatements.append(
369 NormalVariableInitializationStatement(
370 variable=function_variable,
371 expression=function_expression,
375 function_expression = NormalVariableExpression(variable=function_variable)
378 result_variable = '${}'.format(counter)
380 prestatements.append(
381 NormalVariableInitializationStatement(
382 variable=result_variable,
383 expression=NormalFunctionCallExpression(
384 function_expression=function_expression,
385 argument_count=len(arguments),
386 argument_items=NormalVariableExpression(variable=arguments_variable),
393 tuple(prestatements),
394 NormalVariableExpression(variable=result_variable),
397 def normalize_basic_infix_operation(counter, expression):
398 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
399 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
401 left_variable = '${}'.format(counter)
403 right_variable = '${}'.format(counter)
405 center_variable = '${}'.format(counter)
408 root_prestatements = (
409 NormalVariableInitializationStatement(
410 variable=left_variable,
411 expression=left_expression,
413 NormalVariableInitializationStatement(
414 variable=right_variable,
415 expression=right_expression,
417 NormalVariableInitializationStatement(
418 variable=center_variable,
419 expression=NormalInfixExpression(
420 order=expression.order,
421 operator=expression.operator,
422 left=NormalVariableExpression(variable=left_variable),
423 right=NormalVariableExpression(variable=right_variable),
430 left_prestatements + right_prestatements + root_prestatements,
431 NormalVariableExpression(variable=center_variable),
434 def normalize_comparison_expression(counter, expression):
437 while isinstance(expression.left, parsing.FurInfixExpression) and expression.order == 'comparison_level':
438 stack.append((expression.operator, expression.order, expression.right))
439 expression = expression.left
441 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
442 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
444 left_variable = '${}'.format(counter)
446 right_variable = '${}'.format(counter)
449 root_prestatements = (
450 NormalVariableInitializationStatement(
451 variable=left_variable,
452 expression=left_expression,
454 NormalVariableInitializationStatement(
455 variable=right_variable,
456 expression=right_expression,
460 counter, result_prestatements, result_expression = (
462 left_prestatements + right_prestatements + root_prestatements,
463 NormalInfixExpression(
464 order=expression.order,
465 operator=expression.operator,
466 left=NormalVariableExpression(variable=left_variable),
467 right=NormalVariableExpression(variable=right_variable),
471 while len(stack) > 0:
472 right_operator, right_order, right_expression = stack.pop()
473 and_right_expression = parsing.FurInfixExpression(
474 operator=right_operator,
476 left=NormalVariableExpression(variable=right_variable),
477 right=right_expression,
480 and_expression = parsing.FurInfixExpression(
483 left=result_expression,
484 right=and_right_expression,
487 counter, and_prestatements, result_expression = normalize_boolean_expression(
492 result_prestatements = result_prestatements + and_prestatements
494 return (counter, result_prestatements, result_expression)
496 def normalize_boolean_expression(counter, expression):
497 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
498 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
500 result_variable = '${}'.format(counter)
501 if_else_prestatment = NormalVariableInitializationStatement(
502 variable=result_variable,
503 expression=left_expression,
507 condition_expression=NormalVariableExpression(variable=result_variable)
508 short_circuited_statements = right_prestatements + (NormalVariableReassignmentStatement(variable=result_variable, expression=right_expression),)
510 if expression.operator == 'and':
511 if_else_statement = NormalIfElseStatement(
512 condition_expression=condition_expression,
513 if_statement_list=short_circuited_statements,
514 else_statement_list=(),
517 elif expression.operator == 'or':
518 if_else_statement = NormalIfElseStatement(
519 condition_expression=condition_expression,
520 if_statement_list=(),
521 else_statement_list=short_circuited_statements,
525 raise Exception('Unable to handle operator "{}"'.format(expression.operator))
529 left_prestatements + (if_else_prestatment, if_else_statement),
530 NormalVariableExpression(variable=result_variable),
533 def normalize_dot_expression(counter, expression):
534 assert isinstance(expression.right, parsing.FurSymbolExpression)
536 counter, prestatements, left_expression = normalize_expression(counter, expression.left)
538 variable = '${}'.format(counter)
540 dot_expression_prestatement = NormalVariableInitializationStatement(
542 expression=NormalDotExpression(
543 instance=left_expression,
544 field=expression.right.symbol,
550 prestatements + (dot_expression_prestatement,),
551 NormalVariableExpression(variable=variable),
554 def normalize_infix_expression(counter, expression):
556 'multiplication_level': normalize_basic_infix_operation,
557 'addition_level': normalize_basic_infix_operation,
558 'comparison_level': normalize_comparison_expression,
559 'dot_level': normalize_dot_expression,
560 'and_level': normalize_boolean_expression,
561 'or_level': normalize_boolean_expression,
562 }[expression.order](counter, expression)
564 def normalize_if_expression(counter, expression):
565 counter, condition_prestatements, condition_expression = normalize_expression(
567 expression.condition_expression,
570 result_variable = '${}'.format(counter)
573 counter, if_statement_list = normalize_statement_list(
575 expression.if_statement_list,
576 assign_result_to=result_variable,
578 counter, else_statement_list = normalize_statement_list(
580 expression.else_statement_list,
581 assign_result_to=result_variable,
586 condition_prestatements + (
587 NormalVariableInitializationStatement(
588 variable=result_variable,
589 expression=NormalVariableExpression(variable='builtin$nil'),
591 NormalIfElseStatement(
592 condition_expression=condition_expression,
593 if_statement_list=if_statement_list,
594 else_statement_list=else_statement_list,
597 NormalVariableExpression(variable=result_variable),
600 def normalize_negation_expression(counter, expression):
601 counter, prestatements, internal_expression = normalize_expression(counter, expression.value)
603 internal_variable = '${}'.format(counter)
609 NormalVariableInitializationStatement(
610 variable=internal_variable,
611 expression=internal_expression,
614 NormalNegationExpression(internal_expression=NormalVariableExpression(variable=internal_variable)),
617 def normalize_expression(counter, expression):
619 NormalInfixExpression: fake_normalization,
620 NormalVariableExpression: fake_normalization,
621 parsing.FurFunctionCallExpression: normalize_function_call_expression,
622 parsing.FurIfExpression: normalize_if_expression,
623 parsing.FurInfixExpression: normalize_infix_expression,
624 parsing.FurIntegerLiteralExpression: normalize_integer_literal_expression,
625 parsing.FurListLiteralExpression: normalize_list_literal_expression,
626 parsing.FurListItemExpression: normalize_list_item_expression,
627 parsing.FurNegationExpression: normalize_negation_expression,
628 parsing.FurStringLiteralExpression: normalize_string_literal_expression,
629 parsing.FurStructureLiteralExpression: normalize_structure_literal_expression,
630 parsing.FurSymbolExpression: normalize_symbol_expression,
631 }[type(expression)](counter, expression)
633 def normalize_expression_statement(counter, statement):
634 # TODO Normalized will be a NormalVariableExpression, which will go unused
635 # for expression statements in every case except when it's a return
636 # statement. This cases warnings on C compilation. We should only generate
637 # this variable when it will be used on return.
638 counter, prestatements, normalized = normalize_expression(counter, statement.expression)
643 NormalExpressionStatement(expression=normalized),
646 def normalize_function_definition_statement(counter, statement):
647 _, statement_list = normalize_statement_list(
649 statement.statement_list,
650 assign_result_to='result',
655 NormalFunctionDefinitionStatement(
657 argument_name_list=statement.argument_name_list,
658 statement_list=statement_list,
662 def normalize_assignment_statement(counter, statement):
663 counter, prestatements, normalized_expression = normalize_expression(counter, statement.expression)
667 NormalAssignmentStatement(
668 target=statement.target,
669 expression=normalized_expression,
673 def normalize_statement(counter, statement):
675 parsing.FurAssignmentStatement: normalize_assignment_statement,
676 parsing.FurExpressionStatement: normalize_expression_statement,
677 parsing.FurFunctionDefinitionStatement: normalize_function_definition_statement,
678 }[type(statement)](counter, statement)
680 @util.force_generator(tuple)
681 def normalize_statement_list(counter, statement_list, **kwargs):
682 assign_result_to = kwargs.pop('assign_result_to', None)
684 assert len(kwargs) == 0
686 result_statement_list = []
688 for statement in statement_list:
689 counter, prestatements, normalized = normalize_statement(counter, statement)
690 for s in prestatements:
691 result_statement_list.append(s)
692 result_statement_list.append(normalized)
694 # TODO The way we fix the last statement is really confusing
695 last_statement = result_statement_list[-1]
697 if isinstance(last_statement, NormalExpressionStatement) and isinstance(last_statement.expression, NormalVariableExpression):
698 if assign_result_to is not None:
699 result_expression = result_statement_list.pop().expression
700 result_statement_list.append(
701 NormalVariableReassignmentStatement(
702 variable=assign_result_to,
703 expression=result_expression,
709 result_statement_list,
712 def normalize(program):
713 _, statement_list = normalize_statement_list(0, program.statement_list)
715 return NormalProgram(
716 statement_list=statement_list,