steps towards closures and Effects

This commit is contained in:
Folkert 2020-10-17 20:53:57 +02:00
parent edfc96628e
commit 607799b96e
7 changed files with 140 additions and 39 deletions

View file

@ -322,10 +322,8 @@ pub fn constrain_expr(
arguments, arguments,
loc_body: boxed, loc_body: boxed,
captured_symbols, captured_symbols,
name,
.. ..
} => { } => {
dbg!(name, &captured_symbols);
let loc_body_expr = &**boxed; let loc_body_expr = &**boxed;
let mut state = PatternState { let mut state = PatternState {
headers: SendMap::default(), headers: SendMap::default(),

View file

@ -974,6 +974,7 @@ mod gen_primitives {
} }
#[test] #[test]
#[ignore]
fn io_poc() { fn io_poc() {
use roc_std::RocStr; use roc_std::RocStr;
assert_evals_to!( assert_evals_to!(

View file

@ -191,7 +191,6 @@ pub fn helper<'a>(
// because their bodies may reference each other. // because their bodies may reference each other.
let mut scope = Scope::default(); let mut scope = Scope::default();
for ((symbol, layout), proc) in procedures.drain() { for ((symbol, layout), proc) in procedures.drain() {
dbg!(&symbol, &layout);
let fn_val = build_proc_header(&env, &mut layout_ids, symbol, &layout, &proc); let fn_val = build_proc_header(&env, &mut layout_ids, symbol, &layout, &proc);
if proc.args.is_empty() { if proc.args.is_empty() {
@ -230,8 +229,8 @@ pub fn helper<'a>(
mode, mode,
); );
// fn_val.print_to_stderr(); fn_val.print_to_stderr();
module.print_to_stderr(); // module.print_to_stderr();
panic!( panic!(
"The preceding code was from {:?}, which failed LLVM verification in {} build.", "The preceding code was from {:?}, which failed LLVM verification in {} build.",

View file

@ -1440,7 +1440,7 @@ fn update<'a>(
{ {
// state.timings.insert(module_id, module_timing); // state.timings.insert(module_id, module_timing);
// Proc::insert_refcount_operations(arena, &mut state.procedures); Proc::insert_refcount_operations(arena, &mut state.procedures);
msg_tx msg_tx
.send(Msg::FinishedAllSpecialization { .send(Msg::FinishedAllSpecialization {

View file

@ -1,6 +1,6 @@
use self::InProgressProc::*; use self::InProgressProc::*;
use crate::exhaustive::{Ctor, Guard, RenderAs, TagId}; use crate::exhaustive::{Ctor, Guard, RenderAs, TagId};
use crate::layout::{Builtin, Layout, LayoutCache, LayoutProblem}; use crate::layout::{Builtin, ClosureLayout, Layout, LayoutCache, LayoutProblem};
use bumpalo::collections::Vec; use bumpalo::collections::Vec;
use bumpalo::Bump; use bumpalo::Bump;
use roc_collections::all::{default_hasher, MutMap, MutSet}; use roc_collections::all::{default_hasher, MutMap, MutSet};
@ -433,7 +433,15 @@ impl<'a> Procs<'a> {
{ {
Ok((proc, layout)) => { Ok((proc, layout)) => {
debug_assert_eq!(outside_layout, layout); debug_assert_eq!(outside_layout, layout);
self.specialized.insert((symbol, layout), Done(proc)); if let Layout::Closure(args, closure, ret) = layout {
self.specialized.remove(&(symbol, outside_layout));
let layout = ClosureLayout::extend_function_layout(
env.arena, args, closure, ret,
);
self.specialized.insert((symbol, layout), Done(proc));
} else {
self.specialized.insert((symbol, layout), Done(proc));
}
} }
Err(error) => { Err(error) => {
let error_msg = format!( let error_msg = format!(
@ -1405,12 +1413,18 @@ fn specialize_external<'a>(
let field_layouts = layouts.into_bump_slice(); let field_layouts = layouts.into_bump_slice();
let wrapped = if captured.len() > 1 {
Wrapped::RecordOrSingleTagUnion
} else {
Wrapped::SingleElementRecord
};
for (index, (symbol, variable)) in captured.iter().enumerate() { for (index, (symbol, variable)) in captured.iter().enumerate() {
let expr = Expr::AccessAtIndex { let expr = Expr::AccessAtIndex {
index: index as _, index: index as _,
field_layouts, field_layouts,
structure: Symbol::ARG_CLOSURE, structure: Symbol::ARG_CLOSURE,
wrapped: Wrapped::RecordOrSingleTagUnion, wrapped,
}; };
// layout is cached anyway, re-using the one found above leads to // layout is cached anyway, re-using the one found above leads to
@ -2350,8 +2364,6 @@ pub fn with_hole<'a>(
Located::at_zero(roc_can::pattern::Pattern::Identifier(record_symbol)), Located::at_zero(roc_can::pattern::Pattern::Identifier(record_symbol)),
)]; )];
dbg!("aaaa");
match procs.insert_anonymous( match procs.insert_anonymous(
env, env,
name, name,
@ -2488,35 +2500,110 @@ pub fn with_hole<'a>(
return_type, return_type,
name, name,
arguments, arguments,
captured_symbols,
loc_body: boxed_body, loc_body: boxed_body,
.. ..
} => { } => {
let loc_body = *boxed_body; let loc_body = *boxed_body;
dbg!("bbb"); match layout_cache.from_var(env.arena, function_type, env.subs) {
match procs.insert_anonymous( Err(e) => panic!("invalid layout {:?}", e),
env, Ok(Layout::Closure(argument_layouts, closure_layout, ret_layout)) => {
name, let mut captured_symbols = Vec::from_iter_in(captured_symbols, env.arena);
function_type, captured_symbols.sort();
arguments, let captured_symbols = captured_symbols.into_bump_slice();
loc_body,
CapturedSymbols::None,
return_type,
layout_cache,
) {
Ok(layout) => {
// TODO should the let have layout Pointer?
Stmt::Let(
assigned,
Expr::FunctionPointer(name, layout.clone()),
layout,
hole,
)
}
Err(_error) => Stmt::RuntimeError( procs
"TODO convert anonymous function error to a RuntimeError string", .insert_anonymous(
), env,
name,
function_type,
arguments,
loc_body,
CapturedSymbols::Captured(captured_symbols),
return_type,
layout_cache,
)
.unwrap();
let closure_data_layout = closure_layout.into_layout();
// define the function pointer
let function_ptr_layout = {
let mut temp =
Vec::from_iter_in(argument_layouts.iter().cloned(), env.arena);
temp.push(closure_data_layout.clone());
Layout::FunctionPointer(temp.into_bump_slice(), ret_layout)
};
let mut stmt = hole.clone();
let function_pointer = env.unique_symbol();
let closure_data = env.unique_symbol();
// define the closure
let expr = Expr::Struct(env.arena.alloc([function_pointer, closure_data]));
stmt = Stmt::Let(
assigned,
expr,
Layout::Struct(
env.arena
.alloc([function_ptr_layout.clone(), closure_data_layout.clone()]),
),
env.arena.alloc(stmt),
);
// define the closure data
let symbols =
Vec::from_iter_in(captured_symbols.iter().map(|x| x.0), env.arena)
.into_bump_slice();
let expr = Expr::Struct(symbols);
stmt = Stmt::Let(
closure_data,
expr,
closure_data_layout.clone(),
env.arena.alloc(stmt),
);
let expr = Expr::FunctionPointer(name, function_ptr_layout.clone());
stmt = Stmt::Let(
function_pointer,
expr,
function_ptr_layout,
env.arena.alloc(stmt),
);
stmt
}
Ok(_) => {
match procs.insert_anonymous(
env,
name,
function_type,
arguments,
loc_body,
CapturedSymbols::None,
return_type,
layout_cache,
) {
Ok(layout) => {
// TODO should the let have layout Pointer?
Stmt::Let(
assigned,
Expr::FunctionPointer(name, layout.clone()),
layout,
hole,
)
}
Err(_error) => Stmt::RuntimeError(
"TODO convert anonymous function error to a RuntimeError string",
),
}
}
} }
} }
@ -4121,10 +4208,9 @@ fn call_by_name<'a>(
// TODO does this work? // TODO does this work?
let empty = &[] as &[_]; let empty = &[] as &[_];
let (arg_layouts, ret_layout) = if let Layout::FunctionPointer(args, rlayout) = layout { let (arg_layouts, ret_layout) = match layout {
(args, rlayout) Layout::FunctionPointer(args, rlayout) => (args, rlayout),
} else { _ => (empty, &layout),
(empty, &layout)
}; };
// If we've already specialized this one, no further work is needed. // If we've already specialized this one, no further work is needed.

View file

@ -48,6 +48,23 @@ impl<'a> ClosureLayout<'a> {
} }
} }
pub fn extend_function_layout(
arena: &'a Bump,
argument_layouts: &'a [Layout<'a>],
closure_layout: Self,
ret_layout: &'a Layout<'a>,
) -> Layout<'a> {
let closure_data_layout = closure_layout.into_layout();
// define the function pointer
let function_ptr_layout = {
let mut temp = Vec::from_iter_in(argument_layouts.iter().cloned(), arena);
temp.push(closure_data_layout.clone());
Layout::FunctionPointer(temp.into_bump_slice(), ret_layout)
};
function_ptr_layout
}
pub fn stack_size(&self, pointer_size: u32) -> u32 { pub fn stack_size(&self, pointer_size: u32) -> u32 {
self.max_size self.max_size
.iter() .iter()

View file

@ -1152,7 +1152,7 @@ fn adjust_rank_content(
rank rank
} }
Func(arg_vars, closure_var, ret_var) => { Func(arg_vars, _closure_var, ret_var) => {
let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, ret_var); let mut rank = adjust_rank(subs, young_mark, visit_mark, group_rank, ret_var);
// TODO investigate further. // TODO investigate further.