mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 16:21:11 +00:00
Merge branch 'trunk' into zig-list-set
This commit is contained in:
commit
5724f82667
58 changed files with 4928 additions and 2930 deletions
|
@ -73,7 +73,7 @@ const Alignment = packed enum(u8) {
|
|||
Align8KeyFirst,
|
||||
Align8ValueFirst,
|
||||
|
||||
fn toUsize(self: Alignment) usize {
|
||||
fn toU32(self: Alignment) u32 {
|
||||
switch (self) {
|
||||
.Align16KeyFirst => return 16,
|
||||
.Align16ValueFirst => return 16,
|
||||
|
@ -93,18 +93,18 @@ const Alignment = packed enum(u8) {
|
|||
};
|
||||
|
||||
pub fn decref(
|
||||
alignment: Alignment,
|
||||
bytes_or_null: ?[*]u8,
|
||||
data_bytes: usize,
|
||||
alignment: Alignment,
|
||||
) void {
|
||||
return utils.decref(alignment.toUsize(), bytes_or_null, data_bytes);
|
||||
return utils.decref(bytes_or_null, data_bytes, alignment.toU32());
|
||||
}
|
||||
|
||||
pub fn allocateWithRefcount(
|
||||
alignment: Alignment,
|
||||
data_bytes: usize,
|
||||
alignment: Alignment,
|
||||
) [*]u8 {
|
||||
return utils.allocateWithRefcount(alignment.toUsize(), data_bytes);
|
||||
return utils.allocateWithRefcount(data_bytes, alignment.toU32());
|
||||
}
|
||||
|
||||
pub const RocDict = extern struct {
|
||||
|
@ -132,7 +132,7 @@ pub const RocDict = extern struct {
|
|||
const data_bytes = number_of_slots * slot_size;
|
||||
|
||||
return RocDict{
|
||||
.dict_bytes = allocateWithRefcount(alignment, data_bytes),
|
||||
.dict_bytes = allocateWithRefcount(data_bytes, alignment),
|
||||
.number_of_levels = number_of_levels,
|
||||
.dict_entries_len = number_of_entries,
|
||||
};
|
||||
|
@ -152,7 +152,7 @@ pub const RocDict = extern struct {
|
|||
const delta_capacity = new_capacity - old_capacity;
|
||||
|
||||
const data_bytes = new_capacity * slot_size;
|
||||
const first_slot = allocateWithRefcount(alignment, data_bytes);
|
||||
const first_slot = allocateWithRefcount(data_bytes, alignment);
|
||||
|
||||
// transfer the memory
|
||||
|
||||
|
@ -199,7 +199,7 @@ pub const RocDict = extern struct {
|
|||
};
|
||||
|
||||
// NOTE we fuse an increment of all keys/values with a decrement of the input dict
|
||||
decref(alignment, self.dict_bytes, self.capacity() * slotSize(key_width, value_width));
|
||||
decref(self.dict_bytes, self.capacity() * slotSize(key_width, value_width), alignment);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ pub const RocDict = extern struct {
|
|||
|
||||
// NOTE we fuse an increment of all keys/values with a decrement of the input dict
|
||||
const data_bytes = self.capacity() * slotSize(key_width, value_width);
|
||||
decref(alignment, self.dict_bytes, data_bytes);
|
||||
decref(self.dict_bytes, data_bytes, alignment);
|
||||
|
||||
return new_dict;
|
||||
}
|
||||
|
@ -409,8 +409,11 @@ const HashFn = fn (u64, ?[*]u8) callconv(.C) u64;
|
|||
const EqFn = fn (?[*]u8, ?[*]u8) callconv(.C) bool;
|
||||
|
||||
const Inc = fn (?[*]u8) callconv(.C) void;
|
||||
const IncN = fn (?[*]u8, usize) callconv(.C) void;
|
||||
const Dec = fn (?[*]u8) callconv(.C) void;
|
||||
|
||||
const Caller3 = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
|
||||
|
||||
// Dict.insert : Dict k v, k, v -> Dict k v
|
||||
pub fn dictInsert(input: RocDict, alignment: Alignment, key: Opaque, key_width: usize, value: Opaque, value_width: usize, hash_fn: HashFn, is_eq: EqFn, dec_key: Dec, dec_value: Dec, output: *RocDict) callconv(.C) void {
|
||||
var seed: u64 = INITIAL_SEED;
|
||||
|
@ -494,7 +497,7 @@ pub fn dictRemove(input: RocDict, alignment: Alignment, key: Opaque, key_width:
|
|||
// if the dict is now completely empty, free its allocation
|
||||
if (dict.dict_entries_len == 0) {
|
||||
const data_bytes = dict.capacity() * slotSize(key_width, value_width);
|
||||
decref(alignment, dict.dict_bytes, data_bytes);
|
||||
decref(dict.dict_bytes, data_bytes, alignment);
|
||||
output.* = RocDict.empty();
|
||||
return;
|
||||
}
|
||||
|
@ -567,7 +570,7 @@ pub fn dictKeys(dict: RocDict, alignment: Alignment, key_width: usize, value_wid
|
|||
}
|
||||
|
||||
const data_bytes = length * key_width;
|
||||
var ptr = allocateWithRefcount(alignment, data_bytes);
|
||||
var ptr = allocateWithRefcount(data_bytes, alignment);
|
||||
|
||||
var offset = blk: {
|
||||
if (alignment.keyFirst()) {
|
||||
|
@ -616,7 +619,7 @@ pub fn dictValues(dict: RocDict, alignment: Alignment, key_width: usize, value_w
|
|||
}
|
||||
|
||||
const data_bytes = length * value_width;
|
||||
var ptr = allocateWithRefcount(alignment, data_bytes);
|
||||
var ptr = allocateWithRefcount(data_bytes, alignment);
|
||||
|
||||
var offset = blk: {
|
||||
if (alignment.keyFirst()) {
|
||||
|
@ -751,18 +754,35 @@ pub fn setFromList(list: RocList, alignment: Alignment, key_width: usize, value_
|
|||
|
||||
// NOTE: decref checks for the empty case
|
||||
const data_bytes = size * key_width;
|
||||
decref(alignment, list.bytes, data_bytes);
|
||||
decref(list.bytes, data_bytes, alignment);
|
||||
}
|
||||
|
||||
const StepperCaller = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
|
||||
pub fn dictWalk(dict: RocDict, stepper: Opaque, stepper_caller: StepperCaller, accum: Opaque, alignment: Alignment, key_width: usize, value_width: usize, accum_width: usize, inc_key: Inc, inc_value: Inc, output: Opaque) callconv(.C) void {
|
||||
const alignment_usize = alignment.toUsize();
|
||||
pub fn dictWalk(
|
||||
dict: RocDict,
|
||||
caller: Caller3,
|
||||
data: Opaque,
|
||||
inc_n_data: IncN,
|
||||
data_is_owned: bool,
|
||||
accum: Opaque,
|
||||
alignment: Alignment,
|
||||
key_width: usize,
|
||||
value_width: usize,
|
||||
accum_width: usize,
|
||||
inc_key: Inc,
|
||||
inc_value: Inc,
|
||||
output: Opaque,
|
||||
) callconv(.C) void {
|
||||
const alignment_u32 = alignment.toU32();
|
||||
// allocate space to write the result of the stepper into
|
||||
// experimentally aliasing the accum and output pointers is not a good idea
|
||||
const bytes_ptr: [*]u8 = utils.alloc(alignment_usize, accum_width);
|
||||
const bytes_ptr: [*]u8 = utils.alloc(accum_width, alignment_u32);
|
||||
var b1 = output orelse unreachable;
|
||||
var b2 = bytes_ptr;
|
||||
|
||||
if (data_is_owned) {
|
||||
inc_n_data(data, dict.len());
|
||||
}
|
||||
|
||||
@memcpy(b2, accum orelse unreachable, accum_width);
|
||||
|
||||
var i: usize = 0;
|
||||
|
@ -773,7 +793,7 @@ pub fn dictWalk(dict: RocDict, stepper: Opaque, stepper_caller: StepperCaller, a
|
|||
const key = dict.getKey(i, alignment, key_width, value_width);
|
||||
const value = dict.getValue(i, alignment, key_width, value_width);
|
||||
|
||||
stepper_caller(stepper, key, value, b2, b1);
|
||||
caller(data, key, value, b2, b1);
|
||||
|
||||
const temp = b1;
|
||||
b2 = b1;
|
||||
|
@ -784,8 +804,5 @@ pub fn dictWalk(dict: RocDict, stepper: Opaque, stepper_caller: StepperCaller, a
|
|||
}
|
||||
|
||||
@memcpy(output orelse unreachable, b2, accum_width);
|
||||
utils.dealloc(alignment_usize, bytes_ptr);
|
||||
|
||||
const data_bytes = dict.capacity() * slotSize(key_width, value_width);
|
||||
decref(alignment, dict.dict_bytes, data_bytes);
|
||||
utils.dealloc(bytes_ptr, alignment_u32);
|
||||
}
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -53,7 +53,7 @@ pub const RocStr = extern struct {
|
|||
}
|
||||
|
||||
pub fn initBig(in_place: InPlace, number_of_chars: u64) RocStr {
|
||||
const first_element = utils.allocateWithRefcount(@sizeOf(usize), number_of_chars);
|
||||
const first_element = utils.allocateWithRefcount(number_of_chars, @sizeOf(usize));
|
||||
|
||||
return RocStr{
|
||||
.str_bytes = first_element,
|
||||
|
@ -81,7 +81,7 @@ pub const RocStr = extern struct {
|
|||
|
||||
pub fn deinit(self: RocStr) void {
|
||||
if (!self.isSmallStr() and !self.isEmpty()) {
|
||||
utils.decref(RocStr.alignment, self.str_bytes, self.str_len);
|
||||
utils.decref(self.str_bytes, self.str_len, RocStr.alignment);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ pub const RocStr = extern struct {
|
|||
if (length < roc_str_size) {
|
||||
return RocStr.empty();
|
||||
} else {
|
||||
var new_bytes: []T = utils.alloc(RocStr.alignment, length) catch unreachable;
|
||||
var new_bytes: []T = utils.alloc(length, RocStr.alignment) catch unreachable;
|
||||
|
||||
var new_bytes_ptr: [*]u8 = @ptrCast([*]u8, &new_bytes);
|
||||
|
||||
|
@ -920,7 +920,7 @@ fn strConcat(result_in_place: InPlace, arg1: RocStr, arg2: RocStr) RocStr {
|
|||
return RocStr.clone(result_in_place, arg2);
|
||||
} else if (arg2.isEmpty()) {
|
||||
// the first argument is owned, so we can return it without cloning
|
||||
return RocStr.clone(result_in_place, arg1);
|
||||
return arg1;
|
||||
} else {
|
||||
const combined_length = arg1.len() + arg2.len();
|
||||
|
||||
|
@ -948,8 +948,6 @@ fn strConcat(result_in_place: InPlace, arg1: RocStr, arg2: RocStr) RocStr {
|
|||
arg1.memcpy(result_ptr);
|
||||
arg2.memcpy(result_ptr + arg1.len());
|
||||
|
||||
arg1.deinit();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -1072,7 +1070,7 @@ fn strToBytes(arg: RocStr) RocList {
|
|||
return RocList.empty();
|
||||
} else if (arg.isSmallStr()) {
|
||||
const length = arg.len();
|
||||
const ptr = utils.allocateWithRefcount(RocStr.alignment, length);
|
||||
const ptr = utils.allocateWithRefcount(length, RocStr.alignment);
|
||||
|
||||
@memcpy(ptr, arg.asU8ptr(), length);
|
||||
|
||||
|
@ -1104,7 +1102,7 @@ fn fromUtf8(arg: RocList) FromUtf8Result {
|
|||
|
||||
// then decrement the input list
|
||||
const data_bytes = arg.len();
|
||||
utils.decref(RocStr.alignment, arg.bytes, data_bytes);
|
||||
utils.decref(arg.bytes, data_bytes, RocStr.alignment);
|
||||
|
||||
return FromUtf8Result{ .is_ok = true, .string = string, .byte_index = 0, .problem_code = Utf8ByteProblem.InvalidStartByte };
|
||||
} else {
|
||||
|
@ -1119,7 +1117,7 @@ fn fromUtf8(arg: RocList) FromUtf8Result {
|
|||
|
||||
// consume the input list
|
||||
const data_bytes = arg.len();
|
||||
utils.decref(RocStr.alignment, arg.bytes, data_bytes);
|
||||
utils.decref(arg.bytes, data_bytes, RocStr.alignment);
|
||||
|
||||
return FromUtf8Result{ .is_ok = false, .string = RocStr.empty(), .byte_index = temp.index, .problem_code = temp.problem };
|
||||
}
|
||||
|
|
|
@ -2,14 +2,14 @@ const std = @import("std");
|
|||
const always_inline = std.builtin.CallOptions.Modifier.always_inline;
|
||||
|
||||
// If allocation fails, this must cxa_throw - it must not return a null pointer!
|
||||
extern fn roc_alloc(alignment: usize, size: usize) callconv(.C) *c_void;
|
||||
extern fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*c_void;
|
||||
|
||||
// This should never be passed a null pointer.
|
||||
// If allocation fails, this must cxa_throw - it must not return a null pointer!
|
||||
extern fn roc_realloc(alignment: usize, c_ptr: *c_void, old_size: usize, new_size: usize) callconv(.C) *c_void;
|
||||
extern fn roc_realloc(c_ptr: *c_void, new_size: usize, old_size: usize, alignment: u32) callconv(.C) ?*c_void;
|
||||
|
||||
// This should never be passed a null pointer.
|
||||
extern fn roc_dealloc(alignment: usize, c_ptr: *c_void) callconv(.C) void;
|
||||
extern fn roc_dealloc(c_ptr: *c_void, alignment: u32) callconv(.C) void;
|
||||
|
||||
comptime {
|
||||
// During tetsts, use the testing allocators to satisfy these functions.
|
||||
|
@ -20,33 +20,33 @@ comptime {
|
|||
}
|
||||
}
|
||||
|
||||
fn testing_roc_alloc(alignment: usize, size: usize) callconv(.C) *c_void {
|
||||
return @ptrCast(*c_void, std.testing.allocator.alloc(u8, size) catch unreachable);
|
||||
fn testing_roc_alloc(size: usize, alignment: u32) callconv(.C) ?*c_void {
|
||||
return @ptrCast(?*c_void, std.testing.allocator.alloc(u8, size) catch unreachable);
|
||||
}
|
||||
|
||||
fn testing_roc_realloc(alignment: usize, c_ptr: *c_void, old_size: usize, new_size: usize) callconv(.C) *c_void {
|
||||
fn testing_roc_realloc(c_ptr: *c_void, new_size: usize, old_size: usize, alignment: u32) callconv(.C) ?*c_void {
|
||||
const ptr = @ptrCast([*]u8, @alignCast(16, c_ptr));
|
||||
const slice = ptr[0..old_size];
|
||||
|
||||
return @ptrCast(*c_void, std.testing.allocator.realloc(slice, new_size) catch unreachable);
|
||||
return @ptrCast(?*c_void, std.testing.allocator.realloc(slice, new_size) catch unreachable);
|
||||
}
|
||||
|
||||
fn testing_roc_dealloc(alignment: usize, c_ptr: *c_void) callconv(.C) void {
|
||||
fn testing_roc_dealloc(c_ptr: *c_void, alignment: u32) callconv(.C) void {
|
||||
const ptr = @ptrCast([*]u8, @alignCast(16, c_ptr));
|
||||
|
||||
std.testing.allocator.destroy(ptr);
|
||||
}
|
||||
|
||||
pub fn alloc(alignment: usize, size: usize) [*]u8 {
|
||||
return @ptrCast([*]u8, @call(.{ .modifier = always_inline }, roc_alloc, .{ alignment, size }));
|
||||
pub fn alloc(size: usize, alignment: u32) [*]u8 {
|
||||
return @ptrCast([*]u8, @call(.{ .modifier = always_inline }, roc_alloc, .{ size, alignment }));
|
||||
}
|
||||
|
||||
pub fn realloc(alignment: usize, c_ptr: [*]u8, old_size: usize, new_size: usize) [*]u8 {
|
||||
return @ptrCast([*]u8, @call(.{ .modifier = always_inline }, roc_realloc, .{ alignment, c_ptr, old_size, new_size }));
|
||||
pub fn realloc(c_ptr: [*]u8, new_size: usize, old_size: usize, alignment: u32) [*]u8 {
|
||||
return @ptrCast([*]u8, @call(.{ .modifier = always_inline }, roc_realloc, .{ c_ptr, new_size, old_size, alignment }));
|
||||
}
|
||||
|
||||
pub fn dealloc(alignment: usize, c_ptr: [*]u8) void {
|
||||
return @call(.{ .modifier = always_inline }, roc_dealloc, .{ alignment, c_ptr });
|
||||
pub fn dealloc(c_ptr: [*]u8, alignment: u32) void {
|
||||
return @call(.{ .modifier = always_inline }, roc_dealloc, .{ c_ptr, alignment });
|
||||
}
|
||||
|
||||
pub const Inc = fn (?[*]u8) callconv(.C) void;
|
||||
|
@ -110,9 +110,9 @@ pub fn intWidth(width: IntWidth) anytype {
|
|||
}
|
||||
|
||||
pub fn decref(
|
||||
alignment: usize,
|
||||
bytes_or_null: ?[*]u8,
|
||||
data_bytes: usize,
|
||||
alignment: u32,
|
||||
) void {
|
||||
if (data_bytes == 0) {
|
||||
return;
|
||||
|
@ -128,7 +128,7 @@ pub fn decref(
|
|||
switch (alignment) {
|
||||
16 => {
|
||||
if (refcount == REFCOUNT_ONE_ISIZE) {
|
||||
dealloc(alignment, bytes - 16);
|
||||
dealloc(bytes - 16, alignment);
|
||||
} else if (refcount_isize < 0) {
|
||||
(isizes - 1)[0] = refcount - 1;
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ pub fn decref(
|
|||
else => {
|
||||
// NOTE enums can currently have an alignment of < 8
|
||||
if (refcount == REFCOUNT_ONE_ISIZE) {
|
||||
dealloc(alignment, bytes - 8);
|
||||
dealloc(bytes - 8, alignment);
|
||||
} else if (refcount_isize < 0) {
|
||||
(isizes - 1)[0] = refcount - 1;
|
||||
}
|
||||
|
@ -145,8 +145,8 @@ pub fn decref(
|
|||
}
|
||||
|
||||
pub fn allocateWithRefcount(
|
||||
alignment: usize,
|
||||
data_bytes: usize,
|
||||
alignment: u32,
|
||||
) [*]u8 {
|
||||
comptime const result_in_place = false;
|
||||
|
||||
|
@ -154,7 +154,7 @@ pub fn allocateWithRefcount(
|
|||
16 => {
|
||||
const length = 2 * @sizeOf(usize) + data_bytes;
|
||||
|
||||
var new_bytes: [*]align(16) u8 = @alignCast(16, alloc(alignment, length));
|
||||
var new_bytes: [*]align(16) u8 = @alignCast(16, alloc(length, alignment));
|
||||
|
||||
var as_usize_array = @ptrCast([*]usize, new_bytes);
|
||||
if (result_in_place) {
|
||||
|
@ -173,7 +173,7 @@ pub fn allocateWithRefcount(
|
|||
else => {
|
||||
const length = @sizeOf(usize) + data_bytes;
|
||||
|
||||
var new_bytes: [*]align(8) u8 = @alignCast(8, alloc(alignment, length));
|
||||
var new_bytes: [*]align(8) u8 = @alignCast(8, alloc(length, alignment));
|
||||
|
||||
var as_isize_array = @ptrCast([*]isize, new_bytes);
|
||||
if (result_in_place) {
|
||||
|
@ -192,7 +192,7 @@ pub fn allocateWithRefcount(
|
|||
|
||||
pub fn unsafeReallocate(
|
||||
source_ptr: [*]u8,
|
||||
alignment: usize,
|
||||
alignment: u32,
|
||||
old_length: usize,
|
||||
new_length: usize,
|
||||
element_width: usize,
|
||||
|
@ -211,7 +211,7 @@ pub fn unsafeReallocate(
|
|||
// TODO handle out of memory
|
||||
// NOTE realloc will dealloc the original allocation
|
||||
const old_allocation = source_ptr - align_width;
|
||||
const new_allocation = realloc(alignment, old_allocation, old_width, new_width);
|
||||
const new_allocation = realloc(old_allocation, new_width, old_width, alignment);
|
||||
|
||||
const new_source = @ptrCast([*]u8, new_allocation) + align_width;
|
||||
return new_source;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue