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++",
// "-lc++abi", // "-lc++abi",
// "-lunwind", // TODO will eventually need this, see https://github.com/rtfeldman/roc/pull/554#discussion_r496370840 // "-lunwind", // TODO will eventually need this, see https://github.com/rtfeldman/roc/pull/554#discussion_r496370840
"-framework", //"-framework",
"Security", // This "-framework Security" arg is needed for the `rand` crate in examples/cli //"Security", // This "-framework Security" arg is needed for the `rand` crate in examples/cli
// Output // Output
"-o", "-o",
output_path.to_str().unwrap(), // app 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; 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(); const size = list.len();
if (size <= count) { const keep_count = size - drop_count;
if (size <= drop_count) {
return RocList.empty(); return RocList.empty();
} }
if (list.bytes) |source_ptr| { if (list.bytes) |source_ptr| {
var i: usize = 0; const output = RocList.allocate(std.heap.c_allocator, alignment, keep_count, element_width);
const output = RocList.allocate(std.heap.c_allocator, alignment, size - count, element_width);
const target_ptr = output.bytes orelse unreachable; const target_ptr = output.bytes orelse unreachable;
while (i < size - count) : (i += 1) { @memcpy(target_ptr, source_ptr + drop_count * element_width, keep_count * element_width);
@memcpy(target_ptr + (i * element_width), source_ptr + ((i + count) * element_width), element_width);
var i: usize = 0;
while (i < drop_count) : (i += 1) {
const element = source_ptr + i * element_width;
dec(element);
} }
// if (list.isUnique()) { utils.decref(std.heap.c_allocator, alignment, list.bytes, size * element_width);
// std.heap.c_allocator.free(source_ptr);
// } else {
// utils.decref(std.heap.c_allocator, alignment, list.bytes, size * element_width);
// }
return output; return output;
} else { } else {

View file

@ -3891,15 +3891,18 @@ fn run_low_level<'a, 'ctx, 'env>(
let original_wrapper = list.into_struct_value(); let original_wrapper = list.into_struct_value();
let count = load_symbol(scope, &args[1]); 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, env,
inplace, layout_ids,
original_wrapper, original_wrapper,
count.into_int_value(), count.into_int_value(),
list_layout, element_layout,
) ),
_ => unreachable!("Invalid layout {:?} in List.drop", list_layout),
}
} }
ListPrepend => { ListPrepend => {
// List.prepend : List elem, elem -> List elem // 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 /// List.drop : List elem, Nat -> List elem
pub fn list_drop<'a, 'ctx, 'env>( pub fn list_drop<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
_inplace: InPlace, layout_ids: &mut LayoutIds<'a>,
original_wrapper: StructValue<'ctx>, original_wrapper: StructValue<'ctx>,
count: IntValue<'ctx>, count: IntValue<'ctx>,
list_layout: &Layout<'a>, element_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let (_, element_layout) = match *list_layout { let dec_element_fn = build_dec_wrapper(env, layout_ids, &element_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),
};
call_bitcode_fn_returns_list( call_bitcode_fn_returns_list(
env, env,
&[ &[
@ -353,6 +338,7 @@ pub fn list_drop<'a, 'ctx, 'env>(
alignment_intvalue(env, &element_layout), alignment_intvalue(env, &element_layout),
layout_width(env, &element_layout), layout_width(env, &element_layout),
count.into(), count.into(),
dec_element_fn.as_global_value().as_pointer_value().into(),
], ],
&bitcode::LIST_DROP, &bitcode::LIST_DROP,
) )