sort of stable

This commit is contained in:
Folkert 2021-05-13 21:34:22 +02:00
parent c4fc526038
commit ce195034ee
4 changed files with 119 additions and 54 deletions

View file

@ -1877,12 +1877,7 @@ fn specialize_external<'a>(
// if this is a closure, add the closure record argument
let pattern_symbols = match captured_symbols {
CapturedSymbols::None => pattern_symbols,
// CapturedSymbols::Captured([]) => pattern_symbols,
CapturedSymbols::Captured([]) => {
let mut temp = Vec::from_iter_in(pattern_symbols.iter().copied(), env.arena);
temp.push(Symbol::ARG_CLOSURE);
temp.into_bump_slice()
}
CapturedSymbols::Captured([]) => pattern_symbols,
CapturedSymbols::Captured(_) => {
let mut temp = Vec::from_iter_in(pattern_symbols.iter().copied(), env.arena);
temp.push(Symbol::ARG_CLOSURE);
@ -2069,7 +2064,6 @@ fn specialize_external<'a>(
None => None,
};
// dbg!(proc_name, &proc_args, &closure_data_layout, &ret_layout);
let proc = Proc {
name: proc_name,
args: proc_args,
@ -2438,7 +2432,8 @@ impl<'a> TopLevelFunctionLayout<'a> {
for old in old_arguments {
match old {
Layout::Closure(_, lambda_set, _) => {
arguments.push(lambda_set.runtime_representation())
let repr = lambda_set.runtime_representation();
arguments.push(repr)
}
other => arguments.push(*other),
}
@ -2994,7 +2989,13 @@ pub fn with_hole<'a>(
});
// even though this was originally a Tag, we treat it as a Struct from now on
let stmt = Stmt::Let(assigned, Expr::Struct(field_symbols), layout, hole);
let stmt = if let [only_field] = field_symbols {
let mut hole = hole.clone();
substitute_in_exprs(env.arena, &mut hole, assigned, *only_field);
hole
} else {
Stmt::Let(assigned, Expr::Struct(field_symbols), layout, hole)
};
let iter = field_symbols_temp.into_iter().map(|(_, _, data)| data);
assign_to_symbols(env, procs, layout_cache, iter, stmt)
@ -3258,7 +3259,14 @@ pub fn with_hole<'a>(
.unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err));
let field_symbols = field_symbols.into_bump_slice();
let mut stmt = Stmt::Let(assigned, Expr::Struct(field_symbols), layout, hole);
let mut stmt = if let [only_field] = field_symbols {
let mut hole = hole.clone();
substitute_in_exprs(env.arena, &mut hole, assigned, *only_field);
hole
} else {
Stmt::Let(assigned, Expr::Struct(field_symbols), layout, hole)
};
for (opt_field, symbol) in can_fields.into_iter().rev().zip(field_symbols.iter().rev())
{
@ -6135,6 +6143,8 @@ fn call_by_name_help<'a>(
maybe_closure_layout, layout
);
dbg!(maybe_closure_layout, field_symbols, &loc_args);
call_specialized_proc(
env,
procs,
@ -7605,8 +7615,8 @@ fn match_on_lambda_set<'a>(
env: &mut Env<'a, '_>,
lambda_set: LambdaSet<'a>,
closure_data_symbol: Symbol,
argument_symbols: &[Symbol],
argument_layouts: &[Layout<'a>],
argument_symbols: &'a [Symbol],
argument_layouts: &'a [Layout<'a>],
return_layout: Layout<'a>,
assigned: Symbol,
hole: &'a Stmt<'a>,
@ -7702,8 +7712,8 @@ fn union_lambda_set_to_switch<'a>(
closure_tag_id_symbol: Symbol,
closure_tag_id_layout: Layout<'a>,
closure_data_symbol: Symbol,
argument_symbols: &[Symbol],
argument_layouts: &[Layout<'a>],
argument_symbols: &'a [Symbol],
argument_layouts: &'a [Layout<'a>],
return_layout: Layout<'a>,
assigned: Symbol,
hole: &'a Stmt<'a>,
@ -7762,8 +7772,8 @@ fn union_lambda_set_branch<'a>(
function_symbol: Symbol,
closure_data_symbol: Symbol,
closure_data_layout: Layout<'a>,
argument_symbols_slice: &[Symbol],
argument_layouts_slice: &[Layout<'a>],
argument_symbols_slice: &'a [Symbol],
argument_layouts_slice: &'a [Layout<'a>],
return_layout: Layout<'a>,
) -> Stmt<'a> {
let result_symbol = env.unique_symbol();
@ -7788,23 +7798,35 @@ fn union_lambda_set_branch_help<'a>(
function_symbol: Symbol,
closure_data_symbol: Symbol,
closure_data_layout: Layout<'a>,
argument_symbols_slice: &[Symbol],
argument_layouts_slice: &[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)
}
_ => {
// extend layouts with the layout of the closure environment
let mut argument_layouts = Vec::with_capacity_in(argument_layouts_slice.len() + 1, env.arena);
let mut argument_layouts =
Vec::with_capacity_in(argument_layouts_slice.len() + 1, env.arena);
argument_layouts.extend(argument_layouts_slice);
argument_layouts.push(closure_data_layout);
let argument_layouts = argument_layouts.into_bump_slice();
// extend symbols with the symbol of the closure environment
let mut argument_symbols = Vec::with_capacity_in(argument_symbols_slice.len() + 1, env.arena);
let mut argument_symbols =
Vec::with_capacity_in(argument_symbols_slice.len() + 1, env.arena);
argument_symbols.extend(argument_symbols_slice);
argument_symbols.push(closure_data_symbol);
let argument_symbols = argument_symbols.into_bump_slice();
(
argument_layouts.into_bump_slice(),
argument_symbols.into_bump_slice(),
)
}
};
let full_layout = Layout::FunctionPointer(argument_layouts, env.arena.alloc(return_layout));
@ -7831,8 +7853,8 @@ fn enum_lambda_set_to_switch<'a>(
closure_tag_id_symbol: Symbol,
closure_tag_id_layout: Layout<'a>,
closure_data_symbol: Symbol,
argument_symbols: &[Symbol],
argument_layouts: &[Layout<'a>],
argument_symbols: &'a [Symbol],
argument_layouts: &'a [Layout<'a>],
return_layout: Layout<'a>,
assigned: Symbol,
hole: &'a Stmt<'a>,
@ -7893,8 +7915,8 @@ fn enum_lambda_set_branch<'a>(
function_symbol: Symbol,
closure_data_symbol: Symbol,
closure_data_layout: Layout<'a>,
argument_symbols_slice: &[Symbol],
argument_layouts_slice: &[Layout<'a>],
argument_symbols_slice: &'a [Symbol],
argument_layouts_slice: &'a [Layout<'a>],
return_layout: Layout<'a>,
) -> Stmt<'a> {
let result_symbol = env.unique_symbol();
@ -7919,23 +7941,35 @@ fn enum_lambda_set_branch_help<'a>(
function_symbol: Symbol,
closure_data_symbol: Symbol,
closure_data_layout: Layout<'a>,
argument_symbols_slice: &[Symbol],
argument_layouts_slice: &[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)
}
_ => {
// extend layouts with the layout of the closure environment
let mut argument_layouts = Vec::with_capacity_in(argument_layouts_slice.len() + 1, env.arena);
let mut argument_layouts =
Vec::with_capacity_in(argument_layouts_slice.len() + 1, env.arena);
argument_layouts.extend(argument_layouts_slice);
argument_layouts.push(closure_data_layout);
let argument_layouts = argument_layouts.into_bump_slice();
// extend symbols with the symbol of the closure environment
let mut argument_symbols = Vec::with_capacity_in(argument_symbols_slice.len() + 1, env.arena);
let mut argument_symbols =
Vec::with_capacity_in(argument_symbols_slice.len() + 1, env.arena);
argument_symbols.extend(argument_symbols_slice);
argument_symbols.push(closure_data_symbol);
let argument_symbols = argument_symbols.into_bump_slice();
(
argument_layouts.into_bump_slice(),
argument_symbols.into_bump_slice(),
)
}
};
let full_layout = Layout::FunctionPointer(argument_layouts, env.arena.alloc(return_layout));

View file

@ -169,11 +169,18 @@ impl<'a> LambdaSet<'a> {
if let [] = self.set {
// TERRIBLE HACK for builting functions
Layout::FunctionPointer(argument_layouts, ret_layout)
} else if let [(_, [])] = self.set {
} else {
match self.representation {
Layout::Struct(&[]) => {
// this function does not have anything in its closure, and the lambda set is a
// singleton, so we pass no extra argument
Layout::FunctionPointer(argument_layouts, ret_layout)
} else {
}
Layout::Builtin(Builtin::Int1) | Layout::Builtin(Builtin::Int8) => {
// we don't pass this along either
Layout::FunctionPointer(argument_layouts, ret_layout)
}
_ => {
let mut arguments = Vec::with_capacity_in(argument_layouts.len() + 1, arena);
arguments.extend(argument_layouts);
arguments.push(self.runtime_representation());
@ -181,6 +188,8 @@ impl<'a> LambdaSet<'a> {
Layout::FunctionPointer(arguments.into_bump_slice(), ret_layout)
}
}
}
}
pub fn from_var(
arena: &'a Bump,

View file

@ -1094,6 +1094,28 @@ fn return_wrapped_function_pointer() {
}
#[test]
fn return_wrapped_function_pointer_b() {
assert_non_opt_evals_to!(
indoc!(
r#"
app "test" provides [ main ] to "./platform"
foo : { x: (I64 -> Str) }
foo = { x: (\_ -> "foobar") }
main : { x: (I64 -> Str) }
main = foo
"#
),
1,
i64,
|_| 1
);
}
#[test]
#[ignore]
fn return_wrapped_closure() {
assert_non_opt_evals_to!(
indoc!(

View file

@ -275,7 +275,7 @@ pub fn helper<'a>(
mode,
);
fn_val.print_to_stderr();
// fn_val.print_to_stderr();
// module.print_to_stderr();
panic!(
@ -311,7 +311,7 @@ pub fn helper<'a>(
}
// Uncomment this to see the module's optimized LLVM instruction output:
env.module.print_to_stderr();
// env.module.print_to_stderr();
let lib = module_to_dylib(&env.module, &target, opt_level)
.expect("Error loading compiled dylib for test");