mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
correct RC for List.repeat, List.keepIf, List.keepOks
This commit is contained in:
parent
d29b8764f0
commit
9faf84be16
3 changed files with 84 additions and 43 deletions
|
@ -61,7 +61,7 @@ pub const RocList = extern struct {
|
|||
}
|
||||
|
||||
// unfortunately, we have to clone
|
||||
var new_list = RocList.allocate(allocator, self.length, alignment, element_width);
|
||||
var new_list = RocList.allocate(allocator, alignment, self.length, element_width);
|
||||
|
||||
var old_bytes: [*]u8 = @ptrCast([*]u8, self.bytes);
|
||||
var new_bytes: [*]u8 = @ptrCast([*]u8, new_list.bytes);
|
||||
|
@ -152,7 +152,7 @@ pub fn listMapWithIndex(list: RocList, transform: Opaque, caller: Caller2, align
|
|||
}
|
||||
}
|
||||
|
||||
pub fn listKeepIf(list: RocList, transform: Opaque, caller: Caller1, alignment: usize, element_width: usize) callconv(.C) RocList {
|
||||
pub fn listKeepIf(list: RocList, transform: Opaque, caller: Caller1, alignment: usize, element_width: usize, inc: Inc, dec: Dec) callconv(.C) RocList {
|
||||
if (list.bytes) |source_ptr| {
|
||||
const size = list.len();
|
||||
var i: usize = 0;
|
||||
|
@ -163,6 +163,7 @@ pub fn listKeepIf(list: RocList, transform: Opaque, caller: Caller1, alignment:
|
|||
while (i < size) : (i += 1) {
|
||||
var keep = false;
|
||||
const element = source_ptr + (i * element_width);
|
||||
inc(element);
|
||||
caller(transform, element, @ptrCast(?[*]u8, &keep));
|
||||
|
||||
if (keep) {
|
||||
|
@ -170,29 +171,36 @@ pub fn listKeepIf(list: RocList, transform: Opaque, caller: Caller1, alignment:
|
|||
|
||||
kept += 1;
|
||||
} else {
|
||||
// TODO decrement the value?
|
||||
dec(element);
|
||||
}
|
||||
}
|
||||
|
||||
output.length = kept;
|
||||
|
||||
// consume the input list
|
||||
utils.decref(std.heap.c_allocator, alignment, list.bytes, size * element_width);
|
||||
|
||||
return output;
|
||||
if (kept == 0) {
|
||||
// if the output is empty, deallocate the space we made for the result
|
||||
utils.decref(std.heap.c_allocator, alignment, output.bytes, size * element_width);
|
||||
return RocList.empty();
|
||||
} else {
|
||||
output.length = kept;
|
||||
|
||||
return output;
|
||||
}
|
||||
} else {
|
||||
return RocList.empty();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn listKeepOks(list: RocList, transform: Opaque, caller: Caller1, alignment: usize, before_width: usize, result_width: usize, after_width: usize) callconv(.C) RocList {
|
||||
return listKeepResult(list, RocResult.isOk, transform, caller, alignment, before_width, result_width, after_width);
|
||||
pub fn listKeepOks(list: RocList, transform: Opaque, caller: Caller1, alignment: usize, before_width: usize, result_width: usize, after_width: usize, dec_result: Dec) callconv(.C) RocList {
|
||||
return listKeepResult(list, RocResult.isOk, transform, caller, alignment, before_width, result_width, after_width, dec_result);
|
||||
}
|
||||
|
||||
pub fn listKeepErrs(list: RocList, transform: Opaque, caller: Caller1, alignment: usize, before_width: usize, result_width: usize, after_width: usize) callconv(.C) RocList {
|
||||
return listKeepResult(list, RocResult.isErr, transform, caller, alignment, before_width, result_width, after_width);
|
||||
pub fn listKeepErrs(list: RocList, transform: Opaque, caller: Caller1, alignment: usize, before_width: usize, result_width: usize, after_width: usize, dec_result: Dec) callconv(.C) RocList {
|
||||
return listKeepResult(list, RocResult.isErr, transform, caller, alignment, before_width, result_width, after_width, dec_result);
|
||||
}
|
||||
|
||||
pub fn listKeepResult(list: RocList, is_good_constructor: fn (RocResult) bool, transform: Opaque, caller: Caller1, alignment: usize, before_width: usize, result_width: usize, after_width: usize) RocList {
|
||||
pub fn listKeepResult(list: RocList, is_good_constructor: fn (RocResult) bool, transform: Opaque, caller: Caller1, alignment: usize, before_width: usize, result_width: usize, after_width: usize, dec_result: Dec) RocList {
|
||||
if (list.bytes) |source_ptr| {
|
||||
const size = list.len();
|
||||
var i: usize = 0;
|
||||
|
@ -203,23 +211,30 @@ pub fn listKeepResult(list: RocList, is_good_constructor: fn (RocResult) bool, t
|
|||
|
||||
var kept: usize = 0;
|
||||
while (i < size) : (i += 1) {
|
||||
const element = source_ptr + (i * before_width);
|
||||
caller(transform, element, temporary);
|
||||
const before_element = source_ptr + (i * before_width);
|
||||
caller(transform, before_element, temporary);
|
||||
|
||||
const result = utils.RocResult{ .bytes = temporary };
|
||||
|
||||
const after_element = temporary + @sizeOf(i64);
|
||||
if (is_good_constructor(result)) {
|
||||
@memcpy(target_ptr + (kept * after_width), temporary + @sizeOf(i64), after_width);
|
||||
|
||||
@memcpy(target_ptr + (kept * after_width), after_element, after_width);
|
||||
kept += 1;
|
||||
} else {
|
||||
dec_result(temporary);
|
||||
}
|
||||
}
|
||||
|
||||
output.length = kept;
|
||||
|
||||
utils.decref(std.heap.c_allocator, alignment, list.bytes, size * before_width);
|
||||
std.heap.c_allocator.free(temporary[0..result_width]);
|
||||
|
||||
return output;
|
||||
if (kept == 0) {
|
||||
utils.decref(std.heap.c_allocator, alignment, output.bytes, size * after_width);
|
||||
return RocList.empty();
|
||||
} else {
|
||||
output.length = kept;
|
||||
return output;
|
||||
}
|
||||
} else {
|
||||
return RocList.empty();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue