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 NormalPushStatement = collections.namedtuple(
60 'NormalPushStatement',
66 NormalFunctionCallExpression = collections.namedtuple(
67 'NormalFunctionCallExpression',
69 'function_expression',
74 NormalArrayVariableInitializationStatement = collections.namedtuple(
75 'NormalArrayVariableInitializationStatement',
82 NormalSymbolArrayVariableInitializationStatement = collections.namedtuple(
83 'NormalSymbolArrayVariableInitializationStatement',
90 NormalVariableInitializationStatement = collections.namedtuple(
91 'NormalVariableInitializationStatement',
98 NormalVariableReassignmentStatement = collections.namedtuple(
99 'NormalVariableReassignmentStatement',
106 NormalExpressionStatement = collections.namedtuple(
107 'NormalExpressionStatement',
113 NormalAssignmentStatement = collections.namedtuple(
114 'NormalAssignmentStatement',
121 NormalIfElseStatement = collections.namedtuple(
122 'NormalIfElseStatement',
124 'condition_expression',
126 'else_statement_list',
130 NormalFunctionDefinitionStatement = collections.namedtuple(
131 'NormalFunctionDefinitionStatement',
134 'argument_name_list',
139 NormalProgram = collections.namedtuple(
146 def fake_normalization(counter, thing):
147 return (counter, (), thing)
149 def normalize_integer_literal_expression(counter, expression):
150 variable = '${}'.format(counter)
154 NormalVariableInitializationStatement(
156 expression=NormalIntegerLiteralExpression(integer=expression.integer),
159 NormalVariableExpression(variable=variable),
162 NormalListConstructExpression = collections.namedtuple(
163 'NormalListConstructExpression',
169 NormalListAppendStatement = collections.namedtuple(
170 'NormalListAppendStatement',
177 NormalListGetExpression = collections.namedtuple(
178 'NormalListGetExpression',
185 def normalize_list_literal_expression(counter, expression):
186 list_variable = '${}'.format(counter)
190 NormalVariableInitializationStatement(
191 variable=list_variable,
192 expression=NormalListConstructExpression(allocate=len(expression.item_expression_list)),
196 list_expression = NormalVariableExpression(variable=list_variable)
198 for item_expression in expression.item_expression_list:
199 counter, item_expression_prestatements, normalized = normalize_expression(
204 for p in item_expression_prestatements:
205 prestatements.append(p)
207 prestatements.append(
208 NormalListAppendStatement(
209 list_expression=list_expression,
210 item_expression=normalized,
216 tuple(prestatements),
220 def normalize_list_item_expression(counter, expression):
221 counter, list_prestatements, list_expression = normalize_expression(counter, expression.list_expression)
222 counter, index_prestatements, index_expression = normalize_expression(counter, expression.index_expression)
224 result_variable = '${}'.format(counter)
225 result_prestatement = NormalVariableInitializationStatement(
226 variable=result_variable,
227 expression=NormalListGetExpression(
228 list_expression=list_expression,
229 index_expression=index_expression,
235 list_prestatements + index_prestatements + (result_prestatement,),
236 NormalVariableExpression(variable=result_variable),
239 def normalize_string_literal_expression(counter, expression):
240 variable = '${}'.format(counter)
244 NormalVariableInitializationStatement(
246 expression=NormalStringLiteralExpression(string=expression.string),
249 NormalVariableExpression(variable=variable),
252 NormalStructureLiteralExpression = collections.namedtuple(
253 'NormalStructureLiteralExpression',
256 'symbol_list_variable',
257 'value_list_variable',
261 def normalize_structure_literal_expression(counter, expression):
263 field_symbol_array = []
264 field_value_array = []
266 for symbol_expression_pair in expression.fields:
267 counter, field_prestatements, field_expression = normalize_expression(
269 symbol_expression_pair.expression,
272 for p in field_prestatements:
273 prestatements.append(p)
275 field_symbol_array.append(symbol_expression_pair.symbol)
276 field_value_array.append(field_expression)
278 symbol_array_variable = '${}'.format(counter)
281 prestatements.append(
282 NormalSymbolArrayVariableInitializationStatement(
283 variable=symbol_array_variable,
284 symbol_list=tuple(field_symbol_array),
288 value_array_variable = '${}'.format(counter)
291 prestatements.append(
292 NormalArrayVariableInitializationStatement(
293 variable=value_array_variable,
294 items=tuple(field_value_array),
298 variable = '${}'.format(counter)
300 prestatements.append(
301 NormalVariableInitializationStatement(
303 expression=NormalStructureLiteralExpression(
304 field_count=len(expression.fields),
305 symbol_list_variable=symbol_array_variable,
306 value_list_variable=value_array_variable,
313 tuple(prestatements),
314 NormalVariableExpression(variable=variable),
318 def normalize_symbol_expression(counter, expression):
319 variable = '${}'.format(counter)
323 NormalVariableInitializationStatement(
325 expression=NormalSymbolExpression(symbol=expression.symbol),
328 NormalVariableExpression(variable=variable),
331 def normalize_function_call_expression(counter, expression):
332 assert isinstance(expression, parsing.FurFunctionCallExpression)
336 for argument in expression.arguments:
337 counter, argument_prestatements, normalized_argument = normalize_expression(counter, argument)
339 for s in argument_prestatements:
340 prestatements.append(s)
342 variable = '${}'.format(counter)
343 prestatements.append(
344 NormalVariableInitializationStatement(
346 expression=normalized_argument,
349 prestatements.append(
351 expression=NormalVariableExpression(
358 counter, function_prestatements, function_expression = normalize_expression(
363 for ps in function_prestatements:
364 prestatements.append(ps)
366 if not isinstance(function_expression, NormalVariableExpression):
367 function_variable = '${}'.format(counter)
369 prestatements.append(
370 NormalVariableInitializationStatement(
371 variable=function_variable,
372 expression=function_expression,
376 function_expression = NormalVariableExpression(variable=function_variable)
379 result_variable = '${}'.format(counter)
381 prestatements.append(
382 NormalVariableInitializationStatement(
383 variable=result_variable,
384 expression=NormalFunctionCallExpression(
385 function_expression=function_expression,
386 argument_count=len(expression.arguments),
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 desugar_ternary_comparison(counter, expression):
435 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left.left)
436 counter, middle_prestatements, middle_expression = normalize_expression(counter, expression.left.right)
438 left_variable = '${}'.format(counter)
440 middle_variable = '${}'.format(counter)
443 juncture_prestatements = (
444 NormalVariableInitializationStatement(
445 variable=left_variable,
446 expression=left_expression,
448 NormalVariableInitializationStatement(
449 variable=middle_variable,
450 expression=middle_expression,
454 counter, boolean_expression_prestatements, boolean_expression = normalize_boolean_expression(
456 parsing.FurInfixExpression(
459 left=parsing.FurInfixExpression(
460 order='comparison_level',
461 operator=expression.left.operator,
462 left=NormalVariableExpression(variable=left_variable),
463 right=NormalVariableExpression(variable=middle_variable),
465 right=parsing.FurInfixExpression(
466 order='comparison_level',
467 operator=expression.operator,
468 left=NormalVariableExpression(variable=middle_variable),
469 right=expression.right,
476 left_prestatements + middle_prestatements + juncture_prestatements + boolean_expression_prestatements,
480 def normalize_comparison_expression(counter, expression):
481 if isinstance(expression.left, parsing.FurInfixExpression) and expression.order == 'comparison_level':
482 return desugar_ternary_comparison(counter, expression)
484 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
485 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
487 left_variable = '${}'.format(counter)
489 right_variable = '${}'.format(counter)
492 root_prestatements = (
493 NormalVariableInitializationStatement(
494 variable=left_variable,
495 expression=left_expression,
497 NormalVariableInitializationStatement(
498 variable=right_variable,
499 expression=right_expression,
503 counter, result_prestatements, result_expression = (
505 left_prestatements + right_prestatements + root_prestatements,
506 NormalInfixExpression(
507 order=expression.order,
508 operator=expression.operator,
509 left=NormalVariableExpression(variable=left_variable),
510 right=NormalVariableExpression(variable=right_variable),
514 return (counter, result_prestatements, result_expression)
516 def normalize_boolean_expression(counter, expression):
517 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
518 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
520 result_variable = '${}'.format(counter)
521 if_else_prestatment = NormalVariableInitializationStatement(
522 variable=result_variable,
523 expression=left_expression,
527 condition_expression=NormalVariableExpression(variable=result_variable)
528 short_circuited_statements = right_prestatements + (NormalVariableReassignmentStatement(variable=result_variable, expression=right_expression),)
530 if expression.operator == 'and':
531 if_else_statement = NormalIfElseStatement(
532 condition_expression=condition_expression,
533 if_statement_list=short_circuited_statements,
534 else_statement_list=(),
537 elif expression.operator == 'or':
538 if_else_statement = NormalIfElseStatement(
539 condition_expression=condition_expression,
540 if_statement_list=(),
541 else_statement_list=short_circuited_statements,
545 raise Exception('Unable to handle operator "{}"'.format(expression.operator))
549 left_prestatements + (if_else_prestatment, if_else_statement),
550 NormalVariableExpression(variable=result_variable),
553 def normalize_dot_expression(counter, expression):
554 assert isinstance(expression.right, parsing.FurSymbolExpression)
556 counter, prestatements, left_expression = normalize_expression(counter, expression.left)
558 variable = '${}'.format(counter)
560 dot_expression_prestatement = NormalVariableInitializationStatement(
562 expression=NormalDotExpression(
563 instance=left_expression,
564 field=expression.right.symbol,
570 prestatements + (dot_expression_prestatement,),
571 NormalVariableExpression(variable=variable),
574 def normalize_infix_expression(counter, expression):
576 'multiplication_level': normalize_basic_infix_operation,
577 'addition_level': normalize_basic_infix_operation,
578 'comparison_level': normalize_comparison_expression,
579 'dot_level': normalize_dot_expression,
580 'and_level': normalize_boolean_expression,
581 'or_level': normalize_boolean_expression,
582 }[expression.order](counter, expression)
584 def normalize_if_expression(counter, expression):
585 counter, condition_prestatements, condition_expression = normalize_expression(
587 expression.condition_expression,
590 result_variable = '${}'.format(counter)
593 counter, if_statement_list = normalize_statement_list(
595 expression.if_statement_list,
596 assign_result_to=result_variable,
598 counter, else_statement_list = normalize_statement_list(
600 expression.else_statement_list,
601 assign_result_to=result_variable,
606 condition_prestatements + (
607 NormalVariableInitializationStatement(
608 variable=result_variable,
609 expression=NormalVariableExpression(variable='builtin$nil'),
611 NormalIfElseStatement(
612 condition_expression=condition_expression,
613 if_statement_list=if_statement_list,
614 else_statement_list=else_statement_list,
617 NormalVariableExpression(variable=result_variable),
620 def normalize_negation_expression(counter, expression):
621 counter, prestatements, internal_expression = normalize_expression(counter, expression.value)
623 internal_variable = '${}'.format(counter)
629 NormalVariableInitializationStatement(
630 variable=internal_variable,
631 expression=internal_expression,
634 NormalNegationExpression(internal_expression=NormalVariableExpression(variable=internal_variable)),
637 def normalize_expression(counter, expression):
639 NormalInfixExpression: fake_normalization,
640 NormalVariableExpression: fake_normalization,
641 parsing.FurFunctionCallExpression: normalize_function_call_expression,
642 parsing.FurIfExpression: normalize_if_expression,
643 parsing.FurInfixExpression: normalize_infix_expression,
644 parsing.FurIntegerLiteralExpression: normalize_integer_literal_expression,
645 parsing.FurListLiteralExpression: normalize_list_literal_expression,
646 parsing.FurListItemExpression: normalize_list_item_expression,
647 parsing.FurNegationExpression: normalize_negation_expression,
648 parsing.FurStringLiteralExpression: normalize_string_literal_expression,
649 parsing.FurStructureLiteralExpression: normalize_structure_literal_expression,
650 parsing.FurSymbolExpression: normalize_symbol_expression,
651 }[type(expression)](counter, expression)
653 def normalize_expression_statement(counter, statement):
654 # TODO Normalized will be a NormalVariableExpression, which will go unused
655 # for expression statements in every case except when it's a return
656 # statement. This cases warnings on C compilation. We should only generate
657 # this variable when it will be used on return.
658 counter, prestatements, normalized = normalize_expression(counter, statement.expression)
663 NormalExpressionStatement(expression=normalized),
666 def normalize_function_definition_statement(counter, statement):
667 _, statement_list = normalize_statement_list(
669 statement.statement_list,
670 assign_result_to='result',
675 NormalFunctionDefinitionStatement(
677 argument_name_list=statement.argument_name_list,
678 statement_list=statement_list,
682 def normalize_assignment_statement(counter, statement):
683 counter, prestatements, normalized_expression = normalize_expression(counter, statement.expression)
687 NormalAssignmentStatement(
688 target=statement.target,
689 expression=normalized_expression,
693 def normalize_statement(counter, statement):
695 parsing.FurAssignmentStatement: normalize_assignment_statement,
696 parsing.FurExpressionStatement: normalize_expression_statement,
697 parsing.FurFunctionDefinitionStatement: normalize_function_definition_statement,
698 }[type(statement)](counter, statement)
700 @util.force_generator(tuple)
701 def normalize_statement_list(counter, statement_list, **kwargs):
702 assign_result_to = kwargs.pop('assign_result_to', None)
704 assert len(kwargs) == 0
706 result_statement_list = []
708 for statement in statement_list:
709 counter, prestatements, normalized = normalize_statement(counter, statement)
710 for s in prestatements:
711 result_statement_list.append(s)
712 result_statement_list.append(normalized)
714 # TODO The way we fix the last statement is really confusing
715 last_statement = result_statement_list[-1]
717 if isinstance(last_statement, NormalExpressionStatement) and isinstance(last_statement.expression, NormalVariableExpression):
718 if assign_result_to is not None:
719 result_expression = result_statement_list.pop().expression
720 result_statement_list.append(
721 NormalVariableReassignmentStatement(
722 variable=assign_result_to,
723 expression=result_expression,
729 result_statement_list,
732 def normalize(program):
733 _, statement_list = normalize_statement_list(0, program.statement_list)
735 return NormalProgram(
736 statement_list=statement_list,