Merge pull request #6777 from wontem/bang_in_fn_args_desugaring

Ignore def pattern for function args
This commit is contained in:
Luke Boswell 2024-05-28 20:33:54 +10:00 committed by GitHub
commit d9773dde83
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 62 additions and 14 deletions

View File

@ -179,8 +179,8 @@ pub fn desugar_defs_node_values<'a>(
*value_def = desugar_value_def(arena, arena.alloc(*value_def), src, line_info, module_path);
}
// `desugar_defs_node_values` is called recursively in `desugar_expr` and we
// only we only want to unwrap suffixed nodes if they are a top level def.
// `desugar_defs_node_values` is called recursively in `desugar_expr`
// and we only want to unwrap suffixed nodes if they are a top level def.
//
// check here first so we only unwrap the expressions once, and after they have
// been desugared
@ -194,7 +194,7 @@ pub fn desugar_defs_node_values<'a>(
/// For each top-level ValueDef in our module, we will unwrap any suffixed
/// expressions
///
/// e.g. `say! "hi"` desugars to `Task.await (say "hi") -> \{} -> ...`
/// e.g. `say! "hi"` desugars to `Task.await (say "hi") \{} -> ...`
pub fn desugar_value_def_suffixed<'a>(arena: &'a Bump, value_def: ValueDef<'a>) -> ValueDef<'a> {
use ValueDef::*;

View File

@ -129,7 +129,7 @@ pub fn unwrap_suffixed_expression<'a>(
internal_error!("BinOps should have been desugared in desugar_expr");
}
Expr::LowLevelDbg(moduel, arg, rest) => {
Expr::LowLevelDbg(dbg_src, arg, rest) => {
if is_expr_suffixed(&arg.value) {
// we cannot unwrap a suffixed expression within dbg
// e.g. dbg (foo! "bar")
@ -140,14 +140,14 @@ pub fn unwrap_suffixed_expression<'a>(
Ok(unwrapped_expr) => {
let new_dbg = arena.alloc(Loc::at(
loc_expr.region,
LowLevelDbg(moduel, arg, unwrapped_expr),
LowLevelDbg(dbg_src, arg, unwrapped_expr),
));
return Ok(new_dbg);
}
Err(EUnwrapped::UnwrappedDefExpr(unwrapped_expr)) => {
let new_dbg = arena.alloc(Loc::at(
loc_expr.region,
LowLevelDbg(moduel, arg, unwrapped_expr),
LowLevelDbg(dbg_src, arg, unwrapped_expr),
));
Err(EUnwrapped::UnwrappedDefExpr(new_dbg))
}
@ -158,7 +158,7 @@ pub fn unwrap_suffixed_expression<'a>(
}) => {
let new_dbg = arena.alloc(Loc::at(
loc_expr.region,
LowLevelDbg(moduel, arg, unwrapped_expr),
LowLevelDbg(dbg_src, arg, unwrapped_expr),
));
Err(EUnwrapped::UnwrappedSubExpr {
sub_arg: new_dbg,
@ -267,16 +267,13 @@ pub fn unwrap_suffixed_expression_apply_help<'a>(
// Any suffixed arguments will be innermost, therefore we unwrap those first
let local_args = arena.alloc_slice_copy(apply_args);
for arg in local_args.iter_mut() {
match unwrap_suffixed_expression(arena, arg, maybe_def_pat) {
// Args are always expressions, don't pass `maybe_def_pat`
match unwrap_suffixed_expression(arena, arg, None) {
Ok(new_arg) => {
*arg = new_arg;
}
Err(EUnwrapped::UnwrappedDefExpr(unwrapped_arg)) => {
*arg = unwrapped_arg;
let new_apply = arena.alloc(Loc::at(loc_expr.region, Apply(function, local_args, called_via)));
return Err(EUnwrapped::UnwrappedDefExpr(new_apply));
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
internal_error!("unreachable, unwrapped arg cannot be def expression as `None` was passed as pattern");
}
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new: new_arg }) => {

View File

@ -804,6 +804,55 @@ mod suffixed_tests {
r#"Defs { tags: [Index(2147483648)], regions: [@0-85], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@0-4 Identifier { ident: "main" }, @29-36 Apply(@29-36 Var { module_name: "Task", ident: "await" }, [@29-36 Var { module_name: "", ident: "getFoo" }, @29-36 Closure([@23-26 Identifier { ident: "foo" }], @53-85 LowLevelDbg(("test.roc:4", " "), @57-60 Apply(@57-60 Var { module_name: "Inspect", ident: "toStr" }, [@57-60 Var { module_name: "", ident: "foo" }], Space), @77-85 Apply(@77-85 Var { module_name: "", ident: "bar" }, [@82-85 Var { module_name: "", ident: "foo" }], Space)))], BangSuffix))] }"#,
);
}
// main =
// Task.await a \#!a0 ->
// c = b #!a0
// Task.ok c
#[test]
fn apply_argument_single() {
run_test(
r#"
main =
c = b a!
c
"#,
r##"Defs { tags: [Index(2147483648)], regions: [@0-49], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@0-4 Identifier { ident: "main" }, @27-31 Apply(@27-31 Var { module_name: "Task", ident: "await" }, [@29-30 Var { module_name: "", ident: "a" }, @27-31 Closure([@29-30 Identifier { ident: "#!a0" }], @27-31 Defs(Defs { tags: [Index(2147483650)], regions: [@27-31], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@23-24 Identifier { ident: "c" }, @27-31 Apply(@27-28 Var { module_name: "", ident: "b" }, [@29-30 TaskAwaitBang(Var { module_name: "", ident: "a" })], Space)), Body(@23-24 Identifier { ident: "c" }, @27-31 Apply(@27-28 Var { module_name: "", ident: "b" }, [@29-30 Var { module_name: "", ident: "#!a0" }], Space)), Body(@23-24 Identifier { ident: "c" }, @27-31 Apply(@27-28 Var { module_name: "", ident: "b" }, [@29-30 Var { module_name: "", ident: "#!a0" }], Space))] }, @48-49 Var { module_name: "", ident: "c" }))], BangSuffix))] }"##,
);
}
// main =
// Task.await a \#!a0 ->
// Task.await x \#!a1 ->
// c = b #!a0 #!a1
// Task.ok c
#[test]
fn apply_argument_multiple() {
run_test(
r#"
main =
c = b a! x!
c
"#,
r##"Defs { tags: [Index(2147483648)], regions: [@0-52], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@0-4 Identifier { ident: "main" }, @27-34 Apply(@27-34 Var { module_name: "Task", ident: "await" }, [@29-30 Var { module_name: "", ident: "a" }, @27-34 Closure([@29-30 Identifier { ident: "#!a0" }], @27-34 Apply(@27-34 Var { module_name: "Task", ident: "await" }, [@32-33 Var { module_name: "", ident: "x" }, @27-34 Closure([@32-33 Identifier { ident: "#!a1" }], @27-34 Defs(Defs { tags: [Index(2147483651)], regions: [@27-34], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@23-24 Identifier { ident: "c" }, @27-34 Apply(@27-28 Var { module_name: "", ident: "b" }, [@29-30 TaskAwaitBang(Var { module_name: "", ident: "a" }), @32-33 TaskAwaitBang(Var { module_name: "", ident: "x" })], Space)), Body(@23-24 Identifier { ident: "c" }, @27-34 Apply(@27-28 Var { module_name: "", ident: "b" }, [@29-30 Var { module_name: "", ident: "#!a0" }, @32-33 TaskAwaitBang(Var { module_name: "", ident: "x" })], Space)), Body(@23-24 Identifier { ident: "c" }, @27-34 Apply(@27-28 Var { module_name: "", ident: "b" }, [@29-30 Var { module_name: "", ident: "#!a0" }, @32-33 Var { module_name: "", ident: "#!a1" }], Space)), Body(@23-24 Identifier { ident: "c" }, @27-34 Apply(@27-28 Var { module_name: "", ident: "b" }, [@29-30 Var { module_name: "", ident: "#!a0" }, @32-33 Var { module_name: "", ident: "#!a1" }], Space))] }, @51-52 Var { module_name: "", ident: "c" }))], BangSuffix))], BangSuffix))] }"##,
);
}
// main =
// Task.await a \#!a0 ->
// c = b #!a0
// Task.ok c
#[test]
fn bang_in_pipe_root() {
run_test(
r#"
main =
c = a! |> b
c
"#,
r##"Defs { tags: [Index(2147483648)], regions: [@0-52], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@0-4 Identifier { ident: "main" }, @27-34 Apply(@27-34 Var { module_name: "Task", ident: "await" }, [@27-28 Var { module_name: "", ident: "a" }, @27-34 Closure([@27-28 Identifier { ident: "#!a0" }], @27-34 Defs(Defs { tags: [Index(2147483650)], regions: [@27-34], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@23-24 Identifier { ident: "c" }, @27-34 Apply(@33-34 Var { module_name: "", ident: "b" }, [@27-28 TaskAwaitBang(Var { module_name: "", ident: "a" })], BinOp(Pizza))), Body(@23-24 Identifier { ident: "c" }, @27-34 Apply(@33-34 Var { module_name: "", ident: "b" }, [@27-28 Var { module_name: "", ident: "#!a0" }], BinOp(Pizza))), Body(@23-24 Identifier { ident: "c" }, @27-34 Apply(@33-34 Var { module_name: "", ident: "b" }, [@27-28 Var { module_name: "", ident: "#!a0" }], BinOp(Pizza)))] }, @51-52 Var { module_name: "", ident: "c" }))], BangSuffix))] }"##,
);
}
}
#[cfg(test)]

View File

@ -1130,6 +1130,8 @@ impl<'a> ImportAlias<'a> {
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Defs<'a> {
/// A collection of references by index to either `type_defs` or `value_defs`
/// It's an entry point for actual definitions, while `type_defs` and `value_defs` are append-only collections
pub tags: std::vec::Vec<EitherIndex<TypeDef<'a>, ValueDef<'a>>>,
pub regions: std::vec::Vec<Region>,
pub space_before: std::vec::Vec<Slice<CommentOrNewline<'a>>>,