Merge pull request #7038 from mulias/expr-dbg

Support `dbg` in expressions
This commit is contained in:
Anton-4 2024-09-02 13:30:32 +02:00 committed by GitHub
commit 02cf61f985
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 1308 additions and 249 deletions

File diff suppressed because it is too large Load diff

View file

@ -1209,7 +1209,7 @@ pub fn canonicalize_expr<'a>(
output,
)
}
ast::Expr::Dbg(_, _) => {
ast::Expr::Dbg | ast::Expr::DbgStmt(_, _) => {
internal_error!("Dbg should have been desugared by now")
}
ast::Expr::LowLevelDbg((source_location, source), message, continuation) => {
@ -2488,21 +2488,28 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
| ast::Expr::AccessorFunction(_)
| ast::Expr::RecordUpdater(_)
| ast::Expr::Crash
| ast::Expr::Dbg
| ast::Expr::Underscore(_)
| ast::Expr::MalformedIdent(_, _)
| ast::Expr::Tag(_)
| ast::Expr::OpaqueRef(_)
| ast::Expr::MalformedClosure => true,
// Newlines are disallowed inside interpolation, and these all require newlines
ast::Expr::Dbg(_, _)
ast::Expr::DbgStmt(_, _)
| ast::Expr::LowLevelDbg(_, _, _)
| ast::Expr::Defs(_, _)
| ast::Expr::Expect(_, _)
| ast::Expr::When(_, _)
| ast::Expr::Backpassing(_, _, _)
| ast::Expr::SpaceBefore(_, _)
| ast::Expr::Str(StrLiteral::Block(_))
| ast::Expr::SpaceAfter(_, _) => false,
// Desugared dbg expression
ast::Expr::Defs(_, loc_ret) => match loc_ret.value {
ast::Expr::LowLevelDbg(_, _, continuation) => {
is_valid_interpolation(&continuation.value)
}
_ => 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

@ -268,6 +268,7 @@ pub fn canonicalize_module_defs<'a>(
crate::desugar::desugar_defs_node_values(
arena,
var_store,
loc_defs,
src,
&mut None,

View file

@ -55,6 +55,7 @@ pub fn can_expr_with(arena: &Bump, home: ModuleId, expr_str: &str) -> CanExprOut
// rules multiple times unnecessarily.
let loc_expr = desugar::desugar_expr(
arena,
&mut var_store,
&loc_expr,
expr_str,
&mut None,

View file

@ -0,0 +1,145 @@
---
source: crates/compiler/can/tests/test_suffixed.rs
assertion_line: 449
expression: snapshot
---
Defs {
tags: [
Index(2147483648),
],
regions: [
@0-26,
],
space_before: [
Slice(start = 0, length = 0),
],
space_after: [
Slice(start = 0, length = 1),
],
spaces: [
Newline,
],
type_defs: [],
value_defs: [
Body(
@0-4 Identifier {
ident: "main",
},
@11-26 Defs(
Defs {
tags: [
Index(2147483648),
],
regions: [
@15-26,
],
space_before: [
Slice(start = 0, length = 0),
],
space_after: [
Slice(start = 0, length = 0),
],
spaces: [],
type_defs: [],
value_defs: [
Body(
@15-26 Identifier {
ident: "64",
},
@15-26 ParensAround(
Defs(
Defs {
tags: [
Index(2147483648),
],
regions: [
@20-25,
],
space_before: [
Slice(start = 0, length = 0),
],
space_after: [
Slice(start = 0, length = 0),
],
spaces: [],
type_defs: [],
value_defs: [
Body(
@20-25 Identifier {
ident: "63",
},
@20-25 Apply(
@22-23 Var {
module_name: "Num",
ident: "add",
},
[
@20-21 Num(
"1",
),
@24-25 Num(
"1",
),
],
BinOp(
Plus,
),
),
),
],
},
@15-26 LowLevelDbg(
(
"test.roc:3",
" ",
),
@20-25 Apply(
@20-25 Var {
module_name: "Inspect",
ident: "toStr",
},
[
@20-25 Var {
module_name: "",
ident: "63",
},
],
Space,
),
@20-25 Var {
module_name: "",
ident: "63",
},
),
),
),
),
],
},
@11-26 LowLevelDbg(
(
"test.roc:2",
"in =\n ",
),
@15-26 Apply(
@15-26 Var {
module_name: "Inspect",
ident: "toStr",
},
[
@15-26 Var {
module_name: "",
ident: "64",
},
],
Space,
),
@15-26 Var {
module_name: "",
ident: "64",
},
),
),
),
],
}

View file

@ -0,0 +1,81 @@
---
source: crates/compiler/can/tests/test_suffixed.rs
assertion_line: 459
expression: snapshot
---
Defs {
tags: [
Index(2147483648),
],
regions: [
@0-19,
],
space_before: [
Slice(start = 0, length = 0),
],
space_after: [
Slice(start = 0, length = 1),
],
spaces: [
Newline,
],
type_defs: [],
value_defs: [
Body(
@0-4 Identifier {
ident: "main",
},
@11-19 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: "63",
},
@11-12 Num(
"1",
),
),
],
},
@11-19 LowLevelDbg(
(
"test.roc:2",
" ",
),
@11-12 Apply(
@11-12 Var {
module_name: "Inspect",
ident: "toStr",
},
[
@11-12 Var {
module_name: "",
ident: "63",
},
],
Space,
),
@11-12 Var {
module_name: "",
ident: "63",
},
),
),
),
],
}

View file

@ -7,13 +7,16 @@ mod suffixed_tests {
use insta::assert_snapshot;
use roc_can::desugar::desugar_defs_node_values;
use roc_parse::test_helpers::parse_defs_with;
use roc_types::subs::VarStore;
macro_rules! run_test {
($src:expr) => {{
let arena = &Bump::new();
let mut var_store = VarStore::default();
let mut defs = parse_defs_with(arena, indoc!($src)).unwrap();
desugar_defs_node_values(
arena,
&mut var_store,
&mut defs,
$src,
&mut None,
@ -441,6 +444,16 @@ mod suffixed_tests {
);
}
#[test]
fn dbg_expr() {
run_test!(
r#"
main =
dbg (dbg 1 + 1)
"#
);
}
#[test]
fn apply_argument_single() {
run_test!(

View file

@ -46,7 +46,8 @@ impl<'a> Formattable for Expr<'a> {
| MalformedClosure
| Tag(_)
| OpaqueRef(_)
| Crash => false,
| Crash
| Dbg => false,
RecordAccess(inner, _) | TupleAccess(inner, _) | TrySuffix { expr: inner, .. } => {
inner.is_multiline()
@ -65,7 +66,7 @@ impl<'a> Formattable for Expr<'a> {
Expect(condition, continuation) => {
condition.is_multiline() || continuation.is_multiline()
}
Dbg(condition, _) => condition.is_multiline(),
DbgStmt(condition, _) => condition.is_multiline(),
LowLevelDbg(_, _, _) => unreachable!(
"LowLevelDbg should only exist after desugaring, not during formatting"
),
@ -453,8 +454,12 @@ impl<'a> Formattable for Expr<'a> {
Expect(condition, continuation) => {
fmt_expect(buf, condition, continuation, self.is_multiline(), indent);
}
Dbg(condition, continuation) => {
fmt_dbg(buf, condition, continuation, self.is_multiline(), indent);
Dbg => {
buf.indent(indent);
buf.push_str("dbg");
}
DbgStmt(condition, continuation) => {
fmt_dbg_stmt(buf, condition, continuation, self.is_multiline(), indent);
}
LowLevelDbg(_, _, _) => unreachable!(
"LowLevelDbg should only exist after desugaring, not during formatting"
@ -1018,7 +1023,7 @@ fn fmt_when<'a>(
}
}
fn fmt_dbg<'a>(
fn fmt_dbg_stmt<'a>(
buf: &mut Buf,
condition: &'a Loc<Expr<'a>>,
continuation: &'a Loc<Expr<'a>>,

View file

@ -170,6 +170,7 @@ pub fn can_expr_with<'a>(
// rules multiple times unnecessarily.
let loc_expr = desugar::desugar_expr(
arena,
&mut var_store,
&loc_expr,
expr_str,
&mut None,

View file

@ -5760,28 +5760,6 @@ mod test_reporting {
"#
);
test_report!(
dbg_without_final_expression,
indoc!(
r"
dbg 42
"
),
@r#"
INDENT ENDS AFTER EXPRESSION in tmp/dbg_without_final_expression/Test.roc
I am partway through parsing a dbg statement, but I got stuck here:
4 dbg 42
^
I was expecting a final expression, like so
dbg 42
"done"
"#
);
test_report!(
expect_without_final_expression,
indoc!(
@ -14517,6 +14495,76 @@ All branches in an `if` must have the same type!
"
);
test_report!(
dbg_unapplied,
indoc!(
r"
1 + dbg + 2
"
),
@r"
UNAPPLIED DBG in /code/proj/Main.roc
This `dbg` doesn't have a value given to it:
4 1 + dbg + 2
^^^
`dbg` must be passed a value to print at the exact place it's used. `dbg`
can't be used as a value that's passed around, like functions can be -
it must be applied immediately!
TYPE MISMATCH in /code/proj/Main.roc
This 2nd argument to + has an unexpected type:
4 1 + dbg + 2
^^^
This `63` value is a:
{}
But + needs its 2nd argument to be:
Num *
"
);
test_report!(
dbg_overapplied,
indoc!(
r#"
1 + dbg "" "" + 2
"#
),
@r#"
OVERAPPLIED DBG in /code/proj/Main.roc
This `dbg` has too many values given to it:
4 1 + dbg "" "" + 2
^^^^^
`dbg` must be given exactly one value to print.
TYPE MISMATCH in /code/proj/Main.roc
This 2nd argument to + has an unexpected type:
4 1 + dbg "" "" + 2
^^^^^^^^^
This `63` value is a:
{}
But + needs its 2nd argument to be:
Num *
"#
);
// TODO: add the following tests after built-in Tasks are added
// https://github.com/roc-lang/roc/pull/6836

View file

@ -497,7 +497,10 @@ pub enum Expr<'a> {
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>>),
Dbg,
DbgStmt(&'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>),
// This form of debug is a desugared call to roc_dbg
LowLevelDbg(&'a (&'a str, &'a str), &'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>),
@ -663,9 +666,9 @@ pub fn is_expr_suffixed(expr: &Expr) -> bool {
Expr::Tag(_) => false,
Expr::OpaqueRef(_) => 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)
}
Expr::Expect(a, b) => is_expr_suffixed(&a.value) || is_expr_suffixed(&b.value),
Expr::Dbg => false,
Expr::DbgStmt(a, b) => is_expr_suffixed(&a.value) || is_expr_suffixed(&b.value),
Expr::LowLevelDbg(_, a, b) => is_expr_suffixed(&a.value) || is_expr_suffixed(&b.value),
Expr::UnaryOp(a, _) => is_expr_suffixed(&a.value),
Expr::When(cond, branches) => {
@ -958,9 +961,17 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
expr_stack.push(&a.value);
expr_stack.push(&b.value);
}
Expect(condition, cont)
| Dbg(condition, cont)
| LowLevelDbg(_, condition, cont) => {
Expect(condition, cont) => {
expr_stack.reserve(2);
expr_stack.push(&condition.value);
expr_stack.push(&cont.value);
}
DbgStmt(condition, cont) => {
expr_stack.reserve(2);
expr_stack.push(&condition.value);
expr_stack.push(&cont.value);
}
LowLevelDbg(_, condition, cont) => {
expr_stack.reserve(2);
expr_stack.push(&condition.value);
expr_stack.push(&cont.value);
@ -1032,6 +1043,7 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
| Var { .. }
| Underscore(_)
| Crash
| Dbg
| Tag(_)
| OpaqueRef(_)
| MalformedIdent(_, _)
@ -2518,8 +2530,9 @@ impl<'a> Malformed for Expr<'a> {
Closure(args, body) => args.iter().any(|arg| arg.is_malformed()) || body.is_malformed(),
Defs(defs, body) => defs.is_malformed() || body.is_malformed(),
Backpassing(args, call, body) => args.iter().any(|arg| arg.is_malformed()) || call.is_malformed() || body.is_malformed(),
Expect(condition, continuation) |
Dbg(condition, continuation) => condition.is_malformed() || continuation.is_malformed(),
Expect(condition, continuation) => condition.is_malformed() || continuation.is_malformed(),
Dbg => false,
DbgStmt(condition, continuation) => condition.is_malformed() || continuation.is_malformed(),
LowLevelDbg(_, condition, continuation) => condition.is_malformed() || continuation.is_malformed(),
Apply(func, args, _) => func.is_malformed() || args.iter().any(|arg| arg.is_malformed()),
BinOps(firsts, last) => firsts.iter().any(|(expr, _)| expr.is_malformed()) || last.is_malformed(),

View file

@ -194,6 +194,7 @@ fn loc_term_or_underscore_or_conditional<'a>(
)),
loc(specialize_err(EExpr::Closure, closure_help(options))),
loc(crash_kw()),
loc(specialize_err(EExpr::Dbg, dbg_kw())),
loc(underscore_expression()),
loc(record_literal_help()),
loc(specialize_err(EExpr::List, list_literal_help())),
@ -215,6 +216,7 @@ fn loc_term_or_underscore<'a>(
positive_number_literal_help()
)),
loc(specialize_err(EExpr::Closure, closure_help(options))),
loc(specialize_err(EExpr::Dbg, dbg_kw())),
loc(underscore_expression()),
loc(record_literal_help()),
loc(specialize_err(EExpr::List, list_literal_help())),
@ -232,6 +234,7 @@ fn loc_term<'a>(options: ExprParseOptions) -> impl Parser<'a, Loc<Expr<'a>>, EEx
positive_number_literal_help()
)),
loc(specialize_err(EExpr::Closure, closure_help(options))),
loc(specialize_err(EExpr::Dbg, dbg_kw())),
loc(record_literal_help()),
loc(specialize_err(EExpr::List, list_literal_help())),
ident_seq(),
@ -541,7 +544,7 @@ fn stmt_start<'a>(
)),
loc(specialize_err(
EExpr::Dbg,
dbg_help(options, preceding_comment)
dbg_stmt_help(options, preceding_comment)
)),
loc(specialize_err(EExpr::Import, map(import(), Stmt::ValueDef))),
map(
@ -2170,7 +2173,8 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
| Expr::If(_, _)
| Expr::When(_, _)
| Expr::Expect(_, _)
| Expr::Dbg(_, _)
| Expr::Dbg
| Expr::DbgStmt(_, _)
| Expr::LowLevelDbg(_, _, _)
| Expr::MalformedClosure
| Expr::MalformedSuffixed(..)
@ -2647,7 +2651,7 @@ fn expect_help<'a>(
}
}
fn dbg_help<'a>(
fn dbg_stmt_help<'a>(
options: ExprParseOptions,
preceding_comment: Region,
) -> impl Parser<'a, Stmt<'a>, EExpect<'a>> {
@ -2672,7 +2676,17 @@ fn dbg_help<'a>(
Ok((MadeProgress, stmt, state))
})
.trace("dbg_help")
.trace("dbg_stmt_help")
}
fn dbg_kw<'a>() -> impl Parser<'a, Expr<'a>, EExpect<'a>> {
(move |arena: &'a Bump, state: State<'a>, min_indent: u32| {
let (_, _, next_state) =
parser::keyword(keyword::DBG, EExpect::Dbg).parse(arena, state, min_indent)?;
Ok((MadeProgress, Expr::Dbg, next_state))
})
.trace("dbg_kw")
}
fn import<'a>() -> impl Parser<'a, ValueDef<'a>, EImport<'a>> {
@ -2986,14 +3000,17 @@ fn stmts_to_expr<'a>(
arena.alloc(e).before(space)
}
}
Stmt::ValueDef(ValueDef::Dbg { .. }) => {
return Err(EExpr::Dbg(
EExpect::Continuation(
arena.alloc(EExpr::IndentEnd(loc_stmt.region.end())),
loc_stmt.region.end(),
),
loc_stmt.region.start(),
));
Stmt::ValueDef(ValueDef::Dbg { condition, .. }) => {
// If we parse a `dbg` as the last thing in a series of statements then it's
// actually an expression.
Expr::Apply(
arena.alloc(Loc {
value: Expr::Dbg,
region: loc_stmt.region,
}),
arena.alloc([condition]),
CalledVia::Space,
)
}
Stmt::ValueDef(ValueDef::Expect { .. }) => {
return Err(EExpr::Expect(
@ -3145,13 +3162,19 @@ fn stmts_to_defs<'a>(
} = vd
{
if exprify_dbg {
if i + 1 >= stmts.len() {
return Err(EExpr::DbgContinue(sp_stmt.item.region.end()));
}
let rest = stmts_to_expr(&stmts[i + 1..], arena)?;
let e = Expr::Dbg(arena.alloc(condition), arena.alloc(rest));
let e = if i + 1 < stmts.len() {
let rest = stmts_to_expr(&stmts[i + 1..], arena)?;
Expr::DbgStmt(arena.alloc(condition), arena.alloc(rest))
} else {
Expr::Apply(
arena.alloc(Loc {
value: Expr::Dbg,
region: sp_stmt.item.region,
}),
arena.alloc([condition]),
CalledVia::Space,
)
};
let e = if sp_stmt.before.is_empty() {
e

View file

@ -779,7 +779,8 @@ impl<'a> Normalize<'a> for Expr<'a> {
arena.alloc(a.normalize(arena)),
arena.alloc(b.normalize(arena)),
),
Expr::Dbg(a, b) => Expr::Dbg(
Expr::Dbg => Expr::Dbg,
Expr::DbgStmt(a, b) => Expr::DbgStmt(
arena.alloc(a.normalize(arena)),
arena.alloc(b.normalize(arena)),
),

View file

@ -828,8 +828,7 @@ where
}
// This should be enough for anyone. Right? RIGHT?
let indent_text =
"| ; : ! | ; : ! | ; : ! | ; : ! | ; : ! | ; : ! | ; : ! | ; : ! | ; : ! ";
let indent_text = "| ; : ! ".repeat(20);
let cur_indent = INDENT.with(|i| *i.borrow());

View file

@ -220,6 +220,12 @@ pub enum Problem {
OverAppliedCrash {
region: Region,
},
UnappliedDbg {
region: Region,
},
OverAppliedDbg {
region: Region,
},
FileProblem {
filename: PathBuf,
error: io::ErrorKind,
@ -313,6 +319,8 @@ impl Problem {
// injecting a crash message
Problem::UnappliedCrash { .. } => RuntimeError,
Problem::OverAppliedCrash { .. } => RuntimeError,
Problem::UnappliedDbg { .. } => RuntimeError,
Problem::OverAppliedDbg { .. } => RuntimeError,
Problem::DefsOnlyUsedInRecursion(_, _) => Warning,
Problem::FileProblem { .. } => Fatal,
}
@ -477,6 +485,8 @@ impl Problem {
| Problem::UnnecessaryOutputWildcard { region }
| Problem::OverAppliedCrash { region }
| Problem::UnappliedCrash { region }
| Problem::OverAppliedDbg { region }
| Problem::UnappliedDbg { region }
| Problem::DefsOnlyUsedInRecursion(_, region) => Some(*region),
Problem::RuntimeError(RuntimeError::CircularDef(cycle_entries))
| Problem::BadRecursion(cycle_entries) => {

View file

@ -1,3 +1,4 @@
use roc_error_macros::internal_error;
use roc_types::subs::{Rank, Variable};
const DEFAULT_POOLS: usize = 8;
@ -27,14 +28,14 @@ impl Pools {
pub fn get_mut(&mut self, rank: Rank) -> &mut Vec<Variable> {
match self.0.get_mut(rank.into_usize()) {
Some(reference) => reference,
None => panic!("Compiler bug: could not find pool at rank {rank}"),
None => internal_error!("Compiler bug: could not find pool at rank {rank}"),
}
}
pub fn get(&self, rank: Rank) -> &Vec<Variable> {
match self.0.get(rank.into_usize()) {
Some(reference) => reference,
None => panic!("Compiler bug: could not find pool at rank {rank}"),
None => internal_error!("Compiler bug: could not find pool at rank {rank}"),
}
}
@ -46,7 +47,7 @@ impl Pools {
let last = self
.0
.pop()
.unwrap_or_else(|| panic!("Attempted to split_last() on non-empty Pools"));
.unwrap_or_else(|| internal_error!("Attempted to split_last() on non-empty Pools"));
(last, self.0)
}

View file

@ -0,0 +1,56 @@
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.305 : Str = CallByName Inspect.5 Inspect.152;
let Inspect.304 : Str = CallByName Inspect.64 Inspect.305;
ret Inspect.304;
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.1 : I64 = 2i64;
let Test.2 : Str = CallByName Inspect.33 Test.1;
dbg Test.2;
dec Test.2;
let Test.3 : I64 = CallByName Num.19 Test.4 Test.1;
ret Test.3;

View file

@ -0,0 +1,58 @@
procedure Inspect.250 (Inspect.251, Inspect.249):
let Inspect.323 : Str = "\"";
let Inspect.322 : Str = CallByName Inspect.63 Inspect.251 Inspect.323;
dec Inspect.323;
let Inspect.318 : Str = CallByName Inspect.63 Inspect.322 Inspect.249;
let Inspect.319 : Str = "\"";
let Inspect.317 : Str = CallByName Inspect.63 Inspect.318 Inspect.319;
dec Inspect.319;
ret Inspect.317;
procedure Inspect.30 (Inspect.147):
ret Inspect.147;
procedure Inspect.33 (Inspect.152):
let Inspect.305 : Str = CallByName Inspect.5 Inspect.152;
let Inspect.304 : Str = CallByName Inspect.64 Inspect.305;
ret Inspect.304;
procedure Inspect.39 (Inspect.301):
let Inspect.311 : Str = "";
ret Inspect.311;
procedure Inspect.47 (Inspect.249):
let Inspect.313 : Str = CallByName Inspect.30 Inspect.249;
ret Inspect.313;
procedure Inspect.5 (Inspect.150):
let Inspect.312 : Str = CallByName Inspect.47 Inspect.150;
let Inspect.309 : {} = Struct {};
let Inspect.308 : Str = CallByName Inspect.39 Inspect.309;
let Inspect.307 : Str = CallByName Inspect.250 Inspect.308 Inspect.312;
dec Inspect.312;
ret Inspect.307;
procedure Inspect.63 (Inspect.300, Inspect.296):
let Inspect.321 : Str = CallByName Str.3 Inspect.300 Inspect.296;
ret Inspect.321;
procedure Inspect.64 (Inspect.302):
ret Inspect.302;
procedure Str.3 (#Attr.2, #Attr.3):
let Str.238 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
ret Str.238;
procedure Test.0 ():
let Test.4 : Str = "Hello ";
let Test.1 : Str = "world";
inc Test.1;
let Test.2 : Str = CallByName Inspect.33 Test.1;
dbg Test.2;
dec Test.2;
let Test.7 : Str = "!";
let Test.5 : Str = CallByName Str.3 Test.1 Test.7;
dec Test.7;
let Test.3 : Str = CallByName Str.3 Test.4 Test.5;
dec Test.5;
ret Test.3;

View file

@ -0,0 +1,56 @@
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.324 : Str = CallByName Inspect.5 Inspect.152;
let Inspect.323 : Str = CallByName Inspect.64 Inspect.324;
ret Inspect.323;
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.96 (#Attr.2):
let Num.281 : Str = lowlevel NumToStr #Attr.2;
ret Num.281;
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.3 : I64 = 1i64;
let Test.4 : Str = CallByName Inspect.33 Test.3;
dbg Test.4;
dec Test.4;
let Test.5 : Str = CallByName Inspect.33 Test.3;
dbg Test.5;
dec Test.5;
let Test.6 : Str = CallByName Inspect.33 Test.3;
dbg Test.6;
dec Test.6;
ret Test.3;

View file

@ -3243,6 +3243,33 @@ fn dbg_str_followed_by_number() {
)
}
#[mono_test]
fn dbg_expr() {
indoc!(
r#"
1 + (dbg 2)
"#
)
}
#[mono_test]
fn dbg_nested_expr() {
indoc!(
r#"
dbg (dbg (dbg 1))
"#
)
}
#[mono_test]
fn dbg_inside_string() {
indoc!(
r#"
"Hello $(dbg "world")!"
"#
)
}
#[mono_test]
fn linked_list_reverse() {
indoc!(

View file

@ -1,32 +1,12 @@
SpaceBefore(
SpaceAfter(
Dbg(
@5-11 BinOps(
[
(
@5-6 Num(
"1",
),
@7-9 Equals,
),
],
@10-11 Num(
"1",
),
),
@13-14 SpaceBefore(
Num(
"4",
),
[
Newline,
Newline,
],
),
),
SpaceAfter(
Apply(
@0-5 Dbg,
[
Newline,
@4-5 Num(
"1",
),
],
Space,
),
[
Newline,

View file

@ -1,4 +1 @@
dbg 1 == 1
4
dbg 1

View file

@ -0,0 +1,3 @@
dbg 1 == 1
4

View file

@ -0,0 +1,34 @@
SpaceBefore(
SpaceAfter(
DbgStmt(
@5-11 BinOps(
[
(
@5-6 Num(
"1",
),
@7-9 Equals,
),
],
@10-11 Num(
"1",
),
),
@13-14 SpaceBefore(
Num(
"4",
),
[
Newline,
Newline,
],
),
),
[
Newline,
],
),
[
Newline,
],
)

View file

@ -0,0 +1,4 @@
dbg 1 == 1
4

View file

@ -301,8 +301,9 @@ mod test_snapshots {
pass/comment_with_non_ascii.expr,
pass/control_characters_in_scalar.expr,
pass/crash.expr,
pass/dbg_stmt.expr,
pass/dbg_stmt_multiline.expr,
pass/dbg.expr,
pass/dbg_multiline.expr,
pass/defs_suffixed_middle_extra_indents.moduledefs,
pass/deprecated_interpolated_string.expr,
pass/destructure_tag_assignment.expr,