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 return normalize_basic_infix_operation(counter, expression)
486 def normalize_boolean_expression(counter, expression):
487 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
488 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
490 result_variable = '${}'.format(counter)
491 if_else_prestatment = NormalVariableInitializationStatement(
492 variable=result_variable,
493 expression=left_expression,
497 condition_expression=NormalVariableExpression(variable=result_variable)
498 short_circuited_statements = right_prestatements + (NormalVariableReassignmentStatement(variable=result_variable, expression=right_expression),)
500 if expression.operator == 'and':
501 if_else_statement = NormalIfElseStatement(
502 condition_expression=condition_expression,
503 if_statement_list=short_circuited_statements,
504 else_statement_list=(),
507 elif expression.operator == 'or':
508 if_else_statement = NormalIfElseStatement(
509 condition_expression=condition_expression,
510 if_statement_list=(),
511 else_statement_list=short_circuited_statements,
515 raise Exception('Unable to handle operator "{}"'.format(expression.operator))
519 left_prestatements + (if_else_prestatment, if_else_statement),
520 NormalVariableExpression(variable=result_variable),
523 def normalize_dot_expression(counter, expression):
524 assert isinstance(expression.right, parsing.FurSymbolExpression)
526 counter, prestatements, left_expression = normalize_expression(counter, expression.left)
528 variable = '${}'.format(counter)
530 dot_expression_prestatement = NormalVariableInitializationStatement(
532 expression=NormalDotExpression(
533 instance=left_expression,
534 field=expression.right.symbol,
540 prestatements + (dot_expression_prestatement,),
541 NormalVariableExpression(variable=variable),
544 def normalize_infix_expression(counter, expression):
546 'multiplication_level': normalize_basic_infix_operation,
547 'addition_level': normalize_basic_infix_operation,
548 'comparison_level': normalize_comparison_expression,
549 'dot_level': normalize_dot_expression,
550 'and_level': normalize_boolean_expression,
551 'or_level': normalize_boolean_expression,
552 }[expression.order](counter, expression)
554 def normalize_if_expression(counter, expression):
555 counter, condition_prestatements, condition_expression = normalize_expression(
557 expression.condition_expression,
560 result_variable = '${}'.format(counter)
563 counter, if_statement_list = normalize_statement_list(
565 expression.if_statement_list,
566 assign_result_to=result_variable,
568 counter, else_statement_list = normalize_statement_list(
570 expression.else_statement_list,
571 assign_result_to=result_variable,
576 condition_prestatements + (
577 NormalVariableInitializationStatement(
578 variable=result_variable,
579 expression=NormalVariableExpression(variable='builtin$nil'),
581 NormalIfElseStatement(
582 condition_expression=condition_expression,
583 if_statement_list=if_statement_list,
584 else_statement_list=else_statement_list,
587 NormalVariableExpression(variable=result_variable),
590 def normalize_negation_expression(counter, expression):
591 counter, prestatements, internal_expression = normalize_expression(counter, expression.value)
593 internal_variable = '${}'.format(counter)
599 NormalVariableInitializationStatement(
600 variable=internal_variable,
601 expression=internal_expression,
604 NormalNegationExpression(internal_expression=NormalVariableExpression(variable=internal_variable)),
607 def normalize_expression(counter, expression):
609 NormalInfixExpression: fake_normalization,
610 NormalVariableExpression: fake_normalization,
611 parsing.FurFunctionCallExpression: normalize_function_call_expression,
612 parsing.FurIfExpression: normalize_if_expression,
613 parsing.FurInfixExpression: normalize_infix_expression,
614 parsing.FurIntegerLiteralExpression: normalize_integer_literal_expression,
615 parsing.FurListLiteralExpression: normalize_list_literal_expression,
616 parsing.FurListItemExpression: normalize_list_item_expression,
617 parsing.FurNegationExpression: normalize_negation_expression,
618 parsing.FurStringLiteralExpression: normalize_string_literal_expression,
619 parsing.FurStructureLiteralExpression: normalize_structure_literal_expression,
620 parsing.FurSymbolExpression: normalize_symbol_expression,
621 }[type(expression)](counter, expression)
623 def normalize_expression_statement(counter, statement):
624 # TODO Normalized will be a NormalVariableExpression, which will go unused
625 # for expression statements in every case except when it's a return
626 # statement. This cases warnings on C compilation. We should only generate
627 # this variable when it will be used on return.
628 counter, prestatements, normalized = normalize_expression(counter, statement.expression)
633 NormalExpressionStatement(expression=normalized),
636 def normalize_function_definition_statement(counter, statement):
637 _, statement_list = normalize_statement_list(
639 statement.statement_list,
640 assign_result_to='result',
645 NormalFunctionDefinitionStatement(
647 argument_name_list=statement.argument_name_list,
648 statement_list=statement_list,
652 def normalize_assignment_statement(counter, statement):
653 counter, prestatements, normalized_expression = normalize_expression(counter, statement.expression)
657 NormalAssignmentStatement(
658 target=statement.target,
659 expression=normalized_expression,
663 def normalize_statement(counter, statement):
665 parsing.FurAssignmentStatement: normalize_assignment_statement,
666 parsing.FurExpressionStatement: normalize_expression_statement,
667 parsing.FurFunctionDefinitionStatement: normalize_function_definition_statement,
668 }[type(statement)](counter, statement)
670 @util.force_generator(tuple)
671 def normalize_statement_list(counter, statement_list, **kwargs):
672 assign_result_to = kwargs.pop('assign_result_to', None)
674 assert len(kwargs) == 0
676 result_statement_list = []
678 for statement in statement_list:
679 counter, prestatements, normalized = normalize_statement(counter, statement)
680 for s in prestatements:
681 result_statement_list.append(s)
682 result_statement_list.append(normalized)
684 # TODO The way we fix the last statement is really confusing
685 last_statement = result_statement_list[-1]
687 if isinstance(last_statement, NormalExpressionStatement) and isinstance(last_statement.expression, NormalVariableExpression):
688 if assign_result_to is not None:
689 result_expression = result_statement_list.pop().expression
690 result_statement_list.append(
691 NormalVariableReassignmentStatement(
692 variable=assign_result_to,
693 expression=result_expression,
699 result_statement_list,
702 def normalize(program):
703 _, statement_list = normalize_statement_list(0, program.statement_list)
705 return NormalProgram(
706 statement_list=statement_list,