package lyng.stdlib extern fun flow(builder: FlowBuilder.()->Void): Flow /* Built-in exception type. */ extern class Exception extern class IllegalArgumentException extern class NotImplementedException extern class Delegate extern class Iterable { fun iterator(): Iterator fun forEach(action: (T)->Void): Void fun map(transform: (T)->R): List fun toList(): List } extern class Iterator { fun hasNext(): Bool fun next(): T fun cancelIteration(): Void fun toList(): List } extern class Collection : Iterable { } extern class Array : Collection { } extern class List : Array { fun add(value: T, more...): Void } extern class Set : Collection { } extern class Map { } extern class MapEntry // Built-in math helpers (implemented in host runtime). extern fun abs(x: Object): Real extern fun ln(x: Object): Real extern fun pow(x: Object, y: Object): Real extern fun sqrt(x: Object): Real // Last regex match result, updated by =~ / !~. 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(builder: ()->T): ()->T { var calculated: Bool = false var value: Object? = null { if( !calculated ) { value = builder() calculated = true } value as 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(predicate: (T)->Bool): Flow { val list = this flow { for( item in list ) { if( predicate(item) ) { emit(item) } } } } /* Filter this iterable and return List of elements */ fun Iterable.filter(predicate: (T)->Bool): List { var result: List = List() for( item in this ) if( predicate(item) ) result += item result } /* Count all items in this iterable for which predicate returns true */ fun Iterable.count(predicate: (T)->Bool): Int { var hits = 0 this.forEach { if( predicate(it) ) hits++ } hits } /* filter out all null elements from this collection (Iterable); flow of non-null elements is returned */ fun Iterable.filterFlowNotNull(): Flow { filterFlow { it != null } } /* Filter non-null elements and collect them into a List */ fun Iterable.filterNotNull(): List { filter { it != null } } /* Skip the first N elements of this iterable. */ fun Iterable.drop(n: Int): List { var cnt = 0 filter { cnt++ >= n } } /* Return the first element or throw if the iterable is empty. */ val Iterable.first: T get() { val i: Iterator = iterator() if( !i.hasNext() ) throw NoSuchElementException() i.next().also { i.cancelIteration() } } /* Return the first element that matches the predicate or throws NuSuchElementException */ fun Iterable.findFirst(predicate: (T)->Bool): T { for( x in this ) { if( predicate(x) ) break x } else throw NoSuchElementException() } /* return the first element matching the predicate or null */ fun Iterable.findFirstOrNull(predicate: (T)->Bool): T? { for( x in this ) { if( predicate(x) ) break x } else null } /* Return the last element or throw if the iterable is empty. */ val Iterable.last: T get() { var found = false var element: Object = Unset for( i in this ) { element = i found = true } if( !found ) throw NoSuchElementException() element as T } /* Emit all but the last N elements of this iterable. */ fun Iterable.dropLast(n: Int): Flow { val list = this val buffer = RingBuffer(n) flow { for( item in list ) { if( buffer.size == n ) emit( buffer.first() ) buffer += item } } } /* Return the last N elements of this iterable as a buffer/list. */ fun Iterable.takeLast(n: Int): RingBuffer { val buffer: RingBuffer = 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(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 = (result as String) + separator + transformed } result ?: "" } /* Return true if any element matches the predicate. */ fun Iterable.any(predicate: (T)->Bool): Bool { for( i in this ) { if( predicate(i) ) break true } else false } /* Return true if all elements match the predicate. */ fun Iterable.all(predicate: (T)->Bool): Bool { !any { !predicate(it) } } /* Sum all elements; returns null for empty collections. */ fun Iterable.sum(): T? { val i: Iterator = iterator() if( i.hasNext() ) { var result = i.next() while( i.hasNext() ) result += i.next() result } else null } /* Sum mapped values of elements; returns null for empty collections. */ fun Iterable.sumOf(f: (T)->R): R? { val i: Iterator = iterator() if( i.hasNext() ) { var result = f(i.next()) while( i.hasNext() ) result += f(i.next()) result } else null } /* Minimum value of the given function applied to elements of the collection. */ fun Iterable.minOf(lambda: (T)->R): R { val i: Iterator = iterator() var minimum = lambda( i.next() ) while( i.hasNext() ) { val x = lambda(i.next()) if( x < minimum ) minimum = x } minimum } /* Maximum value of the given function applied to elements of the collection. */ fun Iterable.maxOf(lambda: (T)->R): R { val i: Iterator = iterator() var maximum = lambda( i.next() ) while( i.hasNext() ) { val x = lambda(i.next()) if( x > maximum ) maximum = x } maximum } /* Return elements sorted by natural order. */ fun Iterable.sorted(): List { sortedWith { a, b -> a <=> b } } /* Return elements sorted by the key selector. */ fun Iterable.sortedBy(predicate: (T)->R): List { sortedWith { a, b -> predicate(a) <=> predicate(b) } } /* Return a shuffled copy of the iterable as a list. */ fun Iterable.shuffled(): List { val list: List = toList() list.shuffle() list } /* Returns a single list of all elements from all collections in the given collection. @return List */ fun Iterable>.flatten(): List { var result: List = List() forEach { i -> i.forEach { result += it } } result } /* Returns a single list of all elements yielded from results of transform function being invoked on each element of original collection. */ fun Iterable.flatMap(transform: (T)->Iterable): List { val mapped: List> = map(transform) mapped.flatten() } /* Return string representation like [a,b,c]. */ override fun List.toString() { var first = true var result = "[" for (item in this) { if (!first) result += "," result += item.toString() first = false } result + "]" } /* Sort list in-place by key selector. */ fun List.sortBy(predicate: (T)->R): Void { sortWith { a, b -> predicate(a) <=> predicate(b) } } /* Sort list in-place by natural order. */ fun List.sort(): Void { sortWith { a, b -> a <=> b } } /* Print this exception and its stack trace to standard output. */ fun Exception.printStackTrace(): Void { println(this) for( entry in stackTrace ) { println("\tat "+entry.toString()) } } /* Compile this string into a regular expression. */ val String.re: Regex get() = Regex(this) fun TODO(message: Object?=null): Void { throw "not implemented" } /* Provides different access types for delegates. Used in the 'bind' hook to validate delegate usage. */ enum DelegateAccess { Val, Var, Callable } /* Base interface for all delegates. Implementing this interface is optional as Lyng uses dynamic dispatch, but it is recommended for documentation and clarity. */ interface Delegate { /* Called when a delegated 'val' or 'var' is read. */ fun getValue(thisRef: ThisRefType, name: String): T = TODO("delegate getter is not implemented") /* Called when a delegated 'var' is written. */ fun setValue(thisRef: ThisRefType, name: String, newValue: T): Void = TODO("delegate setter is not implemented") /* Called when a delegated function is invoked. */ fun invoke(thisRef: ThisRefType, name: String, args...): Object = TODO("delegate invoke is not implemented") /* Called once during initialization to configure or validate the delegate. Should return the delegate object to be used (usually 'this'). */ fun bind(name: String, access: DelegateAccess, thisRef: ThisRefType): Object = this } /* Executes the block with `this` set to self and returns what the block returns. */ fun with(self: T, block: T.()->R): R { block(self) } /* Standard implementation of a lazy-initialized property delegate. The provided creator lambda is called once on the first access to compute the value. Can only be used with 'val' properties. */ class lazy(creatorParam: ThisRefType.()->T) : Delegate { private val creator: ThisRefType.()->T = creatorParam private var value = Unset override fun bind(name: String, access: DelegateAccess, thisRef: ThisRefType): Object { if (access != DelegateAccess.Val) throw "lazy delegate can only be used with 'val'" this } override fun getValue(thisRef: ThisRefType, name: String): T { if (value == Unset) value = with(thisRef,creator) value as T } } /* Represents a single stack trace element. */ class StackTraceEntry( val sourceName: String, val line: Int, val column: Int, val sourceString: String ) { val at by lazy { "%s:%s:%s"(sourceName,line+1,column+1) } /* Formatted representation: source:line:column: text. */ override fun toString() { "%s: %s"(at, sourceString) } }