mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
parse single backpassing
This commit is contained in:
parent
6da792c62d
commit
66e7e3bc5e
3 changed files with 154 additions and 2 deletions
|
@ -860,7 +860,7 @@ fn parse_defs_end<'a>(
|
|||
return parse_defs_end(start, def_state, arena, state);
|
||||
}
|
||||
Ok((_, BinOp::HasType, state)) => {
|
||||
let (_, mut ann_type, state) = specialize(
|
||||
let (_, ann_type, state) = specialize(
|
||||
EExpr::Type,
|
||||
space0_before_e(
|
||||
type_annotation::located_help(min_indent + 1),
|
||||
|
@ -881,6 +881,34 @@ fn parse_defs_end<'a>(
|
|||
|
||||
return parse_defs_end(start, def_state, arena, state);
|
||||
}
|
||||
Ok((_, BinOp::Backpassing, state)) => {
|
||||
let parse_body = space0_before_e(
|
||||
move |a, s| parse_expr_help(min_indent + 1, a, s),
|
||||
min_indent,
|
||||
EExpr::Space,
|
||||
EExpr::IndentEnd,
|
||||
);
|
||||
|
||||
let (_, loc_body, state) = parse_body.parse(arena, state)?;
|
||||
|
||||
let (_, loc_cont, state) = parse_body.parse(arena, state)?;
|
||||
|
||||
let region = Region::span_across(&loc_pattern.region, &loc_cont.region);
|
||||
|
||||
let ret = Expr::Backpassing(
|
||||
arena.alloc([loc_pattern]),
|
||||
arena.alloc(loc_body),
|
||||
arena.alloc(loc_cont),
|
||||
);
|
||||
|
||||
let loc_ret = Located::at(region, ret);
|
||||
|
||||
return Ok((
|
||||
MadeProgress,
|
||||
Expr::Defs(def_state.defs.into_bump_slice(), arena.alloc(loc_ret)),
|
||||
state,
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
// this is no def, because there is no `=`, `:` or `<-`; parse as an expr
|
||||
let state = initial;
|
||||
|
@ -1026,6 +1054,85 @@ fn parse_expr_operator<'a>(
|
|||
parse_defs_end(start, def_state, arena, state)
|
||||
}
|
||||
}
|
||||
BinOp::Backpassing => {
|
||||
if !expr_state.operators.is_empty() {
|
||||
// this `=` likely occured inline; treat it as an invalid operator
|
||||
let fail = EExpr::BadOperator(
|
||||
arena.alloc([b'=']),
|
||||
loc_op.region.start_line,
|
||||
loc_op.region.start_col,
|
||||
);
|
||||
|
||||
Err((MadeProgress, fail, state))
|
||||
} else if !expr_state.arguments.is_empty() {
|
||||
let region = Region::across_all(expr_state.arguments.iter().map(|v| &v.region));
|
||||
|
||||
let fail = EExpr::ElmStyleFunction(
|
||||
region,
|
||||
loc_op.region.start_line,
|
||||
loc_op.region.start_col,
|
||||
);
|
||||
|
||||
Err((MadeProgress, fail, state))
|
||||
} else {
|
||||
expr_state.consume_spaces(arena);
|
||||
let expr_region = expr_state.expr.region;
|
||||
|
||||
let indented_more = start.col + 1;
|
||||
|
||||
let call = to_call(
|
||||
arena,
|
||||
expr_state.arguments,
|
||||
expr_state.expr,
|
||||
spaces_after_operator,
|
||||
);
|
||||
|
||||
let (loc_pattern, loc_body, state) = {
|
||||
match expr_to_pattern_help(arena, &call.value) {
|
||||
Ok(good) => {
|
||||
let (_, mut ann_type, state) =
|
||||
parse_expr_help(indented_more, arena, state)?;
|
||||
|
||||
// put the spaces from after the operator in front of the call
|
||||
if !spaces_after_operator.is_empty() {
|
||||
ann_type = arena
|
||||
.alloc(ann_type.value)
|
||||
.with_spaces_before(spaces_after_operator, ann_type.region);
|
||||
}
|
||||
|
||||
(Located::at(expr_region, good), ann_type, state)
|
||||
}
|
||||
Err(_) => {
|
||||
// this `=` likely occured inline; treat it as an invalid operator
|
||||
let fail = EExpr::BadOperator(
|
||||
arena.alloc([b'=']),
|
||||
loc_op.region.start_line,
|
||||
loc_op.region.start_col,
|
||||
);
|
||||
|
||||
return Err((MadeProgress, fail, state));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let parse_cont = space0_before_e(
|
||||
move |a, s| parse_expr_help(min_indent + 1, a, s),
|
||||
min_indent,
|
||||
EExpr::Space,
|
||||
EExpr::IndentEnd,
|
||||
);
|
||||
|
||||
let (_, loc_cont, state) = parse_cont.parse(arena, state)?;
|
||||
|
||||
let ret = Expr::Backpassing(
|
||||
arena.alloc([loc_pattern]),
|
||||
arena.alloc(loc_body),
|
||||
arena.alloc(loc_cont),
|
||||
);
|
||||
|
||||
Ok((MadeProgress, ret, state))
|
||||
}
|
||||
}
|
||||
BinOp::HasType => {
|
||||
debug_assert!(expr_state.operators.is_empty());
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue