diff --git a/crates/compiler/parse/src/expr.rs b/crates/compiler/parse/src/expr.rs index 757af05a69..ff6d8e83d2 100644 --- a/crates/compiler/parse/src/expr.rs +++ b/crates/compiler/parse/src/expr.rs @@ -346,6 +346,7 @@ fn parse_expr_start<'a>( loc!(move |a, s, m| parse_expr_operator_chain(m, options, a, s)), fail_expr_start_e() ] + .trace("expr_start") .parse(arena, state, min_indent) } @@ -2076,10 +2077,10 @@ mod when { parser::keyword_e(keyword::IS, EWhen::Is) ) ), - move |arena, state, progress, (case_indent, loc_condition), min_indent| { + move |arena, state, _progress, (case_indent, loc_condition), min_indent| { if case_indent < min_indent { return Err(( - progress, + MadeProgress, // TODO maybe pass case_indent here? EWhen::PatternAlignment(5, state.pos()), state, @@ -2089,15 +2090,18 @@ mod when { // Everything in the branches must be indented at least as much as the case itself. let min_indent = case_indent; - let (p1, branches, state) = branches(options).parse(arena, state, min_indent)?; + let (_p1, branches, state) = branches(options) + .parse(arena, state, min_indent) + .map_err(|(_p, e, s)| (MadeProgress, e, s))?; Ok(( - progress.or(p1), + MadeProgress, Expr::When(arena.alloc(loc_condition), branches.into_bump_slice()), state, )) }, ) + .trace("when") } /// Parsing when with indentation. diff --git a/crates/compiler/parse/src/parser.rs b/crates/compiler/parse/src/parser.rs index bd00602b9a..328d4b3b0a 100644 --- a/crates/compiler/parse/src/parser.rs +++ b/crates/compiler/parse/src/parser.rs @@ -737,6 +737,7 @@ pub trait Parser<'a, Output, Error> { ) -> ParseResult<'a, Output, Error>; #[cfg(not(feature = "parse_debug_trace"))] + #[inline(always)] fn trace(self, _message: &'static str) -> Self where Self: Sized, @@ -789,7 +790,7 @@ impl<'a, O: std::fmt::Debug, E: std::fmt::Debug, P: Parser<'a, O, E>> Parser<'a, where E: 'a, { - fn parse(&self, arena: &'a Bump, state: State<'a>) -> ParseResult<'a, O, E> { + fn parse(&self, arena: &'a Bump, state: State<'a>, min_indent: u32) -> ParseResult<'a, O, E> { use std::cell::RefCell; thread_local! { @@ -803,7 +804,7 @@ where let cur_indent = INDENT.with(|i| *i.borrow()); println!( - "{:>5?}: {}{:<50}", + "{:<5?}: {}{:<50}", state.pos(), &indent_text[..cur_indent * 2], self.message @@ -1379,11 +1380,12 @@ macro_rules! and { macro_rules! one_of { ($p1:expr, $p2:expr) => { move |arena: &'a bumpalo::Bump, state: $crate::state::State<'a>, min_indent: u32| { + let original_state = state.clone(); match $p1.parse(arena, state, min_indent) { valid @ Ok(_) => valid, Err((MadeProgress, fail, state)) => Err((MadeProgress, fail, state)), - Err((NoProgress, _, state)) => $p2.parse(arena, state, min_indent), + Err((NoProgress, _, _)) => $p2.parse(arena, original_state, min_indent), } } }; diff --git a/crates/compiler/parse/tests/snapshots/fail/pattern_binds_keyword.expr.result-ast b/crates/compiler/parse/tests/snapshots/fail/pattern_binds_keyword.expr.result-ast new file mode 100644 index 0000000000..03fd8f2cf8 --- /dev/null +++ b/crates/compiler/parse/tests/snapshots/fail/pattern_binds_keyword.expr.result-ast @@ -0,0 +1 @@ +Expr(When(Condition(Start(@30), @29), @24), @0) \ No newline at end of file diff --git a/crates/compiler/parse/tests/snapshots/fail/pattern_binds_keyword.expr.roc b/crates/compiler/parse/tests/snapshots/fail/pattern_binds_keyword.expr.roc new file mode 100644 index 0000000000..e44e443eb0 --- /dev/null +++ b/crates/compiler/parse/tests/snapshots/fail/pattern_binds_keyword.expr.roc @@ -0,0 +1,6 @@ +when Just 4 is + Just when -> + 4 + + _ -> + 2 \ No newline at end of file diff --git a/crates/compiler/parse/tests/snapshots/fail/when_missing_arrow.expr.result-ast b/crates/compiler/parse/tests/snapshots/fail/when_missing_arrow.expr.result-ast new file mode 100644 index 0000000000..bd2fce1211 --- /dev/null +++ b/crates/compiler/parse/tests/snapshots/fail/when_missing_arrow.expr.result-ast @@ -0,0 +1 @@ +Expr(When(Arrow(@26), @20), @0) \ No newline at end of file diff --git a/crates/compiler/parse/tests/snapshots/fail/when_missing_arrow.expr.roc b/crates/compiler/parse/tests/snapshots/fail/when_missing_arrow.expr.roc new file mode 100644 index 0000000000..31fb667aa9 --- /dev/null +++ b/crates/compiler/parse/tests/snapshots/fail/when_missing_arrow.expr.roc @@ -0,0 +1,3 @@ +when 5 is + 1 -> 2 + _ \ No newline at end of file diff --git a/crates/compiler/parse/tests/test_parse.rs b/crates/compiler/parse/tests/test_parse.rs index 86c5123cc1..8b38116a26 100644 --- a/crates/compiler/parse/tests/test_parse.rs +++ b/crates/compiler/parse/tests/test_parse.rs @@ -124,6 +124,8 @@ mod test_parse { fail/lambda_missing_indent.expr, fail/type_argument_no_arrow.expr, fail/type_double_comma.expr, + fail/when_missing_arrow.expr, + fail/pattern_binds_keyword.expr, pass/ability_demand_signature_is_multiline.expr, pass/ability_multi_line.expr, pass/ability_single_line.expr, diff --git a/crates/compiler/region/src/all.rs b/crates/compiler/region/src/all.rs index 3eed5060d5..457810cdf9 100644 --- a/crates/compiler/region/src/all.rs +++ b/crates/compiler/region/src/all.rs @@ -133,7 +133,8 @@ impl Position { impl Debug for Position { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "@{}", self.offset) + write!(f, "@")?; + self.offset.fmt(f) } } diff --git a/crates/reporting/tests/test_reporting.rs b/crates/reporting/tests/test_reporting.rs index 6f82759b09..997d714d84 100644 --- a/crates/reporting/tests/test_reporting.rs +++ b/crates/reporting/tests/test_reporting.rs @@ -4847,14 +4847,27 @@ mod test_reporting { "# ), @r###" - ── MISSING EXPRESSION ───────────────────── tmp/pattern_binds_keyword/Test.roc ─ + ── MISSING ARROW ────────────────────────── tmp/pattern_binds_keyword/Test.roc ─ - I am partway through parsing a `when` expression, but I got stuck here: + I am partway through parsing a `when` expression, but got stuck here: 5│ Just when -> - ^ + ^ - I was expecting to see an expression like 42 or "hello". + I was expecting to see an arrow next. + + Note: Sometimes I get confused by indentation, so try to make your `when` + look something like this: + + when List.first plants is + Ok n -> + n + + Err _ -> + 200 + + Notice the indentation. All patterns are aligned, and each branch is + indented a bit more than the corresponding pattern. That is important! "### );