mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
rename
This commit is contained in:
parent
434ccbbf68
commit
a4f7ddb1f5
6 changed files with 3 additions and 1061 deletions
|
@ -786,7 +786,6 @@ where
|
||||||
CallType::ByName { .. } => {}
|
CallType::ByName { .. } => {}
|
||||||
CallType::LowLevel { .. } => {}
|
CallType::LowLevel { .. } => {}
|
||||||
CallType::HigherOrderLowLevel { .. } => {}
|
CallType::HigherOrderLowLevel { .. } => {}
|
||||||
CallType::NewHigherOrderLowLevel { .. } => {}
|
|
||||||
CallType::Foreign { .. } => {}
|
CallType::Foreign { .. } => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -952,32 +952,6 @@ pub fn build_exp_call<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
|
|
||||||
CallType::HigherOrderLowLevel {
|
CallType::HigherOrderLowLevel {
|
||||||
op,
|
|
||||||
function_owns_closure_data,
|
|
||||||
specialization_id,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let bytes = specialization_id.to_bytes();
|
|
||||||
let callee_var = CalleeSpecVar(&bytes);
|
|
||||||
let func_spec = func_spec_solutions.callee_spec(callee_var).unwrap();
|
|
||||||
|
|
||||||
run_higher_order_low_level(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
scope,
|
|
||||||
layout,
|
|
||||||
*op,
|
|
||||||
func_spec,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
*function_owns_closure_data,
|
|
||||||
arguments,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
CallType::NewHigherOrderLowLevel {
|
|
||||||
op,
|
op,
|
||||||
function_owns_closure_data,
|
function_owns_closure_data,
|
||||||
specialization_id,
|
specialization_id,
|
||||||
|
@ -4895,451 +4869,6 @@ fn run_new_higher_order_low_level<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
|
||||||
layout_ids: &mut LayoutIds<'a>,
|
|
||||||
scope: &Scope<'a, 'ctx>,
|
|
||||||
return_layout: &Layout<'a>,
|
|
||||||
op: LowLevel,
|
|
||||||
func_spec: FuncSpec,
|
|
||||||
argument_layouts: &[Layout<'a>],
|
|
||||||
result_layout: &Layout<'a>,
|
|
||||||
function_owns_closure_data: bool,
|
|
||||||
args: &[Symbol],
|
|
||||||
) -> BasicValueEnum<'ctx> {
|
|
||||||
use LowLevel::*;
|
|
||||||
|
|
||||||
debug_assert!(op.is_higher_order());
|
|
||||||
|
|
||||||
// macros because functions cause lifetime issues related to the `env` or `layout_ids`
|
|
||||||
macro_rules! passed_function_at_index {
|
|
||||||
($index:expr) => {{
|
|
||||||
let function_symbol = args[$index];
|
|
||||||
|
|
||||||
function_value_by_func_spec(
|
|
||||||
env,
|
|
||||||
func_spec,
|
|
||||||
function_symbol,
|
|
||||||
argument_layouts,
|
|
||||||
return_layout,
|
|
||||||
)
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! list_walk {
|
|
||||||
($variant:expr) => {{
|
|
||||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
|
||||||
|
|
||||||
let (default, default_layout) = load_symbol_and_layout(scope, &args[1]);
|
|
||||||
|
|
||||||
let function = passed_function_at_index!(2);
|
|
||||||
|
|
||||||
let (closure, closure_layout) = load_symbol_and_lambda_set(scope, &args[3]);
|
|
||||||
|
|
||||||
match list_layout {
|
|
||||||
Layout::Builtin(Builtin::EmptyList) => default,
|
|
||||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
|
||||||
let argument_layouts = &[*default_layout, **element_layout];
|
|
||||||
|
|
||||||
let roc_function_call = roc_function_call(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
function,
|
|
||||||
closure,
|
|
||||||
closure_layout,
|
|
||||||
function_owns_closure_data,
|
|
||||||
argument_layouts,
|
|
||||||
);
|
|
||||||
|
|
||||||
crate::llvm::build_list::list_walk_generic(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
roc_function_call,
|
|
||||||
result_layout,
|
|
||||||
list,
|
|
||||||
element_layout,
|
|
||||||
default,
|
|
||||||
default_layout,
|
|
||||||
$variant,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
_ => unreachable!("invalid list layout"),
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
match op {
|
|
||||||
ListMap => {
|
|
||||||
// List.map : List before, (before -> after) -> List after
|
|
||||||
debug_assert_eq!(args.len(), 3);
|
|
||||||
|
|
||||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
|
||||||
|
|
||||||
let function = passed_function_at_index!(1);
|
|
||||||
|
|
||||||
let (closure, closure_layout) = load_symbol_and_lambda_set(scope, &args[2]);
|
|
||||||
|
|
||||||
match (list_layout, return_layout) {
|
|
||||||
(Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
|
||||||
(
|
|
||||||
Layout::Builtin(Builtin::List(element_layout)),
|
|
||||||
Layout::Builtin(Builtin::List(result_layout)),
|
|
||||||
) => {
|
|
||||||
let argument_layouts = &[**element_layout];
|
|
||||||
|
|
||||||
let roc_function_call = roc_function_call(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
function,
|
|
||||||
closure,
|
|
||||||
closure_layout,
|
|
||||||
function_owns_closure_data,
|
|
||||||
argument_layouts,
|
|
||||||
);
|
|
||||||
|
|
||||||
list_map(env, roc_function_call, list, element_layout, result_layout)
|
|
||||||
}
|
|
||||||
_ => unreachable!("invalid list layout"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ListMap2 => {
|
|
||||||
debug_assert_eq!(args.len(), 4);
|
|
||||||
|
|
||||||
let (list1, list1_layout) = load_symbol_and_layout(scope, &args[0]);
|
|
||||||
let (list2, list2_layout) = load_symbol_and_layout(scope, &args[1]);
|
|
||||||
|
|
||||||
let function = passed_function_at_index!(2);
|
|
||||||
let (closure, closure_layout) = load_symbol_and_lambda_set(scope, &args[3]);
|
|
||||||
|
|
||||||
match (list1_layout, list2_layout, return_layout) {
|
|
||||||
(
|
|
||||||
Layout::Builtin(Builtin::List(element1_layout)),
|
|
||||||
Layout::Builtin(Builtin::List(element2_layout)),
|
|
||||||
Layout::Builtin(Builtin::List(result_layout)),
|
|
||||||
) => {
|
|
||||||
let argument_layouts = &[**element1_layout, **element2_layout];
|
|
||||||
|
|
||||||
let roc_function_call = roc_function_call(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
function,
|
|
||||||
closure,
|
|
||||||
closure_layout,
|
|
||||||
function_owns_closure_data,
|
|
||||||
argument_layouts,
|
|
||||||
);
|
|
||||||
|
|
||||||
list_map2(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
roc_function_call,
|
|
||||||
list1,
|
|
||||||
list2,
|
|
||||||
element1_layout,
|
|
||||||
element2_layout,
|
|
||||||
result_layout,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
(Layout::Builtin(Builtin::EmptyList), _, _)
|
|
||||||
| (_, Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
|
||||||
_ => unreachable!("invalid list layout"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ListMap3 => {
|
|
||||||
debug_assert_eq!(args.len(), 5);
|
|
||||||
|
|
||||||
let (list1, list1_layout) = load_symbol_and_layout(scope, &args[0]);
|
|
||||||
let (list2, list2_layout) = load_symbol_and_layout(scope, &args[1]);
|
|
||||||
let (list3, list3_layout) = load_symbol_and_layout(scope, &args[2]);
|
|
||||||
|
|
||||||
let function = passed_function_at_index!(3);
|
|
||||||
let (closure, closure_layout) = load_symbol_and_lambda_set(scope, &args[4]);
|
|
||||||
|
|
||||||
match (list1_layout, list2_layout, list3_layout, return_layout) {
|
|
||||||
(
|
|
||||||
Layout::Builtin(Builtin::List(element1_layout)),
|
|
||||||
Layout::Builtin(Builtin::List(element2_layout)),
|
|
||||||
Layout::Builtin(Builtin::List(element3_layout)),
|
|
||||||
Layout::Builtin(Builtin::List(result_layout)),
|
|
||||||
) => {
|
|
||||||
let argument_layouts =
|
|
||||||
&[**element1_layout, **element2_layout, **element3_layout];
|
|
||||||
|
|
||||||
let roc_function_call = roc_function_call(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
function,
|
|
||||||
closure,
|
|
||||||
closure_layout,
|
|
||||||
function_owns_closure_data,
|
|
||||||
argument_layouts,
|
|
||||||
);
|
|
||||||
|
|
||||||
list_map3(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
roc_function_call,
|
|
||||||
list1,
|
|
||||||
list2,
|
|
||||||
list3,
|
|
||||||
element1_layout,
|
|
||||||
element2_layout,
|
|
||||||
element3_layout,
|
|
||||||
result_layout,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
(Layout::Builtin(Builtin::EmptyList), _, _, _)
|
|
||||||
| (_, Layout::Builtin(Builtin::EmptyList), _, _)
|
|
||||||
| (_, _, Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
|
||||||
_ => unreachable!("invalid list layout"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ListMapWithIndex => {
|
|
||||||
// List.mapWithIndex : List before, (Nat, before -> after) -> List after
|
|
||||||
debug_assert_eq!(args.len(), 3);
|
|
||||||
|
|
||||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
|
||||||
|
|
||||||
let function = passed_function_at_index!(1);
|
|
||||||
|
|
||||||
let (closure, closure_layout) = load_symbol_and_lambda_set(scope, &args[2]);
|
|
||||||
|
|
||||||
match (list_layout, return_layout) {
|
|
||||||
(Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
|
||||||
(
|
|
||||||
Layout::Builtin(Builtin::List(element_layout)),
|
|
||||||
Layout::Builtin(Builtin::List(result_layout)),
|
|
||||||
) => {
|
|
||||||
let argument_layouts = &[Layout::Builtin(Builtin::Usize), **element_layout];
|
|
||||||
|
|
||||||
let roc_function_call = roc_function_call(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
function,
|
|
||||||
closure,
|
|
||||||
closure_layout,
|
|
||||||
function_owns_closure_data,
|
|
||||||
argument_layouts,
|
|
||||||
);
|
|
||||||
|
|
||||||
list_map_with_index(env, roc_function_call, list, element_layout, result_layout)
|
|
||||||
}
|
|
||||||
_ => unreachable!("invalid list layout"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ListKeepIf => {
|
|
||||||
// List.keepIf : List elem, (elem -> Bool) -> List elem
|
|
||||||
debug_assert_eq!(args.len(), 3);
|
|
||||||
|
|
||||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
|
||||||
|
|
||||||
let function = passed_function_at_index!(1);
|
|
||||||
|
|
||||||
let (closure, closure_layout) = load_symbol_and_lambda_set(scope, &args[2]);
|
|
||||||
|
|
||||||
match list_layout {
|
|
||||||
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
|
||||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
|
||||||
let argument_layouts = &[**element_layout];
|
|
||||||
|
|
||||||
let roc_function_call = roc_function_call(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
function,
|
|
||||||
closure,
|
|
||||||
closure_layout,
|
|
||||||
function_owns_closure_data,
|
|
||||||
argument_layouts,
|
|
||||||
);
|
|
||||||
|
|
||||||
list_keep_if(env, layout_ids, roc_function_call, list, element_layout)
|
|
||||||
}
|
|
||||||
_ => unreachable!("invalid list layout"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ListKeepOks => {
|
|
||||||
// List.keepOks : List before, (before -> Result after *) -> List after
|
|
||||||
debug_assert_eq!(args.len(), 3);
|
|
||||||
|
|
||||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
|
||||||
|
|
||||||
let function = passed_function_at_index!(1);
|
|
||||||
|
|
||||||
let (closure, closure_layout) = load_symbol_and_lambda_set(scope, &args[2]);
|
|
||||||
|
|
||||||
match (list_layout, return_layout) {
|
|
||||||
(_, Layout::Builtin(Builtin::EmptyList))
|
|
||||||
| (Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
|
||||||
(
|
|
||||||
Layout::Builtin(Builtin::List(before_layout)),
|
|
||||||
Layout::Builtin(Builtin::List(after_layout)),
|
|
||||||
) => {
|
|
||||||
let argument_layouts = &[**before_layout];
|
|
||||||
|
|
||||||
let roc_function_call = roc_function_call(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
function,
|
|
||||||
closure,
|
|
||||||
closure_layout,
|
|
||||||
function_owns_closure_data,
|
|
||||||
argument_layouts,
|
|
||||||
);
|
|
||||||
|
|
||||||
list_keep_oks(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
roc_function_call,
|
|
||||||
result_layout,
|
|
||||||
list,
|
|
||||||
before_layout,
|
|
||||||
after_layout,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
(other1, other2) => {
|
|
||||||
unreachable!("invalid list layouts:\n{:?}\n{:?}", other1, other2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ListKeepErrs => {
|
|
||||||
// List.keepErrs : List before, (before -> Result * after) -> List after
|
|
||||||
debug_assert_eq!(args.len(), 3);
|
|
||||||
|
|
||||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
|
||||||
|
|
||||||
let function = passed_function_at_index!(1);
|
|
||||||
|
|
||||||
let (closure, closure_layout) = load_symbol_and_lambda_set(scope, &args[2]);
|
|
||||||
|
|
||||||
match (list_layout, return_layout) {
|
|
||||||
(_, Layout::Builtin(Builtin::EmptyList))
|
|
||||||
| (Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
|
||||||
(
|
|
||||||
Layout::Builtin(Builtin::List(before_layout)),
|
|
||||||
Layout::Builtin(Builtin::List(after_layout)),
|
|
||||||
) => {
|
|
||||||
let argument_layouts = &[**before_layout];
|
|
||||||
|
|
||||||
let roc_function_call = roc_function_call(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
function,
|
|
||||||
closure,
|
|
||||||
closure_layout,
|
|
||||||
function_owns_closure_data,
|
|
||||||
argument_layouts,
|
|
||||||
);
|
|
||||||
|
|
||||||
list_keep_errs(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
roc_function_call,
|
|
||||||
result_layout,
|
|
||||||
list,
|
|
||||||
before_layout,
|
|
||||||
after_layout,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
(other1, other2) => {
|
|
||||||
unreachable!("invalid list layouts:\n{:?}\n{:?}", other1, other2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ListWalk => {
|
|
||||||
list_walk!(crate::llvm::build_list::ListWalk::Walk)
|
|
||||||
}
|
|
||||||
ListWalkUntil => {
|
|
||||||
list_walk!(crate::llvm::build_list::ListWalk::WalkUntil)
|
|
||||||
}
|
|
||||||
ListWalkBackwards => {
|
|
||||||
list_walk!(crate::llvm::build_list::ListWalk::WalkBackwards)
|
|
||||||
}
|
|
||||||
ListSortWith => {
|
|
||||||
// List.sortWith : List a, (a, a -> Ordering) -> List a
|
|
||||||
debug_assert_eq!(args.len(), 3);
|
|
||||||
|
|
||||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
|
||||||
|
|
||||||
let function = passed_function_at_index!(1);
|
|
||||||
|
|
||||||
let (closure, closure_layout) = load_symbol_and_lambda_set(scope, &args[2]);
|
|
||||||
|
|
||||||
match list_layout {
|
|
||||||
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
|
||||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
|
||||||
use crate::llvm::bitcode::build_compare_wrapper;
|
|
||||||
|
|
||||||
let argument_layouts = &[**element_layout, **element_layout];
|
|
||||||
|
|
||||||
let compare_wrapper =
|
|
||||||
build_compare_wrapper(env, function, closure_layout, element_layout)
|
|
||||||
.as_global_value()
|
|
||||||
.as_pointer_value();
|
|
||||||
|
|
||||||
let roc_function_call = roc_function_call(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
function,
|
|
||||||
closure,
|
|
||||||
closure_layout,
|
|
||||||
function_owns_closure_data,
|
|
||||||
argument_layouts,
|
|
||||||
);
|
|
||||||
|
|
||||||
list_sort_with(
|
|
||||||
env,
|
|
||||||
roc_function_call,
|
|
||||||
compare_wrapper,
|
|
||||||
list,
|
|
||||||
element_layout,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
_ => unreachable!("invalid list layout"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DictWalk => {
|
|
||||||
debug_assert_eq!(args.len(), 4);
|
|
||||||
|
|
||||||
let (dict, dict_layout) = load_symbol_and_layout(scope, &args[0]);
|
|
||||||
let (default, default_layout) = load_symbol_and_layout(scope, &args[1]);
|
|
||||||
let function = passed_function_at_index!(2);
|
|
||||||
let (closure, closure_layout) = load_symbol_and_lambda_set(scope, &args[3]);
|
|
||||||
|
|
||||||
match dict_layout {
|
|
||||||
Layout::Builtin(Builtin::EmptyDict) => {
|
|
||||||
// no elements, so `key` is not in here
|
|
||||||
panic!("key type unknown")
|
|
||||||
}
|
|
||||||
Layout::Builtin(Builtin::Dict(key_layout, value_layout)) => {
|
|
||||||
let argument_layouts = &[*default_layout, **key_layout, **value_layout];
|
|
||||||
|
|
||||||
let roc_function_call = roc_function_call(
|
|
||||||
env,
|
|
||||||
layout_ids,
|
|
||||||
function,
|
|
||||||
closure,
|
|
||||||
closure_layout,
|
|
||||||
function_owns_closure_data,
|
|
||||||
argument_layouts,
|
|
||||||
);
|
|
||||||
|
|
||||||
dict_walk(
|
|
||||||
env,
|
|
||||||
roc_function_call,
|
|
||||||
dict,
|
|
||||||
default,
|
|
||||||
key_layout,
|
|
||||||
value_layout,
|
|
||||||
default_layout,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
_ => unreachable!("invalid dict layout"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Fix me! I should be different in tests vs. user code!
|
// TODO: Fix me! I should be different in tests vs. user code!
|
||||||
fn expect_failed() {
|
fn expect_failed() {
|
||||||
panic!("An expectation failed!");
|
panic!("An expectation failed!");
|
||||||
|
|
|
@ -605,7 +605,7 @@ fn call_spec(
|
||||||
*update_mode,
|
*update_mode,
|
||||||
call.arguments,
|
call.arguments,
|
||||||
),
|
),
|
||||||
NewHigherOrderLowLevel {
|
HigherOrderLowLevel {
|
||||||
specialization_id,
|
specialization_id,
|
||||||
closure_env_layout,
|
closure_env_layout,
|
||||||
op,
|
op,
|
||||||
|
@ -798,223 +798,6 @@ fn call_spec(
|
||||||
|
|
||||||
let result_type = layout_spec(builder, layout)?;
|
let result_type = layout_spec(builder, layout)?;
|
||||||
|
|
||||||
builder.add_unknown_with(block, &arguments, result_type)
|
|
||||||
}
|
|
||||||
HigherOrderLowLevel {
|
|
||||||
specialization_id,
|
|
||||||
closure_env_layout,
|
|
||||||
op,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let array = specialization_id.to_bytes();
|
|
||||||
let spec_var = CalleeSpecVar(&array);
|
|
||||||
|
|
||||||
let symbol = {
|
|
||||||
use roc_module::low_level::LowLevel::*;
|
|
||||||
|
|
||||||
match op {
|
|
||||||
ListMap | ListMapWithIndex => call.arguments[1],
|
|
||||||
ListMap2 => call.arguments[2],
|
|
||||||
ListMap3 => call.arguments[3],
|
|
||||||
ListWalk | ListWalkUntil | ListWalkBackwards | DictWalk => call.arguments[2],
|
|
||||||
ListKeepIf | ListKeepOks | ListKeepErrs => call.arguments[1],
|
|
||||||
ListSortWith => call.arguments[1],
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let it = arg_layouts.iter().copied();
|
|
||||||
let bytes = func_name_bytes_help(symbol, it, *ret_layout);
|
|
||||||
let name = FuncName(&bytes);
|
|
||||||
let module = MOD_APP;
|
|
||||||
|
|
||||||
{
|
|
||||||
use roc_module::low_level::LowLevel::*;
|
|
||||||
|
|
||||||
match op {
|
|
||||||
DictWalk => {
|
|
||||||
let dict = env.symbols[&call.arguments[0]];
|
|
||||||
let state = env.symbols[&call.arguments[1]];
|
|
||||||
let closure_env = env.symbols[&call.arguments[3]];
|
|
||||||
|
|
||||||
let bag = builder.add_get_tuple_field(block, dict, DICT_BAG_INDEX)?;
|
|
||||||
let _cell = builder.add_get_tuple_field(block, dict, DICT_CELL_INDEX)?;
|
|
||||||
|
|
||||||
let first = builder.add_bag_get(block, bag)?;
|
|
||||||
|
|
||||||
let key = builder.add_get_tuple_field(block, first, 0)?;
|
|
||||||
let val = builder.add_get_tuple_field(block, first, 1)?;
|
|
||||||
|
|
||||||
let argument = if closure_env_layout.is_none() {
|
|
||||||
builder.add_make_tuple(block, &[state, key, val])?
|
|
||||||
} else {
|
|
||||||
builder.add_make_tuple(block, &[state, key, val, closure_env])?
|
|
||||||
};
|
|
||||||
builder.add_call(block, spec_var, module, name, argument)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
ListWalk | ListWalkBackwards | ListWalkUntil => {
|
|
||||||
let list = env.symbols[&call.arguments[0]];
|
|
||||||
let state = env.symbols[&call.arguments[1]];
|
|
||||||
let closure_env = env.symbols[&call.arguments[3]];
|
|
||||||
|
|
||||||
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
|
|
||||||
let _cell = builder.add_get_tuple_field(block, list, LIST_CELL_INDEX)?;
|
|
||||||
|
|
||||||
let first = builder.add_bag_get(block, bag)?;
|
|
||||||
|
|
||||||
let argument = if closure_env_layout.is_none() {
|
|
||||||
builder.add_make_tuple(block, &[state, first])?
|
|
||||||
} else {
|
|
||||||
builder.add_make_tuple(block, &[state, first, closure_env])?
|
|
||||||
};
|
|
||||||
builder.add_call(block, spec_var, module, name, argument)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
ListMapWithIndex => {
|
|
||||||
let list = env.symbols[&call.arguments[0]];
|
|
||||||
let closure_env = env.symbols[&call.arguments[2]];
|
|
||||||
|
|
||||||
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
|
|
||||||
let _cell = builder.add_get_tuple_field(block, list, LIST_CELL_INDEX)?;
|
|
||||||
|
|
||||||
let first = builder.add_bag_get(block, bag)?;
|
|
||||||
let index = builder.add_make_tuple(block, &[])?;
|
|
||||||
|
|
||||||
let argument = if closure_env_layout.is_none() {
|
|
||||||
builder.add_make_tuple(block, &[index, first])?
|
|
||||||
} else {
|
|
||||||
builder.add_make_tuple(block, &[index, first, closure_env])?
|
|
||||||
};
|
|
||||||
builder.add_call(block, spec_var, module, name, argument)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
ListMap => {
|
|
||||||
let list1 = env.symbols[&call.arguments[0]];
|
|
||||||
let closure_env = env.symbols[&call.arguments[2]];
|
|
||||||
|
|
||||||
let bag1 = builder.add_get_tuple_field(block, list1, LIST_BAG_INDEX)?;
|
|
||||||
let _cell1 = builder.add_get_tuple_field(block, list1, LIST_CELL_INDEX)?;
|
|
||||||
|
|
||||||
let elem1 = builder.add_bag_get(block, bag1)?;
|
|
||||||
|
|
||||||
let argument = if closure_env_layout.is_none() {
|
|
||||||
builder.add_make_tuple(block, &[elem1])?
|
|
||||||
} else {
|
|
||||||
builder.add_make_tuple(block, &[elem1, closure_env])?
|
|
||||||
};
|
|
||||||
builder.add_call(block, spec_var, module, name, argument)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
ListSortWith => {
|
|
||||||
let list1 = env.symbols[&call.arguments[0]];
|
|
||||||
let closure_env = env.symbols[&call.arguments[2]];
|
|
||||||
|
|
||||||
let bag1 = builder.add_get_tuple_field(block, list1, LIST_BAG_INDEX)?;
|
|
||||||
let _cell1 = builder.add_get_tuple_field(block, list1, LIST_CELL_INDEX)?;
|
|
||||||
|
|
||||||
let elem1 = builder.add_bag_get(block, bag1)?;
|
|
||||||
|
|
||||||
let argument = if closure_env_layout.is_none() {
|
|
||||||
builder.add_make_tuple(block, &[elem1, elem1])?
|
|
||||||
} else {
|
|
||||||
builder.add_make_tuple(block, &[elem1, elem1, closure_env])?
|
|
||||||
};
|
|
||||||
builder.add_call(block, spec_var, module, name, argument)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
ListMap2 => {
|
|
||||||
let list1 = env.symbols[&call.arguments[0]];
|
|
||||||
let list2 = env.symbols[&call.arguments[1]];
|
|
||||||
let closure_env = env.symbols[&call.arguments[3]];
|
|
||||||
|
|
||||||
let bag1 = builder.add_get_tuple_field(block, list1, LIST_BAG_INDEX)?;
|
|
||||||
let _cell1 = builder.add_get_tuple_field(block, list1, LIST_CELL_INDEX)?;
|
|
||||||
let elem1 = builder.add_bag_get(block, bag1)?;
|
|
||||||
|
|
||||||
let bag2 = builder.add_get_tuple_field(block, list2, LIST_BAG_INDEX)?;
|
|
||||||
let _cell2 = builder.add_get_tuple_field(block, list2, LIST_CELL_INDEX)?;
|
|
||||||
let elem2 = builder.add_bag_get(block, bag2)?;
|
|
||||||
|
|
||||||
let argument = if closure_env_layout.is_none() {
|
|
||||||
builder.add_make_tuple(block, &[elem1, elem2])?
|
|
||||||
} else {
|
|
||||||
builder.add_make_tuple(block, &[elem1, elem2, closure_env])?
|
|
||||||
};
|
|
||||||
builder.add_call(block, spec_var, module, name, argument)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
ListMap3 => {
|
|
||||||
let list1 = env.symbols[&call.arguments[0]];
|
|
||||||
let list2 = env.symbols[&call.arguments[1]];
|
|
||||||
let list3 = env.symbols[&call.arguments[2]];
|
|
||||||
let closure_env = env.symbols[&call.arguments[4]];
|
|
||||||
|
|
||||||
let bag1 = builder.add_get_tuple_field(block, list1, LIST_BAG_INDEX)?;
|
|
||||||
let _cell1 = builder.add_get_tuple_field(block, list1, LIST_CELL_INDEX)?;
|
|
||||||
let elem1 = builder.add_bag_get(block, bag1)?;
|
|
||||||
|
|
||||||
let bag2 = builder.add_get_tuple_field(block, list2, LIST_BAG_INDEX)?;
|
|
||||||
let _cell2 = builder.add_get_tuple_field(block, list2, LIST_CELL_INDEX)?;
|
|
||||||
let elem2 = builder.add_bag_get(block, bag2)?;
|
|
||||||
|
|
||||||
let bag3 = builder.add_get_tuple_field(block, list3, LIST_BAG_INDEX)?;
|
|
||||||
let _cell3 = builder.add_get_tuple_field(block, list3, LIST_CELL_INDEX)?;
|
|
||||||
let elem3 = builder.add_bag_get(block, bag3)?;
|
|
||||||
|
|
||||||
let argument = if closure_env_layout.is_none() {
|
|
||||||
builder.add_make_tuple(block, &[elem1, elem2, elem3])?
|
|
||||||
} else {
|
|
||||||
builder.add_make_tuple(block, &[elem1, elem2, elem3, closure_env])?
|
|
||||||
};
|
|
||||||
builder.add_call(block, spec_var, module, name, argument)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
ListKeepIf | ListKeepOks | ListKeepErrs => {
|
|
||||||
let list = env.symbols[&call.arguments[0]];
|
|
||||||
let closure_env = env.symbols[&call.arguments[2]];
|
|
||||||
|
|
||||||
let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?;
|
|
||||||
// let _cell = builder.add_get_tuple_field(block, list, LIST_CELL_INDEX)?;
|
|
||||||
|
|
||||||
let first = builder.add_bag_get(block, bag)?;
|
|
||||||
|
|
||||||
let argument = if closure_env_layout.is_none() {
|
|
||||||
builder.add_make_tuple(block, &[first])?
|
|
||||||
} else {
|
|
||||||
builder.add_make_tuple(block, &[first, closure_env])?
|
|
||||||
};
|
|
||||||
let result = builder.add_call(block, spec_var, module, name, argument)?;
|
|
||||||
let unit = builder.add_tuple_type(&[])?;
|
|
||||||
builder.add_unknown_with(block, &[result], unit)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
// fake a call to the function argument
|
|
||||||
// to make sure the function is specialized
|
|
||||||
|
|
||||||
// very invalid
|
|
||||||
let arg_value_id = build_tuple_value(builder, env, block, &[])?;
|
|
||||||
|
|
||||||
builder.add_call(block, spec_var, module, name, arg_value_id)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO overly pessimstic
|
|
||||||
// filter_map because one of the arguments is a function name, which
|
|
||||||
// is not defined in the env
|
|
||||||
let arguments: Vec<_> = call
|
|
||||||
.arguments
|
|
||||||
.iter()
|
|
||||||
.filter_map(|symbol| env.symbols.get(symbol))
|
|
||||||
.copied()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let result_type = layout_spec(builder, layout)?;
|
|
||||||
|
|
||||||
builder.add_unknown_with(block, &arguments, result_type)
|
builder.add_unknown_with(block, &arguments, result_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -593,7 +593,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
self.own_args_using_bools(arguments, ps);
|
self.own_args_using_bools(arguments, ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
NewHigherOrderLowLevel {
|
HigherOrderLowLevel {
|
||||||
op,
|
op,
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
ret_layout,
|
ret_layout,
|
||||||
|
@ -678,138 +678,6 @@ impl<'a> BorrowInfState<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HigherOrderLowLevel {
|
|
||||||
op,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
use roc_module::low_level::LowLevel::*;
|
|
||||||
|
|
||||||
debug_assert!(op.is_higher_order());
|
|
||||||
|
|
||||||
let closure_layout = ProcLayout {
|
|
||||||
arguments: arg_layouts,
|
|
||||||
result: *ret_layout,
|
|
||||||
};
|
|
||||||
|
|
||||||
match op {
|
|
||||||
ListMap | ListKeepIf | ListKeepOks | ListKeepErrs => {
|
|
||||||
match param_map.get_symbol(arguments[1], closure_layout) {
|
|
||||||
Some(function_ps) => {
|
|
||||||
// own the list if the function wants to own the element
|
|
||||||
if !function_ps[0].borrow {
|
|
||||||
self.own_var(arguments[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// own the closure environment if the function needs to own it
|
|
||||||
if let Some(false) = function_ps.get(1).map(|p| p.borrow) {
|
|
||||||
self.own_var(arguments[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ListMapWithIndex => {
|
|
||||||
match param_map.get_symbol(arguments[1], closure_layout) {
|
|
||||||
Some(function_ps) => {
|
|
||||||
// own the list if the function wants to own the element
|
|
||||||
if !function_ps[1].borrow {
|
|
||||||
self.own_var(arguments[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// own the closure environment if the function needs to own it
|
|
||||||
if let Some(false) = function_ps.get(2).map(|p| p.borrow) {
|
|
||||||
self.own_var(arguments[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ListMap2 => match param_map.get_symbol(arguments[2], closure_layout) {
|
|
||||||
Some(function_ps) => {
|
|
||||||
// own the lists if the function wants to own the element
|
|
||||||
if !function_ps[0].borrow {
|
|
||||||
self.own_var(arguments[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !function_ps[1].borrow {
|
|
||||||
self.own_var(arguments[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// own the closure environment if the function needs to own it
|
|
||||||
if let Some(false) = function_ps.get(2).map(|p| p.borrow) {
|
|
||||||
self.own_var(arguments[3]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => unreachable!(),
|
|
||||||
},
|
|
||||||
ListMap3 => match param_map.get_symbol(arguments[3], closure_layout) {
|
|
||||||
Some(function_ps) => {
|
|
||||||
// own the lists if the function wants to own the element
|
|
||||||
if !function_ps[0].borrow {
|
|
||||||
self.own_var(arguments[0]);
|
|
||||||
}
|
|
||||||
if !function_ps[1].borrow {
|
|
||||||
self.own_var(arguments[1]);
|
|
||||||
}
|
|
||||||
if !function_ps[2].borrow {
|
|
||||||
self.own_var(arguments[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// own the closure environment if the function needs to own it
|
|
||||||
if let Some(false) = function_ps.get(3).map(|p| p.borrow) {
|
|
||||||
self.own_var(arguments[4]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => unreachable!(),
|
|
||||||
},
|
|
||||||
ListSortWith => {
|
|
||||||
match param_map.get_symbol(arguments[1], closure_layout) {
|
|
||||||
Some(function_ps) => {
|
|
||||||
// always own the input list
|
|
||||||
self.own_var(arguments[0]);
|
|
||||||
|
|
||||||
// own the closure environment if the function needs to own it
|
|
||||||
if let Some(false) = function_ps.get(2).map(|p| p.borrow) {
|
|
||||||
self.own_var(arguments[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ListWalk | ListWalkUntil | ListWalkBackwards | DictWalk => {
|
|
||||||
match param_map.get_symbol(arguments[2], closure_layout) {
|
|
||||||
Some(function_ps) => {
|
|
||||||
// own the default value if the function wants to own it
|
|
||||||
if !function_ps[0].borrow {
|
|
||||||
self.own_var(arguments[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// own the data structure if the function wants to own the element
|
|
||||||
if !function_ps[1].borrow {
|
|
||||||
self.own_var(arguments[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// own the closure environment if the function needs to own it
|
|
||||||
if let Some(false) = function_ps.get(2).map(|p| p.borrow) {
|
|
||||||
self.own_var(arguments[3]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// very unsure what demand RunLowLevel should place upon its arguments
|
|
||||||
self.own_var(z);
|
|
||||||
|
|
||||||
let ps = lowlevel_borrow_signature(self.arena, *op);
|
|
||||||
|
|
||||||
self.own_args_using_bools(arguments, ps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Foreign { .. } => {
|
Foreign { .. } => {
|
||||||
// very unsure what demand ForeignCall should place upon its arguments
|
// very unsure what demand ForeignCall should place upon its arguments
|
||||||
self.own_var(z);
|
self.own_var(z);
|
||||||
|
@ -1156,7 +1024,6 @@ fn call_info_call<'a>(call: &crate::ir::Call<'a>, info: &mut CallInfo<'a>) {
|
||||||
Foreign { .. } => {}
|
Foreign { .. } => {}
|
||||||
LowLevel { .. } => {}
|
LowLevel { .. } => {}
|
||||||
HigherOrderLowLevel { .. } => {}
|
HigherOrderLowLevel { .. } => {}
|
||||||
NewHigherOrderLowLevel { .. } => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -463,7 +463,7 @@ impl<'a> Context<'a> {
|
||||||
&*self.arena.alloc(Stmt::Let(z, v, l, b))
|
&*self.arena.alloc(Stmt::Let(z, v, l, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
NewHigherOrderLowLevel {
|
HigherOrderLowLevel {
|
||||||
op,
|
op,
|
||||||
closure_env_layout,
|
closure_env_layout,
|
||||||
specialization_id,
|
specialization_id,
|
||||||
|
@ -620,222 +620,6 @@ impl<'a> Context<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HigherOrderLowLevel {
|
|
||||||
op,
|
|
||||||
closure_env_layout,
|
|
||||||
specialization_id,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
macro_rules! create_call {
|
|
||||||
($borrows:expr) => {
|
|
||||||
Expr::Call(crate::ir::Call {
|
|
||||||
call_type: if let Some(OWNED) = $borrows.map(|p| p.borrow) {
|
|
||||||
HigherOrderLowLevel {
|
|
||||||
op: *op,
|
|
||||||
closure_env_layout: *closure_env_layout,
|
|
||||||
function_owns_closure_data: true,
|
|
||||||
specialization_id: *specialization_id,
|
|
||||||
arg_layouts,
|
|
||||||
ret_layout: *ret_layout,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
call_type
|
|
||||||
},
|
|
||||||
arguments,
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! decref_if_owned {
|
|
||||||
($borrows:expr, $argument:expr, $stmt:expr) => {
|
|
||||||
if !$borrows {
|
|
||||||
self.arena.alloc(Stmt::Refcounting(
|
|
||||||
ModifyRc::DecRef($argument),
|
|
||||||
self.arena.alloc($stmt),
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
$stmt
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const FUNCTION: bool = BORROWED;
|
|
||||||
const CLOSURE_DATA: bool = BORROWED;
|
|
||||||
|
|
||||||
let function_layout = ProcLayout {
|
|
||||||
arguments: arg_layouts,
|
|
||||||
result: *ret_layout,
|
|
||||||
};
|
|
||||||
|
|
||||||
match op {
|
|
||||||
roc_module::low_level::LowLevel::ListMap
|
|
||||||
| roc_module::low_level::LowLevel::ListKeepIf
|
|
||||||
| roc_module::low_level::LowLevel::ListKeepOks
|
|
||||||
| roc_module::low_level::LowLevel::ListKeepErrs => {
|
|
||||||
match self.param_map.get_symbol(arguments[1], function_layout) {
|
|
||||||
Some(function_ps) => {
|
|
||||||
let borrows = [function_ps[0].borrow, FUNCTION, CLOSURE_DATA];
|
|
||||||
|
|
||||||
let b = self.add_dec_after_lowlevel(
|
|
||||||
arguments,
|
|
||||||
&borrows,
|
|
||||||
b,
|
|
||||||
b_live_vars,
|
|
||||||
);
|
|
||||||
|
|
||||||
// if the list is owned, then all elements have been consumed, but not the list itself
|
|
||||||
let b = decref_if_owned!(function_ps[0].borrow, arguments[0], b);
|
|
||||||
|
|
||||||
let v = create_call!(function_ps.get(1));
|
|
||||||
|
|
||||||
&*self.arena.alloc(Stmt::Let(z, v, l, b))
|
|
||||||
}
|
|
||||||
None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
roc_module::low_level::LowLevel::ListMapWithIndex => {
|
|
||||||
match self.param_map.get_symbol(arguments[1], function_layout) {
|
|
||||||
Some(function_ps) => {
|
|
||||||
let borrows = [function_ps[1].borrow, FUNCTION, CLOSURE_DATA];
|
|
||||||
|
|
||||||
let b = self.add_dec_after_lowlevel(
|
|
||||||
arguments,
|
|
||||||
&borrows,
|
|
||||||
b,
|
|
||||||
b_live_vars,
|
|
||||||
);
|
|
||||||
|
|
||||||
let b = decref_if_owned!(function_ps[1].borrow, arguments[0], b);
|
|
||||||
|
|
||||||
let v = create_call!(function_ps.get(2));
|
|
||||||
|
|
||||||
&*self.arena.alloc(Stmt::Let(z, v, l, b))
|
|
||||||
}
|
|
||||||
None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
roc_module::low_level::LowLevel::ListMap2 => {
|
|
||||||
match self.param_map.get_symbol(arguments[2], function_layout) {
|
|
||||||
Some(function_ps) => {
|
|
||||||
let borrows = [
|
|
||||||
function_ps[0].borrow,
|
|
||||||
function_ps[1].borrow,
|
|
||||||
FUNCTION,
|
|
||||||
CLOSURE_DATA,
|
|
||||||
];
|
|
||||||
|
|
||||||
let b = self.add_dec_after_lowlevel(
|
|
||||||
arguments,
|
|
||||||
&borrows,
|
|
||||||
b,
|
|
||||||
b_live_vars,
|
|
||||||
);
|
|
||||||
|
|
||||||
let b = decref_if_owned!(function_ps[0].borrow, arguments[0], b);
|
|
||||||
let b = decref_if_owned!(function_ps[1].borrow, arguments[1], b);
|
|
||||||
|
|
||||||
let v = create_call!(function_ps.get(2));
|
|
||||||
|
|
||||||
&*self.arena.alloc(Stmt::Let(z, v, l, b))
|
|
||||||
}
|
|
||||||
None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
roc_module::low_level::LowLevel::ListMap3 => {
|
|
||||||
match self.param_map.get_symbol(arguments[3], function_layout) {
|
|
||||||
Some(function_ps) => {
|
|
||||||
let borrows = [
|
|
||||||
function_ps[0].borrow,
|
|
||||||
function_ps[1].borrow,
|
|
||||||
function_ps[2].borrow,
|
|
||||||
FUNCTION,
|
|
||||||
CLOSURE_DATA,
|
|
||||||
];
|
|
||||||
|
|
||||||
let b = self.add_dec_after_lowlevel(
|
|
||||||
arguments,
|
|
||||||
&borrows,
|
|
||||||
b,
|
|
||||||
b_live_vars,
|
|
||||||
);
|
|
||||||
|
|
||||||
let b = decref_if_owned!(function_ps[0].borrow, arguments[0], b);
|
|
||||||
let b = decref_if_owned!(function_ps[1].borrow, arguments[1], b);
|
|
||||||
let b = decref_if_owned!(function_ps[2].borrow, arguments[2], b);
|
|
||||||
|
|
||||||
let v = create_call!(function_ps.get(3));
|
|
||||||
|
|
||||||
&*self.arena.alloc(Stmt::Let(z, v, l, b))
|
|
||||||
}
|
|
||||||
None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
roc_module::low_level::LowLevel::ListSortWith => {
|
|
||||||
match self.param_map.get_symbol(arguments[1], function_layout) {
|
|
||||||
Some(function_ps) => {
|
|
||||||
let borrows = [OWNED, FUNCTION, CLOSURE_DATA];
|
|
||||||
|
|
||||||
let b = self.add_dec_after_lowlevel(
|
|
||||||
arguments,
|
|
||||||
&borrows,
|
|
||||||
b,
|
|
||||||
b_live_vars,
|
|
||||||
);
|
|
||||||
|
|
||||||
let v = create_call!(function_ps.get(2));
|
|
||||||
|
|
||||||
&*self.arena.alloc(Stmt::Let(z, v, l, b))
|
|
||||||
}
|
|
||||||
None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
roc_module::low_level::LowLevel::ListWalk
|
|
||||||
| roc_module::low_level::LowLevel::ListWalkUntil
|
|
||||||
| roc_module::low_level::LowLevel::ListWalkBackwards
|
|
||||||
| roc_module::low_level::LowLevel::DictWalk => {
|
|
||||||
match self.param_map.get_symbol(arguments[2], function_layout) {
|
|
||||||
Some(function_ps) => {
|
|
||||||
// borrow data structure based on first argument of the folded function
|
|
||||||
// borrow the default based on second argument of the folded function
|
|
||||||
let borrows = [
|
|
||||||
function_ps[1].borrow,
|
|
||||||
function_ps[0].borrow,
|
|
||||||
FUNCTION,
|
|
||||||
CLOSURE_DATA,
|
|
||||||
];
|
|
||||||
|
|
||||||
let b = self.add_dec_after_lowlevel(
|
|
||||||
arguments,
|
|
||||||
&borrows,
|
|
||||||
b,
|
|
||||||
b_live_vars,
|
|
||||||
);
|
|
||||||
|
|
||||||
let b = decref_if_owned!(function_ps[1].borrow, arguments[0], b);
|
|
||||||
|
|
||||||
let v = create_call!(function_ps.get(2));
|
|
||||||
|
|
||||||
&*self.arena.alloc(Stmt::Let(z, v, l, b))
|
|
||||||
}
|
|
||||||
None => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let ps = crate::borrow::lowlevel_borrow_signature(self.arena, *op);
|
|
||||||
let b = self.add_dec_after_lowlevel(arguments, ps, b, b_live_vars);
|
|
||||||
|
|
||||||
let v = Expr::Call(crate::ir::Call {
|
|
||||||
call_type,
|
|
||||||
arguments,
|
|
||||||
});
|
|
||||||
|
|
||||||
&*self.arena.alloc(Stmt::Let(z, v, l, b))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Foreign { .. } => {
|
Foreign { .. } => {
|
||||||
let ps = crate::borrow::foreign_borrow_signature(self.arena, arguments.len());
|
let ps = crate::borrow::foreign_borrow_signature(self.arena, arguments.len());
|
||||||
let b = self.add_dec_after_lowlevel(arguments, ps, b, b_live_vars);
|
let b = self.add_dec_after_lowlevel(arguments, ps, b, b_live_vars);
|
||||||
|
|
|
@ -1050,13 +1050,6 @@ impl<'a> Call<'a> {
|
||||||
.text(format!("lowlevel {:?} ", lowlevel))
|
.text(format!("lowlevel {:?} ", lowlevel))
|
||||||
.append(alloc.intersperse(it, " "))
|
.append(alloc.intersperse(it, " "))
|
||||||
}
|
}
|
||||||
NewHigherOrderLowLevel { op: lowlevel, .. } => {
|
|
||||||
let it = arguments.iter().map(|s| symbol_to_doc(alloc, *s));
|
|
||||||
|
|
||||||
alloc
|
|
||||||
.text(format!("lowlevel {:?} ", lowlevel))
|
|
||||||
.append(alloc.intersperse(it, " "))
|
|
||||||
}
|
|
||||||
Foreign {
|
Foreign {
|
||||||
ref foreign_symbol, ..
|
ref foreign_symbol, ..
|
||||||
} => {
|
} => {
|
||||||
|
@ -1109,18 +1102,6 @@ pub enum CallType<'a> {
|
||||||
update_mode: UpdateModeId,
|
update_mode: UpdateModeId,
|
||||||
},
|
},
|
||||||
HigherOrderLowLevel {
|
HigherOrderLowLevel {
|
||||||
op: LowLevel,
|
|
||||||
/// the layout of the closure argument, if any
|
|
||||||
closure_env_layout: Option<Layout<'a>>,
|
|
||||||
/// specialization id of the function argument
|
|
||||||
specialization_id: CallSpecId,
|
|
||||||
/// does the function need to own the closure data
|
|
||||||
function_owns_closure_data: bool,
|
|
||||||
/// function layout
|
|
||||||
arg_layouts: &'a [Layout<'a>],
|
|
||||||
ret_layout: Layout<'a>,
|
|
||||||
},
|
|
||||||
NewHigherOrderLowLevel {
|
|
||||||
op: crate::low_level::HigherOrder,
|
op: crate::low_level::HigherOrder,
|
||||||
/// the layout of the closure argument, if any
|
/// the layout of the closure argument, if any
|
||||||
closure_env_layout: Option<Layout<'a>>,
|
closure_env_layout: Option<Layout<'a>>,
|
||||||
|
@ -5464,7 +5445,6 @@ fn substitute_in_call<'a>(
|
||||||
CallType::Foreign { .. } => None,
|
CallType::Foreign { .. } => None,
|
||||||
CallType::LowLevel { .. } => None,
|
CallType::LowLevel { .. } => None,
|
||||||
CallType::HigherOrderLowLevel { .. } => None,
|
CallType::HigherOrderLowLevel { .. } => None,
|
||||||
CallType::NewHigherOrderLowLevel { .. } => None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut did_change = false;
|
let mut did_change = false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue