Fix order of folded ternary expressions when handling early return statements

This commit is contained in:
Pranav Gaddamadugu 2022-08-05 08:16:19 -07:00
parent 8b3a7a5361
commit d56bd3084d
3 changed files with 11 additions and 8 deletions

View File

@ -31,7 +31,7 @@ pub struct TernaryExpression {
impl fmt::Display for TernaryExpression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "if {} ? {} : {}", self.condition, self.if_true, self.if_false)
write!(f, "(if {} ? {} : {})", self.condition, self.if_true, self.if_false)
}
}

View File

@ -56,14 +56,15 @@ impl ProgramReconstructor for StaticSingleAssigner<'_> {
.fold(last_return_expression, |acc, (guard, expr)| match guard {
None => unreachable!("All return statements except for the last one must have a guard."),
// Note that type checking guarantees that all expressions in return statements in the function body have the same type.
Some(guard) => match (acc, expr) {
Some(guard) => match (expr, acc) {
// If the function returns tuples, fold the return expressions into a tuple of ternary expressions.
(Expression::Tuple(acc_tuple), Expression::Tuple(expr_tuple)) => {
// Note that `expr` and `acc` are correspond to the `if` and `else` cases of the ternary expression respectively.
(Expression::Tuple(expr_tuple), Expression::Tuple(acc_tuple)) => {
Expression::Tuple(TupleExpression {
elements: acc_tuple
elements: expr_tuple
.elements
.into_iter()
.zip_eq(expr_tuple.elements.into_iter())
.zip_eq(acc_tuple.elements.into_iter())
.map(|(if_true, if_false)| {
Expression::Ternary(TernaryExpression {
condition: Box::new(guard.clone()),
@ -77,10 +78,11 @@ impl ProgramReconstructor for StaticSingleAssigner<'_> {
})
}
// Otherwise, fold the return expressions into a single ternary expression.
(acc, expr) => Expression::Ternary(TernaryExpression {
// Note that `expr` and `acc` are correspond to the `if` and `else` cases of the ternary expression respectively.
(expr, acc) => Expression::Ternary(TernaryExpression {
condition: Box::new(guard),
if_true: Box::new(acc),
if_false: Box::new(expr),
if_true: Box::new(expr),
if_false: Box::new(acc),
span: Default::default(),
}),
},

View File

@ -38,6 +38,7 @@ pub struct StaticSingleAssigner<'a> {
/// A stack of condition `Expression`s visited up to the current point in the AST.
pub(crate) condition_stack: Vec<Expression>,
/// A list containing tuples of guards and expressions associated with early `ReturnStatement`s.
/// Note that early returns are inserted in the order they are encountered during a pre-order traversal of the AST.
pub(crate) early_returns: Vec<(Option<Expression>, Expression)>,
}