mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
merge
This commit is contained in:
parent
9d9316d170
commit
9189e3a461
3 changed files with 84 additions and 56 deletions
|
@ -1257,33 +1257,59 @@ pub fn if_expr_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, If<'a>> {
|
||||||
|
|
||||||
let mut branches = Vec::with_capacity_in(1, arena);
|
let mut branches = Vec::with_capacity_in(1, arena);
|
||||||
|
|
||||||
let (_, cond, state) = space0_around_e(
|
let mut loop_state = state;
|
||||||
specialize_ref(
|
|
||||||
If::Syntax,
|
|
||||||
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
|
||||||
),
|
|
||||||
min_indent,
|
|
||||||
If::Space,
|
|
||||||
If::IndentCondition,
|
|
||||||
)
|
|
||||||
.parse(arena, state)?;
|
|
||||||
|
|
||||||
let (_, _, state) = parser::keyword_e(keyword::THEN, If::Then).parse(arena, state)?;
|
let state_final_else = loop {
|
||||||
|
let state = loop_state;
|
||||||
|
let (_, cond, state) = space0_around_e(
|
||||||
|
specialize_ref(
|
||||||
|
If::Syntax,
|
||||||
|
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||||
|
),
|
||||||
|
min_indent,
|
||||||
|
If::Space,
|
||||||
|
If::IndentCondition,
|
||||||
|
)
|
||||||
|
.parse(arena, state)
|
||||||
|
.map_err(|(_, f, s)| (MadeProgress, f, s))?;
|
||||||
|
|
||||||
let (_, then_branch, state) = space0_around_e(
|
let (_, _, state) = parser::keyword_e(keyword::THEN, If::Then)
|
||||||
specialize_ref(
|
.parse(arena, state)
|
||||||
If::Syntax,
|
.map_err(|(_, f, s)| (MadeProgress, f, s))?;
|
||||||
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
|
||||||
),
|
|
||||||
min_indent,
|
|
||||||
If::Space,
|
|
||||||
If::IndentThen,
|
|
||||||
)
|
|
||||||
.parse(arena, state)?;
|
|
||||||
|
|
||||||
let (_, _, state) = parser::keyword_e(keyword::ELSE, If::Else).parse(arena, state)?;
|
let (_, then_branch, state) = space0_around_e(
|
||||||
|
specialize_ref(
|
||||||
|
If::Syntax,
|
||||||
|
loc!(move |arena, state| parse_expr(min_indent, arena, state)),
|
||||||
|
),
|
||||||
|
min_indent,
|
||||||
|
If::Space,
|
||||||
|
If::IndentThen,
|
||||||
|
)
|
||||||
|
.parse(arena, state)
|
||||||
|
.map_err(|(_, f, s)| (MadeProgress, f, s))?;
|
||||||
|
|
||||||
branches.push((cond, then_branch));
|
let (_, _, state) = parser::keyword_e(keyword::ELSE, If::Else)
|
||||||
|
.parse(arena, state)
|
||||||
|
.map_err(|(_, f, s)| (MadeProgress, f, s))?;
|
||||||
|
|
||||||
|
branches.push((cond, then_branch));
|
||||||
|
|
||||||
|
// try to parse another `if`
|
||||||
|
// NOTE this drops spaces between the `else` and the `if`
|
||||||
|
let optional_if = and!(
|
||||||
|
backtrackable(space0_e(min_indent, If::Space, If::IndentIf)),
|
||||||
|
parser::keyword_e(keyword::IF, If::If)
|
||||||
|
);
|
||||||
|
|
||||||
|
match optional_if.parse(arena, state) {
|
||||||
|
Err((_, _, state)) => break state,
|
||||||
|
Ok((_, _, state)) => {
|
||||||
|
loop_state = state;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let (_, else_branch, state) = space0_before_e(
|
let (_, else_branch, state) = space0_before_e(
|
||||||
specialize_ref(
|
specialize_ref(
|
||||||
|
@ -1294,9 +1320,9 @@ pub fn if_expr_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, If<'a>> {
|
||||||
If::Space,
|
If::Space,
|
||||||
If::IndentElse,
|
If::IndentElse,
|
||||||
)
|
)
|
||||||
.parse(arena, state)?;
|
.parse(arena, state_final_else)
|
||||||
|
.map_err(|(_, f, s)| (MadeProgress, f, s))?;
|
||||||
|
|
||||||
// parse the final else
|
|
||||||
let expr = Expr::If(branches.into_bump_slice(), arena.alloc(else_branch));
|
let expr = Expr::If(branches.into_bump_slice(), arena.alloc(else_branch));
|
||||||
|
|
||||||
Ok((MadeProgress, expr, state))
|
Ok((MadeProgress, expr, state))
|
||||||
|
@ -1304,10 +1330,10 @@ pub fn if_expr_help<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, If<'a>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn if_expr<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, SyntaxError<'a>> {
|
pub fn if_expr<'a>(min_indent: u16) -> impl Parser<'a, Expr<'a>, SyntaxError<'a>> {
|
||||||
specialize(
|
debug!(specialize(
|
||||||
|e, r, c| SyntaxError::Expr(EExpr::If(e, r, c)),
|
|e, r, c| SyntaxError::Expr(EExpr::If(e, r, c)),
|
||||||
if_expr_help(min_indent),
|
if_expr_help(min_indent),
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is a helper function for parsing function args.
|
/// This is a helper function for parsing function args.
|
||||||
|
|
|
@ -440,6 +440,7 @@ pub enum If<'a> {
|
||||||
Syntax(&'a SyntaxError<'a>, Row, Col),
|
Syntax(&'a SyntaxError<'a>, Row, Col),
|
||||||
|
|
||||||
IndentCondition(Row, Col),
|
IndentCondition(Row, Col),
|
||||||
|
IndentIf(Row, Col),
|
||||||
IndentThen(Row, Col),
|
IndentThen(Row, Col),
|
||||||
IndentElse(Row, Col),
|
IndentElse(Row, Col),
|
||||||
|
|
||||||
|
|
|
@ -801,35 +801,36 @@ mod test_reporting {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
#[test]
|
||||||
// fn if_3_branch_mismatch() {
|
fn if_3_branch_mismatch() {
|
||||||
// report_problem_as(
|
report_problem_as(
|
||||||
// indoc!(
|
indoc!(
|
||||||
// r#"
|
r#"
|
||||||
// if True then 2 else if False then 2 else "foo"
|
if True then 2 else if False then 2 else "foo"
|
||||||
// "#
|
"#
|
||||||
// ),
|
),
|
||||||
// indoc!(
|
indoc!(
|
||||||
// r#"
|
r#"
|
||||||
// ── TYPE MISMATCH ───────────────────────────────────────────────────────────────
|
── TYPE MISMATCH ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
// The 2nd branch of this `if` does not match all the previous branches:
|
The 3rd branch of this `if` does not match all the previous branches:
|
||||||
|
|
||||||
// 1│ if True then 2 else "foo"
|
1│ if True then 2 else if False then 2 else "foo"
|
||||||
// ^^^^^
|
^^^^^
|
||||||
|
|
||||||
// The 2nd branch is a string of type
|
The 3rd branch is a string of type:
|
||||||
|
|
||||||
// Str
|
Str
|
||||||
|
|
||||||
// But all the previous branches have the type
|
But all the previous branches have type:
|
||||||
|
|
||||||
// Num a
|
Num a
|
||||||
|
|
||||||
// "#
|
I need all branches in an `if` to have the same type!
|
||||||
// ),
|
"#
|
||||||
// )
|
),
|
||||||
// }
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn when_branch_mismatch() {
|
fn when_branch_mismatch() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue