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
|
||||
## 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,
|
||||
}
|
||||
|
||||
Bucket := fn($Key: type, $Value: type, $Allocator: type): type return Vec(Item(Key, Value), Allocator)
|
||||
Buckets := fn($Key: type, $Value: type, $Allocator: type): type return Vec(Bucket(Key, Value, Allocator), Allocator)
|
||||
Bucket := fn($Key: type, $Value: type, $Allocator: type): type {
|
||||
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 {
|
||||
allocator: ^Allocator,
|
||||
|
|
|
@ -69,9 +69,6 @@ Vec := fn($T: type, $Allocator: type): type return struct {
|
|||
i := 0
|
||||
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 {
|
||||
_ = 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 {
|
||||
loop {
|
||||
x := self.next()
|
||||
y := self.next()
|
||||
if y.finished return sum
|
||||
sum += _fold(x.val, y.val)
|
||||
if x.finished return sum
|
||||
sum = _fold(sum, x.val)
|
||||
}
|
||||
}
|
||||
nth := fn(self: ^Self, n: uint): ?Value {
|
||||
|
@ -59,6 +58,23 @@ Iterator := fn($T: type): type {
|
|||
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
|
||||
loop {
|
||||
x := self.iter.next()
|
||||
if n == self.step return x
|
||||
if n == self.step | x.finished return x
|
||||
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,
|
||||
needle: @TypeOf(needle),
|
||||
finished: bool = false,
|
||||
|
||||
next := fn(self: ^Self): IterNext([]u8) {
|
||||
splits := split_once(self.str, self.needle)
|
||||
if self.finished return .(true, Type([]u8).uninit())
|
||||
splits := split_once(self.str, self.needle)
|
||||
if splits != null {
|
||||
self.str = splits.right
|
||||
return .(false, splits.left)
|
||||
} else {
|
||||
self.finished = true
|
||||
return .(false, self.str)
|
||||
}
|
||||
self.finished = true
|
||||
return .(false, self.str)
|
||||
}
|
||||
}) {
|
||||
T := @TypeOf(needle)
|
||||
|
@ -92,11 +91,11 @@ split := fn(str: []u8, needle: @Any()): Iterator(struct {
|
|||
return .(.{str, needle})
|
||||
}
|
||||
|
||||
chars := fn(iter: []u8): Iterator(struct {
|
||||
$chars := fn(iter: []u8): Iterator(struct {
|
||||
str: []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..]
|
||||
return tmp
|
||||
}
|
||||
|
@ -104,7 +103,7 @@ chars := fn(iter: []u8): Iterator(struct {
|
|||
return .(.(iter))
|
||||
}
|
||||
|
||||
chars_ref := fn(iter: []u8): Iterator(struct {
|
||||
$chars_ref := fn(iter: []u8): Iterator(struct {
|
||||
str: []u8,
|
||||
|
||||
$next := fn(self: ^Self): IterNext(^u8) {
|
||||
|
|
58
src/main.hb
58
src/main.hb
|
@ -1,15 +1,4 @@
|
|||
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]
|
||||
}
|
||||
lily := @use("lily/lib.hb");
|
||||
|
||||
Generator := struct {
|
||||
n: uint = 0,
|
||||
|
@ -22,37 +11,28 @@ Generator := struct {
|
|||
}
|
||||
}
|
||||
|
||||
$add := fn(lhs: uint, rhs: uint): uint {
|
||||
return lhs + rhs
|
||||
$add := fn(sum: uint, x: uint): uint {
|
||||
return sum + x
|
||||
}
|
||||
|
||||
chars_ref := lily.string.chars_ref
|
||||
|
||||
main := fn(argc: uint, argv: []^void): uint {
|
||||
a := Generator.{}.into_iter().take(50).fold(add, 0)
|
||||
lily.print(a)
|
||||
sum := Generator.{}.into_iter().take(50).fold(add, 0)
|
||||
lily.print(sum)
|
||||
|
||||
b := chars_ref("Hello,_").chain(chars_ref("World!")).map(ref_char_to_str).for_each(lily.log.info)
|
||||
c := chars_ref("Hello,_").intersperse(chars_ref("World!")).map(ref_char_to_str).for_each(lily.log.info)
|
||||
// ! (libc) (compiler) bug: .collect(T) does not work.
|
||||
if lily.Target.current() != .LibC {
|
||||
str := lily.string.chars("Hello, ").intersperse(
|
||||
lily.string.chars("World!"),
|
||||
).collect([13]u8)
|
||||
|
||||
// allocator := Allocator.new()
|
||||
// defer allocator.deinit()
|
||||
// // ! HashMap only works on AbleOS target (due to compiler bugs)
|
||||
// map := HashMap(uint, uint, Hasher, Allocator).new(&allocator)
|
||||
// defer map.deinit()
|
||||
|
||||
// _ = map.insert(101, 20)
|
||||
// _ = 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)
|
||||
if str != null {
|
||||
lily.log.info(@as([13]u8, str)[..])
|
||||
} else {
|
||||
lily.panic("could not collect (array wrong size)")
|
||||
}
|
||||
} else {
|
||||
lily.log.info("HWeolrllod,! ")
|
||||
}
|
||||
|
||||
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