mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Fix round-trip parse->fmt->parse for dbg stmts with more than one arg
This commit is contained in:
parent
cfd83ffcdf
commit
912db1b76b
25 changed files with 244 additions and 66 deletions
|
@ -491,7 +491,11 @@ pub enum Expr<'a> {
|
|||
Backpassing(&'a [Loc<Pattern<'a>>], &'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>),
|
||||
|
||||
Dbg,
|
||||
DbgStmt(&'a Loc<Expr<'a>>, &'a Loc<Expr<'a>>),
|
||||
DbgStmt {
|
||||
first: &'a Loc<Expr<'a>>,
|
||||
extra_args: &'a [&'a Loc<Expr<'a>>],
|
||||
continuation: &'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>>),
|
||||
|
@ -671,7 +675,15 @@ pub fn is_expr_suffixed(expr: &Expr) -> bool {
|
|||
Expr::OpaqueRef(_) => false,
|
||||
Expr::Backpassing(_, _, _) => false, // TODO: we might want to check this?
|
||||
Expr::Dbg => false,
|
||||
Expr::DbgStmt(a, b) => is_expr_suffixed(&a.value) || is_expr_suffixed(&b.value),
|
||||
Expr::DbgStmt {
|
||||
first,
|
||||
extra_args,
|
||||
continuation,
|
||||
} => {
|
||||
is_expr_suffixed(&first.value)
|
||||
|| extra_args.iter().any(|a| is_expr_suffixed(&a.value))
|
||||
|| is_expr_suffixed(&continuation.value)
|
||||
}
|
||||
Expr::LowLevelDbg(_, a, b) => is_expr_suffixed(&a.value) || is_expr_suffixed(&b.value),
|
||||
Expr::Try => false,
|
||||
Expr::UnaryOp(a, _) => is_expr_suffixed(&a.value),
|
||||
|
@ -930,10 +942,17 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
|
|||
expr_stack.push(&a.value);
|
||||
expr_stack.push(&b.value);
|
||||
}
|
||||
DbgStmt(condition, cont) => {
|
||||
DbgStmt {
|
||||
first,
|
||||
extra_args,
|
||||
continuation,
|
||||
} => {
|
||||
expr_stack.reserve(2);
|
||||
expr_stack.push(&condition.value);
|
||||
expr_stack.push(&cont.value);
|
||||
expr_stack.push(&first.value);
|
||||
for arg in extra_args.iter() {
|
||||
expr_stack.push(&arg.value);
|
||||
}
|
||||
expr_stack.push(&continuation.value);
|
||||
}
|
||||
LowLevelDbg(_, condition, cont) => {
|
||||
expr_stack.reserve(2);
|
||||
|
@ -2476,7 +2495,7 @@ impl<'a> Malformed for Expr<'a> {
|
|||
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(),
|
||||
Dbg => false,
|
||||
DbgStmt(condition, continuation) => condition.is_malformed() || continuation.is_malformed(),
|
||||
DbgStmt { first, extra_args, continuation } => first.is_malformed() || extra_args.iter().any(|a| a.is_malformed()) || continuation.is_malformed(),
|
||||
LowLevelDbg(_, condition, continuation) => condition.is_malformed() || continuation.is_malformed(),
|
||||
Try => false,
|
||||
Return(return_value, after_return) => return_value.is_malformed() || after_return.is_some_and(|ar| ar.is_malformed()),
|
||||
|
|
|
@ -2172,7 +2172,7 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
|
|||
| Expr::If { .. }
|
||||
| Expr::When(_, _)
|
||||
| Expr::Dbg
|
||||
| Expr::DbgStmt(_, _)
|
||||
| Expr::DbgStmt { .. }
|
||||
| Expr::LowLevelDbg(_, _, _)
|
||||
| Expr::Return(_, _)
|
||||
| Expr::MalformedSuffixed(..)
|
||||
|
@ -3086,16 +3086,13 @@ fn stmts_to_defs<'a>(
|
|||
_,
|
||||
) = e
|
||||
{
|
||||
if args.len() != 1 {
|
||||
// TODO: this should be done in can, not parsing!
|
||||
return Err(EExpr::Dbg(
|
||||
EExpect::DbgArity(sp_stmt.item.region.start()),
|
||||
sp_stmt.item.region.start(),
|
||||
));
|
||||
}
|
||||
let condition = &args[0];
|
||||
let rest = stmts_to_expr(&stmts[i + 1..], arena)?;
|
||||
let e = Expr::DbgStmt(condition, arena.alloc(rest));
|
||||
let e = Expr::DbgStmt {
|
||||
first: condition,
|
||||
extra_args: &args[1..],
|
||||
continuation: arena.alloc(rest),
|
||||
};
|
||||
|
||||
let e = if sp_stmt.before.is_empty() {
|
||||
e
|
||||
|
@ -3211,7 +3208,11 @@ fn stmts_to_defs<'a>(
|
|||
if exprify_dbg {
|
||||
let e = if i + 1 < stmts.len() {
|
||||
let rest = stmts_to_expr(&stmts[i + 1..], arena)?;
|
||||
Expr::DbgStmt(arena.alloc(condition), arena.alloc(rest))
|
||||
Expr::DbgStmt {
|
||||
first: arena.alloc(condition),
|
||||
extra_args: &[],
|
||||
continuation: arena.alloc(rest),
|
||||
}
|
||||
} else {
|
||||
Expr::Apply(
|
||||
arena.alloc(Loc {
|
||||
|
|
|
@ -713,33 +713,22 @@ impl<'a> Normalize<'a> for Expr<'a> {
|
|||
arena.alloc(b.normalize(arena)),
|
||||
),
|
||||
Expr::Crash => Expr::Crash,
|
||||
Expr::Defs(a, b) => {
|
||||
let mut defs = a.clone();
|
||||
defs.space_before = vec![Default::default(); defs.len()];
|
||||
defs.space_after = vec![Default::default(); defs.len()];
|
||||
defs.regions = vec![Region::zero(); defs.len()];
|
||||
defs.spaces.clear();
|
||||
|
||||
for type_def in defs.type_defs.iter_mut() {
|
||||
*type_def = type_def.normalize(arena);
|
||||
}
|
||||
|
||||
for value_def in defs.value_defs.iter_mut() {
|
||||
*value_def = value_def.normalize(arena);
|
||||
}
|
||||
|
||||
Expr::Defs(arena.alloc(defs), arena.alloc(b.normalize(arena)))
|
||||
}
|
||||
Expr::Defs(a, b) => fold_defs(arena, a.defs(), b.value.normalize(arena)),
|
||||
Expr::Backpassing(a, b, c) => Expr::Backpassing(
|
||||
arena.alloc(a.normalize(arena)),
|
||||
arena.alloc(b.normalize(arena)),
|
||||
arena.alloc(c.normalize(arena)),
|
||||
),
|
||||
Expr::Dbg => Expr::Dbg,
|
||||
Expr::DbgStmt(a, b) => Expr::DbgStmt(
|
||||
arena.alloc(a.normalize(arena)),
|
||||
arena.alloc(b.normalize(arena)),
|
||||
),
|
||||
Expr::DbgStmt {
|
||||
first,
|
||||
extra_args,
|
||||
continuation,
|
||||
} => Expr::DbgStmt {
|
||||
first: arena.alloc(first.normalize(arena)),
|
||||
extra_args: extra_args.normalize(arena),
|
||||
continuation: arena.alloc(continuation.normalize(arena)),
|
||||
},
|
||||
Expr::LowLevelDbg(x, a, b) => Expr::LowLevelDbg(
|
||||
x,
|
||||
arena.alloc(a.normalize(arena)),
|
||||
|
@ -791,6 +780,61 @@ impl<'a> Normalize<'a> for Expr<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn fold_defs<'a>(
|
||||
arena: &'a Bump,
|
||||
mut defs: impl Iterator<Item = Result<&'a TypeDef<'a>, &'a ValueDef<'a>>>,
|
||||
final_expr: Expr<'a>,
|
||||
) -> Expr<'a> {
|
||||
let mut new_defs = Defs::default();
|
||||
|
||||
while let Some(def) = defs.next() {
|
||||
match def {
|
||||
Ok(td) => {
|
||||
let td = td.normalize(arena);
|
||||
new_defs.push_type_def(td, Region::zero(), &[], &[]);
|
||||
}
|
||||
Err(vd) => {
|
||||
let vd = vd.normalize(arena);
|
||||
|
||||
match vd {
|
||||
ValueDef::Stmt(&Loc {
|
||||
value:
|
||||
Expr::Apply(
|
||||
&Loc {
|
||||
value: Expr::Dbg, ..
|
||||
},
|
||||
args,
|
||||
_,
|
||||
),
|
||||
..
|
||||
}) => {
|
||||
let rest = fold_defs(arena, defs, final_expr);
|
||||
let new_final = Expr::DbgStmt {
|
||||
first: args[0],
|
||||
extra_args: &args[1..],
|
||||
continuation: arena.alloc(Loc::at_zero(rest)),
|
||||
};
|
||||
if new_defs.is_empty() {
|
||||
return new_final;
|
||||
}
|
||||
return Expr::Defs(
|
||||
arena.alloc(new_defs),
|
||||
arena.alloc(Loc::at_zero(new_final)),
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
new_defs.push_value_def(vd, Region::zero(), &[], &[]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if new_defs.is_empty() {
|
||||
return final_expr;
|
||||
}
|
||||
Expr::Defs(arena.alloc(new_defs), arena.alloc(Loc::at_zero(final_expr)))
|
||||
}
|
||||
|
||||
fn remove_spaces_bad_ident(ident: BadIdent) -> BadIdent {
|
||||
match ident {
|
||||
BadIdent::Start(_) => BadIdent::Start(Position::zero()),
|
||||
|
@ -1465,7 +1509,6 @@ impl<'a> Normalize<'a> for EExpect<'a> {
|
|||
EExpect::Continuation(arena.alloc(inner_err.normalize(arena)), Position::zero())
|
||||
}
|
||||
EExpect::IndentCondition(_) => EExpect::IndentCondition(Position::zero()),
|
||||
EExpect::DbgArity(_) => EExpect::DbgArity(Position::zero()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -513,7 +513,6 @@ pub enum EExpect<'a> {
|
|||
Condition(&'a EExpr<'a>, Position),
|
||||
Continuation(&'a EExpr<'a>, Position),
|
||||
IndentCondition(Position),
|
||||
DbgArity(Position),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue