iterator work
improve performance of split, chars, chars_ref properly implement lily.iter.Iterator.fold partially implement lily.iter.Iterator.collect fix lily.iter.Skip logic code cleanup write proposed iterator spec
This commit is contained in:
parent
bfe75481e3
commit
33cf8d7209
|
@ -1,2 +1,20 @@
|
||||||
# iterators
|
# iterators
|
||||||
## spec to-be-defined
|
## spec to-be-defined
|
||||||
|
|
||||||
|
## proposed spec:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
.{IterNext, Iterator} := @use("lily").iter
|
||||||
|
|
||||||
|
Iterable := struct {
|
||||||
|
// ! required
|
||||||
|
// IterNext == struct { finished: bool, val: T }
|
||||||
|
next := fn(self: ^Self): IterNext(T)
|
||||||
|
into_iter := fn(self: Self): Iterator(Self)
|
||||||
|
// ! proposed
|
||||||
|
// addition of these two would allow for cheap implementation of `skip`, and `nth` in lily.iter.Iterator
|
||||||
|
peek := fn(self: ^Self): IterNext(T)
|
||||||
|
advance := fn(self: ^Self, n: uint): IterNext(T)
|
||||||
|
// ! proposed (waiting on compiler)
|
||||||
|
iter := fn(self: ^Self): Iterator(^Self)
|
||||||
|
}
|
|
@ -5,8 +5,12 @@ Item := fn($Key: type, $Value: type): type return packed struct {
|
||||||
value: Value,
|
value: Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
Bucket := fn($Key: type, $Value: type, $Allocator: type): type return Vec(Item(Key, Value), Allocator)
|
Bucket := fn($Key: type, $Value: type, $Allocator: type): type {
|
||||||
Buckets := fn($Key: type, $Value: type, $Allocator: type): type return Vec(Bucket(Key, Value, Allocator), Allocator)
|
return Vec(Item(Key, Value), Allocator)
|
||||||
|
}
|
||||||
|
Buckets := fn($Key: type, $Value: type, $Allocator: type): type {
|
||||||
|
return Vec(Bucket(Key, Value, Allocator), Allocator)
|
||||||
|
}
|
||||||
|
|
||||||
HashMap := fn($Key: type, $Value: type, $Hasher: type, $Allocator: type): type return struct {
|
HashMap := fn($Key: type, $Value: type, $Hasher: type, $Allocator: type): type return struct {
|
||||||
allocator: ^Allocator,
|
allocator: ^Allocator,
|
||||||
|
|
|
@ -69,9 +69,6 @@ Vec := fn($T: type, $Allocator: type): type return struct {
|
||||||
i := 0
|
i := 0
|
||||||
loop if self.get(i) == rhs return i else if i == self.slice.len return null else i += 1
|
loop if self.get(i) == rhs return i else if i == self.slice.len return null else i += 1
|
||||||
}
|
}
|
||||||
$into_iter := fn(self: Self): iter.Iterator(iter.SliceIter(T)) {
|
|
||||||
return .(.(self.slice, 0))
|
|
||||||
}
|
|
||||||
$sort := fn(self: ^Self): void {
|
$sort := fn(self: ^Self): void {
|
||||||
_ = quicksort(compare, self.slice, 0, self.slice.len - 1)
|
_ = quicksort(compare, self.slice, 0, self.slice.len - 1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,9 +46,8 @@ Iterator := fn($T: type): type {
|
||||||
fold := fn(self: ^Self, $_fold: type, sum: Value): Value {
|
fold := fn(self: ^Self, $_fold: type, sum: Value): Value {
|
||||||
loop {
|
loop {
|
||||||
x := self.next()
|
x := self.next()
|
||||||
y := self.next()
|
if x.finished return sum
|
||||||
if y.finished return sum
|
sum = _fold(sum, x.val)
|
||||||
sum += _fold(x.val, y.val)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nth := fn(self: ^Self, n: uint): ?Value {
|
nth := fn(self: ^Self, n: uint): ?Value {
|
||||||
|
@ -59,6 +58,23 @@ Iterator := fn($T: type): type {
|
||||||
i += 1
|
i += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
collect := fn(self: ^Self, $A: type): ?A {
|
||||||
|
if Type(A).kind() != .Array {
|
||||||
|
@error("unsupported collect (for now)")
|
||||||
|
}
|
||||||
|
if @ChildOf(A) != Value {
|
||||||
|
@error("cannot collect of iterator of type", Value, "into type", A)
|
||||||
|
}
|
||||||
|
cont := Type(A).uninit()
|
||||||
|
i := 0
|
||||||
|
loop {
|
||||||
|
defer i += 1
|
||||||
|
x := self.next()
|
||||||
|
if i == @lenof(A) & x.finished return cont
|
||||||
|
if i == @lenof(A) | x.finished return null
|
||||||
|
cont[i] = x.val
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +130,7 @@ Skip := fn($T: type): type {
|
||||||
n := 0
|
n := 0
|
||||||
loop {
|
loop {
|
||||||
x := self.iter.next()
|
x := self.iter.next()
|
||||||
if n == self.step return x
|
if n == self.step | x.finished return x
|
||||||
n += 1
|
n += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,21 +68,20 @@ split_once := fn(haystack: []u8, needle: @Any()): ?struct {left: []u8, right: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
split := fn(str: []u8, needle: @Any()): Iterator(struct {
|
$split := fn(str: []u8, needle: @Any()): Iterator(struct {
|
||||||
str: []u8,
|
str: []u8,
|
||||||
needle: @TypeOf(needle),
|
needle: @TypeOf(needle),
|
||||||
finished: bool = false,
|
finished: bool = false,
|
||||||
|
|
||||||
next := fn(self: ^Self): IterNext([]u8) {
|
next := fn(self: ^Self): IterNext([]u8) {
|
||||||
splits := split_once(self.str, self.needle)
|
|
||||||
if self.finished return .(true, Type([]u8).uninit())
|
if self.finished return .(true, Type([]u8).uninit())
|
||||||
|
splits := split_once(self.str, self.needle)
|
||||||
if splits != null {
|
if splits != null {
|
||||||
self.str = splits.right
|
self.str = splits.right
|
||||||
return .(false, splits.left)
|
return .(false, splits.left)
|
||||||
} else {
|
|
||||||
self.finished = true
|
|
||||||
return .(false, self.str)
|
|
||||||
}
|
}
|
||||||
|
self.finished = true
|
||||||
|
return .(false, self.str)
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
T := @TypeOf(needle)
|
T := @TypeOf(needle)
|
||||||
|
@ -92,11 +91,11 @@ split := fn(str: []u8, needle: @Any()): Iterator(struct {
|
||||||
return .(.{str, needle})
|
return .(.{str, needle})
|
||||||
}
|
}
|
||||||
|
|
||||||
chars := fn(iter: []u8): Iterator(struct {
|
$chars := fn(iter: []u8): Iterator(struct {
|
||||||
str: []u8,
|
str: []u8,
|
||||||
|
|
||||||
$next := fn(self: ^Self): IterNext(u8) {
|
$next := fn(self: ^Self): IterNext(u8) {
|
||||||
tmp := IterNext(u8).(self.str.len == 0, self.str[0])
|
tmp := IterNext(u8).(self.str.len == 0, *self.str.ptr)
|
||||||
self.str = self.str[1..]
|
self.str = self.str[1..]
|
||||||
return tmp
|
return tmp
|
||||||
}
|
}
|
||||||
|
@ -104,7 +103,7 @@ chars := fn(iter: []u8): Iterator(struct {
|
||||||
return .(.(iter))
|
return .(.(iter))
|
||||||
}
|
}
|
||||||
|
|
||||||
chars_ref := fn(iter: []u8): Iterator(struct {
|
$chars_ref := fn(iter: []u8): Iterator(struct {
|
||||||
str: []u8,
|
str: []u8,
|
||||||
|
|
||||||
$next := fn(self: ^Self): IterNext(^u8) {
|
$next := fn(self: ^Self): IterNext(^u8) {
|
||||||
|
|
58
src/main.hb
58
src/main.hb
|
@ -1,15 +1,4 @@
|
||||||
lily := @use("lily/lib.hb")
|
lily := @use("lily/lib.hb");
|
||||||
|
|
||||||
Allocator := lily.alloc.SimpleAllocator
|
|
||||||
Vec := lily.collections.Vec
|
|
||||||
HashMap := lily.collections.HashMap
|
|
||||||
Random := lily.rand.SimpleRandom
|
|
||||||
Result := lily.result.Result
|
|
||||||
Hasher := lily.hash.FoldHasher
|
|
||||||
|
|
||||||
$ref_char_to_str := fn(char: ^u8): []u8 {
|
|
||||||
return char[0..1]
|
|
||||||
}
|
|
||||||
|
|
||||||
Generator := struct {
|
Generator := struct {
|
||||||
n: uint = 0,
|
n: uint = 0,
|
||||||
|
@ -22,37 +11,28 @@ Generator := struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$add := fn(lhs: uint, rhs: uint): uint {
|
$add := fn(sum: uint, x: uint): uint {
|
||||||
return lhs + rhs
|
return sum + x
|
||||||
}
|
}
|
||||||
|
|
||||||
chars_ref := lily.string.chars_ref
|
|
||||||
|
|
||||||
main := fn(argc: uint, argv: []^void): uint {
|
main := fn(argc: uint, argv: []^void): uint {
|
||||||
a := Generator.{}.into_iter().take(50).fold(add, 0)
|
sum := Generator.{}.into_iter().take(50).fold(add, 0)
|
||||||
lily.print(a)
|
lily.print(sum)
|
||||||
|
|
||||||
b := chars_ref("Hello,_").chain(chars_ref("World!")).map(ref_char_to_str).for_each(lily.log.info)
|
// ! (libc) (compiler) bug: .collect(T) does not work.
|
||||||
c := chars_ref("Hello,_").intersperse(chars_ref("World!")).map(ref_char_to_str).for_each(lily.log.info)
|
if lily.Target.current() != .LibC {
|
||||||
|
str := lily.string.chars("Hello, ").intersperse(
|
||||||
|
lily.string.chars("World!"),
|
||||||
|
).collect([13]u8)
|
||||||
|
|
||||||
// allocator := Allocator.new()
|
if str != null {
|
||||||
// defer allocator.deinit()
|
lily.log.info(@as([13]u8, str)[..])
|
||||||
// // ! HashMap only works on AbleOS target (due to compiler bugs)
|
} else {
|
||||||
// map := HashMap(uint, uint, Hasher, Allocator).new(&allocator)
|
lily.panic("could not collect (array wrong size)")
|
||||||
// defer map.deinit()
|
}
|
||||||
|
} else {
|
||||||
// _ = map.insert(101, 20)
|
lily.log.info("HWeolrllod,! ")
|
||||||
// _ = map.insert(202, 30)
|
}
|
||||||
// _ = map.insert(303, 40)
|
|
||||||
|
|
||||||
// // ! This iterator only works on AbleOS target (due to compiler bugs)
|
|
||||||
// map.items().enumerate().for_each(print)
|
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// $print := fn(thing: @Any()): void {
|
|
||||||
// .{n, val: item} := thing
|
|
||||||
// // ! printf ALSO only works on AbleOS target (due to compiler bugs)
|
|
||||||
// lily.printf("nth: {}, key: {}, value: {}", .(n, item.key, item.value))
|
|
||||||
// }
|
|
Loading…
Reference in a new issue