test_gen works again

This commit is contained in:
Folkert 2021-08-18 13:46:09 +02:00
parent 5fc629e5b8
commit c09b3b89f3
11 changed files with 95 additions and 124 deletions

View file

@ -270,6 +270,25 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
arguments_cast.push(argument);
}
match closure_data_layout {
Layout::Struct(&[]) => {
// do nothing
}
other => {
let closure_type = basic_type_from_layout(env, &other).ptr_type(AddressSpace::Generic);
let closure_cast = env
.builder
.build_bitcast(closure_ptr, closure_type, "load_opaque")
.into_pointer_value();
let closure_data = env.builder.build_load(closure_cast, "load_opaque");
arguments_cast.push(closure_data);
}
}
/*
match closure_data_layout {
Layout::Closure(_, lambda_set, _) => {
if let Layout::Struct(&[]) = lambda_set.runtime_representation() {
@ -316,6 +335,7 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
}
other => unreachable!("layout is not valid for a closure: {:?}", other),
}
*/
let call = {
env.builder
@ -624,6 +644,7 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>(
let default = [value1, value2];
/*
let arguments_cast = match closure_data_layout {
Layout::Closure(_, lambda_set, _) => {
if let Layout::Struct(&[]) = lambda_set.runtime_representation() {
@ -646,6 +667,29 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>(
Layout::Struct([]) => &default,
other => unreachable!("layout is not valid for a closure: {:?}", other),
};
*/
let arguments_cast = match closure_data_layout {
Layout::Struct(&[]) => {
// do nothing
&default
}
other => {
//
let closure_type =
basic_type_from_layout(env, &other).ptr_type(AddressSpace::Generic);
let closure_cast = env
.builder
.build_bitcast(closure_ptr, closure_type, "load_opaque")
.into_pointer_value();
let closure_data = env.builder.build_load(closure_cast, "load_opaque");
env.arena.alloc([value1, value2, closure_data]) as &[_]
}
};
let call = env.builder.build_call(
roc_function,

View file

@ -1082,14 +1082,6 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
)
.unwrap()
}
(StructValue(argument), Layout::Closure(_, _, _)) => env
.builder
.build_extract_value(
argument,
*index as u32,
env.arena.alloc(format!("closure_field_access_{}_", index)),
)
.unwrap(),
(
PointerValue(argument),
Layout::Union(UnionLayout::NonNullableUnwrapped(fields)),

View file

@ -88,10 +88,6 @@ fn build_hash_layout<'a, 'ctx, 'env>(
)
}
},
Layout::Closure(_, _, _) => {
unreachable!("the type system will guarantee these are never hashed")
}
}
}

View file

@ -198,10 +198,6 @@ fn build_eq<'a, 'ctx, 'env>(
)
}
},
Layout::Closure(_, _, _) => {
unreachable!("the type system will guarantee these are never compared")
}
}
}
@ -340,10 +336,6 @@ fn build_neq<'a, 'ctx, 'env>(
Layout::RecursivePointer => {
unreachable!("recursion pointers should never be compared directly")
}
Layout::Closure(_, _, _) => {
unreachable!("the type system will guarantee these are never compared")
}
}
}

View file

@ -26,10 +26,6 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
use Layout::*;
match layout {
Closure(_args, closure_layout, _ret_layout) => {
let closure_data_layout = closure_layout.runtime_representation();
basic_type_from_layout(env, &closure_data_layout)
}
Struct(sorted_fields) => basic_type_from_record(env, sorted_fields),
Union(union_layout) => {
use UnionLayout::*;

View file

@ -659,23 +659,6 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
Some(function)
}
Closure(_, lambda_set, _) => {
if lambda_set.contains_refcounted() {
let function = modify_refcount_layout_build_function(
env,
parent,
layout_ids,
mode,
when_recursive,
&lambda_set.runtime_representation(),
)?;
Some(function)
} else {
None
}
}
Struct(layouts) => {
let function = modify_refcount_struct(env, layout_ids, layouts, mode, when_recursive);

View file

@ -65,9 +65,6 @@ where
for layout in argument_layouts {
match layout {
Layout::Closure(_, lambda_set, _) => {
lambda_set.runtime_representation().hash(&mut hasher);
}
_ => {
layout.hash(&mut hasher);
}
@ -75,9 +72,6 @@ where
}
match return_layout {
Layout::Closure(_, lambda_set, _) => {
lambda_set.runtime_representation().hash(&mut hasher);
}
_ => {
return_layout.hash(&mut hasher);
}
@ -1258,11 +1252,6 @@ fn layout_spec_help(
}
},
},
Closure(_, lambda_set, _) => layout_spec_help(
builder,
&lambda_set.runtime_representation(),
when_recursive,
),
}
}

View file

@ -11,7 +11,6 @@ pub const BORROWED: bool = true;
fn should_borrow_layout(layout: &Layout) -> bool {
match layout {
Layout::Closure(_, _, _) => false,
_ => layout.is_refcounted(),
}
}

View file

@ -165,11 +165,6 @@ impl<'a, 'i> Env<'a, 'i> {
self.constructor_map.insert(symbol, 0);
self.layout_map.insert(symbol, Layout::Struct(fields));
}
Closure(_, lambda_set, _) => {
self.constructor_map.insert(symbol, 0);
self.layout_map
.insert(symbol, lambda_set.runtime_representation());
}
_ => {}
}
}
@ -244,10 +239,6 @@ fn layout_for_constructor<'a>(
debug_assert_eq!(constructor, 0);
HasFields(fields)
}
Closure(_arguments, _lambda_set, _result) => {
// HasFields(fields)
ConstructorLayout::Unknown
}
other => unreachable!("weird layout {:?}", other),
}
}
@ -374,13 +365,6 @@ pub fn expand_and_cancel_proc<'a>(
introduced.push(*symbol);
}
Layout::Closure(_arguments, _lambda_set, _result) => {
// TODO can this be improved again?
// let fpointer = Layout::FunctionPointer(arguments, result);
// let fields = env.arena.alloc([fpointer, *closure_layout.layout]);
// env.insert_struct_info(*symbol, fields);
// introduced.push(*symbol);
}
_ => {}
}
}

View file

@ -546,11 +546,11 @@ impl<'a> Procs<'a> {
// anonymous functions cannot reference themselves, therefore cannot be tail-recursive
let is_self_recursive = false;
let layout = layout_cache
.from_var(env.arena, annotation, env.subs)
let raw_layout = layout_cache
.raw_from_var(env.arena, annotation, env.subs)
.unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err));
let top_level = ProcLayout::from_layout(env.arena, layout);
let top_level = ProcLayout::from_raw(env.arena, raw_layout);
match patterns_to_when(env, layout_cache, loc_args, ret_var, loc_body) {
Ok((_, pattern_symbols, body)) => {
@ -617,7 +617,11 @@ impl<'a> Procs<'a> {
Ok((proc, layout)) => {
let top_level = ProcLayout::from_raw(env.arena, layout);
debug_assert_eq!(outside_layout, top_level);
debug_assert_eq!(
outside_layout, top_level,
"different raw layouts for {:?}",
proc.name
);
if self.module_thunks.contains(&proc.name) {
debug_assert!(top_level.arguments.is_empty());
@ -2470,21 +2474,33 @@ fn specialize_solved_type<'a>(
let fn_var = introduce_solved_type_to_subs(env, &solved_type);
// for debugging only
let attempted_layout = layout_cache
.from_var(env.arena, fn_var, env.subs)
let raw = layout_cache
.raw_from_var(env.arena, fn_var, env.subs)
.unwrap_or_else(|err| panic!("TODO handle invalid function {:?}", err));
let raw = match attempted_layout {
Layout::Closure(a, lambda_set, c) => {
if procs.module_thunks.contains(&proc_name) {
let raw = if procs.module_thunks.contains(&proc_name) {
match raw {
RawFunctionLayout::Function(_, lambda_set, _) => {
RawFunctionLayout::ZeroArgumentThunk(lambda_set.runtime_representation())
}
_ => raw,
}
} else {
RawFunctionLayout::Function(a, lambda_set, c)
}
}
_ => RawFunctionLayout::ZeroArgumentThunk(attempted_layout),
raw
};
// TODO this module_thunks.contains check will be important
// let raw = match attempted_layout {
// Layout::Closure(a, lambda_set, c) => {
// if procs.module_thunks.contains(&proc_name) {
// RawFunctionLayout::ZeroArgumentThunk(lambda_set.runtime_representation())
// } else {
// RawFunctionLayout::Function(a, lambda_set, c)
// }
// }
// _ => RawFunctionLayout::ZeroArgumentThunk(attempted_layout),
// };
// make sure rigid variables in the annotation are converted to flex variables
instantiate_rigids(env.subs, partial_proc.annotation);
@ -2509,12 +2525,12 @@ fn specialize_solved_type<'a>(
match specialized {
Ok(proc) => {
// when successful, the layout after unification should be the layout before unification
debug_assert_eq!(
attempted_layout,
layout_cache
.from_var(env.arena, fn_var, env.subs)
.unwrap_or_else(|err| panic!("TODO handle invalid function {:?}", err))
);
// debug_assert_eq!(
// attempted_layout,
// layout_cache
// .from_var(env.arena, fn_var, env.subs)
// .unwrap_or_else(|err| panic!("TODO handle invalid function {:?}", err))
// );
env.subs.rollback_to(snapshot);
layout_cache.rollback_to(cache_snapshot);
@ -2545,16 +2561,11 @@ impl<'a> ProcLayout<'a> {
for old in old_arguments {
match old {
Layout::Closure(_, lambda_set, _) => {
let repr = lambda_set.runtime_representation();
arguments.push(repr)
}
other => arguments.push(*other),
}
}
let new_result = match result {
Layout::Closure(_, lambda_set, _) => lambda_set.runtime_representation(),
other => other,
};
@ -2563,12 +2574,10 @@ impl<'a> ProcLayout<'a> {
result: new_result,
}
}
// TODO remove!!!!!
pub fn from_layout(arena: &'a Bump, layout: Layout<'a>) -> Self {
match layout {
Layout::Closure(arguments, lambda_set, result) => {
let arguments = lambda_set.extend_argument_list(arena, arguments);
ProcLayout::new(arena, arguments, *result)
}
_ => ProcLayout {
arguments: &[],
result: layout,
@ -6048,7 +6057,11 @@ fn reuse_function_symbol<'a>(
)
} else if procs.module_thunks.contains(&original) {
// this is a 0-argument thunk
let layout = Layout::Closure(argument_layouts, lambda_set, ret_layout);
// TODO suspicious
// let layout = Layout::Closure(argument_layouts, lambda_set, ret_layout);
// panic!("suspicious");
let layout = lambda_set.runtime_representation();
let top_level = ProcLayout::new(env.arena, &[], layout);
procs.insert_passed_by_name(
env,
@ -6654,8 +6667,12 @@ fn call_by_name_module_thunk<'a>(
match specialize(env, procs, proc_name, layout_cache, pending, partial_proc)
{
Ok((proc, layout)) => {
debug_assert!(layout.is_zero_argument_thunk());
Ok((proc, raw_layout)) => {
debug_assert!(
raw_layout.is_zero_argument_thunk(),
"but actually {:?}",
raw_layout
);
let was_present =
procs.specialized.remove(&(proc_name, top_level_layout));

View file

@ -160,9 +160,8 @@ pub enum Layout<'a> {
Struct(&'a [Layout<'a>]),
Union(UnionLayout<'a>),
RecursivePointer,
/// A function. The types of its arguments, then the type of its return value.
Closure(&'a [Layout<'a>], LambdaSet<'a>, &'a Layout<'a>),
// /// A function. The types of its arguments, then the type of its return value.
// Closure(&'a [Layout<'a>], LambdaSet<'a>, &'a Layout<'a>),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@ -743,7 +742,6 @@ impl<'a> Layout<'a> {
}
}
}
Closure(_, closure_layout, _) => closure_layout.safe_to_memcpy(),
RecursivePointer => {
// We cannot memcpy pointers, because then we would have the same pointer in multiple places!
false
@ -808,7 +806,6 @@ impl<'a> Layout<'a> {
| NonNullableUnwrapped(_) => pointer_size,
}
}
Closure(_, lambda_set, _) => lambda_set.stack_size(pointer_size),
RecursivePointer => pointer_size,
}
}
@ -840,9 +837,6 @@ impl<'a> Layout<'a> {
}
Layout::Builtin(builtin) => builtin.alignment_bytes(pointer_size),
Layout::RecursivePointer => pointer_size,
Layout::Closure(_, captured, _) => {
pointer_size.max(captured.alignment_bytes(pointer_size))
}
}
}
@ -893,8 +887,6 @@ impl<'a> Layout<'a> {
}
}
RecursivePointer => true,
Closure(_, closure_layout, _) => closure_layout.contains_refcounted(),
}
}
@ -918,20 +910,6 @@ impl<'a> Layout<'a> {
}
Union(union_layout) => union_layout.to_doc(alloc, parens),
RecursivePointer => alloc.text("*self"),
Closure(args, closure_layout, result) => {
let args_doc = args.iter().map(|x| x.to_doc(alloc, Parens::InFunction));
let bom = closure_layout
.representation
.to_doc(alloc, Parens::NotNeeded);
alloc
.intersperse(args_doc, ", ")
.append(alloc.text(" {| "))
.append(bom)
.append(" |} -> ")
.append(result.to_doc(alloc, Parens::InFunction))
}
}
}
}
@ -1257,7 +1235,8 @@ fn layout_from_flat_type<'a>(
let lambda_set = LambdaSet::from_var(env.arena, env.subs, closure_var)?;
Ok(Layout::Closure(fn_args, lambda_set, ret))
// Ok(Layout::Closure(fn_args, lambda_set, ret))
Ok(lambda_set.runtime_representation())
}
Record(fields, ext_var) => {
// extract any values from the ext_var