mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 04:08:19 +00:00
Merge pull request #6649 from roc-lang/suffixed-when
Add support for suffixed `when` expressions
This commit is contained in:
commit
ca8682e93c
2 changed files with 127 additions and 4 deletions
|
@ -6,7 +6,7 @@ use roc_error_macros::internal_error;
|
|||
use roc_module::called_via::CalledVia;
|
||||
use roc_module::ident::ModuleName;
|
||||
use roc_parse::ast::Expr::{self, *};
|
||||
use roc_parse::ast::{is_loc_expr_suffixed, wrap_in_task_ok, Pattern, ValueDef};
|
||||
use roc_parse::ast::{is_loc_expr_suffixed, wrap_in_task_ok, Pattern, ValueDef, WhenBranch};
|
||||
use roc_region::all::{Loc, Region};
|
||||
use std::cell::Cell;
|
||||
|
||||
|
@ -564,11 +564,61 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
|||
}
|
||||
|
||||
pub fn unwrap_suffixed_expression_when_help<'a>(
|
||||
_arena: &'a Bump,
|
||||
arena: &'a Bump,
|
||||
loc_expr: &'a Loc<Expr<'a>>,
|
||||
_maybe_def_pat: Option<&'a Loc<Pattern<'a>>>,
|
||||
maybe_def_pat: Option<&'a Loc<Pattern<'a>>>,
|
||||
) -> Result<&'a Loc<Expr<'a>>, EUnwrapped<'a>> {
|
||||
Ok(loc_expr)
|
||||
match loc_expr.value {
|
||||
Expr::When(condition, branches) => {
|
||||
|
||||
// first unwrap any when branches values
|
||||
// e.g.
|
||||
// when foo is
|
||||
// [] -> line! "bar"
|
||||
// _ -> line! "baz"
|
||||
for (branch_index, WhenBranch{value: branch_loc_expr,patterns, guard}) in branches.iter().enumerate() {
|
||||
|
||||
// if the branch isn't suffixed we can leave it alone
|
||||
if is_loc_expr_suffixed(branch_loc_expr) {
|
||||
let unwrapped_branch_value = match unwrap_suffixed_expression(arena, branch_loc_expr, None) {
|
||||
Ok(unwrapped_branch_value) => unwrapped_branch_value,
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => apply_task_await(arena, branch_loc_expr.region, sub_arg, sub_pat, sub_new),
|
||||
Err(..) => return Err(EUnwrapped::Malformed),
|
||||
};
|
||||
|
||||
let new_branch = WhenBranch{value: *unwrapped_branch_value, patterns, guard: *guard};
|
||||
let mut new_branches = Vec::new_in(arena);
|
||||
let (before, rest) = branches.split_at(branch_index);
|
||||
let after = &rest[1..];
|
||||
|
||||
new_branches.extend_from_slice(before);
|
||||
new_branches.push(arena.alloc(new_branch));
|
||||
new_branches.extend_from_slice(after);
|
||||
|
||||
let new_when = arena.alloc(Loc::at(loc_expr.region, Expr::When(condition, arena.alloc_slice_copy(new_branches.as_slice()))));
|
||||
|
||||
return unwrap_suffixed_expression(arena, new_when, maybe_def_pat);
|
||||
}
|
||||
}
|
||||
|
||||
// then unwrap the when condition
|
||||
match unwrap_suffixed_expression(arena, condition, None) {
|
||||
Ok(unwrapped_condition) => {
|
||||
let new_when = arena.alloc(Loc::at(loc_expr.region, Expr::When(unwrapped_condition, branches)));
|
||||
Ok(new_when)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
||||
let new_when = arena.alloc(Loc::at(loc_expr.region, Expr::When(sub_new, branches)));
|
||||
let applied_task_await = apply_task_await(arena,loc_expr.region,sub_arg,sub_pat,new_when);
|
||||
Ok(applied_task_await)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..))
|
||||
| Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed)
|
||||
}
|
||||
|
||||
}
|
||||
_ => internal_error!("unreachable, expected a When node to be passed into unwrap_suffixed_expression_defs_help"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unwrap_suffixed_expression_defs_help<'a>(
|
||||
|
|
|
@ -665,4 +665,77 @@ mod suffixed_tests {
|
|||
r#"Defs { tags: [Index(2147483648)], regions: [@0-103], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@0-4 Identifier { ident: "copy", suffixed: 0 }, @7-103 Closure([@8-9 Identifier { ident: "a", suffixed: 0 }, @10-11 Identifier { ident: "b", suffixed: 0 }], @36-42 Apply(@36-42 Var { module_name: "Task", ident: "await", suffixed: 0 }, [@36-42 Apply(@36-42 Var { module_name: "", ident: "line", suffixed: 0 }, [@37-42 Str(PlainLine("FOO"))], Space), @36-42 Closure([@36-42 RecordDestructure([])], @60-103 Apply(@60-103 Var { module_name: "", ident: "mapErr", suffixed: 0 }, [@60-72 Apply(@60-67 Var { module_name: "CMD", ident: "new", suffixed: 0 }, [@68-72 Str(PlainLine("cp"))], Space), @100-103 Tag("ERR")], BinOp(Pizza)))], BangSuffix)))] }"#,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwrap a when expression
|
||||
```roc
|
||||
list =
|
||||
when getList! is
|
||||
[] -> "empty"
|
||||
_ -> "non-empty"
|
||||
|
||||
list =
|
||||
Task.await getList \#!a0 ->
|
||||
when #!a0 is
|
||||
[] -> "empty"
|
||||
_ -> "non-empty"
|
||||
```
|
||||
*/
|
||||
#[test]
|
||||
fn when_simple() {
|
||||
run_test(
|
||||
r#"
|
||||
list =
|
||||
when getList! is
|
||||
[] -> "empty"
|
||||
_ -> "non-empty"
|
||||
"#,
|
||||
r##"Defs { tags: [Index(2147483648)], regions: [@0-111], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@0-4 Identifier { ident: "list", suffixed: 0 }, @24-111 Apply(@24-111 Var { module_name: "Task", ident: "await", suffixed: 0 }, [@29-37 Var { module_name: "", ident: "getList", suffixed: 0 }, @24-111 Closure([@29-37 Identifier { ident: "#!a0", suffixed: 0 }], @24-111 When(@29-37 Var { module_name: "", ident: "#!a0", suffixed: 0 }, [WhenBranch { patterns: [@61-63 List([])], value: @67-74 Str(PlainLine("empty")), guard: None }, WhenBranch { patterns: [@95-96 Underscore("")], value: @100-111 Str(PlainLine("non-empty")), guard: None }]))], BangSuffix))] }"##,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwrap a when expression
|
||||
```roc
|
||||
list =
|
||||
when getList! is
|
||||
[] ->
|
||||
line! "foo"
|
||||
line! "bar"
|
||||
_ ->
|
||||
ok {}
|
||||
|
||||
list =
|
||||
Task.await getList \#!a0 ->
|
||||
when getList is
|
||||
[] ->
|
||||
line! "foo"
|
||||
line! "bar"
|
||||
_ ->
|
||||
ok {}
|
||||
|
||||
list =
|
||||
Task.await getList \#!a0 ->
|
||||
when getList is
|
||||
[] ->
|
||||
Task.await line "foo" \{} -> line! "bar"
|
||||
_ ->
|
||||
ok {}
|
||||
```
|
||||
*/
|
||||
#[test]
|
||||
fn when_branches() {
|
||||
run_test(
|
||||
r#"
|
||||
list =
|
||||
when getList! is
|
||||
[] ->
|
||||
line! "foo"
|
||||
line! "bar"
|
||||
_ ->
|
||||
ok {}
|
||||
"#,
|
||||
r##"Defs { tags: [Index(2147483648)], regions: [@0-195], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@0-4 Identifier { ident: "list", suffixed: 0 }, @24-195 Apply(@24-195 Var { module_name: "Task", ident: "await", suffixed: 0 }, [@29-37 Var { module_name: "", ident: "getList", suffixed: 0 }, @24-195 Closure([@29-37 Identifier { ident: "#!a0", suffixed: 0 }], @24-195 When(@29-37 Var { module_name: "", ident: "#!a0", suffixed: 0 }, [WhenBranch { patterns: [@61-63 List([])], value: @97-103 Apply(@97-103 Var { module_name: "Task", ident: "await", suffixed: 0 }, [@97-103 Apply(@97-103 Var { module_name: "", ident: "line", suffixed: 0 }, [@98-103 Str(PlainLine("foo"))], Space), @97-103 Closure([@97-103 RecordDestructure([])], @128-139 Apply(@128-139 Var { module_name: "", ident: "line", suffixed: 0 }, [@134-139 Str(PlainLine("bar"))], Space))], BangSuffix), guard: None }, WhenBranch { patterns: [@160-161 Underscore("")], value: @190-195 Apply(@190-192 Var { module_name: "", ident: "ok", suffixed: 0 }, [@193-195 Record([])], Space), guard: None }]))], BangSuffix))] }"##,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue