Merge branch 'trunk' into zig-list-set

This commit is contained in:
Folkert de Vries 2021-05-25 09:05:18 +02:00 committed by GitHub
commit 5724f82667
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
58 changed files with 4928 additions and 2930 deletions

View file

@ -41,19 +41,19 @@ pub const RocList = extern struct {
}
pub fn allocate(
alignment: usize,
alignment: u32,
length: usize,
element_size: usize,
) RocList {
const data_bytes = length * element_size;
return RocList{
.bytes = utils.allocateWithRefcount(alignment, data_bytes),
.bytes = utils.allocateWithRefcount(data_bytes, alignment),
.length = length,
};
}
pub fn makeUnique(self: RocList, alignment: usize, element_width: usize) RocList {
pub fn makeUnique(self: RocList, alignment: u32, element_width: usize) RocList {
if (self.isEmpty()) {
return self;
}
@ -73,14 +73,14 @@ pub const RocList = extern struct {
// NOTE we fuse an increment of all keys/values with a decrement of the input dict
const data_bytes = self.len() * element_width;
utils.decref(alignment, self.bytes, data_bytes);
utils.decref(self.bytes, data_bytes, alignment);
return new_list;
}
pub fn reallocate(
self: RocList,
alignment: usize,
alignment: u32,
new_length: usize,
element_width: usize,
) RocList {
@ -98,7 +98,7 @@ pub const RocList = extern struct {
/// reallocate by explicitly making a new allocation and copying elements over
fn reallocateFresh(
self: RocList,
alignment: usize,
alignment: u32,
new_length: usize,
element_width: usize,
) RocList {
@ -106,7 +106,7 @@ pub const RocList = extern struct {
const delta_length = new_length - old_length;
const data_bytes = new_length * element_width;
const first_slot = utils.allocateWithRefcount(alignment, data_bytes);
const first_slot = utils.allocateWithRefcount(data_bytes, alignment);
// transfer the memory
@ -122,17 +122,18 @@ pub const RocList = extern struct {
.length = new_length,
};
utils.decref(alignment, self.bytes, old_length * element_width);
utils.decref(self.bytes, old_length * element_width, alignment);
return result;
}
};
const Caller0 = fn (?[*]u8, ?[*]u8) callconv(.C) void;
const Caller1 = fn (?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
const Caller2 = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
const Caller3 = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
pub fn listReverse(list: RocList, alignment: usize, element_width: usize) callconv(.C) RocList {
pub fn listReverse(list: RocList, alignment: u32, element_width: usize) callconv(.C) RocList {
if (list.bytes) |source_ptr| {
const size = list.len();
@ -161,7 +162,7 @@ pub fn listReverse(list: RocList, alignment: usize, element_width: usize) callco
@memcpy(target_ptr + (i * element_width), source_ptr + (last_position * element_width), element_width);
}
utils.decref(alignment, list.bytes, size * element_width);
utils.decref(list.bytes, size * element_width, alignment);
return output;
}
@ -170,18 +171,29 @@ pub fn listReverse(list: RocList, alignment: usize, element_width: usize) callco
}
}
pub fn listMap(list: RocList, transform: Opaque, caller: Caller1, alignment: usize, old_element_width: usize, new_element_width: usize) callconv(.C) RocList {
pub fn listMap(
list: RocList,
caller: Caller1,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
alignment: u32,
old_element_width: usize,
new_element_width: usize,
) callconv(.C) RocList {
if (list.bytes) |source_ptr| {
const size = list.len();
var i: usize = 0;
const output = RocList.allocate(alignment, size, new_element_width);
const target_ptr = output.bytes orelse unreachable;
while (i < size) : (i += 1) {
caller(transform, source_ptr + (i * old_element_width), target_ptr + (i * new_element_width));
if (data_is_owned) {
inc_n_data(data, size);
}
utils.decref(alignment, list.bytes, size * old_element_width);
while (i < size) : (i += 1) {
caller(data, source_ptr + (i * old_element_width), target_ptr + (i * new_element_width));
}
return output;
} else {
@ -189,18 +201,29 @@ pub fn listMap(list: RocList, transform: Opaque, caller: Caller1, alignment: usi
}
}
pub fn listMapWithIndex(list: RocList, transform: Opaque, caller: Caller2, alignment: usize, old_element_width: usize, new_element_width: usize) callconv(.C) RocList {
pub fn listMapWithIndex(
list: RocList,
caller: Caller2,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
alignment: u32,
old_element_width: usize,
new_element_width: usize,
) callconv(.C) RocList {
if (list.bytes) |source_ptr| {
const size = list.len();
var i: usize = 0;
const output = RocList.allocate(alignment, size, new_element_width);
const target_ptr = output.bytes orelse unreachable;
while (i < size) : (i += 1) {
caller(transform, @ptrCast(?[*]u8, &i), source_ptr + (i * old_element_width), target_ptr + (i * new_element_width));
if (data_is_owned) {
inc_n_data(data, size);
}
utils.decref(alignment, list.bytes, size * old_element_width);
while (i < size) : (i += 1) {
caller(data, @ptrCast(?[*]u8, &i), source_ptr + (i * old_element_width), target_ptr + (i * new_element_width));
}
return output;
} else {
@ -208,9 +231,41 @@ pub fn listMapWithIndex(list: RocList, transform: Opaque, caller: Caller2, align
}
}
pub fn listMap2(list1: RocList, list2: RocList, transform: Opaque, caller: Caller2, alignment: usize, a_width: usize, b_width: usize, c_width: usize, dec_a: Dec, dec_b: Dec) callconv(.C) RocList {
fn decrementTail(list: RocList, start_index: usize, element_width: usize, dec: Dec) void {
if (list.bytes) |source| {
var i = start_index;
while (i < list.len()) : (i += 1) {
const element = source + i * element_width;
dec(element);
}
}
}
pub fn listMap2(
list1: RocList,
list2: RocList,
caller: Caller2,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
alignment: u32,
a_width: usize,
b_width: usize,
c_width: usize,
dec_a: Dec,
dec_b: Dec,
) callconv(.C) RocList {
const output_length = std.math.min(list1.len(), list2.len());
// if the lists don't have equal length, we must consume the remaining elements
// In this case we consume by (recursively) decrementing the elements
decrementTail(list1, output_length, a_width, dec_a);
decrementTail(list2, output_length, b_width, dec_b);
if (data_is_owned) {
inc_n_data(data, output_length);
}
if (list1.bytes) |source_a| {
if (list2.bytes) |source_b| {
const output = RocList.allocate(alignment, output_length, c_width);
@ -221,57 +276,46 @@ pub fn listMap2(list1: RocList, list2: RocList, transform: Opaque, caller: Calle
const element_a = source_a + i * a_width;
const element_b = source_b + i * b_width;
const target = target_ptr + i * c_width;
caller(transform, element_a, element_b, target);
caller(data, element_a, element_b, target);
}
// if the lists don't have equal length, we must consume the remaining elements
// In this case we consume by (recursively) decrementing the elements
if (list1.len() > output_length) {
while (i < list1.len()) : (i += 1) {
const element_a = source_a + i * a_width;
dec_a(element_a);
}
} else if (list2.len() > output_length) {
while (i < list2.len()) : (i += 1) {
const element_b = source_b + i * b_width;
dec_b(element_b);
}
}
utils.decref(alignment, list1.bytes, list1.len() * a_width);
utils.decref(alignment, list2.bytes, list2.len() * b_width);
return output;
} else {
// consume list1 elements (we know there is at least one because the list1.bytes pointer is non-null
var i: usize = 0;
while (i < list1.len()) : (i += 1) {
const element_a = source_a + i * a_width;
dec_a(element_a);
}
utils.decref(alignment, list1.bytes, list1.len() * a_width);
return RocList.empty();
}
} else {
// consume list2 elements (if any)
if (list2.bytes) |source_b| {
var i: usize = 0;
while (i < list2.len()) : (i += 1) {
const element_b = source_b + i * b_width;
dec_b(element_b);
}
utils.decref(alignment, list2.bytes, list2.len() * b_width);
}
return RocList.empty();
}
}
pub fn listMap3(list1: RocList, list2: RocList, list3: RocList, transform: Opaque, caller: Caller3, alignment: usize, a_width: usize, b_width: usize, c_width: usize, d_width: usize, dec_a: Dec, dec_b: Dec, dec_c: Dec) callconv(.C) RocList {
pub fn listMap3(
list1: RocList,
list2: RocList,
list3: RocList,
caller: Caller3,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
alignment: u32,
a_width: usize,
b_width: usize,
c_width: usize,
d_width: usize,
dec_a: Dec,
dec_b: Dec,
dec_c: Dec,
) callconv(.C) RocList {
const smaller_length = std.math.min(list1.len(), list2.len());
const output_length = std.math.min(smaller_length, list3.len());
decrementTail(list1, output_length, a_width, dec_a);
decrementTail(list2, output_length, b_width, dec_b);
decrementTail(list3, output_length, c_width, dec_c);
if (data_is_owned) {
inc_n_data(data, output_length);
}
if (list1.bytes) |source_a| {
if (list2.bytes) |source_b| {
if (list3.bytes) |source_c| {
@ -285,125 +329,48 @@ pub fn listMap3(list1: RocList, list2: RocList, list3: RocList, transform: Opaqu
const element_c = source_c + i * c_width;
const target = target_ptr + i * d_width;
caller(transform, element_a, element_b, element_c, target);
caller(data, element_a, element_b, element_c, target);
}
// if the lists don't have equal length, we must consume the remaining elements
// In this case we consume by (recursively) decrementing the elements
if (list1.len() > output_length) {
i = output_length;
while (i < list1.len()) : (i += 1) {
const element_a = source_a + i * a_width;
dec_a(element_a);
}
}
if (list2.len() > output_length) {
i = output_length;
while (i < list2.len()) : (i += 1) {
const element_b = source_b + i * b_width;
dec_b(element_b);
}
}
if (list3.len() > output_length) {
i = output_length;
while (i < list3.len()) : (i += 1) {
const element_c = source_c + i * c_width;
dec_c(element_c);
}
}
utils.decref(alignment, list1.bytes, list1.len() * a_width);
utils.decref(alignment, list2.bytes, list2.len() * b_width);
utils.decref(alignment, list3.bytes, list3.len() * c_width);
return output;
} else {
// consume list1 elements (we know there is at least one because the list1.bytes pointer is non-null
var i: usize = 0;
while (i < list1.len()) : (i += 1) {
const element_a = source_a + i * a_width;
dec_a(element_a);
}
utils.decref(alignment, list1.bytes, list1.len() * a_width);
// consume list2 elements (we know there is at least one because the list1.bytes pointer is non-null
i = 0;
while (i < list2.len()) : (i += 1) {
const element_b = source_b + i * b_width;
dec_b(element_b);
}
utils.decref(alignment, list2.bytes, list2.len() * b_width);
return RocList.empty();
}
} else {
// consume list1 elements (we know there is at least one because the list1.bytes pointer is non-null
var i: usize = 0;
while (i < list1.len()) : (i += 1) {
const element_a = source_a + i * a_width;
dec_a(element_a);
}
utils.decref(alignment, list1.bytes, list1.len() * a_width);
// consume list3 elements (if any)
if (list3.bytes) |source_c| {
i = 0;
while (i < list2.len()) : (i += 1) {
const element_c = source_c + i * c_width;
dec_c(element_c);
}
utils.decref(alignment, list3.bytes, list3.len() * c_width);
}
return RocList.empty();
}
} else {
// consume list2 elements (if any)
if (list2.bytes) |source_b| {
var i: usize = 0;
while (i < list2.len()) : (i += 1) {
const element_b = source_b + i * b_width;
dec_b(element_b);
}
utils.decref(alignment, list2.bytes, list2.len() * b_width);
}
// consume list3 elements (if any)
if (list3.bytes) |source_c| {
var i: usize = 0;
while (i < list2.len()) : (i += 1) {
const element_c = source_c + i * c_width;
dec_c(element_c);
}
utils.decref(alignment, list3.bytes, list3.len() * c_width);
}
return RocList.empty();
}
}
pub fn listKeepIf(list: RocList, transform: Opaque, caller: Caller1, alignment: usize, element_width: usize, inc: Inc, dec: Dec) callconv(.C) RocList {
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(transform, element, @ptrCast(?[*]u8, &keep));
caller(data, element, @ptrCast(?[*]u8, &keep));
if (keep) {
@memcpy(target_ptr + (kept * element_width), element, element_width);
@ -414,12 +381,9 @@ pub fn listKeepIf(list: RocList, transform: Opaque, caller: Caller1, alignment:
}
}
// consume the input list
utils.decref(alignment, list.bytes, size * element_width);
if (kept == 0) {
// if the output is empty, deallocate the space we made for the result
utils.decref(alignment, output.bytes, size * element_width);
utils.decref(output.bytes, size * element_width, alignment);
return RocList.empty();
} else {
output.length = kept;
@ -431,28 +395,89 @@ pub fn listKeepIf(list: RocList, transform: Opaque, caller: Caller1, alignment:
}
}
pub fn listKeepOks(list: RocList, transform: Opaque, caller: Caller1, alignment: usize, before_width: usize, result_width: usize, after_width: usize, inc_closure: Inc, dec_result: Dec) callconv(.C) RocList {
return listKeepResult(list, RocResult.isOk, transform, caller, alignment, before_width, result_width, after_width, inc_closure, dec_result);
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,
dec_result: Dec,
) callconv(.C) RocList {
return listKeepResult(
list,
RocResult.isOk,
caller,
data,
inc_n_data,
data_is_owned,
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, inc_closure: Inc, dec_result: Dec) callconv(.C) RocList {
return listKeepResult(list, RocResult.isErr, transform, caller, alignment, before_width, result_width, after_width, inc_closure, 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,
dec_result: Dec,
) callconv(.C) RocList {
return listKeepResult(
list,
RocResult.isErr,
caller,
data,
inc_n_data,
data_is_owned,
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, inc_closure: Inc, dec_result: Dec) RocList {
pub fn listKeepResult(
list: RocList,
is_good_constructor: fn (RocResult) bool,
caller: Caller1,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
alignment: u32,
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;
var output = RocList.allocate(alignment, list.len(), list.len() * after_width);
const target_ptr = output.bytes orelse unreachable;
var temporary = @ptrCast([*]u8, utils.alloc(alignment, result_width));
var temporary = @ptrCast([*]u8, utils.alloc(result_width, alignment));
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);
inc_closure(transform);
caller(transform, before_element, temporary);
caller(data, before_element, temporary);
const result = utils.RocResult{ .bytes = temporary };
@ -465,11 +490,10 @@ pub fn listKeepResult(list: RocList, is_good_constructor: fn (RocResult) bool, t
}
}
utils.decref(alignment, list.bytes, size * before_width);
utils.dealloc(alignment, temporary);
utils.dealloc(temporary, alignment);
if (kept == 0) {
utils.decref(alignment, output.bytes, size * after_width);
utils.decref(output.bytes, size * after_width, alignment);
return RocList.empty();
} else {
output.length = kept;
@ -480,7 +504,18 @@ pub fn listKeepResult(list: RocList, is_good_constructor: fn (RocResult) bool, t
}
}
pub fn listWalk(list: RocList, stepper: Opaque, stepper_caller: Caller2, accum: Opaque, alignment: usize, element_width: usize, accum_width: usize, output: Opaque) callconv(.C) void {
pub fn listWalk(
list: RocList,
caller: Caller2,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
accum: Opaque,
alignment: u32,
element_width: usize,
accum_width: usize,
output: Opaque,
) callconv(.C) void {
if (accum_width == 0) {
return;
}
@ -490,7 +525,11 @@ pub fn listWalk(list: RocList, stepper: Opaque, stepper_caller: Caller2, accum:
return;
}
const bytes_ptr: [*]u8 = utils.alloc(alignment, accum_width);
if (data_is_owned) {
inc_n_data(data, list.len());
}
const bytes_ptr: [*]u8 = utils.alloc(accum_width, alignment);
var b1 = output orelse unreachable;
var b2 = bytes_ptr;
@ -501,7 +540,7 @@ pub fn listWalk(list: RocList, stepper: Opaque, stepper_caller: Caller2, accum:
const size = list.len();
while (i < size) : (i += 1) {
const element = source_ptr + i * element_width;
stepper_caller(stepper, element, b2, b1);
caller(data, element, b2, b1);
const temp = b1;
b2 = b1;
@ -510,13 +549,21 @@ pub fn listWalk(list: RocList, stepper: Opaque, stepper_caller: Caller2, accum:
}
@memcpy(output orelse unreachable, b2, accum_width);
utils.dealloc(alignment, bytes_ptr);
const data_bytes = list.len() * element_width;
utils.decref(alignment, list.bytes, data_bytes);
utils.dealloc(bytes_ptr, alignment);
}
pub fn listWalkBackwards(list: RocList, stepper: Opaque, stepper_caller: Caller2, accum: Opaque, alignment: usize, element_width: usize, accum_width: usize, output: Opaque) callconv(.C) void {
pub fn listWalkBackwards(
list: RocList,
caller: Caller2,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
accum: Opaque,
alignment: u32,
element_width: usize,
accum_width: usize,
output: Opaque,
) callconv(.C) void {
if (accum_width == 0) {
return;
}
@ -526,7 +573,11 @@ pub fn listWalkBackwards(list: RocList, stepper: Opaque, stepper_caller: Caller2
return;
}
const bytes_ptr: [*]u8 = utils.alloc(alignment, accum_width);
if (data_is_owned) {
inc_n_data(data, list.len());
}
const bytes_ptr: [*]u8 = utils.alloc(accum_width, alignment);
var b1 = output orelse unreachable;
var b2 = bytes_ptr;
@ -538,7 +589,7 @@ pub fn listWalkBackwards(list: RocList, stepper: Opaque, stepper_caller: Caller2
while (i > 0) {
i -= 1;
const element = source_ptr + i * element_width;
stepper_caller(stepper, element, b2, b1);
caller(data, element, b2, b1);
const temp = b1;
b2 = b1;
@ -547,13 +598,22 @@ pub fn listWalkBackwards(list: RocList, stepper: Opaque, stepper_caller: Caller2
}
@memcpy(output orelse unreachable, b2, accum_width);
utils.dealloc(alignment, bytes_ptr);
const data_bytes = list.len() * element_width;
utils.decref(alignment, list.bytes, data_bytes);
utils.dealloc(bytes_ptr, alignment);
}
pub fn listWalkUntil(list: RocList, stepper: Opaque, stepper_caller: Caller2, accum: Opaque, alignment: usize, element_width: usize, accum_width: usize, dec: Dec, output: Opaque) callconv(.C) void {
pub fn listWalkUntil(
list: RocList,
caller: Caller2,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
accum: Opaque,
alignment: u32,
element_width: usize,
accum_width: usize,
dec: Dec,
output: Opaque,
) callconv(.C) void {
// [ Continue a, Stop a ]
const CONTINUE: usize = 0;
@ -566,7 +626,7 @@ pub fn listWalkUntil(list: RocList, stepper: Opaque, stepper_caller: Caller2, ac
return;
}
const bytes_ptr: [*]u8 = utils.alloc(alignment, TAG_WIDTH + accum_width);
const bytes_ptr: [*]u8 = utils.alloc(TAG_WIDTH + accum_width, alignment);
@memcpy(bytes_ptr + TAG_WIDTH, accum orelse unreachable, accum_width);
@ -575,7 +635,12 @@ pub fn listWalkUntil(list: RocList, stepper: Opaque, stepper_caller: Caller2, ac
const size = list.len();
while (i < size) : (i += 1) {
const element = source_ptr + i * element_width;
stepper_caller(stepper, element, bytes_ptr + TAG_WIDTH, bytes_ptr);
if (data_is_owned) {
inc_n_data(data, 1);
}
caller(data, element, bytes_ptr + TAG_WIDTH, bytes_ptr);
const usizes: [*]usize = @ptrCast([*]usize, @alignCast(8, bytes_ptr));
if (usizes[0] != 0) {
@ -590,10 +655,7 @@ pub fn listWalkUntil(list: RocList, stepper: Opaque, stepper_caller: Caller2, ac
}
@memcpy(output orelse unreachable, bytes_ptr + TAG_WIDTH, accum_width);
utils.dealloc(alignment, bytes_ptr);
const data_bytes = list.len() * element_width;
utils.decref(alignment, list.bytes, data_bytes);
utils.dealloc(bytes_ptr, alignment);
}
// List.contains : List k, k -> Bool
@ -612,7 +674,7 @@ pub fn listContains(list: RocList, key: Opaque, key_width: usize, is_eq: EqFn) c
return false;
}
pub fn listRepeat(count: usize, alignment: usize, element: Opaque, element_width: usize, inc_n_element: IncN) callconv(.C) RocList {
pub fn listRepeat(count: usize, alignment: u32, element: Opaque, element_width: usize, inc_n_element: IncN) callconv(.C) RocList {
if (count == 0) {
return RocList.empty();
}
@ -635,7 +697,7 @@ pub fn listRepeat(count: usize, alignment: usize, element: Opaque, element_width
}
}
pub fn listSingle(alignment: usize, element: Opaque, element_width: usize) callconv(.C) RocList {
pub fn listSingle(alignment: u32, element: Opaque, element_width: usize) callconv(.C) RocList {
var output = RocList.allocate(alignment, 1, element_width);
if (output.bytes) |target| {
@ -647,7 +709,7 @@ pub fn listSingle(alignment: usize, element: Opaque, element_width: usize) callc
return output;
}
pub fn listAppend(list: RocList, alignment: usize, element: Opaque, element_width: usize) callconv(.C) RocList {
pub fn listAppend(list: RocList, alignment: u32, element: Opaque, element_width: usize) callconv(.C) RocList {
const old_length = list.len();
var output = list.reallocate(alignment, old_length + 1, element_width);
@ -662,7 +724,7 @@ pub fn listAppend(list: RocList, alignment: usize, element: Opaque, element_widt
pub fn listDrop(
list: RocList,
alignment: usize,
alignment: u32,
element_width: usize,
drop_count: usize,
dec: Dec,
@ -688,7 +750,7 @@ pub fn listDrop(
@memcpy(target_ptr, source_ptr + drop_count * element_width, keep_count * element_width);
utils.decref(alignment, list.bytes, size * element_width);
utils.decref(list.bytes, size * element_width, alignment);
return output;
} else {
@ -815,13 +877,25 @@ fn quicksort(source_ptr: [*]u8, transform: Opaque, wrapper: CompareFn, element_w
}
}
pub fn listSortWith(input: RocList, transform: Opaque, wrapper: CompareFn, alignment: usize, element_width: usize) callconv(.C) RocList {
pub fn listSortWith(
input: RocList,
caller: CompareFn,
data: Opaque,
inc_n_data: IncN,
data_is_owned: bool,
alignment: u32,
element_width: usize,
) callconv(.C) RocList {
var list = input.makeUnique(alignment, element_width);
if (data_is_owned) {
inc_n_data(data, list.len());
}
if (list.bytes) |source_ptr| {
const low = 0;
const high: isize = @intCast(isize, list.len()) - 1;
quicksort(source_ptr, transform, wrapper, element_width, low, high);
quicksort(source_ptr, data, caller, element_width, low, high);
}
return list;
@ -873,7 +947,7 @@ fn swapElements(source_ptr: [*]u8, element_width: usize, index_1: usize, index_2
return swap(element_width, element_at_i, element_at_j);
}
pub fn listJoin(list_of_lists: RocList, alignment: usize, element_width: usize) callconv(.C) RocList {
pub fn listJoin(list_of_lists: RocList, alignment: u32, element_width: usize) callconv(.C) RocList {
var total_length: usize = 0;
const slice_of_lists = @ptrCast([*]RocList, @alignCast(@alignOf(RocList), list_of_lists.bytes));
@ -901,7 +975,7 @@ pub fn listJoin(list_of_lists: RocList, alignment: usize, element_width: usize)
return output;
}
pub fn listConcat(list_a: RocList, list_b: RocList, alignment: usize, element_width: usize) callconv(.C) RocList {
pub fn listConcat(list_a: RocList, list_b: RocList, alignment: u32, element_width: usize) callconv(.C) RocList {
if (list_a.isEmpty()) {
return list_b;
} else if (list_b.isEmpty()) {