Skip to content

Commit

Permalink
Undo special code to not parse if followed by tuple as a call
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite committed Jul 30, 2024
1 parent 0feda15 commit 62a0e67
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 45 deletions.
26 changes: 3 additions & 23 deletions compiler/noirc_frontend/src/ast/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,29 +263,9 @@ impl Expression {
arguments: Vec<Expression>,
span: Span,
) -> Expression {
// Need to check if lhs is an if expression since users can sequence if expressions
// with tuples without calling them. E.g. `if c { t } else { e }(a, b)` is interpreted
// as a sequence of { if, tuple } rather than a function call. This behavior matches rust.
let kind = if matches!(&lhs.kind, ExpressionKind::If(..)) {
ExpressionKind::Block(BlockExpression {
statements: vec![
Statement { kind: StatementKind::Expression(lhs), span },
Statement {
kind: StatementKind::Expression(Expression::new(
ExpressionKind::Tuple(arguments),
span,
)),
span,
},
],
})
} else {
ExpressionKind::Call(Box::new(CallExpression {
func: Box::new(lhs),
is_macro_call,
arguments,
}))
};
let func = Box::new(lhs);
let kind =
ExpressionKind::Call(Box::new(CallExpression { func, is_macro_call, arguments }));
Expression::new(kind, span)
}
}
Expand Down
34 changes: 12 additions & 22 deletions compiler/noirc_frontend/src/parser/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1322,20 +1322,6 @@ mod test {
fn parse_block() {
parse_with(block(fresh_statement()), "{ [0,1,2,3,4] }").unwrap();

// Regression for #1310: this should be parsed as a block and not a function call
let res =
parse_with(block(fresh_statement()), "{ if true { 1 } else { 2 } (3, 4) }").unwrap();
match unwrap_expr(&res.statements.last().unwrap().kind) {
// The `if` followed by a tuple is currently creates a block around both in case
// there was none to start with, so there is an extra block here.
ExpressionKind::Block(block) => {
assert_eq!(block.statements.len(), 2);
assert!(matches!(unwrap_expr(&block.statements[0].kind), ExpressionKind::If(_)));
assert!(matches!(unwrap_expr(&block.statements[1].kind), ExpressionKind::Tuple(_)));
}
_ => unreachable!(),
}

parse_all_failing(
block(fresh_statement()),
vec![
Expand All @@ -1349,14 +1335,6 @@ mod test {
);
}

/// Extract an Statement::Expression from a statement or panic
fn unwrap_expr(stmt: &StatementKind) -> &ExpressionKind {
match stmt {
StatementKind::Expression(expr) => &expr.kind,
_ => unreachable!(),
}
}

#[test]
fn parse_let() {
// Why is it valid to specify a let declaration as having type u8?
Expand Down Expand Up @@ -1677,4 +1655,16 @@ mod test {
let block_expr = block_expr.expect("Failed to parse module");
assert_eq!(block_expr.statements.len(), 2);
}

#[test]
fn test_parses_if_statement_followed_by_tuple_as_two_separate_statements() {
// Regression for #1310: this should not be parsed as a function call
let src = r#"
{
if 1 { 2 } else { 3 } (1, 2)
}"#;
let (block_expr, _) = parse_recover(block(fresh_statement()), src);
let block_expr = block_expr.expect("Failed to parse module");
assert_eq!(block_expr.statements.len(), 2);
}
}

0 comments on commit 62a0e67

Please sign in to comment.