+ return (
+ counter,
+ left_prestatements + right_prestatements + root_prestatements,
+ NormalVariableExpression(variable=center_variable),
+ )
+
+def desugar_ternary_comparison(counter, expression):
+ counter, left_prestatements, left_expression = normalize_expression(counter, expression.left.left)
+ counter, middle_prestatements, middle_expression = normalize_expression(counter, expression.left.right)
+
+ left_variable = '${}'.format(counter)
+ counter += 1
+ middle_variable = '${}'.format(counter)
+ counter += 1
+
+ # 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?
+ juncture_prestatements = (
+ NormalVariableInitializationStatement(
+ variable=left_variable,
+ expression=left_expression,
+ ),
+ NormalVariableInitializationStatement(
+ variable=middle_variable,
+ expression=middle_expression,
+ )
+ )
+
+ counter, boolean_expression_prestatements, boolean_expression = normalize_boolean_expression(
+ counter,
+ parsing.FurInfixExpression(
+ metadata=expression.left.metadata,
+ order='and_level',
+ operator='and',
+ left=parsing.FurInfixExpression(
+ metadata=expression.left.metadata,
+ order='comparison_level',
+ operator=expression.left.operator,
+ left=NormalVariableExpression(variable=left_variable),
+ right=NormalVariableExpression(variable=middle_variable),
+ ),
+ right=parsing.FurInfixExpression(
+ metadata=expression.metadata,
+ order='comparison_level',
+ operator=expression.operator,
+ left=NormalVariableExpression(variable=middle_variable),
+ right=expression.right,
+ ),
+ )
+ )
+
+ return (
+ counter,
+ left_prestatements + middle_prestatements + juncture_prestatements + boolean_expression_prestatements,
+ boolean_expression,
+ )
+
+def normalize_comparison_expression(counter, expression):
+ if isinstance(expression.left, parsing.FurInfixExpression) and expression.order == 'comparison_level':
+ return desugar_ternary_comparison(counter, expression)
+
+ return normalize_basic_infix_operation(counter, expression)
+
+def normalize_boolean_expression(counter, expression):
+ counter, left_prestatements, left_expression = normalize_expression(counter, expression.left)
+ counter, right_prestatements, right_expression = normalize_expression(counter, expression.right)
+
+ result_variable = '${}'.format(counter)
+ if_else_prestatment = NormalVariableInitializationStatement(
+ variable=result_variable,
+ expression=left_expression,
+ )
+ counter += 1
+
+ condition_expression=NormalVariableExpression(variable=result_variable)
+ short_circuited_statements = right_prestatements + (NormalVariableReassignmentStatement(variable=result_variable, expression=right_expression),)
+
+ if expression.operator == 'and':
+ if_else_statement = NormalIfElseStatement(
+ condition_expression=condition_expression,
+ if_statement_list=short_circuited_statements,
+ else_statement_list=(),
+ )
+
+ elif expression.operator == 'or':
+ if_else_statement = NormalIfElseStatement(
+ condition_expression=condition_expression,
+ if_statement_list=(),
+ else_statement_list=short_circuited_statements,
+ )
+
+ else:
+ raise Exception('Unable to handle operator "{}"'.format(expression.operator))
+
+ return (
+ counter,
+ left_prestatements + (if_else_prestatment, if_else_statement),
+ NormalVariableExpression(variable=result_variable),
+ )
+
+def normalize_dot_expression(counter, expression):
+ assert isinstance(expression.right, parsing.FurSymbolExpression)
+
+ counter, prestatements, left_expression = normalize_expression(counter, expression.left)
+
+ variable = '${}'.format(counter)
+
+ dot_expression_prestatement = NormalVariableInitializationStatement(
+ variable=variable,
+ expression=NormalDotExpression(
+ instance=left_expression,
+ field=expression.right.symbol,
+ ),
+ )
+
+ return (
+ counter + 1,
+ prestatements + (dot_expression_prestatement,),
+ NormalVariableExpression(variable=variable),
+ )
+
+def normalize_infix_expression(counter, expression):
+ return {
+ 'multiplication_level': normalize_basic_infix_operation,
+ 'addition_level': normalize_basic_infix_operation,
+ 'comparison_level': normalize_comparison_expression,
+ 'dot_level': normalize_dot_expression,
+ 'and_level': normalize_boolean_expression,
+ 'or_level': normalize_boolean_expression,
+ }[expression.order](counter, expression)
+
+def normalize_if_expression(counter, expression):
+ counter, condition_prestatements, condition_expression = normalize_expression(
+ counter,
+ expression.condition_expression,
+ )
+
+ result_variable = '${}'.format(counter)
+ counter += 1
+
+ counter, if_statement_list = normalize_statement_list(
+ counter,
+ expression.if_statement_list,
+ assign_result_to=result_variable,
+ )
+ counter, else_statement_list = normalize_statement_list(
+ counter,
+ expression.else_statement_list,
+ assign_result_to=result_variable,
+ )
+
+ return (
+ counter,
+ condition_prestatements + (
+ NormalVariableInitializationStatement(
+ variable=result_variable,
+ expression=NormalVariableExpression(variable='builtin$nil'),
+ ),
+ NormalIfElseStatement(
+ condition_expression=condition_expression,
+ if_statement_list=if_statement_list,
+ else_statement_list=else_statement_list,
+ ),
+ ),
+ NormalVariableExpression(variable=result_variable),
+ )
+
+def normalize_negation_expression(counter, expression):
+ counter, prestatements, internal_expression = normalize_expression(counter, expression.value)
+
+ internal_variable = '${}'.format(counter)
+ counter += 1
+
+ return (
+ counter,
+ prestatements + (
+ NormalVariableInitializationStatement(
+ variable=internal_variable,
+ expression=internal_expression,
+ ),
+ ),
+ NormalNegationExpression(internal_expression=NormalVariableExpression(variable=internal_variable)),
+ )
+