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',
57 NormalPushStatement = collections.namedtuple(
58 'NormalPushStatement',
64 NormalFunctionCallExpression = collections.namedtuple(
65 'NormalFunctionCallExpression',
67 'function_expression',
72 NormalArrayVariableInitializationStatement = collections.namedtuple(
73 'NormalArrayVariableInitializationStatement',
80 NormalSymbolArrayVariableInitializationStatement = collections.namedtuple(
81 'NormalSymbolArrayVariableInitializationStatement',
88 NormalVariableInitializationStatement = collections.namedtuple(
89 'NormalVariableInitializationStatement',
96 NormalVariableReassignmentStatement = collections.namedtuple(
97 'NormalVariableReassignmentStatement',
104 NormalExpressionStatement = collections.namedtuple(
105 'NormalExpressionStatement',
111 NormalAssignmentStatement = collections.namedtuple(
112 'NormalAssignmentStatement',
119 NormalIfElseStatement = collections.namedtuple(
120 'NormalIfElseStatement',
122 'condition_expression',
124 'else_statement_list',
128 NormalFunctionDefinitionStatement = collections.namedtuple(
129 'NormalFunctionDefinitionStatement',
132 'argument_name_list',
137 NormalProgram = collections.namedtuple(
144 def fake_normalization(counter, thing):
145 return (counter, (), thing)
147 def normalize_integer_literal_expression(counter, expression):
148 variable = '${}'.format(counter)
152 NormalVariableInitializationStatement(
154 expression=NormalIntegerLiteralExpression(integer=expression.integer),
157 NormalVariableExpression(variable=variable),
160 NormalListConstructExpression = collections.namedtuple(
161 'NormalListConstructExpression',
167 NormalListAppendStatement = collections.namedtuple(
168 'NormalListAppendStatement',
175 NormalListGetExpression = collections.namedtuple(
176 'NormalListGetExpression',
183 def normalize_list_literal_expression(counter, expression):
184 list_variable = '${}'.format(counter)
188 NormalVariableInitializationStatement(
189 variable=list_variable,
190 expression=NormalListConstructExpression(allocate=len(expression.item_expression_list)),
194 list_expression = NormalVariableExpression(variable=list_variable)
196 for item_expression in expression.item_expression_list:
197 counter, item_expression_prestatements, normalized = normalize_expression(
202 for p in item_expression_prestatements:
203 prestatements.append(p)
205 prestatements.append(
206 NormalListAppendStatement(
207 list_expression=list_expression,
208 item_expression=normalized,
214 tuple(prestatements),
218 def normalize_list_item_expression(counter, expression):
219 counter, list_prestatements, list_expression = normalize_expression(counter, expression.list_expression)
220 counter, index_prestatements, index_expression = normalize_expression(counter, expression.index_expression)
222 result_variable = '${}'.format(counter)
223 result_prestatement = NormalVariableInitializationStatement(
224 variable=result_variable,
225 expression=NormalListGetExpression(
226 list_expression=list_expression,
227 index_expression=index_expression,
233 list_prestatements + index_prestatements + (result_prestatement,),
234 NormalVariableExpression(variable=result_variable),
237 def normalize_string_literal_expression(counter, expression):
238 variable = '${}'.format(counter)
242 NormalVariableInitializationStatement(
244 expression=NormalStringLiteralExpression(string=expression.string),
247 NormalVariableExpression(variable=variable),
250 NormalStructureLiteralExpression = collections.namedtuple(
251 'NormalStructureLiteralExpression',
254 'symbol_list_variable',
255 'value_list_variable',
259 def normalize_structure_literal_expression(counter, expression):
261 field_symbol_array = []
262 field_value_array = []
264 for symbol_expression_pair in expression.fields:
265 counter, field_prestatements, field_expression = normalize_expression(
267 symbol_expression_pair.expression,
270 for p in field_prestatements:
271 prestatements.append(p)
273 field_symbol_array.append(symbol_expression_pair.symbol)
274 field_value_array.append(field_expression)
276 symbol_array_variable = '${}'.format(counter)
279 prestatements.append(
280 NormalSymbolArrayVariableInitializationStatement(
281 variable=symbol_array_variable,
282 symbol_list=tuple(field_symbol_array),
286 value_array_variable = '${}'.format(counter)
289 prestatements.append(
290 NormalArrayVariableInitializationStatement(
291 variable=value_array_variable,
292 items=tuple(field_value_array),
296 variable = '${}'.format(counter)
298 prestatements.append(
299 NormalVariableInitializationStatement(
301 expression=NormalStructureLiteralExpression(
302 field_count=len(expression.fields),
303 symbol_list_variable=symbol_array_variable,
304 value_list_variable=value_array_variable,
311 tuple(prestatements),
312 NormalVariableExpression(variable=variable),
316 def normalize_symbol_expression(counter, expression):
317 variable = '${}'.format(counter)
321 NormalVariableInitializationStatement(
323 expression=NormalSymbolExpression(symbol=expression.symbol),
326 NormalVariableExpression(variable=variable),
329 def normalize_function_call_expression(counter, expression):
330 assert isinstance(expression, parsing.FurFunctionCallExpression)
334 for argument in expression.arguments:
335 counter, argument_prestatements, normalized_argument = normalize_expression(counter, argument)
337 for s in argument_prestatements:
338 prestatements.append(s)
340 variable = '${}'.format(counter)
341 prestatements.append(
342 NormalVariableInitializationStatement(
344 expression=normalized_argument,
347 prestatements.append(
349 expression=NormalVariableExpression(
356 counter, function_prestatements, function_expression = normalize_expression(
361 for ps in function_prestatements:
362 prestatements.append(ps)
364 if not isinstance(function_expression, NormalVariableExpression):
365 function_variable = '${}'.format(counter)
367 prestatements.append(
368 NormalVariableInitializationStatement(
369 variable=function_variable,
370 expression=function_expression,
374 function_expression = NormalVariableExpression(variable=function_variable)
377 result_variable = '${}'.format(counter)
379 prestatements.append(
380 NormalVariableInitializationStatement(
381 variable=result_variable,
382 expression=NormalFunctionCallExpression(
383 function_expression=function_expression,
384 argument_count=len(expression.arguments),
391 tuple(prestatements),
392 NormalVariableExpression(variable=result_variable),
395 def normalize_basic_infix_operation(counter, expression):
396 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
397 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
399 center_variable = '${}'.format(counter)
402 root_prestatements = (
403 NormalPushStatement(expression=left_expression),
404 NormalPushStatement(expression=right_expression),
405 NormalVariableInitializationStatement(
406 variable=center_variable,
407 expression=NormalInfixExpression(
408 order=expression.order,
409 operator=expression.operator,
416 left_prestatements + right_prestatements + root_prestatements,
417 NormalVariableExpression(variable=center_variable),
420 def desugar_ternary_comparison(counter, expression):
421 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left.left)
422 counter, middle_prestatements, middle_expression = normalize_expression(counter, expression.left.right)
424 left_variable = '${}'.format(counter)
426 middle_variable = '${}'.format(counter)
429 # TODO Is there a memory leak if the middle expression throws an exception because the first expression result hasn't been added to the stack?
430 juncture_prestatements = (
431 NormalVariableInitializationStatement(
432 variable=left_variable,
433 expression=left_expression,
435 NormalVariableInitializationStatement(
436 variable=middle_variable,
437 expression=middle_expression,
441 counter, boolean_expression_prestatements, boolean_expression = normalize_boolean_expression(
443 parsing.FurInfixExpression(
446 left=parsing.FurInfixExpression(
447 order='comparison_level',
448 operator=expression.left.operator,
449 left=NormalVariableExpression(variable=left_variable),
450 right=NormalVariableExpression(variable=middle_variable),
452 right=parsing.FurInfixExpression(
453 order='comparison_level',
454 operator=expression.operator,
455 left=NormalVariableExpression(variable=middle_variable),
456 right=expression.right,
463 left_prestatements + middle_prestatements + juncture_prestatements + boolean_expression_prestatements,
467 def normalize_comparison_expression(counter, expression):
468 if isinstance(expression.left, parsing.FurInfixExpression) and expression.order == 'comparison_level':
469 return desugar_ternary_comparison(counter, expression)
471 return normalize_basic_infix_operation(counter, expression)
473 def normalize_boolean_expression(counter, expression):
474 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
475 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
477 result_variable = '${}'.format(counter)
478 if_else_prestatment = NormalVariableInitializationStatement(
479 variable=result_variable,
480 expression=left_expression,
484 condition_expression=NormalVariableExpression(variable=result_variable)
485 short_circuited_statements = right_prestatements + (NormalVariableReassignmentStatement(variable=result_variable, expression=right_expression),)
487 if expression.operator == 'and':
488 if_else_statement = NormalIfElseStatement(
489 condition_expression=condition_expression,
490 if_statement_list=short_circuited_statements,
491 else_statement_list=(),
494 elif expression.operator == 'or':
495 if_else_statement = NormalIfElseStatement(
496 condition_expression=condition_expression,
497 if_statement_list=(),
498 else_statement_list=short_circuited_statements,
502 raise Exception('Unable to handle operator "{}"'.format(expression.operator))
506 left_prestatements + (if_else_prestatment, if_else_statement),
507 NormalVariableExpression(variable=result_variable),
510 def normalize_dot_expression(counter, expression):
511 assert isinstance(expression.right, parsing.FurSymbolExpression)
513 counter, prestatements, left_expression = normalize_expression(counter, expression.left)
515 variable = '${}'.format(counter)
517 dot_expression_prestatement = NormalVariableInitializationStatement(
519 expression=NormalDotExpression(
520 instance=left_expression,
521 field=expression.right.symbol,
527 prestatements + (dot_expression_prestatement,),
528 NormalVariableExpression(variable=variable),
531 def normalize_infix_expression(counter, expression):
533 'multiplication_level': normalize_basic_infix_operation,
534 'addition_level': normalize_basic_infix_operation,
535 'comparison_level': normalize_comparison_expression,
536 'dot_level': normalize_dot_expression,
537 'and_level': normalize_boolean_expression,
538 'or_level': normalize_boolean_expression,
539 }[expression.order](counter, expression)
541 def normalize_if_expression(counter, expression):
542 counter, condition_prestatements, condition_expression = normalize_expression(
544 expression.condition_expression,
547 result_variable = '${}'.format(counter)
550 counter, if_statement_list = normalize_statement_list(
552 expression.if_statement_list,
553 assign_result_to=result_variable,
555 counter, else_statement_list = normalize_statement_list(
557 expression.else_statement_list,
558 assign_result_to=result_variable,
563 condition_prestatements + (
564 NormalVariableInitializationStatement(
565 variable=result_variable,
566 expression=NormalVariableExpression(variable='builtin$nil'),
568 NormalIfElseStatement(
569 condition_expression=condition_expression,
570 if_statement_list=if_statement_list,
571 else_statement_list=else_statement_list,
574 NormalVariableExpression(variable=result_variable),
577 def normalize_negation_expression(counter, expression):
578 counter, prestatements, internal_expression = normalize_expression(counter, expression.value)
580 internal_variable = '${}'.format(counter)
586 NormalVariableInitializationStatement(
587 variable=internal_variable,
588 expression=internal_expression,
591 NormalNegationExpression(internal_expression=NormalVariableExpression(variable=internal_variable)),
594 def normalize_expression(counter, expression):
596 NormalInfixExpression: fake_normalization,
597 NormalVariableExpression: fake_normalization,
598 parsing.FurFunctionCallExpression: normalize_function_call_expression,
599 parsing.FurIfExpression: normalize_if_expression,
600 parsing.FurInfixExpression: normalize_infix_expression,
601 parsing.FurIntegerLiteralExpression: normalize_integer_literal_expression,
602 parsing.FurListLiteralExpression: normalize_list_literal_expression,
603 parsing.FurListItemExpression: normalize_list_item_expression,
604 parsing.FurNegationExpression: normalize_negation_expression,
605 parsing.FurStringLiteralExpression: normalize_string_literal_expression,
606 parsing.FurStructureLiteralExpression: normalize_structure_literal_expression,
607 parsing.FurSymbolExpression: normalize_symbol_expression,
608 }[type(expression)](counter, expression)
610 def normalize_expression_statement(counter, statement):
611 # TODO Normalized will be a NormalVariableExpression, which will go unused
612 # for expression statements in every case except when it's a return
613 # statement. This cases warnings on C compilation. We should only generate
614 # this variable when it will be used on return.
615 counter, prestatements, normalized = normalize_expression(counter, statement.expression)
620 NormalExpressionStatement(expression=normalized),
623 def normalize_function_definition_statement(counter, statement):
624 _, statement_list = normalize_statement_list(
626 statement.statement_list,
627 assign_result_to='result',
632 NormalFunctionDefinitionStatement(
634 argument_name_list=statement.argument_name_list,
635 statement_list=statement_list,
639 def normalize_assignment_statement(counter, statement):
640 counter, prestatements, normalized_expression = normalize_expression(counter, statement.expression)
644 NormalAssignmentStatement(
645 target=statement.target,
646 expression=normalized_expression,
650 def normalize_statement(counter, statement):
652 parsing.FurAssignmentStatement: normalize_assignment_statement,
653 parsing.FurExpressionStatement: normalize_expression_statement,
654 parsing.FurFunctionDefinitionStatement: normalize_function_definition_statement,
655 }[type(statement)](counter, statement)
657 @util.force_generator(tuple)
658 def normalize_statement_list(counter, statement_list, **kwargs):
659 assign_result_to = kwargs.pop('assign_result_to', None)
661 assert len(kwargs) == 0
663 result_statement_list = []
665 for statement in statement_list:
666 counter, prestatements, normalized = normalize_statement(counter, statement)
667 for s in prestatements:
668 result_statement_list.append(s)
669 result_statement_list.append(normalized)
671 # TODO The way we fix the last statement is really confusing
672 last_statement = result_statement_list[-1]
674 if isinstance(last_statement, NormalExpressionStatement) and isinstance(last_statement.expression, NormalVariableExpression):
675 if assign_result_to is not None:
676 result_expression = result_statement_list.pop().expression
677 result_statement_list.append(
678 NormalVariableReassignmentStatement(
679 variable=assign_result_to,
680 expression=result_expression,
686 result_statement_list,
689 def normalize(program):
690 _, statement_list = normalize_statement_list(0, program.statement_list)
692 return NormalProgram(
693 statement_list=statement_list,