Support generic extension receivers and Iterable signatures

This commit is contained in:
Sergey Chernov 2026-02-03 23:58:49 +03:00
parent 54c6fca0e8
commit 874f8fc205
2 changed files with 942 additions and 122 deletions

File diff suppressed because it is too large Load Diff

View File

@ -15,15 +15,15 @@ extern fun pow(x: Object, y: Object): Real
extern fun sqrt(x: Object): Real
// Last regex match result, updated by =~ / !~.
var $~ = null
var $~: Object? = null
/*
Wrap a builder into a zero-argument thunk that computes once and caches the result.
The first call invokes builder() and stores the value; subsequent calls return the cached value.
*/
fun cached<T>(builder: ()->T): ()->T {
var calculated = false
var value = null
var calculated: Bool = false
var value: Object? = null
{
if( !calculated ) {
value = builder()
@ -35,7 +35,7 @@ fun cached<T>(builder: ()->T): ()->T {
/* Filter elements of this iterable using the provided predicate and provide a flow
of results. Coudl be used to map infinte flows, etc.
*/
fun Iterable.filterFlow<T>(predicate: (T)->Bool): Flow<T> {
fun Iterable<T>.filterFlow(predicate: (T)->Bool): Flow<T> {
val list = this
flow {
for( item in list ) {
@ -49,7 +49,7 @@ fun Iterable.filterFlow<T>(predicate: (T)->Bool): Flow<T> {
/*
Filter this iterable and return List of elements
*/
fun Iterable.filter<T>(predicate: (T)->Bool): List<T> {
fun Iterable<T>.filter(predicate: (T)->Bool): List<T> {
var result: List<T> = List()
for( item in this ) if( predicate(item) ) result += item
result
@ -58,7 +58,7 @@ fun Iterable.filter<T>(predicate: (T)->Bool): List<T> {
/*
Count all items in this iterable for which predicate returns true
*/
fun Iterable.count<T>(predicate: (T)->Bool): Int {
fun Iterable<T>.count(predicate: (T)->Bool): Int {
var hits = 0
this.forEach {
if( predicate(it) ) hits++
@ -69,25 +69,25 @@ fun Iterable.count<T>(predicate: (T)->Bool): Int {
filter out all null elements from this collection (Iterable); flow of
non-null elements is returned
*/
fun Iterable.filterFlowNotNull<T>(): Flow<T> {
fun Iterable<T>.filterFlowNotNull(): Flow<T> {
filterFlow { it != null }
}
/* Filter non-null elements and collect them into a List
*/
fun Iterable.filterNotNull<T>(): List<T> {
fun Iterable<T>.filterNotNull(): List<T> {
filter { it != null }
}
/* Skip the first N elements of this iterable. */
fun Iterable.drop<T>(n: Int): List<T> {
fun Iterable<T>.drop(n: Int): List<T> {
var cnt = 0
filter { cnt++ >= n }
}
/* Return the first element or throw if the iterable is empty. */
val Iterable.first: Object get() {
val i: Iterator = iterator()
val Iterable<T>.first: T get() {
val i: Iterator<T> = iterator()
if( !i.hasNext() ) throw NoSuchElementException()
i.next().also { i.cancelIteration() }
}
@ -96,7 +96,7 @@ val Iterable.first: Object get() {
Return the first element that matches the predicate or throws
NuSuchElementException
*/
fun Iterable.findFirst<T>(predicate: (T)->Bool): T {
fun Iterable<T>.findFirst(predicate: (T)->Bool): T {
for( x in this ) {
if( predicate(x) )
break x
@ -107,7 +107,7 @@ fun Iterable.findFirst<T>(predicate: (T)->Bool): T {
/*
return the first element matching the predicate or null
*/
fun Iterable.findFirstOrNull<T>(predicate: (T)->Bool): T? {
fun Iterable<T>.findFirstOrNull(predicate: (T)->Bool): T? {
for( x in this ) {
if( predicate(x) )
break x
@ -117,19 +117,19 @@ fun Iterable.findFirstOrNull<T>(predicate: (T)->Bool): T? {
/* Return the last element or throw if the iterable is empty. */
val Iterable.last: Object get() {
val Iterable<T>.last: T get() {
var found = false
var element = null
var element: Object = Unset
for( i in this ) {
element = i
found = true
}
if( !found ) throw NoSuchElementException()
element
element as T
}
/* Emit all but the last N elements of this iterable. */
fun Iterable.dropLast<T>(n: Int): Flow<T> {
fun Iterable<T>.dropLast(n: Int): Flow<T> {
val list = this
val buffer = RingBuffer(n)
flow {
@ -142,25 +142,25 @@ fun Iterable.dropLast<T>(n: Int): Flow<T> {
}
/* Return the last N elements of this iterable as a buffer/list. */
fun Iterable.takeLast<T>(n: Int): RingBuffer<T> {
fun Iterable<T>.takeLast(n: Int): RingBuffer<T> {
val buffer: RingBuffer<T> = RingBuffer(n)
for( item in this ) buffer += item
buffer
}
/* Join elements into a string with a separator (separator parameter) and optional transformer. */
fun Iterable.joinToString<T>(separator: String=" ", transformer: (T)->Object = { it }): String {
var result = null
fun Iterable<T>.joinToString(separator: String=" ", transformer: (T)->Object = { it }): String {
var result: String? = null
for( part in this ) {
val transformed = transformer(part).toString()
if( result == null ) result = transformed
else result += separator + transformed
else result = (result as String) + separator + transformed
}
result ?: ""
}
/* Return true if any element matches the predicate. */
fun Iterable.any<T>(predicate: (T)->Bool): Bool {
fun Iterable<T>.any(predicate: (T)->Bool): Bool {
for( i in this ) {
if( predicate(i) )
break true
@ -168,13 +168,13 @@ fun Iterable.any<T>(predicate: (T)->Bool): Bool {
}
/* Return true if all elements match the predicate. */
fun Iterable.all<T>(predicate: (T)->Bool): Bool {
fun Iterable<T>.all(predicate: (T)->Bool): Bool {
!any { !predicate(it) }
}
/* Sum all elements; returns null for empty collections. */
fun Iterable.sum<T>(): T? {
val i: Iterator = iterator()
fun Iterable<T>.sum(): T? {
val i: Iterator<T> = iterator()
if( i.hasNext() ) {
var result = i.next()
while( i.hasNext() ) result += i.next()
@ -184,8 +184,8 @@ fun Iterable.sum<T>(): T? {
}
/* Sum mapped values of elements; returns null for empty collections. */
fun Iterable.sumOf<T,R>(f: (T)->R): R? {
val i: Iterator = iterator()
fun Iterable<T>.sumOf<R>(f: (T)->R): R? {
val i: Iterator<T> = iterator()
if( i.hasNext() ) {
var result = f(i.next())
while( i.hasNext() ) result += f(i.next())
@ -195,8 +195,8 @@ fun Iterable.sumOf<T,R>(f: (T)->R): R? {
}
/* Minimum value of the given function applied to elements of the collection. */
fun Iterable.minOf<T,R>(lambda: (T)->R): R {
val i: Iterator = iterator()
fun Iterable<T>.minOf<R>(lambda: (T)->R): R {
val i: Iterator<T> = iterator()
var minimum = lambda( i.next() )
while( i.hasNext() ) {
val x = lambda(i.next())
@ -206,8 +206,8 @@ fun Iterable.minOf<T,R>(lambda: (T)->R): R {
}
/* Maximum value of the given function applied to elements of the collection. */
fun Iterable.maxOf<T,R>(lambda: (T)->R): R {
val i: Iterator = iterator()
fun Iterable<T>.maxOf<R>(lambda: (T)->R): R {
val i: Iterator<T> = iterator()
var maximum = lambda( i.next() )
while( i.hasNext() ) {
val x = lambda(i.next())
@ -217,17 +217,17 @@ fun Iterable.maxOf<T,R>(lambda: (T)->R): R {
}
/* Return elements sorted by natural order. */
fun Iterable.sorted<T>(): List<T> {
fun Iterable<T>.sorted(): List<T> {
sortedWith { a, b -> a <=> b }
}
/* Return elements sorted by the key selector. */
fun Iterable.sortedBy<T,R>(predicate: (T)->R): List<T> {
fun Iterable<T>.sortedBy<R>(predicate: (T)->R): List<T> {
sortedWith { a, b -> predicate(a) <=> predicate(b) }
}
/* Return a shuffled copy of the iterable as a list. */
fun Iterable.shuffled<T>(): List<T> {
fun Iterable<T>.shuffled(): List<T> {
val list: List<T> = toList()
list.shuffle()
list
@ -237,7 +237,7 @@ fun Iterable.shuffled<T>(): List<T> {
Returns a single list of all elements from all collections in the given collection.
@return List
*/
fun Iterable.flatten<T>(): List<T> {
fun Iterable<Iterable<T>>.flatten(): List<T> {
var result: List<T> = List()
forEach { i ->
i.forEach { result += it }
@ -249,13 +249,13 @@ fun Iterable.flatten<T>(): List<T> {
Returns a single list of all elements yielded from results of transform function being
invoked on each element of original collection.
*/
fun Iterable.flatMap<T,R>(transform: (T)->Iterable<R>): List<R> {
fun Iterable<T>.flatMap<R>(transform: (T)->Iterable<R>): List<R> {
val mapped: List<Iterable<R>> = map(transform)
mapped.flatten()
}
/* Return string representation like [a,b,c]. */
override fun List.toString() {
override fun List<T>.toString() {
var first = true
var result = "["
for (item in this) {
@ -267,12 +267,12 @@ override fun List.toString() {
}
/* Sort list in-place by key selector. */
fun List.sortBy<T,R>(predicate: (T)->R): Void {
fun List<T>.sortBy<R>(predicate: (T)->R): Void {
sortWith { a, b -> predicate(a) <=> predicate(b) }
}
/* Sort list in-place by natural order. */
fun List.sort<T>(): Void {
fun List<T>.sort(): Void {
sortWith { a, b -> a <=> b }
}
@ -327,9 +327,7 @@ interface Delegate<T,ThisRefType=Void> {
returns what the block returns.
*/
fun with<T,R>(self: T, block: T.()->R): R {
var result = Unset
self.apply { result = block() }
result as R
block(self)
}
/*
@ -337,16 +335,16 @@ fun with<T,R>(self: T, block: T.()->R): R {
The provided creator lambda is called once on the first access to compute the value.
Can only be used with 'val' properties.
*/
class lazy<T>(creatorParam: Object.()->T) : Delegate<T,Object> {
private val creator: Object.()->T = creatorParam
class lazy<T,ThisRefType=Object>(creatorParam: ThisRefType.()->T) : Delegate<T,ThisRefType> {
private val creator: ThisRefType.()->T = creatorParam
private var value = Unset
override fun bind(name: String, access: DelegateAccess, thisRef: Object): Object {
override fun bind(name: String, access: DelegateAccess, thisRef: ThisRefType): Object {
if (access.toString() != "DelegateAccess.Val") throw "lazy delegate can only be used with 'val'"
this
}
override fun getValue(thisRef: Object, name: String): T {
override fun getValue(thisRef: ThisRefType, name: String): T {
if (value == Unset)
value = with(thisRef,creator)
value as T