This commit is contained in:
Folkert 2021-05-15 23:59:54 +02:00
parent 24c9741281
commit 27f8465e9c
5 changed files with 55 additions and 132 deletions

View File

@ -1168,15 +1168,6 @@ fn flex(tvar: VarId) -> SolvedType {
SolvedType::Flex(tvar)
}
#[inline(always)]
fn top_level_function(arguments: Vec<SolvedType>, ret: Box<SolvedType>) -> SolvedType {
SolvedType::Func(
arguments,
Box::new(SolvedType::Flex(TOP_LEVEL_CLOSURE_VAR)),
ret,
)
}
#[inline(always)]
fn closure(arguments: Vec<SolvedType>, closure_var: VarId, ret: Box<SolvedType>) -> SolvedType {
SolvedType::Func(arguments, Box::new(SolvedType::Flex(closure_var)), ret)

View File

@ -157,9 +157,9 @@ impl fmt::Display for Symbol {
}
}
impl Into<u64> for Symbol {
fn into(self) -> u64 {
self.0
impl From<Symbol> for u64 {
fn from(symbol: Symbol) -> Self {
symbol.0
}
}

View File

@ -165,7 +165,7 @@ impl<'a, 'i> Env<'a, 'i> {
self.constructor_map.insert(symbol, 0);
self.layout_map.insert(symbol, Layout::Struct(fields));
}
Closure(arguments, lambda_set, result) => {
Closure(_, lambda_set, _) => {
self.constructor_map.insert(symbol, 0);
self.layout_map
.insert(symbol, lambda_set.runtime_representation());
@ -202,7 +202,7 @@ impl<'a, 'i> Env<'a, 'i> {
}
fn layout_for_constructor<'a>(
arena: &'a Bump,
_arena: &'a Bump,
layout: &Layout<'a>,
constructor: u64,
) -> ConstructorLayout<&'a [Layout<'a>]> {
@ -244,7 +244,7 @@ fn layout_for_constructor<'a>(
debug_assert_eq!(constructor, 0);
HasFields(fields)
}
Closure(arguments, lambda_set, result) => {
Closure(_arguments, _lambda_set, _result) => {
// TODO can this be improved again?
// let fpointer = Layout::FunctionPointer(arguments, result);
// let fields = arena.alloc([fpointer, *lambda_set.layout]);

View File

@ -1,4 +1,4 @@
use crate::borrow::{ParamMap, BORROWED, OWNED};
use crate::borrow::ParamMap;
use crate::ir::{Expr, JoinPointId, ModifyRc, Param, Proc, Stmt};
use crate::layout::Layout;
use bumpalo::collections::Vec;

View File

@ -1687,14 +1687,14 @@ pub fn specialize_all<'a>(
let opt_pending_specializations = std::mem::replace(&mut procs.pending_specializations, None);
for (name, by_layout) in opt_pending_specializations.into_iter().flatten() {
for (layout, pending) in by_layout.into_iter() {
for (outside_layout, pending) in by_layout.into_iter() {
// If we've already seen this (Symbol, Layout) combination before,
// don't try to specialize it again. If we do, we'll loop forever!
//
// NOTE: this #[allow(clippy::map_entry)] here is for correctness!
// Changing it to use .entry() would necessarily make it incorrect.
#[allow(clippy::map_entry)]
if !procs.specialized.contains_key(&(name, layout)) {
if !procs.specialized.contains_key(&(name, outside_layout)) {
// TODO should pending_procs hold a Rc<Proc>?
let partial_proc = match procs.partial_procs.get(&name) {
Some(v) => v.clone(),
@ -1708,7 +1708,6 @@ pub fn specialize_all<'a>(
// Mark this proc as in-progress, so if we're dealing with
// mutually recursive functions, we don't loop forever.
// (We had a bug around this before this system existed!)
let outside_layout = layout;
procs.specialized.insert((name, outside_layout), InProgress);
match specialize(
env,
@ -2160,19 +2159,8 @@ fn build_specialized_proc_from_var<'a>(
fn_var: Variable,
) -> Result<SpecializedLayout<'a>, LayoutProblem> {
match layout_cache.from_var(env.arena, fn_var, env.subs) {
Ok(Layout::FunctionPointer(pattern_layouts, ret_layout)) => {
let mut pattern_layouts_vec = Vec::with_capacity_in(pattern_layouts.len(), env.arena);
pattern_layouts_vec.extend_from_slice(pattern_layouts);
// build_specialized_proc(
// env.arena,
// proc_name,
// pattern_symbols,
// pattern_layouts_vec,
// None,
// *ret_layout,
// )
unreachable!()
Ok(Layout::FunctionPointer(_, _)) => {
unreachable!(r"layout generated by from_var should never by a function pointer")
}
Ok(Layout::Closure(pattern_layouts, closure_layout, ret_layout)) => {
let mut pattern_layouts_vec = Vec::with_capacity_in(pattern_layouts.len(), env.arena);
@ -2268,7 +2256,6 @@ fn build_specialized_proc<'a>(
let mut proc_args = Vec::with_capacity_in(pattern_layouts.len(), arena);
let pattern_layouts_len = pattern_layouts.len();
let pattern_layouts_slice = pattern_layouts.clone().into_bump_slice();
for (arg_layout, arg_name) in pattern_layouts.into_iter().zip(pattern_symbols.iter()) {
proc_args.push((arg_layout, *arg_name));
@ -2502,37 +2489,36 @@ fn specialize_solved_type<'a>(
env.subs.rollback_to(snapshot);
layout_cache.rollback_to(cache_snapshot);
if procs.module_thunks.contains(&proc_name) {
Ok((
proc,
Layout::FunctionPointer(&[], env.arena.alloc(attempted_layout)),
))
} else {
Ok((proc, attempted_layout))
}
Ok((
proc,
cleanup_attempted_type(env, procs, proc_name, attempted_layout),
))
}
Err(error) => {
env.subs.rollback_to(snapshot);
layout_cache.rollback_to(cache_snapshot);
if procs.module_thunks.contains(&proc_name) {
Err(SpecializeFailure {
problem: error,
attempted_layout: Layout::FunctionPointer(
&[],
env.arena.alloc(attempted_layout),
),
})
} else {
Err(SpecializeFailure {
problem: error,
attempted_layout,
})
}
Err(SpecializeFailure {
problem: error,
attempted_layout: cleanup_attempted_type(env, procs, proc_name, attempted_layout),
})
}
}
}
fn cleanup_attempted_type<'a>(
env: &mut Env<'a, '_>,
procs: &mut Procs<'a>,
proc_name: Symbol,
layout: Layout<'a>,
) -> Layout<'a> {
if procs.module_thunks.contains(&proc_name) {
Layout::FunctionPointer(&[], env.arena.alloc(layout))
} else {
layout
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct TopLevelFunctionLayout<'a> {
arguments: &'a [Layout<'a>],
@ -2608,22 +2594,8 @@ fn specialize_naked_symbol<'a>(
} else if env.is_imported_symbol(symbol) {
match layout_cache.from_var(env.arena, variable, env.subs) {
Err(e) => panic!("invalid layout {:?}", e),
Ok(layout @ Layout::FunctionPointer(_, _)) => {
add_needed_external(procs, env, variable, symbol);
match hole {
Stmt::Jump(_, _) => todo!("not sure what to do in this case yet"),
_ => {
let expr = todo!(); // call_by_pointer(env, procs, symbol, layout);
let new_symbol = env.unique_symbol();
return Stmt::Let(
new_symbol,
expr,
layout,
env.arena.alloc(Stmt::Ret(new_symbol)),
);
}
}
Ok(Layout::FunctionPointer(_, _)) => {
unreachable!(r"layout generated by from_var should never by a function pointer")
}
Ok(_) => {
// this is a 0-arity thunk
@ -3052,8 +3024,8 @@ pub fn with_hole<'a>(
);
match inserted {
Ok(layout) => {
todo!()
Ok(_layout) => {
todo!("depends on 0-argument tag unions having a lambda union")
// return Stmt::Let(
// assigned,
// todo!(), // call_by_pointer(env, procs, proc_symbol, layout),
@ -6259,9 +6231,14 @@ fn call_by_name_help<'a>(
add_needed_external(procs, env, original_fn_var, proc_name);
debug_assert_ne!(proc_name.module_id(), ModuleId::ATTR);
if field_symbols.is_empty() {
force_thunk(env, proc_name, function_layout, assigned, hole)
if procs.imported_module_thunks.contains(&proc_name) {
force_thunk(env, proc_name, maybe_closure_layout, assigned, hole)
} else {
debug_assert!(
!field_symbols.is_empty(),
"should be in the list of imported_module_thunks"
);
debug_assert_eq!(
argument_layouts.len(),
field_symbols.len(),
@ -6489,6 +6466,7 @@ fn call_by_name_module_thunk<'a>(
{
Ok((proc, layout)) => {
// NOTE we cannot make the below assertion any more; figure out why
debug_assert_eq!(layout, module_thunk_layout);
let was_present =
procs.specialized.remove(&(proc_name, top_level_layout));
@ -6504,6 +6482,8 @@ fn call_by_name_module_thunk<'a>(
attempted_layout,
problem: _,
}) => {
debug_assert_eq!(attempted_layout, module_thunk_layout);
let proc = generate_runtime_error_function(
env,
proc_name,
@ -7666,6 +7646,7 @@ where
}
/// Use the lambda set to figure out how to make a call-by-name
#[allow(clippy::too_many_arguments)]
fn match_on_lambda_set<'a>(
env: &mut Env<'a, '_>,
lambda_set: LambdaSet<'a>,
@ -7760,6 +7741,7 @@ fn match_on_lambda_set<'a>(
}
}
#[allow(clippy::too_many_arguments)]
fn union_lambda_set_to_switch<'a>(
env: &mut Env<'a, '_>,
lambda_set: &'a [(Symbol, &'a [Layout<'a>])],
@ -7821,6 +7803,7 @@ fn union_lambda_set_to_switch<'a>(
}
}
#[allow(clippy::too_many_arguments)]
fn union_lambda_set_branch<'a>(
env: &mut Env<'a, '_>,
join_point_id: JoinPointId,
@ -7848,6 +7831,7 @@ fn union_lambda_set_branch<'a>(
)
}
#[allow(clippy::too_many_arguments)]
fn union_lambda_set_branch_help<'a>(
env: &mut Env<'a, '_>,
function_symbol: Symbol,
@ -7902,6 +7886,7 @@ fn union_lambda_set_branch_help<'a>(
)
}
#[allow(clippy::too_many_arguments)]
fn enum_lambda_set_to_switch<'a>(
env: &mut Env<'a, '_>,
lambda_set: &'a [(Symbol, &'a [Layout<'a>])],
@ -7964,6 +7949,7 @@ fn enum_lambda_set_to_switch<'a>(
}
}
#[allow(clippy::too_many_arguments)]
fn enum_lambda_set_branch<'a>(
env: &mut Env<'a, '_>,
join_point_id: JoinPointId,
@ -7978,30 +7964,8 @@ fn enum_lambda_set_branch<'a>(
let hole = Stmt::Jump(join_point_id, env.arena.alloc([result_symbol]));
enum_lambda_set_branch_help(
env,
function_symbol,
closure_data_symbol,
closure_data_layout,
argument_symbols_slice,
argument_layouts_slice,
return_layout,
result_symbol,
env.arena.alloc(hole),
)
}
let assigned = result_symbol;
fn enum_lambda_set_branch_help<'a>(
env: &mut Env<'a, '_>,
function_symbol: Symbol,
closure_data_symbol: Symbol,
closure_data_layout: Layout<'a>,
argument_symbols_slice: &'a [Symbol],
argument_layouts_slice: &'a [Layout<'a>],
return_layout: Layout<'a>,
assigned: Symbol,
hole: &'a Stmt<'a>,
) -> Stmt<'a> {
let (argument_layouts, argument_symbols) = match closure_data_layout {
Layout::Struct(&[]) | Layout::Builtin(Builtin::Int1) | Layout::Builtin(Builtin::Int8) => {
(argument_layouts_slice, argument_symbols_slice)
@ -8041,10 +8005,11 @@ fn enum_lambda_set_branch_help<'a>(
arguments: argument_symbols,
}),
return_layout,
hole,
env.arena.alloc(hole),
)
}
#[allow(clippy::too_many_arguments)]
fn lowlevel_enum_lambda_set_to_switch<'a, ToLowLevelCall>(
env: &mut Env<'a, '_>,
lambda_set: &'a [(Symbol, &'a [Layout<'a>])],
@ -8066,8 +8031,6 @@ where
let mut branches = Vec::with_capacity_in(lambda_set.len(), env.arena);
let closure_layout = closure_tag_id_layout;
for (i, (function_symbol, _)) in lambda_set.iter().enumerate() {
let result_symbol = env.unique_symbol();
@ -8115,34 +8078,3 @@ where
remainder: env.arena.alloc(switch),
}
}
#[allow(clippy::too_many_arguments)]
fn lowlevel_enum_lambda_set_branch<'a, ToLowLevelCall>(
env: &mut Env<'a, '_>,
join_point_id: JoinPointId,
function_symbol: Symbol,
closure_data_symbol: Symbol,
_closure_data_layout: Layout<'a>,
to_lowlevel_call: ToLowLevelCall,
function_layout: Layout<'a>,
return_layout: Layout<'a>,
) -> Stmt<'a>
where
ToLowLevelCall: Fn(Symbol, Symbol, Layout<'a>) -> Call<'a> + Copy,
{
let result_symbol = env.unique_symbol();
let hole = Stmt::Jump(join_point_id, env.arena.alloc([result_symbol]));
// build the call
Stmt::Let(
result_symbol,
Expr::Call(to_lowlevel_call(
function_symbol,
closure_data_symbol,
function_layout,
)),
return_layout,
env.arena.alloc(hole),
)
}