Add plumbing for List.swap

This commit is contained in:
tarjei 2021-05-29 21:30:16 +02:00
parent 98011f48a8
commit 107822a5cc
9 changed files with 87 additions and 2 deletions

View file

@ -30,6 +30,7 @@ comptime {
exportListFn(list.listConcat, "concat");
exportListFn(list.listDrop, "drop");
exportListFn(list.listSet, "set");
exportListFn(list.listSwap, "swap");
}
// Dict Module

View file

@ -63,6 +63,7 @@ pub const LIST_CONTAINS: &str = "roc_builtins.list.contains";
pub const LIST_REPEAT: &str = "roc_builtins.list.repeat";
pub const LIST_APPEND: &str = "roc_builtins.list.append";
pub const LIST_DROP: &str = "roc_builtins.list.drop";
pub const LIST_SWAP: &str = "roc_builtins.list.swap";
pub const LIST_SINGLE: &str = "roc_builtins.list.single";
pub const LIST_JOIN: &str = "roc_builtins.list.join";
pub const LIST_RANGE: &str = "roc_builtins.list.range";

View file

@ -856,6 +856,13 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
Box::new(list_type(flex(TVAR1))),
);
// swap : List elem, Nat, Nat -> List elem
add_top_level_function_type!(
Symbol::LIST_SWAP,
vec![list_type(flex(TVAR1)), nat_type(), nat_type()],
Box::new(list_type(flex(TVAR1))),
);
// prepend : List elem, elem -> List elem
add_top_level_function_type!(
Symbol::LIST_PREPEND,

View file

@ -85,6 +85,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
LIST_MAP2 => list_map2,
LIST_MAP3 => list_map3,
LIST_DROP => list_drop,
LIST_SWAP => list_swap,
LIST_MAP_WITH_INDEX => list_map_with_index,
LIST_KEEP_IF => list_keep_if,
LIST_KEEP_OKS => list_keep_oks,
@ -1882,6 +1883,36 @@ fn list_set(symbol: Symbol, var_store: &mut VarStore) -> Def {
list_ret_var,
)
}
/// List.swap : List elem, Nat, Nat -> List elem
fn list_drop(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh();
let index1_var = var_store.fresh();
let index2_var = var_store.fresh();
let body = RunLowLevel {
op: LowLevel::ListDrop,
args: vec![
(list_var, Var(Symbol::ARG_1)),
(index1_var, Var(Symbol::ARG_2)),
(index2_var, Var(Symbol::ARG_3)),
],
ret_var: list_var,
};
defn(
symbol,
vec![
(list_var, Symbol::ARG_1),
(index1_var, Symbol::ARG_2),
(index2_var, Symbol::ARG_3),
],
var_store,
body,
list_var,
)
}
/// List.drop : List elem, Nat -> List elem
fn list_drop(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh();

View file

@ -8,7 +8,7 @@ use crate::llvm::build_list::{
allocate_list, empty_list, empty_polymorphic_list, list_append, list_concat, list_contains,
list_drop, list_get_unsafe, list_join, list_keep_errs, list_keep_if, list_keep_oks, list_len,
list_map, list_map2, list_map3, list_map_with_index, list_prepend, list_range, list_repeat,
list_reverse, list_set, list_single, list_sort_with,
list_reverse, list_set, list_single, list_sort_with, list_swap,
};
use crate::llvm::build_str::{
empty_str, str_concat, str_count_graphemes, str_ends_with, str_from_float, str_from_int,
@ -4164,6 +4164,27 @@ fn run_low_level<'a, 'ctx, 'env>(
list_append(env, layout.in_place(), original_wrapper, elem, elem_layout)
}
ListSwap => {
// List.swap : List elem, Nat, Nat -> List elem
debug_assert_eq!(args.len(), 3);
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
let original_wrapper = list.into_struct_value();
let count = load_symbol(scope, &args[1]);
match list_layout {
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
Layout::Builtin(Builtin::List(element_layout)) => list_swap(
env,
layout_ids,
original_wrapper,
count.into_int_value(),
element_layout,
),
_ => unreachable!("Invalid layout {:?} in List.swap", list_layout),
}
}
ListDrop => {
// List.drop : List elem, Nat -> List elem
debug_assert_eq!(args.len(), 2);

View file

@ -304,7 +304,28 @@ pub fn list_append<'a, 'ctx, 'env>(
)
}
/// List.drop : List elem, Nat -> List elem
/// List.swap : List elem, Nat, Nat -> List elem
pub fn list_swap<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_ids: &mut LayoutIds<'a>,
original_wrapper: StructValue<'ctx>,
count: IntValue<'ctx>,
element_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
let dec_element_fn = build_dec_wrapper(env, layout_ids, &element_layout);
call_bitcode_fn_returns_list(
env,
&[
pass_list_as_i128(env, original_wrapper.into()),
env.alignment_intvalue(&element_layout),
layout_width(env, &element_layout),
count.into(),
],
&bitcode::LIST_SWAP,
)
}
/// List.drop : List elem, Nat, Nat -> List elem
pub fn list_drop<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_ids: &mut LayoutIds<'a>,

View file

@ -135,6 +135,7 @@ impl LowLevel {
| ListPrepend
| ListJoin
| ListRange
| ListSwap
| DictSize
| DictEmpty
| DictInsert

View file

@ -939,6 +939,7 @@ define_builtins! {
30 LIST_RANGE: "range"
31 LIST_SORT_WITH: "sortWith"
32 LIST_DROP: "drop"
33 LIST_SWAP: "swap"
}
5 RESULT: "Result" => {
0 RESULT_RESULT: "Result" imported // the Result.Result type alias

View file

@ -748,6 +748,7 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
// List.append should own its first argument
ListAppend => arena.alloc_slice_copy(&[owned, owned]),
ListDrop => arena.alloc_slice_copy(&[owned, irrelevant]),
ListSwap => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]),
Eq | NotEq => arena.alloc_slice_copy(&[borrowed, borrowed]),