get poc-effect working

This commit is contained in:
Folkert 2021-05-14 15:09:55 +02:00
parent a055fa3626
commit 3c7e849830
5 changed files with 73 additions and 28 deletions

View file

@ -3069,6 +3069,8 @@ pub fn build_proc_header_new<'a, 'ctx, 'env>(
) -> FunctionValue<'ctx> { ) -> FunctionValue<'ctx> {
let layout = env.arena.alloc(layout).full(); let layout = env.arena.alloc(layout).full();
dbg!(symbol, layout);
build_proc_header(env, layout_ids, symbol, &layout, proc) build_proc_header(env, layout_ids, symbol, &layout, proc)
} }

View file

@ -19,7 +19,7 @@ use roc_types::subs::{Content, FlatType, Subs, Variable};
use std::collections::HashMap; use std::collections::HashMap;
use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder}; use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder};
pub const PRETTY_PRINT_IR_SYMBOLS: bool = false; pub const PRETTY_PRINT_IR_SYMBOLS: bool = true;
macro_rules! return_on_layout_error { macro_rules! return_on_layout_error {
($env:expr, $layout_result:expr) => { ($env:expr, $layout_result:expr) => {
@ -1946,7 +1946,7 @@ fn specialize_external<'a>(
args: &[], args: &[],
body: specialized_body, body: specialized_body,
closure_data_layout: Some(closure_data_layout), closure_data_layout: Some(closure_data_layout),
ret_layout: closure_data_layout, ret_layout,
is_self_recursive: recursivity, is_self_recursive: recursivity,
must_own_arguments: false, must_own_arguments: false,
host_exposed_layouts, host_exposed_layouts,
@ -2257,7 +2257,48 @@ fn build_specialized_proc<'a>(
ret_layout, ret_layout,
}) })
} }
Some(_) | None => { Some(lambda_set) => {
// a function that returns a function, but is not itself a closure
// e.g. f = Num.add
// make sure there is not arg_closure argument without a closure layout
debug_assert!(pattern_symbols.last() != Some(&Symbol::ARG_CLOSURE));
use std::cmp::Ordering;
match pattern_layouts_len.cmp(&pattern_symbols.len()) {
Ordering::Equal => {
let proc_args = proc_args.into_bump_slice();
Ok(FunctionBody {
arguments: proc_args,
closure: None,
ret_layout,
})
}
Ordering::Greater => {
if pattern_symbols.is_empty() {
let ret_layout = lambda_set.runtime_representation();
Ok(FunctionPointerBody {
arguments: pattern_layouts_slice,
closure: None,
ret_layout,
})
} else {
// so far, the problem when hitting this branch was always somewhere else
// I think this branch should not be reachable in a bugfree compiler
panic!(
"more arguments (according to the layout) than argument symbols for {:?}",
proc_name
)
}
}
Ordering::Less => panic!(
"more argument symbols than arguments (according to the layout) for {:?}",
proc_name
),
}
}
None => {
// else we're making a normal function, no closure problems to worry about // else we're making a normal function, no closure problems to worry about
// we'll just assert some things // we'll just assert some things
@ -2983,9 +3024,7 @@ pub fn with_hole<'a>(
"The `[]` type has no constructors, source var {:?}", "The `[]` type has no constructors, source var {:?}",
variant_var variant_var
), ),
Unit | UnitWithArguments => { Unit | UnitWithArguments => let_empty_struct(assigned, hole),
Stmt::Let(assigned, Expr::Struct(&[]), Layout::Struct(&[]), hole)
}
BoolUnion { ttrue, .. } => Stmt::Let( BoolUnion { ttrue, .. } => Stmt::Let(
assigned, assigned,
Expr::Literal(Literal::Bool(tag_name == ttrue)), Expr::Literal(Literal::Bool(tag_name == ttrue)),
@ -3334,7 +3373,7 @@ pub fn with_hole<'a>(
stmt stmt
} }
EmptyRecord => Stmt::Let(assigned, Expr::Struct(&[]), Layout::Struct(&[]), hole), EmptyRecord => let_empty_struct(assigned, hole),
Expect(_, _) => unreachable!("I think this is unreachable"), Expect(_, _) => unreachable!("I think this is unreachable"),
@ -5678,9 +5717,7 @@ fn handle_variable_aliasing<'a>(
// then we must construct its closure; since imported symbols have no closure, we use the // then we must construct its closure; since imported symbols have no closure, we use the
// empty struct // empty struct
let layout = Layout::Struct(&[]); let_empty_struct(left, env.arena.alloc(result))
let expr = Expr::Struct(&[]);
Stmt::Let(left, expr, layout, env.arena.alloc(result))
} else { } else {
substitute_in_exprs(env.arena, &mut result, left, right); substitute_in_exprs(env.arena, &mut result, left, right);
@ -5719,6 +5756,10 @@ fn force_thunk<'a>(
Stmt::Let(assigned, Expr::Call(call), layout, env.arena.alloc(hole)) Stmt::Let(assigned, Expr::Call(call), layout, env.arena.alloc(hole))
} }
fn let_empty_struct<'a>(assigned: Symbol, hole: &'a Stmt<'a>) -> Stmt<'a> {
Stmt::Let(assigned, Expr::Struct(&[]), Layout::Struct(&[]), hole)
}
/// If the symbol is a function, make sure it is properly specialized /// If the symbol is a function, make sure it is properly specialized
fn reuse_function_symbol<'a>( fn reuse_function_symbol<'a>(
env: &mut Env<'a, '_>, env: &mut Env<'a, '_>,
@ -5745,12 +5786,7 @@ fn reuse_function_symbol<'a>(
// an imported symbol is either a function, or a top-level 0-argument thunk // an imported symbol is either a function, or a top-level 0-argument thunk
// it never has closure data, so we use the empty struct // it never has closure data, so we use the empty struct
return Stmt::Let( return let_empty_struct(symbol, env.arena.alloc(result));
symbol,
Expr::Struct(&[]),
Layout::Struct(&[]),
env.arena.alloc(result),
);
} }
_ => { _ => {
@ -5816,12 +5852,20 @@ fn reuse_function_symbol<'a>(
env.arena.alloc(result), env.arena.alloc(result),
) )
} else { } else {
return Stmt::Let( debug_assert!(procs.module_thunks.contains(&original));
symbol,
Expr::Struct(&[]), // this is a 0-argument thunk
Layout::Struct(&[]), let layout = Layout::Closure(argument_layouts, lambda_set, ret_layout);
env.arena.alloc(result), let top_level = TopLevelFunctionLayout::new(env.arena, &[], layout);
procs.insert_passed_by_name(
env,
arg_var,
original,
top_level,
layout_cache,
); );
force_thunk(env, original, layout, symbol, env.arena.alloc(result))
} }
} }
Ok(layout) => { Ok(layout) => {

View file

@ -102,6 +102,7 @@ pub struct LambdaSet<'a> {
} }
/// representation of the closure *for a particular function* /// representation of the closure *for a particular function*
#[derive(Debug)]
pub enum ClosureRepresentation<'a> { pub enum ClosureRepresentation<'a> {
/// the closure is represented as a union. Includes the tag ID! /// the closure is represented as a union. Includes the tag ID!
Union { Union {

View file

@ -1013,7 +1013,6 @@ fn specialize_closure() {
} }
#[test] #[test]
#[ignore]
fn io_poc_effect() { fn io_poc_effect() {
assert_non_opt_evals_to!( assert_non_opt_evals_to!(
indoc!( indoc!(
@ -1044,7 +1043,6 @@ fn io_poc_effect() {
} }
#[test] #[test]
#[ignore]
fn io_poc_desugared() { fn io_poc_desugared() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -1052,14 +1050,14 @@ fn io_poc_desugared() {
app "test" provides [ main ] to "./platform" app "test" provides [ main ] to "./platform"
# succeed : a -> ({} -> a) # succeed : a -> ({} -> a)
succeed = \x -> \{} -> x succeed = \x -> \_ -> x
foo : {} -> F64 foo : Str -> F64
foo = foo =
succeed 3.14 succeed 3.14
# runEffect : ({} -> a) -> a # runEffect : ({} -> a) -> a
runEffect = \thunk -> thunk {} runEffect = \thunk -> thunk ""
main : F64 main : F64
main = main =

View file

@ -275,7 +275,7 @@ 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!(