mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
steps towards closures and Effects
This commit is contained in:
parent
edfc96628e
commit
607799b96e
7 changed files with 140 additions and 39 deletions
|
@ -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(),
|
||||||
|
|
|
@ -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!(
|
||||||
|
|
|
@ -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.",
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
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));
|
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,12 +2500,85 @@ 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) {
|
||||||
|
Err(e) => panic!("invalid layout {:?}", e),
|
||||||
|
Ok(Layout::Closure(argument_layouts, closure_layout, ret_layout)) => {
|
||||||
|
let mut captured_symbols = Vec::from_iter_in(captured_symbols, env.arena);
|
||||||
|
captured_symbols.sort();
|
||||||
|
let captured_symbols = captured_symbols.into_bump_slice();
|
||||||
|
|
||||||
|
procs
|
||||||
|
.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(
|
match procs.insert_anonymous(
|
||||||
env,
|
env,
|
||||||
name,
|
name,
|
||||||
|
@ -2519,6 +2604,8 @@ pub fn with_hole<'a>(
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Call(boxed, loc_args, _) => {
|
Call(boxed, loc_args, _) => {
|
||||||
let (fn_var, loc_expr, _closure_var, ret_var) = *boxed;
|
let (fn_var, loc_expr, _closure_var, ret_var) = *boxed;
|
||||||
|
@ -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.
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue