add closure size variable

This commit is contained in:
Folkert 2020-10-02 00:50:18 +02:00
parent 0422d565ce
commit 2e1e87ad6a
21 changed files with 546 additions and 262 deletions

View file

@ -438,7 +438,9 @@ impl<'a> Procs<'a> {
fn get_args_ret_var(subs: &Subs, var: Variable) -> Option<(std::vec::Vec<Variable>, Variable)> {
match subs.get_without_compacting(var).content {
Content::Structure(FlatType::Func(pattern_vars, ret_var)) => Some((pattern_vars, ret_var)),
Content::Structure(FlatType::Func(pattern_vars, _closure_var, ret_var)) => {
Some((pattern_vars, ret_var))
}
Content::Structure(FlatType::Apply(Symbol::ATTR_ATTR, args)) => {
get_args_ret_var(subs, args[1])
}
@ -1334,24 +1336,32 @@ pub fn with_hole<'a>(
},
LetNonRec(def, cont, _, _) => {
if let roc_can::pattern::Pattern::Identifier(symbol) = &def.loc_pattern.value {
if let Closure(ann, _, recursivity, loc_args, boxed_body) = def.loc_expr.value {
if let Closure {
function_type,
return_type,
recursive,
arguments,
loc_body: boxed_body,
..
} = def.loc_expr.value
{
// Extract Procs, but discard the resulting Expr::Load.
// That Load looks up the pointer, which we won't use here!
let (loc_body, ret_var) = *boxed_body;
let loc_body = *boxed_body;
let is_self_recursive =
!matches!(recursivity, roc_can::expr::Recursive::NotRecursive);
!matches!(recursive, roc_can::expr::Recursive::NotRecursive);
procs.insert_named(
env,
layout_cache,
*symbol,
ann,
loc_args,
function_type,
arguments,
loc_body,
is_self_recursive,
ret_var,
return_type,
);
return with_hole(env, cont.value, procs, layout_cache, assigned, hole);
@ -1418,24 +1428,32 @@ pub fn with_hole<'a>(
// because Roc is strict, only functions can be recursive!
for def in defs.into_iter() {
if let roc_can::pattern::Pattern::Identifier(symbol) = &def.loc_pattern.value {
if let Closure(ann, _, recursivity, loc_args, boxed_body) = def.loc_expr.value {
if let Closure {
function_type,
return_type,
recursive,
arguments,
loc_body: boxed_body,
..
} = def.loc_expr.value
{
// Extract Procs, but discard the resulting Expr::Load.
// That Load looks up the pointer, which we won't use here!
let (loc_body, ret_var) = *boxed_body;
let loc_body = *boxed_body;
let is_self_recursive =
!matches!(recursivity, roc_can::expr::Recursive::NotRecursive);
!matches!(recursive, roc_can::expr::Recursive::NotRecursive);
procs.insert_named(
env,
layout_cache,
*symbol,
ann,
loc_args,
function_type,
arguments,
loc_body,
is_self_recursive,
ret_var,
return_type,
);
continue;
@ -1943,11 +1961,25 @@ pub fn with_hole<'a>(
Accessor { .. } | Update { .. } => todo!("record access/accessor/update"),
Closure(ann, name, _, loc_args, boxed_body) => {
let (loc_body, ret_var) = *boxed_body;
Closure {
function_type,
return_type,
name,
arguments,
loc_body: boxed_body,
..
} => {
let loc_body = *boxed_body;
match procs.insert_anonymous(env, name, ann, loc_args, loc_body, ret_var, layout_cache)
{
match procs.insert_anonymous(
env,
name,
function_type,
arguments,
loc_body,
return_type,
layout_cache,
) {
Ok(layout) => {
// TODO should the let have layout Pointer?
Stmt::Let(
@ -1965,7 +1997,7 @@ pub fn with_hole<'a>(
}
Call(boxed, loc_args, _) => {
let (fn_var, loc_expr, ret_var) = *boxed;
let (fn_var, loc_expr, _closure_var, ret_var) = *boxed;
// even if a call looks like it's by name, it may in fact be by-pointer.
// E.g. in `(\f, x -> f x)` the call is in fact by pointer.
@ -2197,24 +2229,31 @@ pub fn from_can<'a>(
// Now that we know for sure it's a closure, get an owned
// version of these variant args so we can use them properly.
match def.loc_expr.value {
Closure(ann, _, recursivity, loc_args, boxed_body) => {
Closure {
function_type,
return_type,
recursive,
arguments,
loc_body: boxed_body,
..
} => {
// Extract Procs, but discard the resulting Expr::Load.
// That Load looks up the pointer, which we won't use here!
let (loc_body, ret_var) = *boxed_body;
let loc_body = *boxed_body;
let is_self_recursive =
!matches!(recursivity, roc_can::expr::Recursive::NotRecursive);
!matches!(recursive, roc_can::expr::Recursive::NotRecursive);
procs.insert_named(
env,
layout_cache,
*symbol,
ann,
loc_args,
function_type,
arguments,
loc_body,
is_self_recursive,
ret_var,
return_type,
);
continue;
@ -2229,28 +2268,35 @@ pub fn from_can<'a>(
}
LetNonRec(def, cont, _, _) => {
if let roc_can::pattern::Pattern::Identifier(symbol) = &def.loc_pattern.value {
if let Closure(_, _, _, _, _) = &def.loc_expr.value {
if let Closure { .. } = &def.loc_expr.value {
// Now that we know for sure it's a closure, get an owned
// version of these variant args so we can use them properly.
match def.loc_expr.value {
Closure(ann, _, recursivity, loc_args, boxed_body) => {
Closure {
function_type,
return_type,
recursive,
arguments,
loc_body: boxed_body,
..
} => {
// Extract Procs, but discard the resulting Expr::Load.
// That Load looks up the pointer, which we won't use here!
let (loc_body, ret_var) = *boxed_body;
let loc_body = *boxed_body;
let is_self_recursive =
!matches!(recursivity, roc_can::expr::Recursive::NotRecursive);
!matches!(recursive, roc_can::expr::Recursive::NotRecursive);
procs.insert_named(
env,
layout_cache,
*symbol,
ann,
loc_args,
function_type,
arguments,
loc_body,
is_self_recursive,
ret_var,
return_type,
);
return from_can(env, cont.value, procs, layout_cache);