Support passing values into dbg with the pipe operator

In order to desugar `dbg` in a pipeline we need to allow a bare `dbg`
node in desugaring and only report it as an error if the bare node
survives to the next step of canonicalization. This means we move the
error code out of `desugar_expr` and into `canonicalize_expr`. This is
much simpler to do now that these functions use the same `env` struct,
since previously we would have had to pass down extra args to
`canonicalize_expr`. Sharing the `env` struct means that we also don't
have to worry about calculating `line_info` more than once.
This commit is contained in:
Elias Mulhall 2024-09-03 22:27:45 -04:00
parent b515bfa77e
commit 19931ecd43
No known key found for this signature in database
GPG key ID: 8D1F3C219EAB45F2
10 changed files with 200 additions and 28 deletions

View file

@ -25,7 +25,7 @@ use roc_region::all::{Loc, Region};
fn new_op_call_expr<'a>(
env: &mut Env<'a>,
_scope: &mut Scope,
scope: &mut Scope,
left: &'a Loc<Expr<'a>>,
loc_op: Loc<BinOp>,
right: &'a Loc<Expr<'a>>,
@ -47,6 +47,7 @@ fn new_op_call_expr<'a>(
Apply(function, args, CalledVia::BinOp(Pizza))
}
Dbg => *desugar_dbg_expr(env, scope, left, region),
_ => {
// e.g. `1 |> (if b then (\a -> a) else (\c -> c))`
Apply(right, env.arena.alloc([left]), CalledVia::BinOp(Pizza))
@ -1020,14 +1021,8 @@ pub fn desugar_expr<'a>(
})
}
Dbg => {
env.problem(Problem::UnappliedDbg {
region: loc_expr.region,
});
env.arena.alloc(Loc {
value: *desugar_invalid_dbg_expr(env, scope, loc_expr.region),
region: loc_expr.region,
})
// Allow naked dbg, necessary for piping values into dbg with the `Pizza` binop
loc_expr
}
DbgStmt(condition, continuation) => {
let desugared_condition = &*env.arena.alloc(desugar_expr(env, scope, condition));
@ -1321,7 +1316,7 @@ fn desugar_dbg_expr<'a>(
/// Build a desugared `dbg {}` expression to act as a placeholder when the AST
/// is invalid.
fn desugar_invalid_dbg_expr<'a>(
pub fn desugar_invalid_dbg_expr<'a>(
env: &mut Env<'a>,
scope: &mut Scope,
outer_region: Region,

View file

@ -1209,8 +1209,20 @@ pub fn canonicalize_expr<'a>(
output,
)
}
ast::Expr::Dbg | ast::Expr::DbgStmt(_, _) => {
internal_error!("Dbg should have been desugared by now")
ast::Expr::Dbg => {
// Dbg was not desugared as either part of an `Apply` or a `Pizza` binop, so it's
// invalid.
env.problem(Problem::UnappliedDbg { region });
let invalid_dbg_expr = crate::desugar::desugar_invalid_dbg_expr(env, scope, region);
let (loc_expr, output) =
canonicalize_expr(env, var_store, scope, region, invalid_dbg_expr);
(loc_expr.value, output)
}
ast::Expr::DbgStmt(_, _) => {
internal_error!("DbgStmt should have been desugared by now")
}
ast::Expr::LowLevelDbg((source_location, source), message, continuation) => {
let mut output = Output::default();

View file

@ -1,6 +1,6 @@
---
source: crates/compiler/can/tests/test_suffixed.rs
assertion_line: 459
assertion_line: 473
expression: snapshot
---
Defs {
@ -8,7 +8,7 @@ Defs {
Index(2147483648),
],
regions: [
@0-19,
@0-51,
],
space_before: [
Slice(start = 0, length = 0),
@ -25,13 +25,13 @@ Defs {
@0-4 Identifier {
ident: "main",
},
@11-19 Defs(
@11-51 Defs(
Defs {
tags: [
Index(2147483648),
],
regions: [
@11-12,
@11-40,
],
space_before: [
Slice(start = 0, length = 0),
@ -43,36 +43,98 @@ Defs {
type_defs: [],
value_defs: [
Body(
@11-12 Identifier {
ident: "63",
@11-40 Identifier {
ident: "1",
},
@11-12 Num(
"1",
@11-40 Apply(
@31-38 Var {
module_name: "Num",
ident: "add",
},
[
@11-23 Defs(
Defs {
tags: [
Index(2147483648),
],
regions: [
@11-12,
],
space_before: [
Slice(start = 0, length = 0),
],
space_after: [
Slice(start = 0, length = 0),
],
spaces: [],
type_defs: [],
value_defs: [
Body(
@11-12 Identifier {
ident: "0",
},
@11-12 Num(
"1",
),
),
],
},
@11-23 LowLevelDbg(
(
"test.roc:2",
" ",
),
@11-12 Apply(
@11-12 Var {
module_name: "Inspect",
ident: "toStr",
},
[
@11-12 Var {
module_name: "",
ident: "0",
},
],
Space,
),
@11-12 Var {
module_name: "",
ident: "0",
},
),
),
@39-40 Num(
"2",
),
],
BinOp(
Pizza,
),
),
),
],
},
@11-19 LowLevelDbg(
@11-51 LowLevelDbg(
(
"test.roc:2",
" ",
" main =\n 1\n ",
),
@11-12 Apply(
@11-12 Var {
@11-40 Apply(
@11-40 Var {
module_name: "Inspect",
ident: "toStr",
},
[
@11-12 Var {
@11-40 Var {
module_name: "",
ident: "63",
ident: "1",
},
],
Space,
),
@11-12 Var {
@11-40 Var {
module_name: "",
ident: "63",
ident: "1",
},
),
),

View file

@ -468,6 +468,19 @@ mod suffixed_tests {
);
}
#[test]
fn pizza_dbg() {
run_test!(
r#"
main =
1
|> dbg
|> Num.add 2
|> dbg
"#
)
}
#[test]
fn apply_argument_single() {
run_test!(

View file

@ -0,0 +1,59 @@
procedure Inspect.278 (Inspect.279, Inspect.277):
let Inspect.318 : Str = CallByName Num.96 Inspect.277;
let Inspect.317 : Str = CallByName Inspect.63 Inspect.279 Inspect.318;
dec Inspect.318;
ret Inspect.317;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.33 (Inspect.152):
let Inspect.322 : Str = CallByName Inspect.5 Inspect.152;
let Inspect.321 : Str = CallByName Inspect.64 Inspect.322;
ret Inspect.321;
procedure Inspect.39 (Inspect.301):
let Inspect.311 : Str = "";
ret Inspect.311;
procedure Inspect.5 (Inspect.150):
let Inspect.312 : I64 = CallByName Inspect.57 Inspect.150;
let Inspect.309 : {} = Struct {};
let Inspect.308 : Str = CallByName Inspect.39 Inspect.309;
let Inspect.307 : Str = CallByName Inspect.278 Inspect.308 Inspect.312;
ret Inspect.307;
procedure Inspect.57 (Inspect.277):
let Inspect.313 : I64 = CallByName Inspect.30 Inspect.277;
ret Inspect.313;
procedure Inspect.63 (Inspect.300, Inspect.296):
let Inspect.320 : Str = CallByName Str.3 Inspect.300 Inspect.296;
ret Inspect.320;
procedure Inspect.64 (Inspect.302):
ret Inspect.302;
procedure Num.19 (#Attr.2, #Attr.3):
let Num.281 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
ret Num.281;
procedure Num.96 (#Attr.2):
let Num.282 : Str = lowlevel NumToStr #Attr.2;
ret Num.282;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.236 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.236;
procedure Test.0 ():
let Test.4 : I64 = 1i64;
let Test.5 : Str = CallByName Inspect.33 Test.4;
dbg Test.5;
dec Test.5;
let Test.9 : I64 = 2i64;
let Test.3 : I64 = CallByName Num.19 Test.4 Test.9;
let Test.6 : Str = CallByName Inspect.33 Test.3;
dbg Test.6;
dec Test.6;
ret Test.3;

View file

@ -3295,6 +3295,18 @@ fn dbg_inside_string() {
)
}
#[mono_test]
fn pizza_dbg() {
indoc!(
r#"
1
|> dbg
|> Num.add 2
|> dbg
"#
)
}
#[mono_test]
fn linked_list_reverse() {
indoc!(

View file

@ -0,0 +1,16 @@
SpaceAfter(
BinOps(
[
(
@0-1 Num(
"1",
),
@2-4 Pizza,
),
],
@5-8 Dbg,
),
[
Newline,
],
)

View file

@ -0,0 +1 @@
1 |> dbg

View file

@ -442,6 +442,7 @@ mod test_snapshots {
pass/pattern_as_spaces.expr,
pass/pattern_with_space_in_parens.expr, // https://github.com/roc-lang/roc/issues/929
pass/pizza_bang.moduledefs,
pass/pizza_dbg.expr,
pass/plus_if.expr,
pass/plus_when.expr,
pass/pos_inf_float.expr,