module std::core::array; import std::core::array::slice; <* @param [in] array @param [in] element @return "the first index of the element" @return! SearchResult.MISSING *> macro index_of(array, element) { foreach (i, &e : array) { if (*e == element) return i; } return SearchResult.MISSING?; } <* @require @typekind(array) == VECTOR || @typekind(array) == ARRAY @require @typekind(array[0]) == VECTOR || @typekind(array[0]) == ARRAY *> macro slice2d(array, x = 0, xlen = 0, y = 0, ylen = 0) { if (xlen < 1) xlen = $typeof(array[0]).len + xlen; if (ylen < 1) ylen = $typeof(array).len + ylen; var $ElementType = $typeof(array[0][0]); return Slice2d(<$ElementType>) { ($ElementType*)&array, $typeof(array[0]).len, y, ylen, x, xlen }; } <* @param [in] array @param [in] element @return "the last index of the element" @return! SearchResult.MISSING *> macro rindex_of(array, element) { foreach_r (i, &e : array) { if (*e == element) return i; } return SearchResult.MISSING?; } <* Concatenate two arrays or slices, returning a slice containing the concatenation of them. @param [in] arr1 @param [in] arr2 @param [&inout] allocator "The allocator to use, default is the heap allocator" @require @typekind(arr1) == SLICE || @typekind(arr1) == ARRAY @require @typekind(arr2) == SLICE || @typekind(arr2) == ARRAY @require @typeis(arr1[0], $typeof(arr2[0])) "Arrays must have the same type" @ensure result.len == arr1.len + arr2.len *> macro concat(arr1, arr2, Allocator allocator) @nodiscard { var $Type = $typeof(arr1[0]); $Type[] result = allocator::alloc_array(allocator, $Type, arr1.len + arr2.len); if (arr1.len > 0) { mem::copy(result.ptr, &arr1[0], arr1.len * $Type.sizeof, $Type.alignof, $Type.alignof); } if (arr2.len > 0) { mem::copy(&result[arr1.len], &arr2[0], arr2.len * $Type.sizeof, $Type.alignof, $Type.alignof); } return result; } <* Concatenate two arrays or slices, returning a slice containing the concatenation of them. @param [in] arr1 @param [in] arr2 @param [&inout] allocator "The allocator to use, default is the heap allocator" @require @typekind(arr1) == SLICE || @typekind(arr1) == ARRAY @require @typekind(arr2) == SLICE || @typekind(arr2) == ARRAY @require @typeis(arr1[0], $typeof(arr2[0])) "Arrays must have the same type" @ensure result.len == arr1.len + arr2.len *> macro concat_new(arr1, arr2, Allocator allocator = allocator::heap()) @nodiscard { return concat(arr1, arr2, allocator); } <* Concatenate two arrays or slices, returning a slice containing the concatenation of them, allocated using the temp allocator. @param [in] arr1 @param [in] arr2 @require @typekind(arr1) == SLICE || @typekind(arr1) == ARRAY @require @typekind(arr2) == SLICE || @typekind(arr2) == ARRAY @require @typeis(arr1[0], $typeof(arr2[0])) "Arrays must have the same type" @ensure result.len == arr1.len + arr2.len *> macro tconcat(arr1, arr2) @nodiscard => concat(arr1, arr2, allocator::temp()); module std::core::array::slice(); struct Slice2d { Type* ptr; usz inner_len; usz ystart; usz ylen; usz xstart; usz xlen; } fn usz Slice2d.len(&self) @operator(len) { return self.ylen; } fn usz Slice2d.count(&self) { return self.ylen * self.xlen; } macro void Slice2d.@each(&self; @body(usz[<2>], Type)) { foreach (y, line : *self) { foreach (x, val : line) { @body({ x, y }, val); } } } macro void Slice2d.@each_ref(&self; @body(usz[<2>], Type*)) { foreach (y, line : *self) { foreach (x, &val : line) { @body({ x, y }, val); } } } <* @require idy >= 0 && idy < self.ylen *> macro Type[] Slice2d.get(self, usz idy) @operator([]) { return (self.ptr + self.inner_len * (idy + self.ystart))[self.xstart:self.xlen]; } <* @require y >= 0 && y < self.ylen @require x >= 0 && x < self.xlen *> fn Slice2d Slice2d.slice(&self, isz x = 0, isz xlen = 0, isz y = 0, isz ylen = 0) { if (xlen < 1) xlen = self.xlen + xlen; if (ylen < 1) ylen = self.ylen + ylen; return { self.ptr, self.inner_len, y + self.ystart, ylen, x + self.xstart, xlen }; }