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 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,