From e29a89d33c5ab4e14571ea952147582df4f63034 Mon Sep 17 00:00:00 2001 From: Folkert Date: Sat, 2 Jul 2022 13:55:48 +0200 Subject: [PATCH] remove zig implementation of keepIf/keepErrs/keepOks --- crates/compiler/alias_analysis/src/lib.rs | 180 ----------------- crates/compiler/builtins/bitcode/src/list.zig | 190 ++---------------- crates/compiler/builtins/bitcode/src/main.zig | 3 - crates/compiler/builtins/src/bitcode.rs | 3 - crates/compiler/can/src/builtins.rs | 36 ---- crates/compiler/gen_llvm/src/llvm/build.rs | 116 +---------- .../compiler/gen_llvm/src/llvm/build_list.rs | 132 ------------ crates/compiler/gen_wasm/src/low_level.rs | 8 +- crates/compiler/module/src/low_level.rs | 12 -- crates/compiler/mono/src/borrow.rs | 11 +- crates/compiler/mono/src/inc_dec.rs | 8 +- crates/compiler/mono/src/ir.rs | 28 --- crates/compiler/mono/src/low_level.rs | 15 -- 13 files changed, 21 insertions(+), 721 deletions(-) diff --git a/crates/compiler/alias_analysis/src/lib.rs b/crates/compiler/alias_analysis/src/lib.rs index c46c6d9084..c49b8a3b8a 100644 --- a/crates/compiler/alias_analysis/src/lib.rs +++ b/crates/compiler/alias_analysis/src/lib.rs @@ -594,69 +594,6 @@ fn build_tuple_type( builder.add_tuple_type(&field_types) } -#[repr(u32)] -#[derive(Clone, Copy)] -enum KeepResult { - Errs = ERR_TAG_ID, - Oks = OK_TAG_ID, -} - -impl KeepResult { - fn invert(&self) -> Self { - match self { - KeepResult::Errs => KeepResult::Oks, - KeepResult::Oks => KeepResult::Errs, - } - } -} - -#[derive(Clone, Copy)] -enum ResultRepr<'a> { - /// This is basically a `Result * whatever` or `Result [] whatever` (in keepOks, arguments flipped for keepErrs). - /// Such a `Result` gets a `Bool` layout at currently. We model the `*` or `[]` as a unit - /// (empty tuple) in morphic, otherwise we run into trouble when we need to crate a value of - /// type void - ResultStarStar, - ResultConcrete { - err: Layout<'a>, - ok: Layout<'a>, - }, -} - -impl<'a> ResultRepr<'a> { - fn from_layout(layout: &Layout<'a>) -> Self { - match layout { - Layout::Union(UnionLayout::NonRecursive(tags)) => ResultRepr::ResultConcrete { - err: tags[ERR_TAG_ID as usize][0], - ok: tags[OK_TAG_ID as usize][0], - }, - Layout::Builtin(Builtin::Bool) => ResultRepr::ResultStarStar, - other => unreachable!("unexpected layout: {:?}", other), - } - } - - fn unwrap( - &self, - builder: &mut FuncDefBuilder, - block: BlockId, - err_or_ok: ValueId, - keep_tag_id: u32, - ) -> Result { - match self { - ResultRepr::ResultConcrete { .. } => { - let unwrapped = builder.add_unwrap_union(block, err_or_ok, keep_tag_id)?; - - builder.add_get_tuple_field(block, unwrapped, 0) - } - ResultRepr::ResultStarStar => { - // Void/EmptyTagUnion is represented as a unit value in morphic - // using `union {}` runs into trouble where we have to crate a value of that type - builder.add_make_tuple(block, &[]) - } - } - } -} - fn add_loop( builder: &mut FuncDefBuilder, block: BlockId, @@ -1026,120 +963,6 @@ fn call_spec( add_loop(builder, block, state_type, init_state, loop_body) } - ListKeepIf { xs } => { - let list = env.symbols[xs]; - - let loop_body = |builder: &mut FuncDefBuilder, block, state| { - let bag = builder.add_get_tuple_field(block, state, LIST_BAG_INDEX)?; - let cell = builder.add_get_tuple_field(block, state, LIST_CELL_INDEX)?; - - let element = builder.add_bag_get(block, bag)?; - - let _ = call_function!(builder, block, [element]); - - // NOTE: we assume the element is not kept - builder.add_update(block, update_mode_var, cell)?; - - let removed = builder.add_bag_remove(block, bag)?; - - // decrement the removed element - let removed_element = builder.add_get_tuple_field(block, removed, 1)?; - builder.add_recursive_touch(block, removed_element)?; - - let new_bag = builder.add_get_tuple_field(block, removed, 0)?; - - with_new_heap_cell(builder, block, new_bag) - }; - - let state_layout = Layout::Builtin(Builtin::List(&argument_layouts[0])); - let state_type = - layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?; - let init_state = list; - - add_loop(builder, block, state_type, init_state, loop_body) - } - ListKeepOks { xs } | ListKeepErrs { xs } => { - let list = env.symbols[xs]; - - let keep_result = match op { - ListKeepOks { .. } => KeepResult::Oks, - ListKeepErrs { .. } => KeepResult::Errs, - _ => unreachable!(), - }; - - let result_repr = ResultRepr::from_layout(return_layout); - - let output_element_layout = match (keep_result, result_repr) { - (KeepResult::Errs, ResultRepr::ResultConcrete { err, .. }) => err, - (KeepResult::Oks, ResultRepr::ResultConcrete { ok, .. }) => ok, - (_, ResultRepr::ResultStarStar) => { - // we represent this case as Unit, while Void is maybe more natural - // but using Void we'd need to crate values of type Void, which is not - // possible - Layout::UNIT - } - }; - - let loop_body = |builder: &mut FuncDefBuilder, block, state| { - let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?; - - let element = builder.add_bag_get(block, bag)?; - - let err_or_ok = call_function!(builder, block, [element]); - - let kept_branch = builder.add_block(); - let not_kept_branch = builder.add_block(); - - let element_kept = { - let block = kept_branch; - - // a Result can be represented as a Int1 - let new_element = result_repr.unwrap( - builder, - block, - err_or_ok, - keep_result as u32, - )?; - - list_append(builder, block, update_mode_var, state, new_element)? - }; - - let element_not_kept = { - let block = not_kept_branch; - - // a Result can be represented as a Int1 - let dropped_element = result_repr.unwrap( - builder, - block, - err_or_ok, - keep_result.invert() as u32, - )?; - - // decrement the element we will not keep - builder.add_recursive_touch(block, dropped_element)?; - - state - }; - - builder.add_choice( - block, - &[ - BlockExpr(not_kept_branch, element_not_kept), - BlockExpr(kept_branch, element_kept), - ], - ) - }; - - let output_element_type = - layout_spec(builder, &output_element_layout, &WhenRecursive::Unreachable)?; - let init_state = new_list(builder, block, output_element_type)?; - - let state_layout = Layout::Builtin(Builtin::List(&output_element_layout)); - let state_type = - layout_spec(builder, &state_layout, &WhenRecursive::Unreachable)?; - - add_loop(builder, block, state_type, init_state, loop_body) - } ListAny { xs } => { let list = env.symbols[xs]; @@ -1831,9 +1654,6 @@ fn static_list_type(builder: &mut TC) -> Result { builder.add_tuple_type(&[cell, bag]) } -const OK_TAG_ID: u32 = 1; -const ERR_TAG_ID: u32 = 0; - const LIST_CELL_INDEX: u32 = 0; const LIST_BAG_INDEX: u32 = 1; diff --git a/crates/compiler/builtins/bitcode/src/list.zig b/crates/compiler/builtins/bitcode/src/list.zig index 88d32f3424..c721fbb2fb 100644 --- a/crates/compiler/builtins/bitcode/src/list.zig +++ b/crates/compiler/builtins/bitcode/src/list.zig @@ -422,179 +422,6 @@ pub fn listMap4( } } -pub fn listKeepIf( - list: RocList, - caller: Caller1, - data: Opaque, - inc_n_data: IncN, - data_is_owned: bool, - alignment: u32, - element_width: usize, - inc: Inc, - dec: Dec, -) callconv(.C) RocList { - if (list.bytes) |source_ptr| { - const size = list.len(); - var i: usize = 0; - var output = RocList.allocate(alignment, list.len(), list.len() * element_width); - const target_ptr = output.bytes orelse unreachable; - - if (data_is_owned) { - inc_n_data(data, size); - } - - var kept: usize = 0; - while (i < size) : (i += 1) { - var keep = false; - const element = source_ptr + (i * element_width); - inc(element); - caller(data, element, @ptrCast(?[*]u8, &keep)); - - if (keep) { - @memcpy(target_ptr + (kept * element_width), element, element_width); - - kept += 1; - } else { - dec(element); - } - } - - if (kept == 0) { - // if the output is empty, deallocate the space we made for the result - utils.decref(output.bytes, size * element_width, alignment); - return RocList.empty(); - } else { - output.length = kept; - - return output; - } - } else { - return RocList.empty(); - } -} - -pub fn listKeepOks( - list: RocList, - caller: Caller1, - data: Opaque, - inc_n_data: IncN, - data_is_owned: bool, - alignment: u32, - before_width: usize, - result_width: usize, - after_width: usize, - has_tag_id: HasTagId, - dec_result: Dec, -) callconv(.C) RocList { - const good_constructor: u16 = 1; - - return listKeepResult( - list, - good_constructor, - caller, - data, - inc_n_data, - data_is_owned, - alignment, - before_width, - result_width, - after_width, - has_tag_id, - dec_result, - ); -} - -pub fn listKeepErrs( - list: RocList, - caller: Caller1, - data: Opaque, - inc_n_data: IncN, - data_is_owned: bool, - alignment: u32, - before_width: usize, - result_width: usize, - after_width: usize, - has_tag_id: HasTagId, - dec_result: Dec, -) callconv(.C) RocList { - const good_constructor: u16 = 0; - - return listKeepResult( - list, - good_constructor, - caller, - data, - inc_n_data, - data_is_owned, - alignment, - before_width, - result_width, - after_width, - has_tag_id, - dec_result, - ); -} - -pub fn listKeepResult( - list: RocList, - good_constructor: u16, - caller: Caller1, - data: Opaque, - inc_n_data: IncN, - data_is_owned: bool, - alignment: u32, - before_width: usize, - result_width: usize, - after_width: usize, - has_tag_id: HasTagId, - dec_result: Dec, -) RocList { - if (list.bytes) |source_ptr| { - const size = list.len(); - var i: usize = 0; - var output = RocList.allocate(alignment, list.len(), list.len() * after_width); - const target_ptr = output.bytes orelse unreachable; - - // TODO handle alloc failing! - var temporary = utils.alloc(result_width, alignment) orelse unreachable; - - if (data_is_owned) { - inc_n_data(data, size); - } - - var kept: usize = 0; - while (i < size) : (i += 1) { - const before_element = source_ptr + (i * before_width); - caller(data, before_element, temporary); - - // a record { matched: bool, data: ?[*]u8 } - // for now, that data pointer is just the input `temporary` pointer - // this will change in the future to only return a pointer to the - // payload of the tag - const answer = has_tag_id(good_constructor, temporary); - if (answer.matched) { - const contents = (answer.data orelse unreachable); - @memcpy(target_ptr + (kept * after_width), contents, after_width); - kept += 1; - } else { - dec_result(temporary); - } - } - - utils.dealloc(temporary, alignment); - - if (kept == 0) { - utils.decref(output.bytes, size * after_width, alignment); - return RocList.empty(); - } else { - output.length = kept; - return output; - } - } else { - return RocList.empty(); - } -} - pub fn listWalk( list: RocList, caller: Caller2, @@ -891,6 +718,7 @@ pub fn listSublist( if (len == 0) { return RocList.empty(); } + if (list.bytes) |source_ptr| { const size = list.len(); @@ -916,14 +744,20 @@ pub fn listSublist( dec(element); } - const output = RocList.allocate(alignment, keep_len, element_width); - const target_ptr = output.bytes orelse unreachable; + if (start == 0 and list.isUnique()) { + var output = list; + output.length = keep_len; + return output; + } else { + const output = RocList.allocate(alignment, keep_len, element_width); + const target_ptr = output.bytes orelse unreachable; - @memcpy(target_ptr, source_ptr + start * element_width, keep_len * element_width); + @memcpy(target_ptr, source_ptr + start * element_width, keep_len * element_width); - utils.decref(list.bytes, size * element_width, alignment); + utils.decref(list.bytes, size * element_width, alignment); - return output; + return output; + } } return RocList.empty(); diff --git a/crates/compiler/builtins/bitcode/src/main.zig b/crates/compiler/builtins/bitcode/src/main.zig index 2fd6cd2d11..6ab5877656 100644 --- a/crates/compiler/builtins/bitcode/src/main.zig +++ b/crates/compiler/builtins/bitcode/src/main.zig @@ -41,12 +41,9 @@ comptime { exportListFn(list.listMap3, "map3"); exportListFn(list.listMap4, "map4"); exportListFn(list.listMapWithIndex, "map_with_index"); - exportListFn(list.listKeepIf, "keep_if"); exportListFn(list.listWalk, "walk"); exportListFn(list.listWalkUntil, "walkUntil"); exportListFn(list.listWalkBackwards, "walk_backwards"); - exportListFn(list.listKeepOks, "keep_oks"); - exportListFn(list.listKeepErrs, "keep_errs"); exportListFn(list.listContains, "contains"); exportListFn(list.listRepeat, "repeat"); exportListFn(list.listAppend, "append"); diff --git a/crates/compiler/builtins/src/bitcode.rs b/crates/compiler/builtins/src/bitcode.rs index 37c0f53899..c81a2747cb 100644 --- a/crates/compiler/builtins/src/bitcode.rs +++ b/crates/compiler/builtins/src/bitcode.rs @@ -353,9 +353,6 @@ pub const LIST_MAP2: &str = "roc_builtins.list.map2"; pub const LIST_MAP3: &str = "roc_builtins.list.map3"; pub const LIST_MAP4: &str = "roc_builtins.list.map4"; pub const LIST_MAP_WITH_INDEX: &str = "roc_builtins.list.map_with_index"; -pub const LIST_KEEP_IF: &str = "roc_builtins.list.keep_if"; -pub const LIST_KEEP_OKS: &str = "roc_builtins.list.keep_oks"; -pub const LIST_KEEP_ERRS: &str = "roc_builtins.list.keep_errs"; pub const LIST_WALK: &str = "roc_builtins.list.walk"; pub const LIST_WALK_UNTIL: &str = "roc_builtins.list.walkUntil"; pub const LIST_WALK_BACKWARDS: &str = "roc_builtins.list.walk_backwards"; diff --git a/crates/compiler/can/src/builtins.rs b/crates/compiler/can/src/builtins.rs index c57f480b1b..bdbc0652e8 100644 --- a/crates/compiler/can/src/builtins.rs +++ b/crates/compiler/can/src/builtins.rs @@ -119,9 +119,6 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option LIST_DROP_AT => list_drop_at, LIST_SWAP => list_swap, LIST_MAP_WITH_INDEX => list_map_with_index, - LIST_KEEP_IF => list_keep_if, - LIST_KEEP_OKS => list_keep_oks, - LIST_KEEP_ERRS=> list_keep_errs, LIST_WALK => list_walk, LIST_WALK_BACKWARDS => list_walk_backwards, LIST_WALK_UNTIL => list_walk_until, @@ -2478,39 +2475,6 @@ fn list_walk_until(symbol: Symbol, var_store: &mut VarStore) -> Def { lowlevel_3(symbol, LowLevel::ListWalkUntil, var_store) } -/// List.keepIf : List elem, (elem -> Bool) -> List elem -fn list_keep_if(symbol: Symbol, var_store: &mut VarStore) -> Def { - let list_var = var_store.fresh(); - let func_var = var_store.fresh(); - - let body = RunLowLevel { - op: LowLevel::ListKeepIf, - args: vec![ - (list_var, Var(Symbol::ARG_1)), - (func_var, Var(Symbol::ARG_2)), - ], - ret_var: list_var, - }; - - defn( - symbol, - vec![(list_var, Symbol::ARG_1), (func_var, Symbol::ARG_2)], - var_store, - body, - list_var, - ) -} - -/// List.keepOks : List before, (before -> Result after *) -> List after -fn list_keep_oks(symbol: Symbol, var_store: &mut VarStore) -> Def { - lowlevel_2(symbol, LowLevel::ListKeepOks, var_store) -} - -/// List.keepErrs: List before, (before -> Result * after) -> List after -fn list_keep_errs(symbol: Symbol, var_store: &mut VarStore) -> Def { - lowlevel_2(symbol, LowLevel::ListKeepErrs, var_store) -} - /// List.map : List before, (before -> after) -> List after fn list_map(symbol: Symbol, var_store: &mut VarStore) -> Def { lowlevel_2(symbol, LowLevel::ListMap, var_store) diff --git a/crates/compiler/gen_llvm/src/llvm/build.rs b/crates/compiler/gen_llvm/src/llvm/build.rs index 897df6065a..c30197ac50 100644 --- a/crates/compiler/gen_llvm/src/llvm/build.rs +++ b/crates/compiler/gen_llvm/src/llvm/build.rs @@ -9,10 +9,9 @@ use crate::llvm::build_dict::{ use crate::llvm::build_hash::generic_hash; use crate::llvm::build_list::{ self, allocate_list, empty_polymorphic_list, list_all, list_any, list_append, list_concat, - list_drop_at, list_find_unsafe, list_get_unsafe, list_keep_errs, list_keep_if, list_keep_oks, - list_len, list_map, list_map2, list_map3, list_map4, list_map_with_index, list_prepend, - list_replace_unsafe, list_sort_with, list_sublist, list_swap, list_symbol_to_c_abi, - list_to_c_abi, list_with_capacity, + list_drop_at, list_find_unsafe, list_get_unsafe, list_len, list_map, list_map2, list_map3, + list_map4, list_map_with_index, list_prepend, list_replace_unsafe, list_sort_with, + list_sublist, list_swap, list_symbol_to_c_abi, list_to_c_abi, list_with_capacity, }; use crate::llvm::build_str::{ str_from_float, str_from_int, str_from_utf8, str_from_utf8_range, str_split, @@ -5120,110 +5119,6 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>( _ => unreachable!("invalid list layout"), } } - ListKeepIf { xs } => { - // List.keepIf : List elem, (elem -> Bool) -> List elem - let (list, list_layout) = load_symbol_and_layout(scope, xs); - - let (function, closure, closure_layout) = function_details!(); - - match list_layout { - 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, - result_layout, - ); - - list_keep_if(env, layout_ids, roc_function_call, list, element_layout) - } - _ => unreachable!("invalid list layout"), - } - } - ListKeepOks { xs } => { - // List.keepOks : List before, (before -> Result after *) -> List after - let (list, list_layout) = load_symbol_and_layout(scope, xs); - - let (function, closure, closure_layout) = function_details!(); - - match (list_layout, return_layout) { - ( - 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, - result_layout, - ); - - 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 { xs } => { - // List.keepErrs : List before, (before -> Result * after) -> List after - let (list, list_layout) = load_symbol_and_layout(scope, xs); - - let (function, closure, closure_layout) = function_details!(); - - match (list_layout, return_layout) { - ( - 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, - result_layout, - ); - - 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 { xs, state } => { list_walk!(crate::llvm::build_list::ListWalk::Walk, xs, state) } @@ -6161,9 +6056,8 @@ fn run_low_level<'a, 'ctx, 'env>( set } - ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListKeepIf | ListWalk - | ListWalkUntil | ListWalkBackwards | ListKeepOks | ListKeepErrs | ListSortWith - | ListFindUnsafe | DictWalk => { + ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListWalk | ListWalkUntil + | ListWalkBackwards | ListSortWith | ListFindUnsafe | DictWalk => { unreachable!("these are higher order, and are handled elsewhere") } diff --git a/crates/compiler/gen_llvm/src/llvm/build_list.rs b/crates/compiler/gen_llvm/src/llvm/build_list.rs index 2ba7664f77..cf07101d32 100644 --- a/crates/compiler/gen_llvm/src/llvm/build_list.rs +++ b/crates/compiler/gen_llvm/src/llvm/build_list.rs @@ -473,42 +473,6 @@ pub fn list_walk_generic<'a, 'ctx, 'env>( } } -/// List.keepIf : List elem, (elem -> Bool) -> List elem -pub fn list_keep_if<'a, 'ctx, 'env>( - env: &Env<'a, 'ctx, 'env>, - layout_ids: &mut LayoutIds<'a>, - roc_function_call: RocFunctionCall<'ctx>, - list: BasicValueEnum<'ctx>, - element_layout: &Layout<'a>, -) -> BasicValueEnum<'ctx> { - let inc_element_fn = build_inc_wrapper(env, layout_ids, element_layout); - let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout); - - call_list_bitcode_fn( - env, - &[ - list_to_c_abi(env, list).into(), - roc_function_call.caller.into(), - pass_as_opaque(env, roc_function_call.data), - roc_function_call.inc_n_data.into(), - roc_function_call.data_is_owned.into(), - env.alignment_intvalue(element_layout), - layout_width(env, element_layout), - inc_element_fn.as_global_value().as_pointer_value().into(), - dec_element_fn.as_global_value().as_pointer_value().into(), - ], - bitcode::LIST_KEEP_IF, - ) -} - -fn empty_list<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> BasicValueEnum<'ctx> { - let struct_type = super::convert::zig_list_type(env); - - // The pointer should be null (aka zero) and the length should be zero, - // so the whole struct should be a const_zero - BasicValueEnum::StructValue(struct_type.const_zero()) -} - fn has_tag_id_helper<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, has_tag_id: FunctionValue<'ctx>, @@ -533,102 +497,6 @@ fn has_tag_id_helper<'a, 'ctx, 'env>( ) } -/// List.keepOks : List before, (before -> Result after *) -> List after -pub fn list_keep_oks<'a, 'ctx, 'env>( - env: &Env<'a, 'ctx, 'env>, - layout_ids: &mut LayoutIds<'a>, - roc_function_call: RocFunctionCall<'ctx>, - // Layout of the `Result after *` - result_layout: &Layout<'a>, - list: BasicValueEnum<'ctx>, - before_layout: &Layout<'a>, - after_layout: &Layout<'a>, -) -> BasicValueEnum<'ctx> { - let dec_result_fn = build_dec_wrapper(env, layout_ids, result_layout); - - let function = env - .builder - .get_insert_block() - .unwrap() - .get_parent() - .unwrap(); - - let has_tag_id = match result_layout { - Layout::Union(union_layout) => build_has_tag_id(env, function, *union_layout), - Layout::Builtin(Builtin::Bool) => { - // a `Result whatever []`, so there is nothing to keep - return empty_list(env); - } - _ => unreachable!(), - }; - - call_list_bitcode_fn( - env, - &[ - list_to_c_abi(env, list).into(), - roc_function_call.caller.into(), - pass_as_opaque(env, roc_function_call.data), - roc_function_call.inc_n_data.into(), - roc_function_call.data_is_owned.into(), - env.alignment_intvalue(before_layout), - layout_width(env, before_layout), - layout_width(env, result_layout), - layout_width(env, after_layout), - has_tag_id_helper(env, has_tag_id).into(), - dec_result_fn.as_global_value().as_pointer_value().into(), - ], - bitcode::LIST_KEEP_OKS, - ) -} - -/// List.keepErrs : List before, (before -> Result * after) -> List after -pub fn list_keep_errs<'a, 'ctx, 'env>( - env: &Env<'a, 'ctx, 'env>, - layout_ids: &mut LayoutIds<'a>, - roc_function_call: RocFunctionCall<'ctx>, - // Layout of the `Result * err` - result_layout: &Layout<'a>, - list: BasicValueEnum<'ctx>, - before_layout: &Layout<'a>, - after_layout: &Layout<'a>, -) -> BasicValueEnum<'ctx> { - let dec_result_fn = build_dec_wrapper(env, layout_ids, result_layout); - - let function = env - .builder - .get_insert_block() - .unwrap() - .get_parent() - .unwrap(); - - let has_tag_id = match result_layout { - Layout::Union(union_layout) => build_has_tag_id(env, function, *union_layout), - Layout::Builtin(Builtin::Bool) => { - // a `Result whatever []`, so there is nothing to keep - return empty_list(env); - } - _ => unreachable!(), - }; - - call_list_bitcode_fn( - env, - &[ - list_to_c_abi(env, list).into(), - roc_function_call.caller.into(), - pass_as_opaque(env, roc_function_call.data), - roc_function_call.inc_n_data.into(), - roc_function_call.data_is_owned.into(), - env.alignment_intvalue(before_layout), - layout_width(env, before_layout), - layout_width(env, result_layout), - layout_width(env, after_layout), - has_tag_id_helper(env, has_tag_id).into(), - dec_result_fn.as_global_value().as_pointer_value().into(), - ], - bitcode::LIST_KEEP_ERRS, - ) -} - /// List.sortWith : List a, (a, a -> Ordering) -> List a pub fn list_sort_with<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index 122b6393bd..4a8067010a 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -288,9 +288,8 @@ impl<'a> LowLevelCall<'a> { ListIsUnique => self.load_args_and_call_zig(backend, bitcode::LIST_IS_UNIQUE), - ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListKeepIf | ListWalk - | ListWalkUntil | ListWalkBackwards | ListKeepOks | ListKeepErrs | ListSortWith - | ListFindUnsafe | DictWalk => { + ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListWalk + | ListWalkUntil | ListWalkBackwards | ListSortWith | ListFindUnsafe | DictWalk => { internal_error!("HigherOrder lowlevels should not be handled here") } @@ -2019,12 +2018,9 @@ pub fn call_higher_order_lowlevel<'a>( ), ListMapWithIndex { .. } - | ListKeepIf { .. } | ListWalk { .. } | ListWalkUntil { .. } | ListWalkBackwards { .. } - | ListKeepOks { .. } - | ListKeepErrs { .. } | ListSortWith { .. } | ListAny { .. } | ListAll { .. } diff --git a/crates/compiler/module/src/low_level.rs b/crates/compiler/module/src/low_level.rs index 5c3b0f8fa2..2562fa8198 100644 --- a/crates/compiler/module/src/low_level.rs +++ b/crates/compiler/module/src/low_level.rs @@ -35,12 +35,9 @@ pub enum LowLevel { ListMap3, ListMap4, ListMapWithIndex, - ListKeepIf, ListWalk, ListWalkUntil, ListWalkBackwards, - ListKeepOks, - ListKeepErrs, ListSortWith, ListSublist, ListDropAt, @@ -131,12 +128,9 @@ macro_rules! higher_order { | ListMap3 | ListMap4 | ListMapWithIndex - | ListKeepIf | ListWalk | ListWalkUntil | ListWalkBackwards - | ListKeepOks - | ListKeepErrs | ListSortWith | ListFindUnsafe | DictWalk @@ -161,12 +155,9 @@ impl LowLevel { ListMap3 => 3, ListMap4 => 4, ListMapWithIndex => 1, - ListKeepIf => 1, ListWalk => 2, ListWalkUntil => 2, ListWalkBackwards => 2, - ListKeepOks => 1, - ListKeepErrs => 1, ListSortWith => 1, ListFindUnsafe => 1, DictWalk => 2, @@ -232,12 +223,9 @@ impl LowLevelWrapperType { Symbol::LIST_MAP3 => WrapperIsRequired, Symbol::LIST_MAP4 => WrapperIsRequired, Symbol::LIST_MAP_WITH_INDEX => WrapperIsRequired, - Symbol::LIST_KEEP_IF => WrapperIsRequired, Symbol::LIST_WALK => WrapperIsRequired, Symbol::LIST_WALK_UNTIL => WrapperIsRequired, Symbol::LIST_WALK_BACKWARDS => WrapperIsRequired, - Symbol::LIST_KEEP_OKS => WrapperIsRequired, - Symbol::LIST_KEEP_ERRS => WrapperIsRequired, Symbol::LIST_SORT_WITH => WrapperIsRequired, Symbol::LIST_SUBLIST => WrapperIsRequired, Symbol::LIST_DROP_AT => CanBeReplacedBy(ListDropAt), diff --git a/crates/compiler/mono/src/borrow.rs b/crates/compiler/mono/src/borrow.rs index 76f690c34c..0b69c40368 100644 --- a/crates/compiler/mono/src/borrow.rs +++ b/crates/compiler/mono/src/borrow.rs @@ -552,13 +552,7 @@ impl<'a> BorrowInfState<'a> { }; match op { - ListMap { xs } - | ListKeepIf { xs } - | ListKeepOks { xs } - | ListKeepErrs { xs } - | ListAny { xs } - | ListAll { xs } - | ListFindUnsafe { xs } => { + ListMap { xs } | ListAny { xs } | ListAll { xs } | ListFindUnsafe { xs } => { // own the list if the function wants to own the element if !function_ps[0].borrow { self.own_var(*xs); @@ -913,9 +907,6 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] { ListMap2 => arena.alloc_slice_copy(&[owned, owned, function, closure_data]), ListMap3 => arena.alloc_slice_copy(&[owned, owned, owned, function, closure_data]), ListMap4 => arena.alloc_slice_copy(&[owned, owned, owned, owned, function, closure_data]), - ListKeepIf | ListKeepOks | ListKeepErrs => { - arena.alloc_slice_copy(&[owned, function, closure_data]) - } ListWalk | ListWalkUntil | ListWalkBackwards => { arena.alloc_slice_copy(&[owned, owned, function, closure_data]) } diff --git a/crates/compiler/mono/src/inc_dec.rs b/crates/compiler/mono/src/inc_dec.rs index 278d8a9a76..38fbbaa479 100644 --- a/crates/compiler/mono/src/inc_dec.rs +++ b/crates/compiler/mono/src/inc_dec.rs @@ -693,13 +693,7 @@ impl<'a> Context<'a> { let after_arguments = &arguments[op.function_index()..]; match *op { - ListMap { xs } - | ListKeepIf { xs } - | ListKeepOks { xs } - | ListKeepErrs { xs } - | ListAny { xs } - | ListAll { xs } - | ListFindUnsafe { xs } => { + ListMap { xs } | ListAny { xs } | ListAll { xs } | ListFindUnsafe { xs } => { let ownerships = [(xs, function_ps[0])]; let b = self.add_dec_after_lowlevel(after_arguments, &borrows, b, b_live_vars); diff --git a/crates/compiler/mono/src/ir.rs b/crates/compiler/mono/src/ir.rs index 1a8603f800..2a85e01328 100644 --- a/crates/compiler/mono/src/ir.rs +++ b/crates/compiler/mono/src/ir.rs @@ -5043,34 +5043,6 @@ pub fn with_hole<'a>( let xs = arg_symbols[0]; match_on_closure_argument!(ListMapWithIndex, [xs]) } - ListKeepIf => { - debug_assert_eq!(arg_symbols.len(), 2); - let xs = arg_symbols[0]; - let stmt = match_on_closure_argument!(ListKeepIf, [xs]); - - // See the comment in `walk!`. We use List.keepIf to implement - // other builtins, where the closure can be an actual closure rather - // than a symbol. - assign_to_symbol( - env, - procs, - layout_cache, - args[1].0, // the closure - Loc::at_zero(args[1].1.clone()), - arg_symbols[1], - stmt, - ) - } - ListKeepOks => { - debug_assert_eq!(arg_symbols.len(), 2); - let xs = arg_symbols[0]; - match_on_closure_argument!(ListKeepOks, [xs]) - } - ListKeepErrs => { - debug_assert_eq!(arg_symbols.len(), 2); - let xs = arg_symbols[0]; - match_on_closure_argument!(ListKeepErrs, [xs]) - } ListSortWith => { debug_assert_eq!(arg_symbols.len(), 2); let xs = arg_symbols[0]; diff --git a/crates/compiler/mono/src/low_level.rs b/crates/compiler/mono/src/low_level.rs index 6c150a61d8..aaddcc25f3 100644 --- a/crates/compiler/mono/src/low_level.rs +++ b/crates/compiler/mono/src/low_level.rs @@ -23,9 +23,6 @@ pub enum HigherOrder { ListMapWithIndex { xs: Symbol, }, - ListKeepIf { - xs: Symbol, - }, ListWalk { xs: Symbol, state: Symbol, @@ -38,12 +35,6 @@ pub enum HigherOrder { xs: Symbol, state: Symbol, }, - ListKeepOks { - xs: Symbol, - }, - ListKeepErrs { - xs: Symbol, - }, ListSortWith { xs: Symbol, }, @@ -70,12 +61,9 @@ impl HigherOrder { HigherOrder::ListMap3 { .. } => 3, HigherOrder::ListMap4 { .. } => 4, HigherOrder::ListMapWithIndex { .. } => 2, - HigherOrder::ListKeepIf { .. } => 1, HigherOrder::ListWalk { .. } => 2, HigherOrder::ListWalkUntil { .. } => 2, HigherOrder::ListWalkBackwards { .. } => 2, - HigherOrder::ListKeepOks { .. } => 1, - HigherOrder::ListKeepErrs { .. } => 1, HigherOrder::ListSortWith { .. } => 2, HigherOrder::ListFindUnsafe { .. } => 1, HigherOrder::DictWalk { .. } => 2, @@ -93,9 +81,6 @@ impl HigherOrder { ListMap { .. } | ListMapWithIndex { .. } | ListSortWith { .. } - | ListKeepIf { .. } - | ListKeepOks { .. } - | ListKeepErrs { .. } | ListAny { .. } | ListAll { .. } | ListFindUnsafe { .. } => 2,