export Slice, * use Mem (offset-ptr, TypeSize, size-i32, i32-size) use Error (or-fail, panic, todo) use Iter IntoIter, Iter, for-each, from, to, down-to, zip, all use StrInst as Str Str(*) use Misc (is-just) # slice definition in prelude.kkc Idx = Size fn empty (): Slice { ptr: Mem.null-ptr(), count: 0 } fn elem-size-of (slice Slice a): slice.ptr Mem.ptr-size-of() fn get-ptr (slice Slice a, i Idx) -> Ptr a if i < 0 or i >= slice.count panic('Access to slice at index \(i). (max: \(slice.count))') elem-ptr = slice.ptr Mem.offset-ptr(Mem.size-i64(i)) return elem-ptr fn try-get (slice Slice a, i Idx) -> Maybe a if i < 0 or i >= slice.count return None elem-ptr = slice.ptr Mem.offset-ptr(Mem.size-i64(i)) return Just(elem-ptr&) fn get (slice Slice a, i Idx) -> a: slice try-get(i) or-fail('Access to slice at index \(i). (max: \(slice.count))') fn set (slice Slice a, i Idx, x a) ep = slice get-ptr(i) ep <&= x inst Indexable Slice elem-get (self, idx): get(self, idx) inst ListLike Slice from-listlike (arr Ptr (Array n a)) -> Slice a: { ptr: arr Mem.cast-ptr(), count: n Mem.i32-size() } # i32-size conversion temporary (related to type number type TODO entry) fn subslice (slice Slice a, from Idx, to Idx) -> Slice a # just return an empty slice or trim it bruh. # if from > slice.count or to > slice.count # panic('tried to sublice [\(from):\(to)], but slice has \(slice.count) elements') begin-ptr = slice.ptr Mem.offset-ptr(Mem.size-i64(from)) if from >= to or from >= slice.count return Slice { ptr: begin-ptr, count: 0 } count = Math.min(to, slice.count) - from return Slice { ptr: begin-ptr, count: count } fn from (slice Slice a, from Idx) -> Slice a: slice subslice(from, slice.count) fn zero-initialize (s Slice a) -> () sz = (Mem.get-typesize() as TypeSize a).size Cnile.memset(Mem.cast-ptr(s.ptr), 0, sz * s.count) fn swap (s Slice a, l Idx, r Idx) -> () x = s get(l) s set(l, s get(r)) s set(r, x) fn reverse (s Slice a) -> () i = 0 until = s.count / 2 while i < until other = s.count - 1 - i swap(s, i, other) i <= i + 1 fn sort (slice Slice a) <= Ord a if slice.count <= 1 return pivot = slice get(0) l = 0 r = slice.count - 1 while True while slice get(l) < pivot l <= l + 1 while slice get(r) > pivot r <= r - 1 if l >= r break # swap slice swap(l, r) l <= l + 1 r <= r - 1 p = r sort(slice subslice(0, p + 1)) sort(slice subslice(p + 1, slice.count)) fn rotate-right (s Slice a) if s.count <= 1 return t = s[s.count - 1] for i in Mem.size-i32(s.count - 1) down-to (1) s set(Mem.i32-size(i), s[Mem.i32-size(i - 1)]) s set(0, t) SliceIter a slice Slice a current-offset Idx inst IntoIter Slice into-iter (self): SliceIter { slice: self, current-offset: 0 } inst IntoIter SliceIter into-iter (self): self inst Iter SliceIter next (self Ptr (SliceIter a)) -> Maybe a off = self&.current-offset if off + 1 > self&.slice.count return None elem = self&.slice.ptr offset-ptr(Mem.size-i64(off))& self <&.current-offset= off + 1 return Just(elem) inst Str SliceIter print-str (self) Str.print-as-list(self) chars (self) todo() SliceAddressIter a slice Slice a current-offset Idx fn addresses (slice Slice a): SliceAddressIter { slice: slice, current-offset: 0 } inst IntoIter SliceAddressIter into-iter (self): self inst Iter SliceAddressIter next (self Ptr (SliceAddressIter a)) -> Maybe (Ptr a) off = self&.current-offset if off + 1 > self&.slice.count return None elem = self&.slice.ptr offset-ptr(Mem.size-i64(off)) self <&.current-offset= off + 1 return Just(elem) fn copy-to (src Slice a, dest Slice a) -> Unit if src.count > dest.count panic('cannot copy to a slice that is smaller! (copying from \(src.count)-element slice to \(dest.count)-element slice)') src zip(Iter.from(0)) for-each(fn Tuple2(elem, i): set(dest, Mem.i32-size(i), elem)) inst Eq Slice eq (l, r) if l.count /= r.count return False return l zip(r) all(fn ((le, re)): le == re) inst Str Slice print-str (self): Str.print-as-list(self) chars (self): Str.list-chars(self) inst ListDecon Slice deconstruct (self, lp, lc, spread, rp, rc) if lc > 0 if lc > self.count return False lp <&= self.ptr if rc > 0 if rc + lc > self.count return False cut = self subslice(self.count - rc, self.count) rp <&= cut.ptr case spread NoSpread return lc + rc == self.count UnassignedSpread return True AssignedSpread(xptr) xptr <&= self subslice(lc, self.count - rc) return True SliceReversedIter a slice Slice a current-offset Idx fn reversed(slice Slice a): SliceReversedIter { slice, current-offset: slice.count } inst IntoIter SliceReversedIter into-iter (self): self inst Iter SliceReversedIter next (self Ptr (SliceReversedIter a)) -> Maybe a off = self&.current-offset if off == 0 return None self <&.current-offset= off - 1 return Just(self&.slice[self&.current-offset]) fn map (s Slice a, fun a -> a) 0 to ((s.count - 1) size-i32()) for-each(fn i: s set(i i32-size(), fun(s[i i32-size()]))) fn find-slice (haystack Slice a, needle Slice a) -> Maybe Idx <= Eq a for i in 0 to (haystack.count size-i32() - needle.count size-i32()) if haystack subslice(i i32-size(), i i32-size() + needle.count) == needle return Just(i i32-size()) return None fn find-last-occurence-of-slice (haystack Slice a, needle Slice a) -> Maybe Idx <= Eq a for i in (haystack.count size-i32() - needle.count size-i32()) down-to (0) if haystack subslice(i i32-size(), i i32-size() + needle.count) == needle return Just(i i32-size()) return None fn contains-slice (haystack Slice a, needle Slice a) -> Bool <= Eq a: haystack find-slice(needle) is-just() fn cast-slice (s Slice a) -> Slice b: Slice { ptr: Mem.cast-ptr(s.ptr), count: s.count } fn last(s Slice a) -> a if s.count == 0 panic('(Slice.last) called on empty slice.') return s[s.count - 1] fn last-ptr(s Slice a) -> Ptr a if s.count == 0 panic('(Slice.last-ptr) called on empty slice.') return s get-ptr(s.count - 1)