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',
58 NormalPushStatement = collections.namedtuple(
59 'NormalPushStatement',
65 NormalFunctionCallExpression = collections.namedtuple(
66 'NormalFunctionCallExpression',
68 'function_expression',
73 NormalArrayVariableInitializationStatement = collections.namedtuple(
74 'NormalArrayVariableInitializationStatement',
81 NormalSymbolArrayVariableInitializationStatement = collections.namedtuple(
82 'NormalSymbolArrayVariableInitializationStatement',
89 NormalVariableInitializationStatement = collections.namedtuple(
90 'NormalVariableInitializationStatement',
97 NormalVariableReassignmentStatement = collections.namedtuple(
98 'NormalVariableReassignmentStatement',
105 NormalExpressionStatement = collections.namedtuple(
106 'NormalExpressionStatement',
112 NormalAssignmentStatement = collections.namedtuple(
113 'NormalAssignmentStatement',
120 NormalIfElseStatement = collections.namedtuple(
121 'NormalIfElseStatement',
123 'condition_expression',
125 'else_statement_list',
129 NormalFunctionDefinitionStatement = collections.namedtuple(
130 'NormalFunctionDefinitionStatement',
133 'argument_name_list',
138 NormalProgram = collections.namedtuple(
145 def fake_normalization(counter, thing):
146 return (counter, (), thing)
148 def normalize_integer_literal_expression(counter, expression):
149 variable = '${}'.format(counter)
153 NormalVariableInitializationStatement(
155 expression=NormalIntegerLiteralExpression(integer=expression.integer),
158 NormalVariableExpression(variable=variable),
161 NormalListConstructExpression = collections.namedtuple(
162 'NormalListConstructExpression',
168 NormalListAppendStatement = collections.namedtuple(
169 'NormalListAppendStatement',
176 NormalListGetExpression = collections.namedtuple(
177 'NormalListGetExpression',
184 def normalize_list_literal_expression(counter, expression):
185 list_variable = '${}'.format(counter)
189 NormalVariableInitializationStatement(
190 variable=list_variable,
191 expression=NormalListConstructExpression(allocate=len(expression.item_expression_list)),
195 list_expression = NormalVariableExpression(variable=list_variable)
197 for item_expression in expression.item_expression_list:
198 counter, item_expression_prestatements, normalized = normalize_expression(
203 for p in item_expression_prestatements:
204 prestatements.append(p)
206 prestatements.append(
207 NormalListAppendStatement(
208 list_expression=list_expression,
209 item_expression=normalized,
215 tuple(prestatements),
219 def normalize_list_item_expression(counter, expression):
220 counter, list_prestatements, list_expression = normalize_expression(counter, expression.list_expression)
221 counter, index_prestatements, index_expression = normalize_expression(counter, expression.index_expression)
223 result_variable = '${}'.format(counter)
224 result_prestatement = NormalVariableInitializationStatement(
225 variable=result_variable,
226 expression=NormalListGetExpression(
227 list_expression=list_expression,
228 index_expression=index_expression,
234 list_prestatements + index_prestatements + (result_prestatement,),
235 NormalVariableExpression(variable=result_variable),
238 def normalize_string_literal_expression(counter, expression):
239 variable = '${}'.format(counter)
243 NormalVariableInitializationStatement(
245 expression=NormalStringLiteralExpression(string=expression.string),
248 NormalVariableExpression(variable=variable),
251 NormalStructureLiteralExpression = collections.namedtuple(
252 'NormalStructureLiteralExpression',
255 'symbol_list_variable',
256 'value_list_variable',
260 def normalize_structure_literal_expression(counter, expression):
262 field_symbol_array = []
263 field_value_array = []
265 for symbol_expression_pair in expression.fields:
266 counter, field_prestatements, field_expression = normalize_expression(
268 symbol_expression_pair.expression,
271 for p in field_prestatements:
272 prestatements.append(p)
274 field_symbol_array.append(symbol_expression_pair.symbol)
275 field_value_array.append(field_expression)
277 symbol_array_variable = '${}'.format(counter)
280 prestatements.append(
281 NormalSymbolArrayVariableInitializationStatement(
282 variable=symbol_array_variable,
283 symbol_list=tuple(field_symbol_array),
287 value_array_variable = '${}'.format(counter)
290 prestatements.append(
291 NormalArrayVariableInitializationStatement(
292 variable=value_array_variable,
293 items=tuple(field_value_array),
297 variable = '${}'.format(counter)
299 prestatements.append(
300 NormalVariableInitializationStatement(
302 expression=NormalStructureLiteralExpression(
303 field_count=len(expression.fields),
304 symbol_list_variable=symbol_array_variable,
305 value_list_variable=value_array_variable,
312 tuple(prestatements),
313 NormalVariableExpression(variable=variable),
317 def normalize_symbol_expression(counter, expression):
318 variable = '${}'.format(counter)
322 NormalVariableInitializationStatement(
324 expression=NormalSymbolExpression(symbol=expression.symbol),
327 NormalVariableExpression(variable=variable),
330 def normalize_function_call_expression(counter, expression):
331 assert isinstance(expression, parsing.FurFunctionCallExpression)
335 for argument in expression.arguments:
336 counter, argument_prestatements, normalized_argument = normalize_expression(counter, argument)
338 for s in argument_prestatements:
339 prestatements.append(s)
341 variable = '${}'.format(counter)
342 prestatements.append(
343 NormalVariableInitializationStatement(
345 expression=normalized_argument,
348 prestatements.append(
350 expression=NormalVariableExpression(
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(expression.arguments),
392 tuple(prestatements),
393 NormalVariableExpression(variable=result_variable),
396 def normalize_basic_infix_operation(counter, expression):
397 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
398 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
400 center_variable = '${}'.format(counter)
403 root_prestatements = (
404 NormalPushStatement(expression=left_expression),
405 NormalPushStatement(expression=right_expression),
406 NormalVariableInitializationStatement(
407 variable=center_variable,
408 expression=NormalInfixExpression(
409 metadata=expression.metadata,
410 order=expression.order,
411 operator=expression.operator,
418 left_prestatements + right_prestatements + root_prestatements,
419 NormalVariableExpression(variable=center_variable),
422 def desugar_ternary_comparison(counter, expression):
423 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left.left)
424 counter, middle_prestatements, middle_expression = normalize_expression(counter, expression.left.right)
426 left_variable = '${}'.format(counter)
428 middle_variable = '${}'.format(counter)
431 # 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?
432 juncture_prestatements = (
433 NormalVariableInitializationStatement(
434 variable=left_variable,
435 expression=left_expression,
437 NormalVariableInitializationStatement(
438 variable=middle_variable,
439 expression=middle_expression,
443 counter, boolean_expression_prestatements, boolean_expression = normalize_boolean_expression(
445 parsing.FurInfixExpression(
446 metadata=expression.left.metadata,
449 left=parsing.FurInfixExpression(
450 metadata=expression.left.metadata,
451 order='comparison_level',
452 operator=expression.left.operator,
453 left=NormalVariableExpression(variable=left_variable),
454 right=NormalVariableExpression(variable=middle_variable),
456 right=parsing.FurInfixExpression(
457 metadata=expression.metadata,
458 order='comparison_level',
459 operator=expression.operator,
460 left=NormalVariableExpression(variable=middle_variable),
461 right=expression.right,
468 left_prestatements + middle_prestatements + juncture_prestatements + boolean_expression_prestatements,
472 def normalize_comparison_expression(counter, expression):
473 if isinstance(expression.left, parsing.FurInfixExpression) and expression.order == 'comparison_level':
474 return desugar_ternary_comparison(counter, expression)
476 return normalize_basic_infix_operation(counter, expression)
478 def normalize_boolean_expression(counter, expression):
479 counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
480 counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
482 result_variable = '${}'.format(counter)
483 if_else_prestatment = NormalVariableInitializationStatement(
484 variable=result_variable,
485 expression=left_expression,
489 condition_expression=NormalVariableExpression(variable=result_variable)
490 short_circuited_statements = right_prestatements + (NormalVariableReassignmentStatement(variable=result_variable, expression=right_expression),)
492 if expression.operator == 'and':
493 if_else_statement = NormalIfElseStatement(
494 condition_expression=condition_expression,
495 if_statement_list=short_circuited_statements,
496 else_statement_list=(),
499 elif expression.operator == 'or':
500 if_else_statement = NormalIfElseStatement(
501 condition_expression=condition_expression,
502 if_statement_list=(),
503 else_statement_list=short_circuited_statements,
507 raise Exception('Unable to handle operator "{}"'.format(expression.operator))
511 left_prestatements + (if_else_prestatment, if_else_statement),
512 NormalVariableExpression(variable=result_variable),
515 def normalize_dot_expression(counter, expression):
516 assert isinstance(expression.right, parsing.FurSymbolExpression)
518 counter, prestatements, left_expression = normalize_expression(counter, expression.left)
520 variable = '${}'.format(counter)
522 dot_expression_prestatement = NormalVariableInitializationStatement(
524 expression=NormalDotExpression(
525 instance=left_expression,
526 field=expression.right.symbol,
532 prestatements + (dot_expression_prestatement,),
533 NormalVariableExpression(variable=variable),
536 def normalize_infix_expression(counter, expression):
538 'multiplication_level': normalize_basic_infix_operation,
539 'addition_level': normalize_basic_infix_operation,
540 'comparison_level': normalize_comparison_expression,
541 'dot_level': normalize_dot_expression,
542 'and_level': normalize_boolean_expression,
543 'or_level': normalize_boolean_expression,
544 }[expression.order](counter, expression)
546 def normalize_if_expression(counter, expression):
547 counter, condition_prestatements, condition_expression = normalize_expression(
549 expression.condition_expression,
552 result_variable = '${}'.format(counter)
555 counter, if_statement_list = normalize_statement_list(
557 expression.if_statement_list,
558 assign_result_to=result_variable,
560 counter, else_statement_list = normalize_statement_list(
562 expression.else_statement_list,
563 assign_result_to=result_variable,
568 condition_prestatements + (
569 NormalVariableInitializationStatement(
570 variable=result_variable,
571 expression=NormalVariableExpression(variable='builtin$nil'),
573 NormalIfElseStatement(
574 condition_expression=condition_expression,
575 if_statement_list=if_statement_list,
576 else_statement_list=else_statement_list,
579 NormalVariableExpression(variable=result_variable),
582 def normalize_negation_expression(counter, expression):
583 counter, prestatements, internal_expression = normalize_expression(counter, expression.value)
585 internal_variable = '${}'.format(counter)
591 NormalVariableInitializationStatement(
592 variable=internal_variable,
593 expression=internal_expression,
596 NormalNegationExpression(internal_expression=NormalVariableExpression(variable=internal_variable)),
599 def normalize_expression(counter, expression):
601 NormalInfixExpression: fake_normalization,
602 NormalVariableExpression: fake_normalization,
603 parsing.FurFunctionCallExpression: normalize_function_call_expression,
604 parsing.FurIfExpression: normalize_if_expression,
605 parsing.FurInfixExpression: normalize_infix_expression,
606 parsing.FurIntegerLiteralExpression: normalize_integer_literal_expression,
607 parsing.FurListLiteralExpression: normalize_list_literal_expression,
608 parsing.FurListItemExpression: normalize_list_item_expression,
609 parsing.FurNegationExpression: normalize_negation_expression,
610 parsing.FurStringLiteralExpression: normalize_string_literal_expression,
611 parsing.FurStructureLiteralExpression: normalize_structure_literal_expression,
612 parsing.FurSymbolExpression: normalize_symbol_expression,
613 }[type(expression)](counter, expression)
615 def normalize_expression_statement(counter, statement):
616 # TODO Normalized will be a NormalVariableExpression, which will go unused
617 # for expression statements in every case except when it's a return
618 # statement. This cases warnings on C compilation. We should only generate
619 # this variable when it will be used on return.
620 counter, prestatements, normalized = normalize_expression(counter, statement.expression)
625 NormalExpressionStatement(expression=normalized),
628 def normalize_function_definition_statement(counter, statement):
629 _, statement_list = normalize_statement_list(
631 statement.statement_list,
632 assign_result_to='result',
637 NormalFunctionDefinitionStatement(
639 argument_name_list=statement.argument_name_list,
640 statement_list=statement_list,
644 def normalize_assignment_statement(counter, statement):
645 counter, prestatements, normalized_expression = normalize_expression(counter, statement.expression)
649 NormalAssignmentStatement(
650 target=statement.target,
651 expression=normalized_expression,
655 def normalize_statement(counter, statement):
657 parsing.FurAssignmentStatement: normalize_assignment_statement,
658 parsing.FurExpressionStatement: normalize_expression_statement,
659 parsing.FurFunctionDefinitionStatement: normalize_function_definition_statement,
660 }[type(statement)](counter, statement)
662 @util.force_generator(tuple)
663 def normalize_statement_list(counter, statement_list, **kwargs):
664 assign_result_to = kwargs.pop('assign_result_to', None)
666 assert len(kwargs) == 0
668 result_statement_list = []
670 for statement in statement_list:
671 counter, prestatements, normalized = normalize_statement(counter, statement)
672 for s in prestatements:
673 result_statement_list.append(s)
674 result_statement_list.append(normalized)
676 # TODO The way we fix the last statement is really confusing
677 last_statement = result_statement_list[-1]
679 if isinstance(last_statement, NormalExpressionStatement) and isinstance(last_statement.expression, NormalVariableExpression):
680 if assign_result_to is not None:
681 result_expression = result_statement_list.pop().expression
682 result_statement_list.append(
683 NormalVariableReassignmentStatement(
684 variable=assign_result_to,
685 expression=result_expression,
691 result_statement_list,
694 def normalize(program):
695 _, statement_list = normalize_statement_list(0, program.statement_list)
697 return NormalProgram(
698 statement_list=statement_list,