better desugared idents

This commit is contained in:
Kiryl Dziamura 2024-07-12 13:22:14 +02:00
parent 9a37aeb82f
commit 10bdabf52e
No known key found for this signature in database
GPG key ID: FB539501A4561ACF
2 changed files with 58 additions and 28 deletions

View file

@ -159,7 +159,7 @@ fn desugar_value_def<'a>(
// _ = stmt_expr! // _ = stmt_expr!
let region = stmt_expr.region; let region = stmt_expr.region;
let new_pat = arena.alloc(Loc::at(region, Pattern::Underscore(""))); let new_pat = arena.alloc(Loc::at(region, Pattern::Underscore("#!stmt")));
ValueDef::AnnotatedBody { ValueDef::AnnotatedBody {
ann_pattern: new_pat, ann_pattern: new_pat,
@ -265,7 +265,7 @@ pub fn desugar_value_def_suffixed<'a>(arena: &'a Bump, value_def: ValueDef<'a>)
sub_arg, sub_arg,
sub_pat, sub_pat,
sub_new, sub_new,
Some(ann_type), Some((ann_pattern, ann_type)),
), ),
}, },
), ),

View file

@ -23,7 +23,7 @@ fn next_unique_suffixed_ident() -> String {
// # is used as prefix because it's impossible for code authors to define names like this. // # is used as prefix because it's impossible for code authors to define names like this.
// This makes it easy to see this identifier was created by the compiler. // This makes it easy to see this identifier was created by the compiler.
format!("#!a{}", count) format!("#!{}", count)
}) })
} }
@ -70,19 +70,17 @@ fn init_unwrapped_err<'a>(
// Provide an intermediate answer expression and pattern when unwrapping a // Provide an intermediate answer expression and pattern when unwrapping a
// (sub) expression. // (sub) expression.
// e.g. `x = foo (bar!)` unwraps to `x = Task.await (bar) \#!a0 -> foo #!a0` // e.g. `x = foo (bar!)` unwraps to `x = Task.await (bar) \#!a0 -> foo #!a0`
let answer_ident = arena.alloc(next_unique_suffixed_ident()); let ident = arena.alloc(format!("{}_arg", next_unique_suffixed_ident()));
let sub_new = arena.alloc(Loc::at( let sub_new = arena.alloc(Loc::at(
unwrapped_expr.region, unwrapped_expr.region,
Expr::Var { Expr::Var {
module_name: "", module_name: "",
ident: answer_ident, ident,
}, },
)); ));
let sub_pat = arena.alloc(Loc::at( let sub_pat = arena.alloc(Loc::at(
unwrapped_expr.region, unwrapped_expr.region,
Pattern::Identifier { Pattern::Identifier { ident },
ident: answer_ident,
},
)); ));
Err(EUnwrapped::UnwrappedSubExpr { Err(EUnwrapped::UnwrappedSubExpr {
@ -619,8 +617,7 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
let maybe_suffixed_value_def = match current_value_def { let maybe_suffixed_value_def = match current_value_def {
Annotation(..) | Dbg{..} | Expect{..} | ExpectFx{..} | Stmt(..) | ModuleImport{..} | IngestedFileImport(_) => None, Annotation(..) | Dbg{..} | Expect{..} | ExpectFx{..} | Stmt(..) | ModuleImport{..} | IngestedFileImport(_) => None,
AnnotatedBody { body_pattern, body_expr, ann_type, ann_pattern, .. } if body_pattern.value == ann_pattern.value => Some((body_pattern, body_expr, Some(ann_type))), AnnotatedBody { body_pattern, body_expr, ann_type, ann_pattern, .. } => Some((body_pattern, body_expr, Some((ann_pattern, ann_type)))),
AnnotatedBody { body_pattern, body_expr, .. } => Some((body_pattern, body_expr, None)),
Body (def_pattern, def_expr) => Some((def_pattern, def_expr, None)), Body (def_pattern, def_expr) => Some((def_pattern, def_expr, None)),
}; };
@ -846,47 +843,72 @@ pub fn apply_task_await<'a>(
loc_expr: &'a Loc<Expr<'a>>, loc_expr: &'a Loc<Expr<'a>>,
loc_pat: &'a Loc<Pattern<'a>>, loc_pat: &'a Loc<Pattern<'a>>,
loc_cont: &'a Loc<Expr<'a>>, loc_cont: &'a Loc<Expr<'a>>,
maybe_loc_type: Option<&'a Loc<TypeAnnotation<'a>>>, maybe_loc_ann: Option<(&'a Loc<Pattern>, &'a Loc<TypeAnnotation<'a>>)>,
) -> &'a Loc<Expr<'a>> { ) -> &'a Loc<Expr<'a>> {
let task_await_first_arg = match maybe_loc_type { let task_await_first_arg = match maybe_loc_ann {
Some(loc_type) => { Some((loc_ann_pat, loc_type)) => {
// loc_pat : loc_type // loc_ann_pat : loc_type
// loc_pat = loc_expr! // loc_pat = loc_expr!
// loc_cont // loc_cont
// desugar to // desugar to
// Task.await // Task.await
// ( // (
// #!a0 : Task loc_type _ // #!0_expr : Task loc_type _
// #!a0 = loc_expr // #!0_expr = loc_expr
// #!a0 // #!0_expr
// ) // )
// \loc_pat -> loc_cont // \loc_pat -> loc_cont
use roc_parse::ast::*; use roc_parse::ast::*;
// #!a0 // #!a0
let new_ident = arena.alloc(next_unique_suffixed_ident()); let new_ident = next_unique_suffixed_ident();
// #!a0 (pattern) let new_ident = match loc_pat.value {
let new_pat = arena.alloc(Loc::at(region, Pattern::Identifier { ident: new_ident })); Pattern::Underscore("#!stmt") => format!("{}_stmt", new_ident),
Pattern::Identifier { ident }
if ident.starts_with('#') && ident.ends_with("_stmt") =>
{
format!("{}_stmt", new_ident)
}
_ => format!("{}_expr", new_ident),
};
let new_ident = arena.alloc(new_ident);
// #!a0 : Task loc_type _ // #!0_expr (pattern)
// #!a0 = loc_expr // #!0_expr : Task loc_type _
// #!0_expr = loc_expr
let value_def = ValueDef::AnnotatedBody { let value_def = ValueDef::AnnotatedBody {
ann_pattern: new_pat, ann_pattern: arena.alloc(Loc::at(
loc_ann_pat.region,
Pattern::Identifier {
ident: if loc_ann_pat.value.equivalent(&loc_pat.value) {
new_ident
} else {
// create another pattern to preserve inconsistency
arena.alloc(next_unique_suffixed_ident())
},
},
)),
ann_type: arena.alloc(Loc::at( ann_type: arena.alloc(Loc::at(
region, loc_type.region,
TypeAnnotation::Apply( TypeAnnotation::Apply(
arena.alloc(""), arena.alloc(""),
arena.alloc("Task"), arena.alloc("Task"),
arena.alloc([*loc_type, Loc::at(region, TypeAnnotation::Inferred)]), arena.alloc([
*loc_type,
Loc::at(loc_type.region, TypeAnnotation::Inferred),
]),
), ),
)), )),
comment: None, comment: None,
body_pattern: new_pat, body_pattern: arena.alloc(Loc::at(
loc_pat.region,
Pattern::Identifier { ident: new_ident },
)),
body_expr: loc_expr, body_expr: loc_expr,
}; };
// #!a0 (variable) // #!0_expr (variable)
let new_var = arena.alloc(Loc::at( let new_var = arena.alloc(Loc::at(
region, region,
Expr::Var { Expr::Var {
@ -895,10 +917,18 @@ pub fn apply_task_await<'a>(
}, },
)); ));
// (
// #!0_expr : Task loc_type _
// #!0_expr = loc_expr
// #!0_expr
// )
let mut defs = roc_parse::ast::Defs::default(); let mut defs = roc_parse::ast::Defs::default();
defs.push_value_def(value_def, region, &[], &[]); defs.push_value_def(value_def, region, &[], &[]);
arena.alloc(Loc::at(region, Defs(arena.alloc(defs), new_var))) arena.alloc(Loc::at(
Region::span_across(&loc_ann_pat.region, &loc_expr.region),
Defs(arena.alloc(defs), new_var),
))
} }
_ => { _ => {
// loc_pat = loc_expr! // loc_pat = loc_expr!