mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 00:01:16 +00:00
Register accessor closures when they are bound
Previously we only registered record accessor closures in anonymous contexts, where we assume they must already be specialized based on the surrounding contexts. This is not true in general since one might bind an accessor to a name. Closes #2567
This commit is contained in:
parent
d7c8c8de42
commit
3bff99b0a2
5 changed files with 154 additions and 26 deletions
|
@ -816,6 +816,11 @@ impl<'a> Procs<'a> {
|
|||
ret_var: Variable,
|
||||
layout_cache: &mut LayoutCache<'a>,
|
||||
) -> Result<ProcLayout<'a>, RuntimeError> {
|
||||
dbg!(env
|
||||
.subs
|
||||
.get_content_without_compacting(annotation)
|
||||
.clone()
|
||||
.dbg(env.subs));
|
||||
let raw_layout = layout_cache
|
||||
.raw_from_var(env.arena, annotation, env.subs)
|
||||
.unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err));
|
||||
|
@ -3088,6 +3093,53 @@ fn try_make_literal<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
fn accessor_to_closure<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
name: Symbol,
|
||||
function_var: Variable,
|
||||
record_var: Variable,
|
||||
closure_var: Variable,
|
||||
closure_ext_var: Variable,
|
||||
ext_var: Variable,
|
||||
field_var: Variable,
|
||||
field: Lowercase,
|
||||
) -> ClosureData {
|
||||
// IDEA: convert accessor fromt
|
||||
//
|
||||
// .foo
|
||||
//
|
||||
// into
|
||||
//
|
||||
// (\r -> r.foo)
|
||||
let record_symbol = env.unique_symbol();
|
||||
let body = roc_can::expr::Expr::Access {
|
||||
record_var,
|
||||
ext_var,
|
||||
field_var,
|
||||
loc_expr: Box::new(Loc::at_zero(roc_can::expr::Expr::Var(record_symbol))),
|
||||
field,
|
||||
};
|
||||
|
||||
let loc_body = Loc::at_zero(body);
|
||||
|
||||
let arguments = vec![(
|
||||
record_var,
|
||||
Loc::at_zero(roc_can::pattern::Pattern::Identifier(record_symbol)),
|
||||
)];
|
||||
|
||||
ClosureData {
|
||||
function_type: function_var,
|
||||
closure_type: closure_var,
|
||||
closure_ext_var,
|
||||
return_type: field_var,
|
||||
name,
|
||||
captured_symbols: vec![],
|
||||
recursive: roc_can::expr::Recursive::NotRecursive,
|
||||
arguments,
|
||||
loc_body: Box::new(loc_body),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_hole<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
can_expr: roc_can::expr::Expr,
|
||||
|
@ -3886,40 +3938,36 @@ pub fn with_hole<'a>(
|
|||
name,
|
||||
function_var,
|
||||
record_var,
|
||||
closure_ext_var: _,
|
||||
closure_var,
|
||||
closure_ext_var,
|
||||
ext_var,
|
||||
field_var,
|
||||
field,
|
||||
} => {
|
||||
// IDEA: convert accessor fromt
|
||||
//
|
||||
// .foo
|
||||
//
|
||||
// into
|
||||
//
|
||||
// (\r -> r.foo)
|
||||
let record_symbol = env.unique_symbol();
|
||||
let body = roc_can::expr::Expr::Access {
|
||||
let ClosureData {
|
||||
name,
|
||||
function_type,
|
||||
arguments,
|
||||
loc_body,
|
||||
..
|
||||
} = accessor_to_closure(
|
||||
env,
|
||||
name,
|
||||
function_var,
|
||||
record_var,
|
||||
closure_var,
|
||||
closure_ext_var,
|
||||
ext_var,
|
||||
field_var,
|
||||
loc_expr: Box::new(Loc::at_zero(roc_can::expr::Expr::Var(record_symbol))),
|
||||
field,
|
||||
};
|
||||
|
||||
let loc_body = Loc::at_zero(body);
|
||||
|
||||
let arguments = vec![(
|
||||
record_var,
|
||||
Loc::at_zero(roc_can::pattern::Pattern::Identifier(record_symbol)),
|
||||
)];
|
||||
);
|
||||
|
||||
match procs.insert_anonymous(
|
||||
env,
|
||||
name,
|
||||
function_var,
|
||||
function_type,
|
||||
arguments,
|
||||
loc_body,
|
||||
*loc_body,
|
||||
CapturedSymbols::None,
|
||||
field_var,
|
||||
layout_cache,
|
||||
|
@ -5445,6 +5493,38 @@ pub fn from_can<'a>(
|
|||
|
||||
return from_can(env, variable, cont.value, procs, layout_cache);
|
||||
}
|
||||
roc_can::expr::Expr::Accessor {
|
||||
name,
|
||||
function_var,
|
||||
record_var,
|
||||
closure_var,
|
||||
closure_ext_var,
|
||||
ext_var,
|
||||
field_var,
|
||||
field,
|
||||
} => {
|
||||
let closure_data = accessor_to_closure(
|
||||
env,
|
||||
name,
|
||||
function_var,
|
||||
record_var,
|
||||
closure_var,
|
||||
closure_ext_var,
|
||||
ext_var,
|
||||
field_var,
|
||||
field,
|
||||
);
|
||||
|
||||
register_noncapturing_closure(
|
||||
env,
|
||||
procs,
|
||||
layout_cache,
|
||||
*symbol,
|
||||
closure_data,
|
||||
);
|
||||
|
||||
return from_can(env, variable, cont.value, procs, layout_cache);
|
||||
}
|
||||
roc_can::expr::Expr::Var(original) => {
|
||||
// a variable is aliased, e.g.
|
||||
//
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue