more toplevel

This commit is contained in:
Folkert 2021-06-18 22:25:31 +02:00
parent fe81eabbfa
commit 4256c22004
4 changed files with 90 additions and 87 deletions

View file

@ -3694,7 +3694,7 @@ pub fn with_hole<'a>(
} => {
let loc_body = *boxed_body;
match layout_cache.from_var(env.arena, function_type, env.subs) {
match layout_cache.raw_from_var(env.arena, function_type, env.subs) {
Err(e) => panic!("invalid layout {:?}", e),
Ok(Layout::Closure(_argument_layouts, lambda_set, _ret_layout)) => {
let mut captured_symbols = Vec::from_iter_in(captured_symbols, env.arena);
@ -3731,43 +3731,6 @@ pub fn with_hole<'a>(
construct_closure_data(env, lambda_set, name, symbols, assigned, hole)
}
Ok(Layout::FunctionPointer(_, _)) => {
// CLEANUP
unreachable!("closures should never have a function pointer layout");
// match procs.insert_anonymous(
// env,
// name,
// function_type,
// arguments,
// loc_body,
// CapturedSymbols::None,
// return_type,
// layout_cache,
// ) {
// Ok(layout) => {
// bg!(name);
// // TODO should the let have layout Pointer?
// // Stmt::Let(assigned, Expr::Struct(&[]), Layout::Struct(&[]), hole)
// if false {
// let mut hole = hole.clone();
// substitute_in_exprs(env.arena, &mut hole, assigned, name);
// hole
// } else {
// Stmt::Let(
// assigned,
// call_by_pointer(env, procs, name, layout),
// layout,
// hole,
// )
// }
// }
//
// Err(_error) => Stmt::RuntimeError(
// "TODO convert anonymous function error to a RuntimeError string",
// ),
// }
}
Ok(_) => unreachable!(),
}
}
@ -3826,11 +3789,10 @@ pub fn with_hole<'a>(
let full_layout = return_on_layout_error!(
env,
layout_cache.from_var(env.arena, fn_var, env.subs)
layout_cache.raw_from_var(env.arena, fn_var, env.subs)
);
let arg_layouts = match full_layout {
Layout::FunctionPointer(args, _) => args,
Layout::Closure(args, _, _) => args,
_ => unreachable!("function has layout that is not function pointer"),
};
@ -3898,38 +3860,6 @@ pub fn with_hole<'a>(
env.arena.alloc(result),
);
}
Layout::FunctionPointer(_, _) => {
// CLEANUP
unreachable!("should not be a function pointer");
// let function_symbol = env.unique_symbol();
// let closure_data_symbol = function_symbol;
//
// // layout of the closure record
// let closure_data_layout = Layout::Struct(&[]);
//
// result = lambda_set_to_switch_make_branch_help(
// env,
// function_symbol,
// closure_data_symbol,
// closure_data_layout,
// arg_symbols,
// arg_layouts,
// ret_layout,
// assigned,
// hole,
// );
//
// result = with_hole(
// env,
// loc_expr.value,
// fn_var,
// procs,
// layout_cache,
// closure_data_symbol,
// env.arena.alloc(result),
// );
}
_ => {
todo!("{:?}", full_layout)
}

View file

@ -791,6 +791,50 @@ impl<'a> LayoutCache<'a> {
}
}
pub fn raw_from_var(
&mut self,
arena: &'a Bump,
var: Variable,
subs: &Subs,
) -> Result<Layout<'a>, LayoutProblem> {
// Store things according to the root Variable, to avoid duplicate work.
let var = subs.get_root_key_without_compacting(var);
let cached_var = CachedVariable::new(var);
self.expand_to_fit(cached_var);
use CachedLayout::*;
match self.layouts.probe_value(cached_var) {
Cached(result) => Ok(result),
Problem(problem) => Err(problem),
NotCached => {
let mut env = Env {
arena,
subs,
seen: MutSet::default(),
};
let result = Layout::from_var(&mut env, var);
// Don't actually cache. The layout cache is very hard to get right in the presence
// of specialization, it's turned of for now so an invalid cache is never the cause
// of a problem
if false {
let cached_layout = match &result {
Ok(layout) => Cached(*layout),
Err(problem) => Problem(problem.clone()),
};
self.layouts
.update_value(cached_var, |existing| existing.value = cached_layout);
}
result
}
}
}
fn expand_to_fit(&mut self, var: CachedVariable<'a>) {
use ven_ena::unify::UnifyKey;
@ -1909,6 +1953,7 @@ impl LayoutId {
struct IdsByLayout<'a> {
by_id: MutMap<Layout<'a>, u32>,
toplevels_by_id: MutMap<crate::ir::TopLevelFunctionLayout<'a>, u32>,
next_id: u32,
}
@ -1925,6 +1970,7 @@ impl<'a> LayoutIds<'a> {
// There's probably a nicer way to write it that still works.
let ids = self.by_symbol.entry(symbol).or_insert_with(|| IdsByLayout {
by_id: HashMap::with_capacity_and_hasher(1, default_hasher()),
toplevels_by_id: Default::default(),
next_id: 1,
});
@ -1941,6 +1987,39 @@ impl<'a> LayoutIds<'a> {
LayoutId(answer)
}
/// Returns a LayoutId which is unique for the given symbol and layout.
/// If given the same symbol and same layout, returns the same LayoutId.
pub fn get_toplevel<'b>(
&mut self,
symbol: Symbol,
layout: &'b crate::ir::TopLevelFunctionLayout<'a>,
) -> LayoutId {
// Note: this function does some weird stuff to satisfy the borrow checker.
// There's probably a nicer way to write it that still works.
let ids = self.by_symbol.entry(symbol).or_insert_with(|| IdsByLayout {
by_id: Default::default(),
toplevels_by_id: HashMap::with_capacity_and_hasher(1, default_hasher()),
next_id: 1,
});
// Get the id associated with this layout, or default to next_id.
let answer = ids
.toplevels_by_id
.get(&layout)
.copied()
.unwrap_or(ids.next_id);
// If we had to default to next_id, it must not have been found;
// store the ID we're going to return and increment next_id.
if answer == ids.next_id {
ids.toplevels_by_id.insert(*layout, ids.next_id);
ids.next_id += 1;
}
LayoutId(answer)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]