Fix most of deref logic

Still doesn't handle empty lists properly.
This commit is contained in:
tarjei 2021-05-21 21:53:55 +02:00
parent f45d89270b
commit 85e5b0ff82
4 changed files with 28 additions and 40 deletions

View file

@ -466,8 +466,8 @@ fn link_macos(
"-lc++",
// "-lc++abi",
// "-lunwind", // TODO will eventually need this, see https://github.com/rtfeldman/roc/pull/554#discussion_r496370840
"-framework",
"Security", // This "-framework Security" arg is needed for the `rand` crate in examples/cli
//"-framework",
//"Security", // This "-framework Security" arg is needed for the `rand` crate in examples/cli
// Output
"-o",
output_path.to_str().unwrap(), // app

View file

@ -665,26 +665,25 @@ pub fn listAppend(list: RocList, alignment: usize, element: Opaque, element_widt
return output;
}
pub fn listDrop(list: RocList, alignment: usize, element_width: usize, count: usize) callconv(.C) RocList {
pub fn listDrop(list: RocList, alignment: usize, element_width: usize, drop_count: usize, dec: Dec) callconv(.C) RocList {
const size = list.len();
if (size <= count) {
const keep_count = size - drop_count;
if (size <= drop_count) {
return RocList.empty();
}
if (list.bytes) |source_ptr| {
var i: usize = 0;
const output = RocList.allocate(std.heap.c_allocator, alignment, size - count, element_width);
const output = RocList.allocate(std.heap.c_allocator, alignment, keep_count, element_width);
const target_ptr = output.bytes orelse unreachable;
while (i < size - count) : (i += 1) {
@memcpy(target_ptr + (i * element_width), source_ptr + ((i + count) * element_width), element_width);
@memcpy(target_ptr, source_ptr + drop_count * element_width, keep_count * element_width);
var i: usize = 0;
while (i < drop_count) : (i += 1) {
const element = source_ptr + i * element_width;
dec(element);
}
// if (list.isUnique()) {
// std.heap.c_allocator.free(source_ptr);
// } else {
// utils.decref(std.heap.c_allocator, alignment, list.bytes, size * element_width);
// }
utils.decref(std.heap.c_allocator, alignment, list.bytes, size * element_width);
return output;
} else {

View file

@ -3891,15 +3891,18 @@ fn run_low_level<'a, 'ctx, 'env>(
let original_wrapper = list.into_struct_value();
let count = load_symbol(scope, &args[1]);
let inplace = get_inplace_from_layout(layout);
list_drop(
match list_layout {
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
Layout::Builtin(Builtin::List(_, element_layout)) => list_drop(
env,
inplace,
layout_ids,
original_wrapper,
count.into_int_value(),
list_layout,
)
element_layout,
),
_ => unreachable!("Invalid layout {:?} in List.drop", list_layout),
}
}
ListPrepend => {
// List.prepend : List elem, elem -> List elem

View file

@ -325,27 +325,12 @@ pub fn list_append<'a, 'ctx, 'env>(
/// List.drop : List elem, Nat -> List elem
pub fn list_drop<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
_inplace: InPlace,
layout_ids: &mut LayoutIds<'a>,
original_wrapper: StructValue<'ctx>,
count: IntValue<'ctx>,
list_layout: &Layout<'a>,
element_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
let (_, element_layout) = match *list_layout {
Layout::Builtin(Builtin::EmptyList) => (
InPlace::InPlace,
// this pointer will never actually be dereferenced
Layout::Builtin(Builtin::Int64),
),
Layout::Builtin(Builtin::List(memory_mode, elem_layout)) => (
match memory_mode {
MemoryMode::Unique => InPlace::InPlace,
MemoryMode::Refcounted => InPlace::Clone,
},
*elem_layout,
),
_ => unreachable!("Invalid layout {:?} in List.drop", list_layout),
};
let dec_element_fn = build_dec_wrapper(env, layout_ids, &element_layout);
call_bitcode_fn_returns_list(
env,
&[
@ -353,6 +338,7 @@ pub fn list_drop<'a, 'ctx, 'env>(
alignment_intvalue(env, &element_layout),
layout_width(env, &element_layout),
count.into(),
dec_element_fn.as_global_value().as_pointer_value().into(),
],
&bitcode::LIST_DROP,
)