mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
List.keepOks and List.keepErrs
This commit is contained in:
parent
45edb12b22
commit
3fe80b1a1e
12 changed files with 339 additions and 44 deletions
|
@ -1,5 +1,6 @@
|
|||
const std = @import("std");
|
||||
const utils = @import("utils.zig");
|
||||
const RocResult = utils.RocResult;
|
||||
const mem = std.mem;
|
||||
const Allocator = mem.Allocator;
|
||||
|
||||
|
@ -152,7 +153,48 @@ pub fn listKeepIf(list: RocList, transform: Opaque, caller: Caller1, alignment:
|
|||
|
||||
output.length = kept;
|
||||
|
||||
// utils.decref(std.heap.c_allocator, alignment, list.bytes, size * old_element_width);
|
||||
utils.decref(std.heap.c_allocator, alignment, list.bytes, size * element_width);
|
||||
|
||||
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 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 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 {
|
||||
if (list.bytes) |source_ptr| {
|
||||
const size = list.len();
|
||||
var i: usize = 0;
|
||||
var output = RocList.allocate(std.heap.c_allocator, alignment, list.len(), list.len() * after_width);
|
||||
const target_ptr = output.bytes orelse unreachable;
|
||||
|
||||
var temporary = @ptrCast([*]u8, std.heap.c_allocator.alloc(u8, result_width) catch unreachable);
|
||||
|
||||
var kept: usize = 0;
|
||||
while (i < size) : (i += 1) {
|
||||
const element = source_ptr + (i * before_width);
|
||||
caller(transform, element, temporary);
|
||||
|
||||
const result = utils.RocResult{ .bytes = temporary };
|
||||
|
||||
if (is_good_constructor(result)) {
|
||||
@memcpy(target_ptr + (kept * after_width), temporary + @sizeOf(i64), after_width);
|
||||
|
||||
kept += 1;
|
||||
}
|
||||
}
|
||||
|
||||
output.length = kept;
|
||||
|
||||
utils.decref(std.heap.c_allocator, alignment, list.bytes, size * before_width);
|
||||
|
||||
return output;
|
||||
} else {
|
||||
|
|
|
@ -10,6 +10,8 @@ comptime {
|
|||
exportListFn(list.listKeepIf, "keep_if");
|
||||
exportListFn(list.listWalk, "walk");
|
||||
exportListFn(list.listWalkBackwards, "walk_backwards");
|
||||
exportListFn(list.listKeepOks, "keep_oks");
|
||||
exportListFn(list.listKeepErrs, "keep_errs");
|
||||
}
|
||||
|
||||
// Dict Module
|
||||
|
|
|
@ -86,3 +86,22 @@ pub fn allocateWithRefcount(
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub const RocResult = extern struct {
|
||||
bytes: ?[*]u8,
|
||||
|
||||
pub fn isOk(self: RocResult) bool {
|
||||
// assumptions
|
||||
//
|
||||
// - the tag is the first field
|
||||
// - the tag is usize bytes wide
|
||||
// - Ok has tag_id 1, because Err < Ok
|
||||
const usizes: [*]usize = @ptrCast([*]usize, @alignCast(8, self.bytes));
|
||||
|
||||
return usizes[0] == 1;
|
||||
}
|
||||
|
||||
pub fn isErr(self: RocResult) bool {
|
||||
return !self.isOk();
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue