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