mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
List.walk in zig
This commit is contained in:
parent
7aceb8dc70
commit
56427c5fac
7 changed files with 193 additions and 255 deletions
|
@ -107,6 +107,8 @@ pub const RocList = extern struct {
|
|||
};
|
||||
|
||||
const Caller1 = fn (?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
|
||||
const Caller2 = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
|
||||
|
||||
pub fn listMap(list: RocList, transform: Opaque, caller: Caller1, alignment: usize, old_element_width: usize, new_element_width: usize) callconv(.C) RocList {
|
||||
if (list.bytes) |source_ptr| {
|
||||
const size = list.len();
|
||||
|
@ -157,3 +159,44 @@ pub fn listKeepIf(list: RocList, transform: Opaque, caller: Caller1, alignment:
|
|||
return RocList.empty();
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
if (accum_width == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@memcpy(output orelse unreachable, accum orelse unreachable, accum_width);
|
||||
|
||||
if (list.bytes) |source_ptr| {
|
||||
var i: usize = 0;
|
||||
const size = list.len();
|
||||
while (i < size) : (i += 1) {
|
||||
const element = source_ptr + i * element_width;
|
||||
stepper_caller(stepper, element, output, output);
|
||||
}
|
||||
|
||||
const data_bytes = list.len() * element_width;
|
||||
utils.decref(std.heap.c_allocator, alignment, list.bytes, data_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
if (accum_width == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@memcpy(output orelse unreachable, accum orelse unreachable, accum_width);
|
||||
|
||||
if (list.bytes) |source_ptr| {
|
||||
const size = list.len();
|
||||
var i: usize = size;
|
||||
while (i > 0) {
|
||||
i -= 1;
|
||||
const element = source_ptr + i * element_width;
|
||||
stepper_caller(stepper, element, output, output);
|
||||
}
|
||||
|
||||
const data_bytes = list.len() * element_width;
|
||||
utils.decref(std.heap.c_allocator, alignment, list.bytes, data_bytes);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ const list = @import("list.zig");
|
|||
comptime {
|
||||
exportListFn(list.listMap, "map");
|
||||
exportListFn(list.listKeepIf, "keep_if");
|
||||
exportListFn(list.listWalk, "walk");
|
||||
exportListFn(list.listWalkBackwards, "walk_backwards");
|
||||
}
|
||||
|
||||
// Dict Module
|
||||
|
|
|
@ -22,13 +22,6 @@ pub fn decref(
|
|||
const refcount_isize = @bitCast(isize, refcount);
|
||||
|
||||
switch (alignment) {
|
||||
8 => {
|
||||
if (refcount == REFCOUNT_ONE) {
|
||||
allocator.free((bytes - 8)[0 .. 8 + data_bytes]);
|
||||
} else if (refcount_isize < 0) {
|
||||
(usizes - 1)[0] = refcount + 1;
|
||||
}
|
||||
},
|
||||
16 => {
|
||||
if (refcount == REFCOUNT_ONE) {
|
||||
allocator.free((bytes - 16)[0 .. 16 + data_bytes]);
|
||||
|
@ -36,7 +29,14 @@ pub fn decref(
|
|||
(usizes - 1)[0] = refcount + 1;
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
else => {
|
||||
// NOTE enums can currently have an alignment of < 8
|
||||
if (refcount == REFCOUNT_ONE) {
|
||||
allocator.free((bytes - 8)[0 .. 8 + data_bytes]);
|
||||
} else if (refcount_isize < 0) {
|
||||
(usizes - 1)[0] = refcount + 1;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,23 +48,6 @@ pub fn allocateWithRefcount(
|
|||
comptime const result_in_place = false;
|
||||
|
||||
switch (alignment) {
|
||||
8 => {
|
||||
const length = @sizeOf(usize) + data_bytes;
|
||||
|
||||
var new_bytes: []align(8) u8 = allocator.alignedAlloc(u8, 8, length) catch unreachable;
|
||||
|
||||
var as_usize_array = @ptrCast([*]usize, new_bytes);
|
||||
if (result_in_place) {
|
||||
as_usize_array[0] = @intCast(usize, number_of_slots);
|
||||
} else {
|
||||
as_usize_array[0] = REFCOUNT_ONE;
|
||||
}
|
||||
|
||||
var as_u8_array = @ptrCast([*]u8, new_bytes);
|
||||
const first_slot = as_u8_array + @sizeOf(usize);
|
||||
|
||||
return first_slot;
|
||||
},
|
||||
16 => {
|
||||
const length = 2 * @sizeOf(usize) + data_bytes;
|
||||
|
||||
|
@ -84,6 +67,22 @@ pub fn allocateWithRefcount(
|
|||
|
||||
return first_slot;
|
||||
},
|
||||
else => unreachable,
|
||||
else => {
|
||||
const length = @sizeOf(usize) + data_bytes;
|
||||
|
||||
var new_bytes: []align(8) u8 = allocator.alignedAlloc(u8, 8, length) catch unreachable;
|
||||
|
||||
var as_usize_array = @ptrCast([*]usize, new_bytes);
|
||||
if (result_in_place) {
|
||||
as_usize_array[0] = @intCast(usize, number_of_slots);
|
||||
} else {
|
||||
as_usize_array[0] = REFCOUNT_ONE;
|
||||
}
|
||||
|
||||
var as_u8_array = @ptrCast([*]u8, new_bytes);
|
||||
const first_slot = as_u8_array + @sizeOf(usize);
|
||||
|
||||
return first_slot;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue