more raw layout

This commit is contained in:
Folkert 2021-06-19 12:36:19 +02:00
parent 4c6048de7d
commit 4a8ec50c0e
2 changed files with 40 additions and 44 deletions

View file

@ -25,14 +25,22 @@ macro_rules! return_on_layout_error {
($env:expr, $layout_result:expr) => { ($env:expr, $layout_result:expr) => {
match $layout_result { match $layout_result {
Ok(cached) => cached, Ok(cached) => cached,
Err(LayoutProblem::UnresolvedTypeVar(_)) => { Err(error) => return_on_layout_error_help!($env, error),
}
};
}
macro_rules! return_on_layout_error_help {
($env:expr, $error:expr) => {
match $error {
LayoutProblem::UnresolvedTypeVar(_) => {
return Stmt::RuntimeError($env.arena.alloc(format!( return Stmt::RuntimeError($env.arena.alloc(format!(
"UnresolvedTypeVar {} line {}", "UnresolvedTypeVar {} line {}",
file!(), file!(),
line!() line!()
))); )));
} }
Err(LayoutProblem::Erroneous) => { LayoutProblem::Erroneous => {
return Stmt::RuntimeError($env.arena.alloc(format!( return Stmt::RuntimeError($env.arena.alloc(format!(
"Erroneous {} line {}", "Erroneous {} line {}",
file!(), file!(),
@ -3731,9 +3739,13 @@ pub fn with_hole<'a>(
} => { } => {
let loc_body = *boxed_body; let loc_body = *boxed_body;
match layout_cache.raw_from_var(env.arena, function_type, env.subs) { let raw = 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)) => { match return_on_layout_error!(env, raw) {
RawFunctionLayout::ZeroArgumentThunk(_) => {
unreachable!("a closure syntactically always must have at least one argument")
}
RawFunctionLayout::Function(_argument_layouts, lambda_set, _ret_layout) => {
let mut captured_symbols = Vec::from_iter_in(captured_symbols, env.arena); let mut captured_symbols = Vec::from_iter_in(captured_symbols, env.arena);
captured_symbols.sort(); captured_symbols.sort();
let captured_symbols = captured_symbols.into_bump_slice(); let captured_symbols = captured_symbols.into_bump_slice();
@ -3768,7 +3780,6 @@ pub fn with_hole<'a>(
construct_closure_data(env, lambda_set, name, symbols, assigned, hole) construct_closure_data(env, lambda_set, name, symbols, assigned, hole)
} }
Ok(_) => unreachable!(),
} }
} }
@ -3829,16 +3840,6 @@ pub fn with_hole<'a>(
layout_cache.raw_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::Closure(args, _, _) => args,
_ => unreachable!("function has layout that is not function pointer"),
};
let ret_layout = return_on_layout_error!(
env,
layout_cache.from_var(env.arena, ret_var, env.subs)
);
// if the function expression (loc_expr) is already a symbol, // if the function expression (loc_expr) is already a symbol,
// re-use that symbol, and don't define its value again // re-use that symbol, and don't define its value again
let mut result; let mut result;
@ -3850,8 +3851,8 @@ pub fn with_hole<'a>(
Imported(_) => { Imported(_) => {
unreachable!("an imported value is never an anonymous function") unreachable!("an imported value is never an anonymous function")
} }
Value(function_symbol) => { Value(function_symbol) => match full_layout {
if let Layout::Closure(_, lambda_set, _) = full_layout { RawFunctionLayout::Function(arg_layouts, lambda_set, ret_layout) => {
let closure_data_symbol = function_symbol; let closure_data_symbol = function_symbol;
result = match_on_lambda_set( result = match_on_lambda_set(
@ -3860,20 +3861,25 @@ pub fn with_hole<'a>(
closure_data_symbol, closure_data_symbol,
arg_symbols, arg_symbols,
arg_layouts, arg_layouts,
ret_layout, *ret_layout,
assigned, assigned,
hole, hole,
); );
} else { }
RawFunctionLayout::ZeroArgumentThunk(_) => {
unreachable!("calling a non-closure layout") unreachable!("calling a non-closure layout")
} }
} },
NotASymbol => { NotASymbol => {
// the expression is not a symbol. That means it's an expression // the expression is not a symbol. That means it's an expression
// evaluating to a function value. // evaluating to a function value.
match full_layout { match full_layout {
Layout::Closure(_, lambda_set, _) => { RawFunctionLayout::Function(
arg_layouts,
lambda_set,
ret_layout,
) => {
let closure_data_symbol = env.unique_symbol(); let closure_data_symbol = env.unique_symbol();
result = match_on_lambda_set( result = match_on_lambda_set(
@ -3882,7 +3888,7 @@ pub fn with_hole<'a>(
closure_data_symbol, closure_data_symbol,
arg_symbols, arg_symbols,
arg_layouts, arg_layouts,
ret_layout, *ret_layout,
assigned, assigned,
hole, hole,
); );
@ -3897,8 +3903,11 @@ pub fn with_hole<'a>(
env.arena.alloc(result), env.arena.alloc(result),
); );
} }
_ => { RawFunctionLayout::ZeroArgumentThunk(_) => {
todo!("{:?}", full_layout) unreachable!(
"{:?} cannot be called in the source language",
full_layout
)
} }
} }
} }

View file

@ -808,7 +808,7 @@ impl<'a> LayoutCache<'a> {
arena: &'a Bump, arena: &'a Bump,
var: Variable, var: Variable,
subs: &Subs, subs: &Subs,
) -> Result<Layout<'a>, LayoutProblem> { ) -> Result<RawFunctionLayout<'a>, LayoutProblem> {
// Store things according to the root Variable, to avoid duplicate work. // Store things according to the root Variable, to avoid duplicate work.
let var = subs.get_root_key_without_compacting(var); let var = subs.get_root_key_without_compacting(var);
@ -818,31 +818,18 @@ impl<'a> LayoutCache<'a> {
use CachedLayout::*; use CachedLayout::*;
match self.layouts.probe_value(cached_var) { match self.layouts.probe_value(cached_var) {
Cached(result) => Ok(result),
Problem(problem) => Err(problem), Problem(problem) => Err(problem),
NotCached => { Cached(_) | NotCached => {
let mut env = Env { let mut env = Env {
arena, arena,
subs, subs,
seen: MutSet::default(), seen: MutSet::default(),
}; };
let result = Layout::from_var(&mut env, var); Layout::from_var(&mut env, var).map(|l| match l {
Layout::Closure(a, b, c) => RawFunctionLayout::Function(a, b, c),
// Don't actually cache. The layout cache is very hard to get right in the presence other => RawFunctionLayout::ZeroArgumentThunk(other),
// 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
} }
} }
} }