mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-25 03:04:13 +03:00
Fix order of folded ternary expressions when handling early return statements
This commit is contained in:
parent
8b3a7a5361
commit
d56bd3084d
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
}),
|
||||
},
|
||||
|
@ -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)>,
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user