Merge pull request #6851 from kdziamura/last-expr-desugar

Simplify Defs parsing
This commit is contained in:
Luke Boswell 2024-07-02 08:48:31 +10:00 committed by GitHub
commit a44a6889bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 165 additions and 217 deletions

View file

@ -755,28 +755,6 @@ pub fn desugar_expr<'a>(
})
}
// Replace an empty final def with a `Task.ok {}`
EmptyDefsFinal => {
let mut apply_args: Vec<&'a Loc<Expr<'a>>> = Vec::new_in(arena);
apply_args
.push(arena.alloc(Loc::at(loc_expr.region, Expr::Record(Collection::empty()))));
arena.alloc(Loc::at(
loc_expr.region,
Expr::Apply(
arena.alloc(Loc::at(
loc_expr.region,
Expr::Var {
module_name: ModuleName::TASK,
ident: "ok",
},
)),
arena.alloc(apply_args),
CalledVia::BangSuffix,
),
))
}
// note this only exists after desugaring
LowLevelDbg(_, _, _) => loc_expr,
}

View file

@ -621,9 +621,6 @@ pub fn canonicalize_expr<'a>(
use Expr::*;
let (expr, output) = match expr {
&ast::Expr::EmptyDefsFinal => {
internal_error!("EmptyDefsFinal should have been desugared")
}
&ast::Expr::Num(str) => {
let answer = num_expr_from_result(var_store, finish_parsing_num(str), region, env);
@ -2392,8 +2389,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
| ast::Expr::Backpassing(_, _, _)
| ast::Expr::SpaceBefore(_, _)
| ast::Expr::Str(StrLiteral::Block(_))
| ast::Expr::SpaceAfter(_, _)
| ast::Expr::EmptyDefsFinal => false,
| ast::Expr::SpaceAfter(_, _) => false,
// These can contain subexpressions, so we need to recursively check those
ast::Expr::Str(StrLiteral::Line(segments)) => {
segments.iter().all(|segment| match segment {

View file

@ -619,7 +619,8 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
let after_empty = split_defs.after.is_empty();
if before_empty && after_empty {
// NIL before, NIL after -> SINGLE DEF
let next_expr = match unwrap_suffixed_expression(arena,loc_ret,maybe_def_pat) {
// We pass None as a def pattern here because it's desugaring of the ret expression
let next_expr = match unwrap_suffixed_expression(arena,loc_ret, None) {
Ok(next_expr) => next_expr,
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
// We need to apply Task.ok here as the defs final expression was unwrapped
@ -649,7 +650,8 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
return unwrap_suffixed_expression(arena, apply_task_await(arena,def_expr.region,unwrapped_expr,def_pattern,next_expr), maybe_def_pat);
} else if after_empty {
// SOME before, NIL after -> LAST DEF
match unwrap_suffixed_expression(arena,loc_ret,maybe_def_pat){
// We pass None as a def pattern here because it's desugaring of the ret expression
match unwrap_suffixed_expression(arena,loc_ret,None){
Ok(new_loc_ret) => {
let applied_task_await = apply_task_await(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret);
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(split_defs.before), applied_task_await)));

View file

@ -1,3 +1,6 @@
#[macro_use]
extern crate indoc;
#[cfg(test)]
mod suffixed_tests {
@ -375,7 +378,7 @@ mod suffixed_tests {
x = foo! msg
bar x
"#,
r#"Defs { tags: [Index(2147483648)], regions: [@0-88], 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" }, @0-88 Defs(Defs { tags: [Index(2147483649)], regions: [@30-37], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@24-27 Identifier { ident: "msg" }, @30-37 Str(PlainLine("hello"))), Body(@24-27 Identifier { ident: "msg" }, @30-37 Str(PlainLine("hello")))] }, @0-88 Apply(@0-88 Var { module_name: "Task", ident: "await" }, [@54-66 Apply(@54-66 Var { module_name: "", ident: "foo" }, [@63-66 Var { module_name: "", ident: "msg" }], Space), @0-88 Closure([@54-55 Identifier { ident: "x" }], @83-88 Apply(@83-86 Var { module_name: "", ident: "bar" }, [@87-88 Var { module_name: "", ident: "x" }], Space))], BangSuffix)))] }"#,
r#"Defs { tags: [Index(2147483648)], regions: [@0-88], 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" }, @24-88 Defs(Defs { tags: [Index(2147483649)], regions: [@30-37], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@24-27 Identifier { ident: "msg" }, @30-37 Str(PlainLine("hello"))), Body(@24-27 Identifier { ident: "msg" }, @30-37 Str(PlainLine("hello")))] }, @24-88 Apply(@24-88 Var { module_name: "Task", ident: "await" }, [@54-66 Apply(@54-66 Var { module_name: "", ident: "foo" }, [@63-66 Var { module_name: "", ident: "msg" }], Space), @24-88 Closure([@54-55 Identifier { ident: "x" }], @83-88 Apply(@83-86 Var { module_name: "", ident: "bar" }, [@87-88 Var { module_name: "", ident: "x" }], Space))], BangSuffix)))] }"#,
);
}
@ -416,7 +419,7 @@ mod suffixed_tests {
x "foo"
"#,
r#"Defs { tags: [Index(2147483648)], regions: [@0-187], 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" }, @0-187 Defs(Defs { tags: [Index(2147483650)], regions: [@60-162], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Annotation(@24-25 Identifier { ident: "x" }, @28-43 Function([@28-31 Apply("", "Str", [])], @35-43 Apply("", "Task", [@40-41 Inferred, @42-43 Inferred]))), AnnotatedBody { ann_pattern: @24-25 Identifier { ident: "x" }, ann_type: @28-43 Function([@28-31 Apply("", "Str", [])], @35-43 Apply("", "Task", [@40-41 Inferred, @42-43 Inferred])), comment: None, body_pattern: @60-61 Identifier { ident: "x" }, body_expr: @60-162 Closure([@65-68 Identifier { ident: "msg" }], @93-162 Defs(Defs { tags: [Index(2147483649)], regions: [@93-140], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Annotation(@93-94 Identifier { ident: "y" }, @97-106 Apply("", "Task", [@102-104 Record { fields: [], ext: None }, @105-106 Inferred])), AnnotatedBody { ann_pattern: @93-94 Identifier { ident: "y" }, ann_type: @97-106 Apply("", "Task", [@102-104 Record { fields: [], ext: None }, @105-106 Inferred]), comment: None, body_pattern: @127-128 Identifier { ident: "y" }, body_expr: @127-140 Apply(@131-135 TaskAwaitBang(Var { module_name: "", ident: "line" }), [@137-140 Var { module_name: "", ident: "msg" }], Space) }] }, @161-162 Var { module_name: "", ident: "y" })) }, AnnotatedBody { ann_pattern: @24-25 Identifier { ident: "x" }, ann_type: @28-43 Function([@28-31 Apply("", "Str", [])], @35-43 Apply("", "Task", [@40-41 Inferred, @42-43 Inferred])), comment: None, body_pattern: @60-61 Identifier { ident: "x" }, body_expr: @60-162 Closure([@65-68 Identifier { ident: "msg" }], @127-140 Apply(@127-140 Var { module_name: "Task", ident: "await" }, [@127-140 Apply(@127-140 Var { module_name: "", ident: "line" }, [@137-140 Var { module_name: "", ident: "msg" }], Space), @127-140 Closure([@127-128 Identifier { ident: "y" }], @161-162 Var { module_name: "", ident: "y" })], BangSuffix)) }] }, @180-187 Apply(@180-181 Var { module_name: "", ident: "x" }, [@182-187 Str(PlainLine("foo"))], Space)))] }"#,
r#"Defs { tags: [Index(2147483648)], regions: [@0-187], 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" }, @24-187 Defs(Defs { tags: [Index(2147483650)], regions: [@64-162], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Annotation(@24-25 Identifier { ident: "x" }, @28-43 Function([@28-31 Apply("", "Str", [])], @35-43 Apply("", "Task", [@40-41 Inferred, @42-43 Inferred]))), AnnotatedBody { ann_pattern: @24-25 Identifier { ident: "x" }, ann_type: @28-43 Function([@28-31 Apply("", "Str", [])], @35-43 Apply("", "Task", [@40-41 Inferred, @42-43 Inferred])), comment: None, body_pattern: @60-61 Identifier { ident: "x" }, body_expr: @64-162 Closure([@65-68 Identifier { ident: "msg" }], @93-162 Defs(Defs { tags: [Index(2147483649)], regions: [@93-140], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Annotation(@93-94 Identifier { ident: "y" }, @97-106 Apply("", "Task", [@102-104 Record { fields: [], ext: None }, @105-106 Inferred])), AnnotatedBody { ann_pattern: @93-94 Identifier { ident: "y" }, ann_type: @97-106 Apply("", "Task", [@102-104 Record { fields: [], ext: None }, @105-106 Inferred]), comment: None, body_pattern: @127-128 Identifier { ident: "y" }, body_expr: @127-140 Apply(@131-135 TaskAwaitBang(Var { module_name: "", ident: "line" }), [@137-140 Var { module_name: "", ident: "msg" }], Space) }] }, @161-162 Var { module_name: "", ident: "y" })) }, AnnotatedBody { ann_pattern: @24-25 Identifier { ident: "x" }, ann_type: @28-43 Function([@28-31 Apply("", "Str", [])], @35-43 Apply("", "Task", [@40-41 Inferred, @42-43 Inferred])), comment: None, body_pattern: @60-61 Identifier { ident: "x" }, body_expr: @64-162 Closure([@65-68 Identifier { ident: "msg" }], @127-140 Apply(@127-140 Var { module_name: "Task", ident: "await" }, [@127-140 Apply(@127-140 Var { module_name: "", ident: "line" }, [@137-140 Var { module_name: "", ident: "msg" }], Space), @127-140 Closure([@127-128 Identifier { ident: "y" }], @161-162 Var { module_name: "", ident: "y" })], BangSuffix)) }] }, @180-187 Apply(@180-181 Var { module_name: "", ident: "x" }, [@182-187 Str(PlainLine("foo"))], Space)))] }"#,
);
}
@ -610,7 +613,7 @@ mod suffixed_tests {
else
line "fail"
"#,
r##"Defs { tags: [Index(2147483648)], regions: [@0-286], 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" }, @0-286 Defs(Defs { tags: [Index(2147483650), Index(2147483651)], regions: [@32-49, @76-94], space_before: [Slice(start = 0, length = 0), Slice(start = 0, length = 1)], space_after: [Slice(start = 0, length = 0), Slice(start = 1, length = 0)], spaces: [Newline], type_defs: [], value_defs: [Body(@23-29 Identifier { ident: "isTrue" }, @32-49 Apply(@32-39 Var { module_name: "Task", ident: "ok" }, [@40-49 Var { module_name: "Bool", ident: "true" }], Space)), Body(@66-73 Identifier { ident: "isFalse" }, @76-94 Apply(@76-83 Var { module_name: "Task", ident: "ok" }, [@84-94 Var { module_name: "Bool", ident: "false" }], Space)), Body(@23-29 Identifier { ident: "isTrue" }, @32-49 Apply(@32-39 Var { module_name: "Task", ident: "ok" }, [@40-49 Var { module_name: "Bool", ident: "true" }], Space)), Body(@66-73 Identifier { ident: "isFalse" }, @76-94 Apply(@76-83 Var { module_name: "Task", ident: "ok" }, [@84-94 Var { module_name: "Bool", ident: "false" }], Space))] }, @115-123 Apply(@115-123 Var { module_name: "Task", ident: "await" }, [@115-123 Var { module_name: "", ident: "isFalse" }, @115-123 Closure([@115-123 Identifier { ident: "#!a0" }], @112-286 If([(@115-123 Var { module_name: "", ident: "#!a0" }, @149-160 Apply(@149-153 Var { module_name: "", ident: "line" }, [@154-160 Str(PlainLine("fail"))], Space))], @185-192 Apply(@185-192 Var { module_name: "Task", ident: "await" }, [@185-192 Var { module_name: "", ident: "isTrue" }, @185-192 Closure([@185-192 Identifier { ident: "#!a1" }], @112-286 If([(@185-192 Var { module_name: "", ident: "#!a1" }, @219-233 Apply(@219-223 Var { module_name: "", ident: "line" }, [@224-233 Str(PlainLine("success"))], Space))], @275-286 Apply(@275-279 Var { module_name: "", ident: "line" }, [@280-286 Str(PlainLine("fail"))], Space)))], BangSuffix)))], BangSuffix)))] }"##,
r##"Defs { tags: [Index(2147483648)], regions: [@0-286], 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" }, @23-286 Defs(Defs { tags: [Index(2147483650), Index(2147483651)], regions: [@32-49, @76-94], space_before: [Slice(start = 0, length = 0), Slice(start = 0, length = 1)], space_after: [Slice(start = 0, length = 0), Slice(start = 1, length = 0)], spaces: [Newline], type_defs: [], value_defs: [Body(@23-29 Identifier { ident: "isTrue" }, @32-49 Apply(@32-39 Var { module_name: "Task", ident: "ok" }, [@40-49 Var { module_name: "Bool", ident: "true" }], Space)), Body(@66-73 Identifier { ident: "isFalse" }, @76-94 Apply(@76-83 Var { module_name: "Task", ident: "ok" }, [@84-94 Var { module_name: "Bool", ident: "false" }], Space)), Body(@23-29 Identifier { ident: "isTrue" }, @32-49 Apply(@32-39 Var { module_name: "Task", ident: "ok" }, [@40-49 Var { module_name: "Bool", ident: "true" }], Space)), Body(@66-73 Identifier { ident: "isFalse" }, @76-94 Apply(@76-83 Var { module_name: "Task", ident: "ok" }, [@84-94 Var { module_name: "Bool", ident: "false" }], Space))] }, @115-123 Apply(@115-123 Var { module_name: "Task", ident: "await" }, [@115-123 Var { module_name: "", ident: "isFalse" }, @115-123 Closure([@115-123 Identifier { ident: "#!a0" }], @112-286 If([(@115-123 Var { module_name: "", ident: "#!a0" }, @149-160 Apply(@149-153 Var { module_name: "", ident: "line" }, [@154-160 Str(PlainLine("fail"))], Space))], @185-192 Apply(@185-192 Var { module_name: "Task", ident: "await" }, [@185-192 Var { module_name: "", ident: "isTrue" }, @185-192 Closure([@185-192 Identifier { ident: "#!a1" }], @112-286 If([(@185-192 Var { module_name: "", ident: "#!a1" }, @219-233 Apply(@219-223 Var { module_name: "", ident: "line" }, [@224-233 Str(PlainLine("success"))], Space))], @275-286 Apply(@275-279 Var { module_name: "", ident: "line" }, [@280-286 Str(PlainLine("fail"))], Space)))], BangSuffix)))], BangSuffix)))] }"##,
);
}
@ -650,7 +653,7 @@ mod suffixed_tests {
msg
"#,
r##"Defs { tags: [Index(2147483648)], regions: [@0-466], 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" }, @0-466 Defs(Defs { tags: [Index(2147483652), Index(2147483653), Index(2147483654)], regions: [@32-49, @77-92, @143-445], space_before: [Slice(start = 0, length = 0), Slice(start = 0, length = 1), Slice(start = 1, length = 1)], space_after: [Slice(start = 0, length = 0), Slice(start = 1, length = 0), Slice(start = 2, length = 0)], spaces: [Newline, Newline], type_defs: [], value_defs: [Body(@23-29 Identifier { ident: "isTrue" }, @32-49 Apply(@32-39 Var { module_name: "Task", ident: "ok" }, [@40-49 Var { module_name: "Bool", ident: "true" }], Space)), Body(@66-74 Identifier { ident: "isFalsey" }, @77-92 Closure([@78-79 Identifier { ident: "x" }], @83-92 Apply(@83-90 Var { module_name: "Task", ident: "ok" }, [@91-92 Var { module_name: "", ident: "x" }], Space))), Annotation(@109-112 Identifier { ident: "msg" }, @115-126 Apply("", "Task", [@120-122 Record { fields: [], ext: None }, @123-126 Apply("", "I32", [])])), AnnotatedBody { ann_pattern: @109-112 Identifier { ident: "msg" }, ann_type: @115-126 Apply("", "Task", [@120-122 Record { fields: [], ext: None }, @123-126 Apply("", "I32", [])]), comment: None, body_pattern: @143-146 Identifier { ident: "msg" }, body_expr: @143-445 If([(@173-183 Apply(@173-174 Var { module_name: "Bool", ident: "not" }, [@175-182 ParensAround(TaskAwaitBang(Var { module_name: "", ident: "isTrue" }))], UnaryOp(Not)), @213-256 Defs(Defs { tags: [Index(2147483648)], regions: [@218-225], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@218-225 RecordDestructure([]), @218-225 Apply(@213-217 TaskAwaitBang(Var { module_name: "", ident: "line" }), [@219-225 Str(PlainLine("fail"))], Space))] }, @251-256 Apply(@251-254 Var { module_name: "", ident: "err" }, [@255-256 Num("1")], Space))), (@285-307 ParensAround(Apply(@286-294 TaskAwaitBang(Var { module_name: "", ident: "isFalsey" }), [@296-306 Var { module_name: "Bool", ident: "false" }], Space)), @338-380 Defs(Defs { tags: [Index(2147483648)], regions: [@343-350], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@343-350 RecordDestructure([]), @343-350 Apply(@338-342 TaskAwaitBang(Var { module_name: "", ident: "line" }), [@344-350 Str(PlainLine("nope"))], Space))] }, @375-380 Apply(@375-377 Var { module_name: "", ident: "ok" }, [@378-380 Record([])], Space)))], @430-445 Apply(@430-434 TaskAwaitBang(Var { module_name: "", ident: "line" }), [@436-445 Str(PlainLine("success"))], Space)) }, Body(@23-29 Identifier { ident: "isTrue" }, @32-49 Apply(@32-39 Var { module_name: "Task", ident: "ok" }, [@40-49 Var { module_name: "Bool", ident: "true" }], Space)), Body(@66-74 Identifier { ident: "isFalsey" }, @77-92 Closure([@78-79 Identifier { ident: "x" }], @83-92 Apply(@83-90 Var { module_name: "Task", ident: "ok" }, [@91-92 Var { module_name: "", ident: "x" }], Space))), AnnotatedBody { ann_pattern: @109-112 Identifier { ident: "msg" }, ann_type: @115-126 Apply("", "Task", [@120-122 Record { fields: [], ext: None }, @123-126 Apply("", "I32", [])]), comment: None, body_pattern: @143-146 Identifier { ident: "msg" }, body_expr: Apply(Var { module_name: "Task", ident: "await" }, [Var { module_name: "", ident: "isTrue" }, Closure([Identifier { ident: "#!a0" }], @143-445 If([(@173-183 Apply(@173-174 Var { module_name: "Bool", ident: "not" }, [@175-182 ParensAround(Var { module_name: "", ident: "#!a0" })], UnaryOp(Not)), @218-225 Apply(@218-225 Var { module_name: "Task", ident: "await" }, [@218-225 Apply(@218-225 Var { module_name: "", ident: "line" }, [@219-225 Str(PlainLine("fail"))], Space), @218-225 Closure([@218-225 RecordDestructure([])], @251-256 Apply(@251-254 Var { module_name: "", ident: "err" }, [@255-256 Num("1")], Space))], BangSuffix))], Apply(Var { module_name: "Task", ident: "await" }, [Apply(Var { module_name: "", ident: "isFalsey" }, [@296-306 Var { module_name: "Bool", ident: "false" }], Space), Closure([Identifier { ident: "#!a1" }], @143-445 If([(@285-307 ParensAround(Var { module_name: "", ident: "#!a1" }), @343-350 Apply(@343-350 Var { module_name: "Task", ident: "await" }, [@343-350 Apply(@343-350 Var { module_name: "", ident: "line" }, [@344-350 Str(PlainLine("nope"))], Space), @343-350 Closure([@343-350 RecordDestructure([])], @375-380 Apply(@375-377 Var { module_name: "", ident: "ok" }, [@378-380 Record([])], Space))], BangSuffix))], @430-445 Apply(@430-445 Var { module_name: "", ident: "line" }, [@436-445 Str(PlainLine("success"))], Space)))], BangSuffix)))], BangSuffix) }] }, @463-466 Var { module_name: "", ident: "msg" }))] }"##,
r##"Defs { tags: [Index(2147483648)], regions: [@0-466], 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" }, @23-466 Defs(Defs { tags: [Index(2147483652), Index(2147483653), Index(2147483654)], regions: [@32-49, @77-92, @170-445], space_before: [Slice(start = 0, length = 0), Slice(start = 0, length = 1), Slice(start = 1, length = 1)], space_after: [Slice(start = 0, length = 0), Slice(start = 1, length = 0), Slice(start = 2, length = 0)], spaces: [Newline, Newline], type_defs: [], value_defs: [Body(@23-29 Identifier { ident: "isTrue" }, @32-49 Apply(@32-39 Var { module_name: "Task", ident: "ok" }, [@40-49 Var { module_name: "Bool", ident: "true" }], Space)), Body(@66-74 Identifier { ident: "isFalsey" }, @77-92 Closure([@78-79 Identifier { ident: "x" }], @83-92 Apply(@83-90 Var { module_name: "Task", ident: "ok" }, [@91-92 Var { module_name: "", ident: "x" }], Space))), Annotation(@109-112 Identifier { ident: "msg" }, @115-126 Apply("", "Task", [@120-122 Record { fields: [], ext: None }, @123-126 Apply("", "I32", [])])), AnnotatedBody { ann_pattern: @109-112 Identifier { ident: "msg" }, ann_type: @115-126 Apply("", "Task", [@120-122 Record { fields: [], ext: None }, @123-126 Apply("", "I32", [])]), comment: None, body_pattern: @143-146 Identifier { ident: "msg" }, body_expr: @170-445 If([(@173-183 Apply(@173-174 Var { module_name: "Bool", ident: "not" }, [@175-182 ParensAround(TaskAwaitBang(Var { module_name: "", ident: "isTrue" }))], UnaryOp(Not)), @213-256 Defs(Defs { tags: [Index(2147483648)], regions: [@218-225], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@218-225 RecordDestructure([]), @218-225 Apply(@213-217 TaskAwaitBang(Var { module_name: "", ident: "line" }), [@219-225 Str(PlainLine("fail"))], Space))] }, @251-256 Apply(@251-254 Var { module_name: "", ident: "err" }, [@255-256 Num("1")], Space))), (@285-307 ParensAround(Apply(@286-294 TaskAwaitBang(Var { module_name: "", ident: "isFalsey" }), [@296-306 Var { module_name: "Bool", ident: "false" }], Space)), @338-380 Defs(Defs { tags: [Index(2147483648)], regions: [@343-350], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@343-350 RecordDestructure([]), @343-350 Apply(@338-342 TaskAwaitBang(Var { module_name: "", ident: "line" }), [@344-350 Str(PlainLine("nope"))], Space))] }, @375-380 Apply(@375-377 Var { module_name: "", ident: "ok" }, [@378-380 Record([])], Space)))], @430-445 Apply(@430-434 TaskAwaitBang(Var { module_name: "", ident: "line" }), [@436-445 Str(PlainLine("success"))], Space)) }, Body(@23-29 Identifier { ident: "isTrue" }, @32-49 Apply(@32-39 Var { module_name: "Task", ident: "ok" }, [@40-49 Var { module_name: "Bool", ident: "true" }], Space)), Body(@66-74 Identifier { ident: "isFalsey" }, @77-92 Closure([@78-79 Identifier { ident: "x" }], @83-92 Apply(@83-90 Var { module_name: "Task", ident: "ok" }, [@91-92 Var { module_name: "", ident: "x" }], Space))), AnnotatedBody { ann_pattern: @109-112 Identifier { ident: "msg" }, ann_type: @115-126 Apply("", "Task", [@120-122 Record { fields: [], ext: None }, @123-126 Apply("", "I32", [])]), comment: None, body_pattern: @143-146 Identifier { ident: "msg" }, body_expr: Apply(Var { module_name: "Task", ident: "await" }, [Var { module_name: "", ident: "isTrue" }, Closure([Identifier { ident: "#!a0" }], @170-445 If([(@173-183 Apply(@173-174 Var { module_name: "Bool", ident: "not" }, [@175-182 ParensAround(Var { module_name: "", ident: "#!a0" })], UnaryOp(Not)), @218-225 Apply(@218-225 Var { module_name: "Task", ident: "await" }, [@218-225 Apply(@218-225 Var { module_name: "", ident: "line" }, [@219-225 Str(PlainLine("fail"))], Space), @218-225 Closure([@218-225 RecordDestructure([])], @251-256 Apply(@251-254 Var { module_name: "", ident: "err" }, [@255-256 Num("1")], Space))], BangSuffix))], Apply(Var { module_name: "Task", ident: "await" }, [Apply(Var { module_name: "", ident: "isFalsey" }, [@296-306 Var { module_name: "Bool", ident: "false" }], Space), Closure([Identifier { ident: "#!a1" }], @170-445 If([(@285-307 ParensAround(Var { module_name: "", ident: "#!a1" }), @343-350 Apply(@343-350 Var { module_name: "Task", ident: "await" }, [@343-350 Apply(@343-350 Var { module_name: "", ident: "line" }, [@344-350 Str(PlainLine("nope"))], Space), @343-350 Closure([@343-350 RecordDestructure([])], @375-380 Apply(@375-377 Var { module_name: "", ident: "ok" }, [@378-380 Record([])], Space))], BangSuffix))], @430-445 Apply(@430-445 Var { module_name: "", ident: "line" }, [@436-445 Str(PlainLine("success"))], Space)))], BangSuffix)))], BangSuffix) }] }, @463-466 Var { module_name: "", ident: "msg" }))] }"##,
);
}
@ -681,7 +684,7 @@ mod suffixed_tests {
CMD.new "cp"
|> mapErr! ERR
"#,
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" }, @0-103 Closure([@8-9 Identifier { ident: "a" }, @10-11 Identifier { ident: "b" }], @36-42 Apply(@36-42 Var { module_name: "Task", ident: "await" }, [@36-42 Apply(@36-42 Var { module_name: "", ident: "line" }, [@37-42 Str(PlainLine("FOO"))], Space), @36-42 Closure([@36-42 RecordDestructure([])], @60-103 Apply(@60-103 Var { module_name: "", ident: "mapErr" }, [@60-72 Apply(@60-67 Var { module_name: "CMD", ident: "new" }, [@68-72 Str(PlainLine("cp"))], Space), @100-103 Tag("ERR")], BinOp(Pizza)))], BangSuffix)))] }"#,
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" }, @7-103 Closure([@8-9 Identifier { ident: "a" }, @10-11 Identifier { ident: "b" }], @36-42 Apply(@36-42 Var { module_name: "Task", ident: "await" }, [@36-42 Apply(@36-42 Var { module_name: "", ident: "line" }, [@37-42 Str(PlainLine("FOO"))], Space), @36-42 Closure([@36-42 RecordDestructure([])], @60-103 Apply(@60-103 Var { module_name: "", ident: "mapErr" }, [@60-72 Apply(@60-67 Var { module_name: "CMD", ident: "new" }, [@68-72 Str(PlainLine("cp"))], Space), @100-103 Tag("ERR")], BinOp(Pizza)))], BangSuffix)))] }"#,
);
}
@ -709,7 +712,7 @@ mod suffixed_tests {
[] -> "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" }, @0-111 Apply(@0-111 Var { module_name: "Task", ident: "await" }, [@29-37 Var { module_name: "", ident: "getList" }, @0-111 Closure([@29-37 Identifier { ident: "#!a0" }], @0-111 When(@29-37 Var { module_name: "", ident: "#!a0" }, [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))] }"##,
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" }, @24-111 Apply(@24-111 Var { module_name: "Task", ident: "await" }, [@29-37 Var { module_name: "", ident: "getList" }, @24-111 Closure([@29-37 Identifier { ident: "#!a0" }], @24-111 When(@29-37 Var { module_name: "", ident: "#!a0" }, [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))] }"##,
);
}
@ -754,7 +757,7 @@ mod suffixed_tests {
_ ->
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" }, @0-195 Apply(@0-195 Var { module_name: "Task", ident: "await" }, [@29-37 Var { module_name: "", ident: "getList" }, @0-195 Closure([@29-37 Identifier { ident: "#!a0" }], @0-195 When(@29-37 Var { module_name: "", ident: "#!a0" }, [WhenBranch { patterns: [@61-63 List([])], value: @97-103 Apply(@97-103 Var { module_name: "Task", ident: "await" }, [@97-103 Apply(@97-103 Var { module_name: "", ident: "line" }, [@98-103 Str(PlainLine("foo"))], Space), @97-103 Closure([@97-103 RecordDestructure([])], @128-139 Apply(@128-139 Var { module_name: "", ident: "line" }, [@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" }, [@193-195 Record([])], Space), guard: None }]))], BangSuffix))] }"##,
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" }, @24-195 Apply(@24-195 Var { module_name: "Task", ident: "await" }, [@29-37 Var { module_name: "", ident: "getList" }, @24-195 Closure([@29-37 Identifier { ident: "#!a1" }], @24-195 When(@29-37 Var { module_name: "", ident: "#!a1" }, [WhenBranch { patterns: [@61-63 List([])], value: @97-103 Apply(@97-103 Var { module_name: "Task", ident: "await" }, [@97-103 Apply(@97-103 Var { module_name: "", ident: "line" }, [@98-103 Str(PlainLine("foo"))], Space), @97-103 Closure([@97-103 RecordDestructure([])], @128-139 Apply(@128-139 Var { module_name: "", ident: "line" }, [@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" }, [@193-195 Record([])], Space), guard: None }]))], BangSuffix))] }"##,
);
}
@ -862,7 +865,7 @@ mod suffixed_tests {
expect 1 == 2
x!
"#,
r#"Defs { tags: [Index(2147483648)], regions: [@0-55], 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" }, @0-55 Expect(@30-36 Apply(@32-34 Var { module_name: "Bool", ident: "isEq" }, [@30-31 Num("1"), @35-36 Num("2")], BinOp(Equals)), @53-55 Var { module_name: "", ident: "x" }))] }"#,
r#"Defs { tags: [Index(2147483648)], regions: [@0-55], 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" }, @23-55 Expect(@30-36 Apply(@32-34 Var { module_name: "Bool", ident: "isEq" }, [@30-31 Num("1"), @35-36 Num("2")], BinOp(Equals)), @53-55 Var { module_name: "", ident: "x" }))] }"#,
);
}
@ -877,7 +880,7 @@ mod suffixed_tests {
1 ->
c!
"#,
r#"Defs { tags: [Index(2147483648)], regions: [@0-159], 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" }, @0-159 When(@28-29 Var { module_name: "", ident: "a" }, [WhenBranch { patterns: [@53-54 NumLiteral("0")], value: @82-159 When(@87-88 Var { module_name: "", ident: "b" }, [WhenBranch { patterns: [@120-121 NumLiteral("1")], value: @157-159 Var { module_name: "", ident: "c" }, guard: None }]), guard: None }]))] }"#,
r#"Defs { tags: [Index(2147483648)], regions: [@0-159], 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" }, @23-159 When(@28-29 Var { module_name: "", ident: "a" }, [WhenBranch { patterns: [@53-54 NumLiteral("0")], value: @82-159 When(@87-88 Var { module_name: "", ident: "b" }, [WhenBranch { patterns: [@120-121 NumLiteral("1")], value: @157-159 Var { module_name: "", ident: "c" }, guard: None }]), guard: None }]))] }"#,
);
}
@ -897,7 +900,7 @@ mod suffixed_tests {
B ->
d!
"#,
r#"Defs { tags: [Index(2147483648)], regions: [@0-266], 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" }, @0-266 When(@28-29 Var { module_name: "", ident: "x" }, [WhenBranch { patterns: [@53-54 Tag("A")], value: @82-214 Defs(Defs { tags: [Index(2147483649)], regions: [@86-88], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@82-83 Identifier { ident: "y" }, @86-88 Num("42")), Body(@82-83 Identifier { ident: "y" }, @86-88 Num("42"))] }, @114-214 If([(@117-118 Var { module_name: "", ident: "a" }, @152-154 Var { module_name: "", ident: "b" })], @212-214 Var { module_name: "", ident: "c" })), guard: None }, WhenBranch { patterns: [@235-236 Tag("B")], value: @264-266 Var { module_name: "", ident: "d" }, guard: None }]))] }"#,
r#"Defs { tags: [Index(2147483648)], regions: [@0-266], 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" }, @23-266 When(@28-29 Var { module_name: "", ident: "x" }, [WhenBranch { patterns: [@53-54 Tag("A")], value: @82-214 Defs(Defs { tags: [Index(2147483649)], regions: [@86-88], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@82-83 Identifier { ident: "y" }, @86-88 Num("42")), Body(@82-83 Identifier { ident: "y" }, @86-88 Num("42"))] }, @114-214 If([(@117-118 Var { module_name: "", ident: "a" }, @152-154 Var { module_name: "", ident: "b" })], @212-214 Var { module_name: "", ident: "c" })), guard: None }, WhenBranch { patterns: [@235-236 Tag("B")], value: @264-266 Var { module_name: "", ident: "d" }, guard: None }]))] }"#,
);
}
@ -910,9 +913,38 @@ mod suffixed_tests {
b
"#,
r##"Defs { tags: [Index(2147483648)], regions: [@0-48], 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" }, @0-48 Apply(@0-48 Var { module_name: "Task", ident: "await" }, [@27-29 Var { module_name: "", ident: "a" }, @0-48 Closure([@27-29 Identifier { ident: "#!a0" }], @0-48 LowLevelDbg(("test.roc:3", " "), @27-29 Apply(@27-29 Var { module_name: "Inspect", ident: "toStr" }, [@27-29 Var { module_name: "", ident: "#!a0" }], Space), @47-48 Var { module_name: "", ident: "b" }))], BangSuffix))] }"##,
r##"Defs { tags: [Index(2147483648)], regions: [@0-48], 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" }, @23-48 Apply(@23-48 Var { module_name: "Task", ident: "await" }, [@27-29 Var { module_name: "", ident: "a" }, @23-48 Closure([@27-29 Identifier { ident: "#!a0" }], @23-48 LowLevelDbg(("test.roc:3", " "), @27-29 Apply(@27-29 Var { module_name: "Inspect", ident: "toStr" }, [@27-29 Var { module_name: "", ident: "#!a0" }], Space), @47-48 Var { module_name: "", ident: "b" }))], BangSuffix))] }"##,
)
}
#[test]
fn last_stmt_not_top_level_suffixed() {
run_test(
r#"
main =
x = 42
a b!
"#,
r##"Defs { tags: [Index(2147483648)], regions: [@0-50], 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" }, @23-50 Defs(Defs { tags: [Index(2147483650)], regions: [@27-29], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@23-24 Identifier { ident: "x" }, @27-29 Num("42")), Body(@23-24 Identifier { ident: "x" }, @27-29 Num("42")), Body(@23-24 Identifier { ident: "x" }, @27-29 Num("42"))] }, @23-50 Apply(@23-50 Var { module_name: "Task", ident: "await" }, [@48-49 Var { module_name: "", ident: "b" }, @23-50 Closure([@48-49 Identifier { ident: "#!a0" }], @46-50 Apply(@46-47 Var { module_name: "", ident: "a" }, [@48-49 Var { module_name: "", ident: "#!a0" }], Space))], BangSuffix)))] }"##,
);
}
#[test]
fn nested_defs() {
run_test(
indoc!(
r##"
main =
x =
a = b!
c! a
x
"##,
),
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" }, @11-49 Defs(Defs { tags: [Index(2147483649)], regions: [@23-42], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@11-12 Identifier { ident: "x" }, @23-42 Defs(Defs { tags: [Index(2147483648)], regions: [@23-29], space_before: [Slice(start = 0, length = 0)], space_after: [Slice(start = 0, length = 0)], spaces: [], type_defs: [], value_defs: [Body(@23-24 Identifier { ident: "a" }, @27-29 TaskAwaitBang(Var { module_name: "", ident: "b" }))] }, @38-42 Apply(@38-39 TaskAwaitBang(Var { module_name: "", ident: "c" }), [@41-42 Var { module_name: "", ident: "a" }], Space))), Body(@11-12 Identifier { ident: "x" }, @27-29 Apply(@27-29 Var { module_name: "Task", ident: "await" }, [@27-29 Var { module_name: "", ident: "b" }, @27-29 Closure([@23-24 Identifier { ident: "a" }], @38-42 Apply(@38-42 Var { module_name: "", ident: "c" }, [@41-42 Var { module_name: "", ident: "a" }], Space))], BangSuffix))] }, @48-49 Var { module_name: "", ident: "x" }))] }"##,
);
}
}
#[cfg(test)]

View file

@ -45,7 +45,6 @@ impl<'a> Formattable for Expr<'a> {
| MalformedClosure
| Tag(_)
| OpaqueRef(_)
| EmptyDefsFinal
| Crash => false,
RecordAccess(inner, _) | TupleAccess(inner, _) | TaskAwaitBang(inner) => {
@ -420,9 +419,6 @@ impl<'a> Formattable for Expr<'a> {
indent,
);
}
EmptyDefsFinal => {
// no need to print anything
}
_ => {
buf.ensure_ends_with_newline();
buf.indent(indent);
@ -439,9 +435,6 @@ impl<'a> Formattable for Expr<'a> {
buf.push(')');
}
}
EmptyDefsFinal => {
// no need to print anything
}
Expect(condition, continuation) => {
fmt_expect(buf, condition, continuation, self.is_multiline(), indent);
}

View file

@ -768,7 +768,6 @@ impl<'a> RemoveSpaces<'a> for StrSegment<'a> {
impl<'a> RemoveSpaces<'a> for Expr<'a> {
fn remove_spaces(&self, arena: &'a Bump) -> Self {
match *self {
Expr::EmptyDefsFinal => Expr::EmptyDefsFinal,
Expr::Float(a) => Expr::Float(a),
Expr::Num(a) => Expr::Num(a),
Expr::NonBase10Int {

View file

@ -462,10 +462,6 @@ pub enum Expr<'a> {
/// Multiple defs in a row
Defs(&'a Defs<'a>, &'a Loc<Expr<'a>>),
/// Used in place of an expression when the final expression is empty
/// This may happen if the final expression is actually a suffixed statement
EmptyDefsFinal,
Backpassing(&'a [Loc<Pattern<'a>>], &'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>),
Expect(&'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>),
Dbg(&'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>),
@ -536,6 +532,19 @@ pub fn split_loc_exprs_around<'a>(
(before, after)
}
/// Checks if the bang suffix is applied only at the top level of expression
pub fn is_top_level_suffixed(expr: &Expr) -> bool {
// TODO: should we check BinOps with pizza where the last expression is TaskAwaitBang?
match expr {
Expr::TaskAwaitBang(..) => true,
Expr::Apply(a, _, _) => is_top_level_suffixed(&a.value),
Expr::SpaceBefore(a, _) => is_top_level_suffixed(a),
Expr::SpaceAfter(a, _) => is_top_level_suffixed(a),
_ => false,
}
}
/// Check if the bang suffix is applied recursevely in expression
pub fn is_expr_suffixed(expr: &Expr) -> bool {
match expr {
// expression without arguments, `read!`
@ -613,7 +622,6 @@ pub fn is_expr_suffixed(expr: &Expr) -> bool {
Expr::Crash => false,
Expr::Tag(_) => false,
Expr::OpaqueRef(_) => false,
Expr::EmptyDefsFinal => false,
Expr::Backpassing(_, _, _) => false, // TODO: we might want to check this?
Expr::Expect(a, b) | Expr::Dbg(a, b) => {
is_expr_suffixed(&a.value) || is_expr_suffixed(&b.value)
@ -975,8 +983,7 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
| MalformedIdent(_, _)
| MalformedClosure
| PrecedenceConflict(_)
| MalformedSuffixed(_)
| EmptyDefsFinal => { /* terminal */ }
| MalformedSuffixed(_) => { /* terminal */ }
}
}
}
@ -1183,51 +1190,39 @@ impl<'a> Defs<'a> {
})
}
// We could have a type annotation as the last tag,
// this helper ensures we refer to the last value_def
// and that we remove the correct tag
pub fn last_value_suffixed(&self) -> Option<(Self, &'a Loc<Expr<'a>>)> {
let value_indexes =
self.tags
.clone()
.into_iter()
.enumerate()
.filter_map(|(tag_index, tag)| match tag.split() {
Ok(_) => None,
Err(value_index) => Some((tag_index, value_index.index())),
});
pub fn pop_last_value(&mut self) -> Option<&'a Loc<Expr<'a>>> {
let last_value_suffix = self
.tags
.iter()
.enumerate()
.rev()
.find_map(|(tag_index, tag)| match tag.split() {
Ok(_) => None,
Err(value_index) => match self.value_defs[value_index.index()] {
ValueDef::Body(
Loc {
value: Pattern::RecordDestructure(collection),
..
},
loc_expr,
) if collection.is_empty() => Some((tag_index, loc_expr)),
ValueDef::Stmt(loc_expr) => Some((tag_index, loc_expr)),
_ => None,
},
});
if let Some((tag_index, value_index)) = value_indexes.last() {
match self.value_defs[value_index] {
ValueDef::Body(
Loc {
value: Pattern::RecordDestructure(collection),
..
},
loc_expr,
) if collection.is_empty() && is_expr_suffixed(&loc_expr.value) => {
let mut new_defs = self.clone();
new_defs.remove_value_def(tag_index);
return Some((new_defs, loc_expr));
}
ValueDef::Stmt(loc_expr) if is_expr_suffixed(&loc_expr.value) => {
let mut new_defs = self.clone();
new_defs.remove_value_def(tag_index);
return Some((new_defs, loc_expr));
}
_ => {}
}
if let Some((tag_index, loc_expr)) = last_value_suffix {
self.remove_tag(tag_index);
Some(loc_expr)
} else {
None
}
None
}
pub fn remove_value_def(&mut self, index: usize) {
pub fn remove_tag(&mut self, tag_index: usize) {
match self
.tags
.get(index)
.get(tag_index)
.expect("got an invalid index for Defs")
.split()
{
@ -1260,10 +1255,10 @@ impl<'a> Defs<'a> {
}
}
}
self.tags.remove(index);
self.regions.remove(index);
self.space_after.remove(index);
self.space_before.remove(index);
self.tags.remove(tag_index);
self.regions.remove(tag_index);
self.space_after.remove(tag_index);
self.space_before.remove(tag_index);
}
/// NOTE assumes the def itself is pushed already!
@ -2394,7 +2389,6 @@ impl<'a> Malformed for Expr<'a> {
Tag(_) |
OpaqueRef(_) |
SingleQuote(_) | // This is just a &str - not a bunch of segments
EmptyDefsFinal |
Crash => false,
Str(inner) => inner.is_malformed(),

View file

@ -1,9 +1,9 @@
use crate::ast::{
is_expr_suffixed, AssignedField, Collection, CommentOrNewline, Defs, Expr, ExtractSpaces,
Implements, ImplementsAbilities, ImportAlias, ImportAsKeyword, ImportExposingKeyword,
ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport,
ModuleImportParams, Pattern, RecordBuilderField, Spaceable, Spaced, Spaces, TypeAnnotation,
TypeDef, TypeHeader, ValueDef,
is_expr_suffixed, is_top_level_suffixed, AssignedField, Collection, CommentOrNewline, Defs,
Expr, ExtractSpaces, Implements, ImplementsAbilities, ImportAlias, ImportAsKeyword,
ImportExposingKeyword, ImportedModuleName, IngestedFileAnnotation, IngestedFileImport,
ModuleImport, ModuleImportParams, Pattern, RecordBuilderField, Spaceable, Spaced, Spaces,
TypeAnnotation, TypeDef, TypeHeader, ValueDef,
};
use crate::blankspace::{
space0_after_e, space0_around_e_no_after_indent_check, space0_around_ee, space0_before_e,
@ -384,7 +384,7 @@ fn expr_operator_chain<'a>(options: ExprParseOptions) -> impl Parser<'a, Expr<'a
Ok((progress, expr, new_state)) => {
// We need to check if we have just parsed a suffixed statement,
// if so, this is a defs node.
if is_expr_suffixed(&expr) {
if is_top_level_suffixed(&expr) {
let def_region = Region::new(end, new_state.pos());
let value_def = ValueDef::Stmt(arena.alloc(Loc::at(def_region, expr)));
@ -1154,13 +1154,13 @@ pub fn parse_single_def_assignment<'a>(
// If the expression is actually a suffixed statement, then we need to continue
// to parse the rest of the expression
if crate::ast::is_expr_suffixed(&first_loc_expr.value) {
if is_top_level_suffixed(&first_loc_expr.value) {
let mut defs = Defs::default();
// Take the suffixed value and make it a e.g. Body(`{}=`, Apply(Var(...)))
// we will keep the pattern `def_loc_pattern` for the new Defs
defs.push_value_def(
ValueDef::Stmt(arena.alloc(first_loc_expr)),
Region::span_across(&def_loc_pattern.region, &first_loc_expr.region),
region,
spaces_before_current,
&[],
);
@ -1169,16 +1169,16 @@ pub fn parse_single_def_assignment<'a>(
match parse_defs_expr(
options,
min_indent,
defs.clone(),
defs,
arena,
state_after_first_expression.clone(),
state_after_first_expression,
) {
Ok((progress_after_rest_of_def, expr, state_after_rest_of_def)) => {
let final_loc_expr = arena.alloc(Loc::at(region, expr));
let value_def = ValueDef::Body(arena.alloc(def_loc_pattern), final_loc_expr);
return Ok((
Ok((
progress_after_rest_of_def,
Some(SingleDef {
type_or_value: Either::Second(value_def),
@ -1187,45 +1187,24 @@ pub fn parse_single_def_assignment<'a>(
spaces_after: &[],
}),
state_after_rest_of_def,
));
}
Err(_) => {
// Unable to parse more defs, continue and return the first parsed expression as a stement
let empty_return =
arena.alloc(Loc::at(first_loc_expr.region, Expr::EmptyDefsFinal));
let value_def = ValueDef::Body(
arena.alloc(def_loc_pattern),
arena.alloc(Loc::at(
first_loc_expr.region,
Expr::Defs(arena.alloc(defs), empty_return),
)),
);
return Ok((
progress_after_first,
Some(SingleDef {
type_or_value: Either::Second(value_def),
region,
spaces_before: spaces_before_current,
spaces_after: &[],
}),
state_after_first_expression,
));
))
}
Err((progress, err)) => Err((progress, err)),
}
} else {
let value_def = ValueDef::Body(arena.alloc(def_loc_pattern), arena.alloc(first_loc_expr));
Ok((
progress_after_first,
Some(SingleDef {
type_or_value: Either::Second(value_def),
region,
spaces_before: spaces_before_current,
spaces_after: &[],
}),
state_after_first_expression,
))
}
let value_def = ValueDef::Body(arena.alloc(def_loc_pattern), arena.alloc(first_loc_expr));
Ok((
progress_after_first,
Some(SingleDef {
type_or_value: Either::Second(value_def),
region,
spaces_before: spaces_before_current,
spaces_after: &[],
}),
state_after_first_expression,
))
}
/// e.g. Things that can be on their own line in a def, e.g. `expect`, `expect-fx`, or `dbg`
@ -1460,48 +1439,31 @@ fn parse_defs_expr<'a>(
Err(bad) => Err(bad),
Ok((_, def_state, state)) => {
// this is no def, because there is no `=` or `:`; parse as an expr
let parse_final_expr = space0_before_e(expr_start(options), EExpr::IndentEnd);
match parse_final_expr.parse(arena, state.clone(), min_indent) {
match space0_before_e(expr_start(options), EExpr::IndentEnd).parse(
arena,
state.clone(),
min_indent,
) {
Err((_, fail)) => {
// If the last def was a suffixed statement, assume this was
// intentional by the application author instead of giving
// an error.
if let Some((new_defs, loc_ret)) = def_state.last_value_suffixed() {
// note we check the tags here and not value_defs, as there may be redundant defs in Defs
let mut local_defs = new_defs.clone();
let last_stmt = ValueDef::Stmt(loc_ret);
local_defs.push_value_def(last_stmt, loc_ret.region, &[], &[]);
//check the length of the defs we would return, if we only have one
// we can just return the expression
// note we use tags here, as we may have redundant defs in Defs
if local_defs
.tags
.iter()
.filter(|tag| tag.split().is_err())
.count()
== 1
{
return Ok((MadeProgress, loc_ret.value, state));
let mut def_state = def_state;
match def_state.pop_last_value() {
Some(loc_ret) => {
// If the poped value was the only item in defs - just return it as an expression
if def_state.is_empty() {
Ok((MadeProgress, loc_ret.value, state))
} else {
Ok((
MadeProgress,
Expr::Defs(arena.alloc(def_state), arena.alloc(loc_ret)),
state,
))
}
}
return Ok((
None => Err((
MadeProgress,
Expr::Defs(
arena.alloc(local_defs),
arena.alloc(Loc::at_zero(Expr::EmptyDefsFinal)),
),
state,
));
EExpr::DefMissingFinalExpr2(arena.alloc(fail), state.pos()),
)),
}
Err((
MadeProgress,
EExpr::DefMissingFinalExpr2(arena.alloc(fail), state.pos()),
))
}
Ok((_, loc_ret, state)) => Ok((
MadeProgress,
@ -2408,8 +2370,7 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
Expr::SpaceBefore(..)
| Expr::SpaceAfter(..)
| Expr::ParensAround(..)
| Expr::RecordBuilder(..)
| Expr::EmptyDefsFinal => unreachable!(),
| Expr::RecordBuilder(..) => unreachable!(),
Expr::Record(fields) => {
let patterns = fields.map_items_result(arena, |loc_assigned_field| {

View file

@ -1,4 +1,5 @@
main =
a! "Bar"
x = B.b! "Foo"
c! x

View file

@ -18,28 +18,24 @@ Defs {
@0-4 Identifier {
ident: "main",
},
@0-49 SpaceBefore(
@12-49 SpaceBefore(
Defs(
Defs {
tags: [
Index(2147483648),
Index(2147483649),
Index(2147483650),
],
regions: [
@14-21,
@26-39,
@45-49,
],
space_before: [
Slice(start = 0, length = 0),
Slice(start = 0, length = 1),
Slice(start = 1, length = 0),
],
space_after: [
Slice(start = 0, length = 0),
Slice(start = 1, length = 0),
Slice(start = 1, length = 0),
],
spaces: [
Newline,
@ -85,32 +81,29 @@ Defs {
Space,
),
),
Stmt(
@45-49 SpaceBefore(
Apply(
@45-46 TaskAwaitBang(
Var {
module_name: "",
ident: "c",
},
),
[
@48-49 Var {
module_name: "",
ident: "x",
},
],
Space,
),
[
Newline,
Newline,
],
),
),
],
},
EmptyDefsFinal,
@45-49 SpaceBefore(
Apply(
@45-46 TaskAwaitBang(
Var {
module_name: "",
ident: "c",
},
),
[
@48-49 Var {
module_name: "",
ident: "x",
},
],
Space,
),
[
Newline,
Newline,
],
),
),
[
Newline,

View file

@ -64,7 +64,7 @@ Full {
@88-92 Identifier {
ident: "main",
},
@88-202 SpaceBefore(
@100-202 SpaceBefore(
BinOps(
[
(