From 3beec4847afde28065381411a6c37e078d54b253 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 6 Mar 2012 19:35:12 +0400 Subject: [PATCH] stdlib sources re-added --- libraries/stdlib/src/Arrays.kt | 112 +++++ libraries/stdlib/src/Filter.kt | 49 +++ libraries/stdlib/src/Integer.kt | 9 + libraries/stdlib/src/Iterators.kt | 26 ++ libraries/stdlib/src/JavaCollections.kt | 15 + libraries/stdlib/src/JavaIo.kt | 171 ++++++++ libraries/stdlib/src/JavaIterables.kt | 197 +++++++++ libraries/stdlib/src/JavaIterablesSpecial.kt | 121 ++++++ libraries/stdlib/src/JavaLang.kt | 11 + libraries/stdlib/src/JavaMath.kt | 27 ++ libraries/stdlib/src/JavaUtil.kt | 118 ++++++ libraries/stdlib/src/JavaUtilMap.kt | 58 +++ libraries/stdlib/src/Standard.kt | 71 ++++ libraries/stdlib/src/String.kt | 167 ++++++++ libraries/stdlib/src/System.kt | 19 + .../stdlib/src/concurrent/FunctionalList.kt | 57 +++ .../stdlib/src/concurrent/FunctionalQueue.kt | 30 ++ libraries/stdlib/src/concurrent/Locks.kt | 58 +++ libraries/stdlib/src/concurrent/Thread.kt | 53 +++ libraries/stdlib/src/concurrent/Timer.kt | 71 ++++ libraries/stdlib/src/dom/Dom.kt | 384 ++++++++++++++++++ libraries/stdlib/src/dom/DomJVM.kt | 73 ++++ .../generated/ArraysFromJavaCollections.kt | 16 + .../src/generated/ArraysFromJavaIterables.kt | 200 +++++++++ .../JavaUtilIterablesFromJavaCollections.kt | 16 + .../generated/StandardFromJavaCollections.kt | 16 + .../generated/StandardFromJavaIterables.kt | 188 +++++++++ libraries/stdlib/src/modules/ModuleBuilder.kt | 47 +++ .../kotlin/support/AsserterLoader.kt | 6 + libraries/stdlib/src/properties/Properties.kt | 107 +++++ libraries/stdlib/src/test/Test.kt | 163 ++++++++ 31 files changed, 2656 insertions(+) create mode 100644 libraries/stdlib/src/Arrays.kt create mode 100644 libraries/stdlib/src/Filter.kt create mode 100644 libraries/stdlib/src/Integer.kt create mode 100644 libraries/stdlib/src/Iterators.kt create mode 100644 libraries/stdlib/src/JavaCollections.kt create mode 100644 libraries/stdlib/src/JavaIo.kt create mode 100644 libraries/stdlib/src/JavaIterables.kt create mode 100644 libraries/stdlib/src/JavaIterablesSpecial.kt create mode 100644 libraries/stdlib/src/JavaLang.kt create mode 100644 libraries/stdlib/src/JavaMath.kt create mode 100644 libraries/stdlib/src/JavaUtil.kt create mode 100644 libraries/stdlib/src/JavaUtilMap.kt create mode 100644 libraries/stdlib/src/Standard.kt create mode 100644 libraries/stdlib/src/String.kt create mode 100644 libraries/stdlib/src/System.kt create mode 100644 libraries/stdlib/src/concurrent/FunctionalList.kt create mode 100644 libraries/stdlib/src/concurrent/FunctionalQueue.kt create mode 100644 libraries/stdlib/src/concurrent/Locks.kt create mode 100644 libraries/stdlib/src/concurrent/Thread.kt create mode 100644 libraries/stdlib/src/concurrent/Timer.kt create mode 100644 libraries/stdlib/src/dom/Dom.kt create mode 100644 libraries/stdlib/src/dom/DomJVM.kt create mode 100644 libraries/stdlib/src/generated/ArraysFromJavaCollections.kt create mode 100644 libraries/stdlib/src/generated/ArraysFromJavaIterables.kt create mode 100644 libraries/stdlib/src/generated/JavaUtilIterablesFromJavaCollections.kt create mode 100644 libraries/stdlib/src/generated/StandardFromJavaCollections.kt create mode 100644 libraries/stdlib/src/generated/StandardFromJavaIterables.kt create mode 100644 libraries/stdlib/src/modules/ModuleBuilder.kt create mode 100644 libraries/stdlib/src/org/jetbrains/kotlin/support/AsserterLoader.kt create mode 100644 libraries/stdlib/src/properties/Properties.kt create mode 100644 libraries/stdlib/src/test/Test.kt diff --git a/libraries/stdlib/src/Arrays.kt b/libraries/stdlib/src/Arrays.kt new file mode 100644 index 00000000000..be457620ccc --- /dev/null +++ b/libraries/stdlib/src/Arrays.kt @@ -0,0 +1,112 @@ +package kotlin + +import java.io.ByteArrayInputStream + +import java.util.Arrays + +// Array "constructor" +inline fun array(vararg t : T) : Array = t + +// "constructors" for primitive types array +inline fun doubleArray(vararg content : Double) = content + +inline fun floatArray(vararg content : Float) = content + +inline fun longArray(vararg content : Long) = content + +inline fun intArray(vararg content : Int) = content + +inline fun charArray(vararg content : Char) = content + +inline fun shortArray(vararg content : Short) = content + +inline fun byteArray(vararg content : Byte) = content + +inline fun booleanArray(vararg content : Boolean) = content + +inline fun ByteArray.binarySearch(key: Byte) = Arrays.binarySearch(this, key) +inline fun ShortArray.binarySearch(key: Short) = Arrays.binarySearch(this, key) +inline fun IntArray.binarySearch(key: Int) = Arrays.binarySearch(this, key) +inline fun LongArray.binarySearch(key: Long) = Arrays.binarySearch(this, key) +inline fun FloatArray.binarySearch(key: Float) = Arrays.binarySearch(this, key) +inline fun DoubleArray.binarySearch(key: Double) = Arrays.binarySearch(this, key) +inline fun CharArray.binarySearch(key: Char) = Arrays.binarySearch(this, key) + +inline fun ByteArray.binarySearch(fromIndex: Int, toIndex: Int, key: Byte) = Arrays.binarySearch(this, fromIndex, toIndex, key) +inline fun ShortArray.binarySearch(fromIndex: Int, toIndex: Int, key: Short) = Arrays.binarySearch(this, fromIndex, toIndex, key) +inline fun IntArray.binarySearch(fromIndex: Int, toIndex: Int, key: Int) = Arrays.binarySearch(this, fromIndex, toIndex, key) +inline fun LongArray.binarySearch(fromIndex: Int, toIndex: Int, key: Long) = Arrays.binarySearch(this, fromIndex, toIndex, key) +inline fun FloatArray.binarySearch(fromIndex: Int, toIndex: Int, key: Float) = Arrays.binarySearch(this, fromIndex, toIndex, key) +inline fun DoubleArray.binarySearch(fromIndex: Int, toIndex: Int, key: Double) = Arrays.binarySearch(this, fromIndex, toIndex, key) +inline fun CharArray.binarySearch(fromIndex: Int, toIndex: Int, key: Char) = Arrays.binarySearch(this, fromIndex, toIndex, key) + +/* +inline fun Array.binarySearch(key: T, comparator: fun(T,T):Int) = Arrays.binarySearch(this, key, object: java.util.Comparator { + override fun compare(a: T, b: T) = comparator(a, b) + + override fun equals(obj: Any?) = obj.identityEquals(this) +}) +*/ +inline fun BooleanArray.fill(value: Boolean) = Arrays.fill(this, value) +inline fun ByteArray.fill(value: Byte) = Arrays.fill(this, value) +inline fun ShortArray.fill(value: Short) = Arrays.fill(this, value) +inline fun IntArray.fill(value: Int) = Arrays.fill(this, value) +inline fun LongArray.fill(value: Long) = Arrays.fill(this, value) +inline fun FloatArray.fill(value: Float) = Arrays.fill(this, value) +inline fun DoubleArray.fill(value: Double) = Arrays.fill(this, value) +inline fun CharArray.fill(value: Char) = Arrays.fill(this, value) + +inline fun Array.fill(value: T) = Arrays.fill(this as Array, value) + +inline fun ByteArray.sort() = Arrays.sort(this) +inline fun ShortArray.sort() = Arrays.sort(this) +inline fun IntArray.sort() = Arrays.sort(this) +inline fun LongArray.sort() = Arrays.sort(this) +inline fun FloatArray.sort() = Arrays.sort(this) +inline fun DoubleArray.sort() = Arrays.sort(this) +inline fun CharArray.sort() = Arrays.sort(this) + +inline fun ByteArray.sort(fromIndex: Int, toIndex: Int) = Arrays.sort(this, fromIndex, toIndex) +inline fun ShortArray.sort(fromIndex: Int, toIndex: Int) = Arrays.sort(this, fromIndex, toIndex) +inline fun IntArray.sort(fromIndex: Int, toIndex: Int) = Arrays.sort(this, fromIndex, toIndex) +inline fun LongArray.sort(fromIndex: Int, toIndex: Int) = Arrays.sort(this, fromIndex, toIndex) +inline fun FloatArray.sort(fromIndex: Int, toIndex: Int) = Arrays.sort(this, fromIndex, toIndex) +inline fun DoubleArray.sort(fromIndex: Int, toIndex: Int) = Arrays.sort(this, fromIndex, toIndex) +inline fun CharArray.sort(fromIndex: Int, toIndex: Int) = Arrays.sort(this, fromIndex, toIndex) + +inline fun BooleanArray.copyOf(newLength: Int = this.size) = Arrays.copyOf(this, newLength) +inline fun ByteArray.copyOf(newLength: Int = this.size) = Arrays.copyOf(this, newLength) +inline fun ShortArray.copyOf(newLength: Int = this.size) = Arrays.copyOf(this, newLength) +inline fun IntArray.copyOf(newLength: Int = this.size) = Arrays.copyOf(this, newLength) +inline fun LongArray.copyOf(newLength: Int = this.size) = Arrays.copyOf(this, newLength) +inline fun FloatArray.copyOf(newLength: Int = this.size) = Arrays.copyOf(this, newLength) +inline fun DoubleArray.copyOf(newLength: Int = this.size) = Arrays.copyOf(this, newLength) +inline fun CharArray.copyOf(newLength: Int = this.size) = Arrays.copyOf(this, newLength) + +inline fun Array.copyOf(newLength: Int = this.size) : Array = Arrays.copyOf(this, newLength).sure() + +inline fun BooleanArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(this, from, to) +inline fun ByteArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(this, from, to) +inline fun ShortArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(this, from, to) +inline fun IntArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(this, from, to) +inline fun LongArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(this, from, to) +inline fun FloatArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(this, from, to) +inline fun DoubleArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(this, from, to) +inline fun CharArray.copyOfRange(from: Int, to: Int) = Arrays.copyOfRange(this, from, to) + +inline fun Array.copyOfRange(from: Int, to: Int) : Array = Arrays.copyOfRange(this, from, to).sure() + +inline val ByteArray.inputStream : ByteArrayInputStream + get() = ByteArrayInputStream(this) + +inline fun ByteArray.inputStream(offset: Int, length: Int) = ByteArrayInputStream(this, offset, length) + +/** Returns true if the array is not empty */ +inline fun Array.notEmpty() : Boolean = !this.isEmpty() + +/** Returns true if the array is empty */ +inline fun Array.isEmpty() : Boolean = this.size == 0 + +/** Returns the array if its not null or else returns an empty array */ +inline fun Array?.orEmpty() : Array = if (this != null) this else array() + diff --git a/libraries/stdlib/src/Filter.kt b/libraries/stdlib/src/Filter.kt new file mode 100644 index 00000000000..c0a15369b75 --- /dev/null +++ b/libraries/stdlib/src/Filter.kt @@ -0,0 +1,49 @@ +package kotlin + +import java.util.* +import java.lang.Iterable + +/** Filters given iterator */ +inline fun java.util.Iterator.filter(f: (T)-> Boolean) : java.util.Iterator = FilterIterator(this, f) + +/** Create iterator filtering given java.lang.Iterable */ +/* +inline fun java.lang.Iterable.filter(f: (T)->Boolean) : java.util.Iterator = (iterator() as java.util.Iterator).filter(f) +*/ + +private class FilterIterator(val original: java.util.Iterator, val filter: (T)-> Boolean) : java.util.Iterator { + var state = 0 + var nextElement: T? = null + + override fun hasNext(): Boolean = + when(state) { + 1 -> true // checked and next present + 2 -> false // checked and next not present + else -> { + while(original.hasNext()) { + val candidate = original.next() + if((filter)(candidate)) { + nextElement = candidate + state = 1 + true + } + } + state = 2 + false + } + } + + override fun next(): T = + if(state != 1) + throw java.util.NoSuchElementException() + else { + val res = nextElement as T + nextElement = null + state = 0 + res + } + + override fun remove() { + throw java.lang.UnsupportedOperationException() + } +} diff --git a/libraries/stdlib/src/Integer.kt b/libraries/stdlib/src/Integer.kt new file mode 100644 index 00000000000..dd8af8e21be --- /dev/null +++ b/libraries/stdlib/src/Integer.kt @@ -0,0 +1,9 @@ +package kotlin + +inline fun Int.times(body : () -> Unit) { + var count = this; + while (count > 0) { + body() + count-- + } +} diff --git a/libraries/stdlib/src/Iterators.kt b/libraries/stdlib/src/Iterators.kt new file mode 100644 index 00000000000..8350e149e34 --- /dev/null +++ b/libraries/stdlib/src/Iterators.kt @@ -0,0 +1,26 @@ +package kotlin.util + +import java.util.* +import java.util.Iterator + +/** Add iterated elements to given container */ +fun > java.util.Iterator.to(container: U) : U { + while(hasNext()) + container.add(next()) + return container +} + +/** Add iterated elements to java.util.ArrayList */ +inline fun java.util.Iterator.toArrayList() = to(ArrayList()) + +/** Add iterated elements to java.util.LinkedList */ +inline fun java.util.Iterator.toLinkedList() = to(LinkedList()) + +/** Add iterated elements to java.util.HashSet */ +inline fun java.util.Iterator.toHashSet() = to(HashSet()) + +/** Add iterated elements to java.util.LinkedHashSet */ +inline fun java.util.Iterator.toLinkedHashSet() = to(LinkedHashSet()) + +/** Add iterated elements to java.util.TreeSet */ +inline fun java.util.Iterator.toTreeSet() = to(TreeSet()) diff --git a/libraries/stdlib/src/JavaCollections.kt b/libraries/stdlib/src/JavaCollections.kt new file mode 100644 index 00000000000..5b39244aa19 --- /dev/null +++ b/libraries/stdlib/src/JavaCollections.kt @@ -0,0 +1,15 @@ +package kotlin.util + +import java.util.* + +/** Returns a new List containing the results of applying the given function to each element in this collection */ +inline fun java.util.Collection.map(transform : (T) -> R) : java.util.List { + return mapTo(java.util.ArrayList(this.size), transform) +} + +/** Transforms each element of this collection with the given function then adds the results to the given collection */ +inline fun > java.util.Collection.mapTo(result: C, transform : (T) -> R) : C { + for (item in this) + result.add(transform(item)) + return result +} diff --git a/libraries/stdlib/src/JavaIo.kt b/libraries/stdlib/src/JavaIo.kt new file mode 100644 index 00000000000..e687c90a655 --- /dev/null +++ b/libraries/stdlib/src/JavaIo.kt @@ -0,0 +1,171 @@ +package kotlin.io + +import java.io.* +import java.nio.charset.* +import java.util.NoSuchElementException + +inline fun print(message : Any?) { System.out?.print(message) } +inline fun print(message : Int) { System.out?.print(message) } +inline fun print(message : Long) { System.out?.print(message) } +inline fun print(message : Byte) { System.out?.print(message) } +inline fun print(message : Short) { System.out?.print(message) } +inline fun print(message : Char) { System.out?.print(message) } +inline fun print(message : Boolean) { System.out?.print(message) } +inline fun print(message : Float) { System.out?.print(message) } +inline fun print(message : Double) { System.out?.print(message) } +inline fun print(message : CharArray) { System.out?.print(message) } + +inline fun println(message : Any?) { System.out?.println(message) } +inline fun println(message : Int) { System.out?.println(message) } +inline fun println(message : Long) { System.out?.println(message) } +inline fun println(message : Byte) { System.out?.println(message) } +inline fun println(message : Short) { System.out?.println(message) } +inline fun println(message : Char) { System.out?.println(message) } +inline fun println(message : Boolean) { System.out?.println(message) } +inline fun println(message : Float) { System.out?.println(message) } +inline fun println(message : Double) { System.out?.println(message) } +inline fun println(message : CharArray) { System.out?.println(message) } +inline fun println() { System.out?.println() } + +private val stdin : BufferedReader = BufferedReader(InputStreamReader(object : InputStream() { + override fun read() : Int { + return System.`in`?.read() ?: -1 + } + + override fun reset() { + System.`in`?.reset() + } + + override fun read(b: ByteArray?): Int { + return System.`in`?.read(b) ?: -1 + } + + override fun close() { + System.`in`?.close() + } + + override fun mark(readlimit: Int) { + System.`in`?.mark(readlimit) + } + + override fun skip(n: Long): Long { + return System.`in`?.skip(n) ?: -1.toLong() + } + + override fun available(): Int { + return System.`in`?.available() ?: 0 + } + + override fun markSupported(): Boolean { + return System.`in`?.markSupported() ?: false + } + + override fun read(b: ByteArray?, off: Int, len: Int): Int { + return System.`in`?.read(b, off, len) ?: -1 + } +})) + +inline fun readLine() : String? = stdin.readLine() + +/** Uses the given resource then closes it down correctly whether an exception is thrown or not */ +inline fun T.use(block: (T)-> R) : R { + var closed = false + try { + return block(this) + } catch (e: Exception) { + closed = true + try { + this.close() + } catch (closeException: Exception) { + // eat the closeException as we are already throwing the original cause + // and we don't want to mask the real exception + + // TODO on Java 7 we should call + // e.addSuppressed(closeException) + // to work like try-with-resources + // http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html#suppressed-exceptions + } + throw e + } finally { + if (!closed) { + this.close() + } + } +} + +fun InputStream.iterator() : ByteIterator = + object: ByteIterator() { + override val hasNext : Boolean + get() = available() > 0 + + override fun nextByte() = read().toByte() + } + +inline fun InputStream.buffered(bufferSize: Int) = BufferedInputStream(this, bufferSize) + +inline val InputStream.reader : InputStreamReader + get() = InputStreamReader(this) + +inline val InputStream.bufferedReader : BufferedReader + get() = BufferedReader(reader) + +inline fun InputStream.reader(charset: Charset) : InputStreamReader = InputStreamReader(this, charset) + +inline fun InputStream.reader(charsetName: String) = InputStreamReader(this, charsetName) + +inline fun InputStream.reader(charsetDecoder: CharsetDecoder) = InputStreamReader(this, charsetDecoder) + +inline val InputStream.buffered : BufferedInputStream + get() = if(this is BufferedInputStream) this else BufferedInputStream(this) + +// inline val Reader.buffered : BufferedReader +// get() = if(this is BufferedReader) this else BufferedReader(this) + +inline fun Reader.buffered(): BufferedReader = if(this is BufferedReader) this else BufferedReader(this) + +inline fun Reader.buffered(bufferSize: Int) = BufferedReader(this, bufferSize) + +inline fun Reader.foreachLine(block: (String) -> Unit): Unit { + this.use{ + val iter = buffered().lineIterator() + while (iter.hasNext) { + val elem = iter.next() + block(elem) + } + } +} + +inline fun Reader.useLines(block: (Iterator) -> T): T = this.buffered().use{block(it.lineIterator())} +/** + * Returns an iterator over each line. + * Note the caller must close the underlying BufferedReader + * when the iteration is finished; as the user may not complete the iteration loop (e.g. using a method like find() or any() on the iterator + * may terminate the iteration early. + *
+ * We suggest you try the method useLines() instead which closes the stream when the processing is complete. + */ +inline fun BufferedReader.lineIterator() : Iterator = LineIterator(this) + +protected class LineIterator(val reader: BufferedReader) : Iterator { + private var nextValue: String? = null + private var done = false + + override val hasNext: Boolean + get() { + if (nextValue == null && !done) { + nextValue = reader.readLine() + if (nextValue == null) done = true + } + return nextValue != null + } + + override fun next(): String { + if (!hasNext) { + throw NoSuchElementException() + } + val answer = nextValue + nextValue = null + return answer.sure() + } +} + diff --git a/libraries/stdlib/src/JavaIterables.kt b/libraries/stdlib/src/JavaIterables.kt new file mode 100644 index 00000000000..14092aad1a2 --- /dev/null +++ b/libraries/stdlib/src/JavaIterables.kt @@ -0,0 +1,197 @@ +package kotlin.util + +import java.util.* + +/** Returns true if any elements in the collection match the given predicate */ +inline fun java.lang.Iterable.any(predicate: (T)-> Boolean) : Boolean { + for (elem in this) { + if (predicate(elem)) { + return true + } + } + return false +} + +/** Returns true if all elements in the collection match the given predicate */ +inline fun java.lang.Iterable.all(predicate: (T)-> Boolean) : Boolean { + for (elem in this) { + if (!predicate(elem)) { + return false + } + } + return true +} + +/** Returns the number of items which match the given predicate */ +inline fun java.lang.Iterable.count(predicate: (T)-> Boolean) : Int { + var answer = 0 + for (elem in this) { + if (predicate(elem)) + answer += 1 + } + return answer +} + +/** Returns the first item in the collection which matches the given predicate or null if none matched */ +inline fun java.lang.Iterable.find(predicate: (T)-> Boolean) : T? { + for (elem in this) { + if (predicate(elem)) + return elem + } + return null +} + +/** Returns a new List containing all elements in this collection which match the given predicate */ +inline fun java.lang.Iterable.filter(predicate: (T)-> Boolean) : Collection = filterTo(java.util.ArrayList(), predicate) + +/** Filters all elements in this collection which match the given predicate into the given result collection */ +inline fun > java.lang.Iterable.filterTo(result: C, predicate: (T)-> Boolean) : C { + for (elem in this) { + if (predicate(elem)) + result.add(elem) + } + return result +} + +/** Returns a List containing all the non null elements in this collection */ +inline fun java.lang.Iterable?.filterNulls() : Collection = filterNullsTo(java.util.ArrayList()) + +/** Filters all the null elements in this collection winto the given result collection */ +inline fun > java.lang.Iterable?.filterNullsTo(result: C) : C { + if (this != null) { + for (elem in this) { + if (elem != null) + result.add(elem) + } + } + return result +} + +/** Returns a new collection containing all elements in this collection which do not match the given predicate */ +inline fun java.lang.Iterable.filterNot(predicate: (T)-> Boolean) : Collection = filterNotTo(ArrayList(), predicate) + +/** Returns a new collection containing all elements in this collection which do not match the given predicate */ +inline fun > java.lang.Iterable.filterNotTo(result: C, predicate: (T)-> Boolean) : C { + for (elem in this) { + if (!predicate(elem)) + result.add(elem) + } + return result +} + +/** + * Returns the result of transforming each item in the collection to a one or more values which + * are concatenated together into a single collection + */ +inline fun java.lang.Iterable.flatMap(transform: (T)-> Collection) : Collection { + return flatMapTo(ArrayList(), transform) +} + +/** + * Returns the result of transforming each item in the collection to a one or more values which + * are concatenated together into a single collection + */ +inline fun java.lang.Iterable.flatMapTo(result: Collection, transform: (T)-> Collection) : Collection { + for (elem in this) { + val coll = transform(elem) + if (coll != null) { + for (r in coll) { + result.add(r) + } + } + } + return result +} + +/** Performs the given operation on each element inside the collection */ +inline fun java.lang.Iterable.foreach(operation: (element: T) -> Unit) { + for (elem in this) + operation(elem) +} + +/** + * Folds all the values from from left to right with the initial value to perform the operation on sequential pairs of values + * + * For example to sum together all numeric values in a collection of numbers it would be + * {code}val total = numbers.fold(0){(a, b) -> a + b}{code} + */ +inline fun java.lang.Iterable.fold(initial: T, operation: (it: T, it2: T) -> T): T { + var answer = initial + for (elem in this) { + answer = operation(answer, elem) + } + return answer +} + +/** + * Folds all the values from right to left with the initial value to perform the operation on sequential pairs of values + */ +inline fun java.lang.Iterable.foldRight(initial: T, operation: (it: T, it2: T) -> T): T { + val reversed = this.reverse() + return reversed.fold(initial, operation) +} + +/** + * Iterates through the collection performing the transformation on each element and using the result + * as the key in a map to group elements by the result + */ +inline fun java.lang.Iterable.groupBy(result: Map> = HashMap>(), toKey: (T)-> K) : Map> { + for (elem in this) { + val key = toKey(elem) + val list = result.getOrPut(key){ ArrayList() } + list.add(elem) + } + return result +} + + +/** Creates a String from all the elements in the collection, using the seperator between them and using the given prefix and postfix if supplied */ +inline fun java.lang.Iterable.join(separator: String, prefix: String = "", postfix: String = "") : String { + val buffer = StringBuilder(prefix) + var first = true + for (elem in this) { + if (first) + first = false + else + buffer.append(separator) + buffer.append(elem) + } + buffer.append(postfix) + return buffer.toString().sure() +} + +/** Returns a reversed List of this collection */ +inline fun java.lang.Iterable.reverse() : List { + val answer = LinkedList() + for (elem in this) { + answer.addFirst(elem) + } + return answer +} + +/** Copies the collection into the given collection */ +inline fun > java.lang.Iterable.to(result: C) : C { + for (elem in this) + result.add(elem) + return result +} + +/** Converts the collection into a LinkedList */ +inline fun java.lang.Iterable.toLinkedList() : LinkedList = this.to(LinkedList()) + +/** Converts the collection into a List */ +inline fun java.lang.Iterable.toList() : List = this.to(ArrayList()) + +/** Converts the collection into a Set */ +inline fun java.lang.Iterable.toSet() : Set = this.to(HashSet()) + +/** Converts the collection into a SortedSet */ +inline fun java.lang.Iterable.toSortedSet() : SortedSet = this.to(TreeSet()) +/** + TODO figure out necessary variance/generics ninja stuff... :) +inline fun java.lang.Iterable.toSortedList(transform: fun(T) : java.lang.Comparable<*>) : List { + val answer = this.toList() + answer.sort(transform) + return answer +} +*/ diff --git a/libraries/stdlib/src/JavaIterablesSpecial.kt b/libraries/stdlib/src/JavaIterablesSpecial.kt new file mode 100644 index 00000000000..266593b150c --- /dev/null +++ b/libraries/stdlib/src/JavaIterablesSpecial.kt @@ -0,0 +1,121 @@ +package kotlin.util +// Number of extension function for java.lang.Iterable that shouldn't participate in auto generation + +import java.util.Collection +import java.util.List +import java.util.AbstractList +import java.util.Iterator + +/** + * Count the number of elements in collection. + * + * If base collection implements [[Collection]] interface method [[Collection.size()]] will be used. + * Otherwise, this method determines the count by iterating through the all items. + */ +fun java.lang.Iterable.count() : Int { + if (this is Collection) { + return this.size() + } + + var number : Int = 0 + for (elem in this) { + ++number + } + return number +} + +/** + * Get the first element in the collection. + * + * Will throw an exception if there are no elements + * TODO: Specify type of the exception + */ +inline fun java.lang.Iterable.first() : T { + if (this is AbstractList) { + return this.get(0) + } + + return this.iterator().sure().next() +} + +/** + * Get the last element in the collection. + * + * If base collection implements List interface, the combination of size() and get() + * methods will be used for getting last element. Otherwise, this method determines the + * last item by iterating through the all items. + * + * Will throw an exception if there are no elements. + * TODO: Specify type of the exception + */ +fun java.lang.Iterable.last() : T { + if (this is List) { + return this.get(this.size() - 1); + } + + val iterator = this.iterator().sure() + var last : T = iterator.next() + + while (iterator.hasNext()) { + last = iterator.next() + } + + return last; +} + +/** + * Checks if collection contains given item. + * + * Method checks equality of the objects with T.equals method. + * If collection implements java.util.AbstractCollection an overridden implementation of the contains + * method will be used. + */ +fun java.lang.Iterable.contains(item : T) : Boolean { + kotlin.io.println("!!!!!") + if (this is java.util.AbstractCollection) { + return this.contains(item); + } + + for (var elem in this) { + if (elem.equals(item)) { + return true + } + } + + return false +} + +/** + * Convert collection of arbitrary elements to collection of + */ +fun java.lang.Iterable.withIndices() : java.lang.Iterable<#(Int, T)> { + return object : java.lang.Iterable<#(Int, T)> { + override fun iterator(): java.util.Iterator<#(Int, T)> { + // TODO explicit typecast as a workaround for KT-1457, should be removed when it is fixed + return NumberedIterator(this@withIndices.iterator().sure()) as java.util.Iterator<#(Int, T)> + } + } +} + +private class NumberedIterator(private val sourceIterator : java.util.Iterator) : java.util.Iterator<#(Int, TT)> { + private var nextIndex = 0 + + override fun remove() { + try { + sourceIterator.remove() + nextIndex--; + } catch (e : UnsupportedOperationException) { + throw e + } + } + + override fun hasNext(): Boolean { + return sourceIterator.hasNext(); + } + + override fun next(): #(Int, TT) { + val result = #(nextIndex, sourceIterator.next()) + nextIndex++ + return result + } +} \ No newline at end of file diff --git a/libraries/stdlib/src/JavaLang.kt b/libraries/stdlib/src/JavaLang.kt new file mode 100644 index 00000000000..83212bc03e6 --- /dev/null +++ b/libraries/stdlib/src/JavaLang.kt @@ -0,0 +1,11 @@ +package kotlin + +import java.lang.Class +import java.lang.Object + +import jet.runtime.Intrinsic + +val T.javaClass : Class + [Intrinsic("kotlin.javaClass.property")] get() = (this as java.lang.Object).getClass() as Class + +[Intrinsic("kotlin.javaClass.function")] fun javaClass() : Class = null as Class diff --git a/libraries/stdlib/src/JavaMath.kt b/libraries/stdlib/src/JavaMath.kt new file mode 100644 index 00000000000..40aeb16336f --- /dev/null +++ b/libraries/stdlib/src/JavaMath.kt @@ -0,0 +1,27 @@ +package kotlin.math + +import java.math.BigInteger +import java.math.BigDecimal + +fun BigInteger.plus(other: BigInteger) = this.add(other).sure() + +fun BigInteger.minus(other: BigInteger) = this.subtract(other).sure() + +fun BigInteger.times(other: BigInteger) = this.multiply(other).sure() + +fun BigInteger.div(other: BigInteger) = this.divide(other).sure() + +fun BigInteger.minus() = this.negate().sure() + + +fun BigDecimal.plus(other: BigDecimal) = this.add(other).sure() + +fun BigDecimal.minus(other: BigDecimal) = this.subtract(other).sure() + +fun BigDecimal.times(other: BigDecimal) = this.multiply(other).sure() + +fun BigDecimal.div(other: BigDecimal) = this.divide(other).sure() + +fun BigDecimal.mod(other: BigDecimal) = this.remainder(other).sure() + +fun BigDecimal.minus() = this.negate().sure() \ No newline at end of file diff --git a/libraries/stdlib/src/JavaUtil.kt b/libraries/stdlib/src/JavaUtil.kt new file mode 100644 index 00000000000..3ae59cbf6ad --- /dev/null +++ b/libraries/stdlib/src/JavaUtil.kt @@ -0,0 +1,118 @@ +package kotlin.util + +import java.util.* +import java.util.regex.Pattern + +/** Returns the size of the collection */ +val Collection<*>.size : Int + get() = size() + +/** Returns true if this collection is empty */ +val Collection<*>.empty : Boolean + get() = isEmpty() + +/** Returns a new ArrayList with a variable number of initial elements */ +inline fun arrayList(vararg values: T) : ArrayList = values.to(ArrayList(values.size)) + +/** Returns a new LinkedList with a variable number of initial elements */ +inline fun linkedList(vararg values: T) : LinkedList = values.to(LinkedList()) + +/** Returns a new HashSet with a variable number of initial elements */ +inline fun hashSet(vararg values: T) : HashSet = values.to(HashSet(values.size)) + +inline fun hashMap(): HashMap = HashMap() + +inline fun sortedMap(): SortedMap = TreeMap() + + +val Collection<*>.indices : IntRange + get() = 0..size-1 + +inline fun java.util.Collection.toArray() : Array { + val answer = Array(this.size) + var idx = 0 + for (elem in this) + answer[idx++] = elem + return answer as Array +} + +/** TODO these functions don't work when they generate the Array versions when they are in JavaIterables */ +inline fun > java.lang.Iterable.toSortedList() : List = toList().sort() + +inline fun > java.lang.Iterable.toSortedList(comparator: java.util.Comparator) : List = toList().sort(comparator) + + + +// List APIs + +inline fun > List.sort() : List { + Collections.sort(this) + return this +} + +inline fun > List.sort(comparator: java.util.Comparator) : List { + Collections.sort(this, comparator) + return this +} + +/** Returns the List if its not null otherwise returns the empty list */ +inline fun java.util.List?.orEmpty() : java.util.List + = if (this != null) this else Collections.EMPTY_LIST as java.util.List + +/** Returns the Set if its not null otherwise returns the empty set */ +inline fun java.util.Set?.orEmpty() : java.util.Set + = if (this != null) this else Collections.EMPTY_SET as java.util.Set + +/** + TODO figure out necessary variance/generics ninja stuff... :) +inline fun List.sort(transform: fun(T) : java.lang.Comparable<*>) : List { + val comparator = java.util.Comparator() { + fun compare(o1: T, o2: T): Int { + val v1 = transform(o1) + val v2 = transform(o2) + if (v1 == v2) { + return 0 + } else { + return v1.compareTo(v2) + } + } + } + answer.sort(comparator) +} +*/ + +val List.head : T? + get() = this.get(0) + +val List.first : T? + get() = this.head + +val List.tail : T? + get() { + val s = this.size + return if (s > 0) this.get(s - 1) else null + } + +val List.last : T? + get() = this.tail + + +/** Returns true if the collection is not empty */ +inline fun java.util.Collection.notEmpty() : Boolean = !this.isEmpty() + +/** Returns the Collection if its not null otherwise it returns the empty list */ +inline fun java.util.Collection?.orEmpty() : Collection + = if (this != null) this else Collections.EMPTY_LIST as Collection + +/** Converts the string into a regular expression [[Pattern]] so that strings can be split or matched on */ +inline fun String.toRegex(): Pattern { + return Pattern.compile(this).sure() +} + +/** + * Converts the string into a regular expression [[Pattern]] with the given flags from [[Pattern]] or'd together + * so that strings can be split or matched on + */ +inline fun String.toRegex(flags: Int): Pattern { + return Pattern.compile(this, flags).sure() +} \ No newline at end of file diff --git a/libraries/stdlib/src/JavaUtilMap.kt b/libraries/stdlib/src/JavaUtilMap.kt new file mode 100644 index 00000000000..4ef04bddf6f --- /dev/null +++ b/libraries/stdlib/src/JavaUtilMap.kt @@ -0,0 +1,58 @@ +package kotlin.util + +import java.util.Map as JMap +import java.util.HashMap +import java.util.Collections + +// Temporary workaround: commenting out +//import java.util.Map.Entry as JEntry + +// Map APIs + +/** Returns the size of the map */ +val JMap<*,*>.size : Int + get() = size() + +/** Returns true if this map is empty */ +val JMap<*,*>.empty : Boolean + get() = isEmpty() + +/** Provides [] access to maps */ +fun JMap.set(key : K, value : V) = this.put(key, value) + +/** Returns the Mao if its not null otherwise it returns the empty Map */ +inline fun java.util.Map?.orEmpty() : java.util.Map + = if (this != null) this else Collections.EMPTY_MAP as java.util.Map + + +/** Returns the key of the entry */ +// Temporary workaround: commenting out +//val JEntry.key : K +// get() = getKey().sure() + +/** Returns the value of the entry */ +// Temporary workaround: commenting out +//val JEntry.value : V +// get() = getValue().sure() + +/** Returns the value for the given key or returns the result of the defaultValue function if there was no entry for the given key */ +inline fun java.util.Map.getOrElse(key: K, defaultValue: ()-> V) : V { + val current = this.get(key) + if (current != null) { + return current + } else { + return defaultValue() + } +} + +/** Returns the value for the given key or the result of the defaultValue function is put into the map for the given value and returned */ +inline fun java.util.Map.getOrPut(key: K, defaultValue: ()-> V) : V { + val current = this.get(key) + if (current != null) { + return current + } else { + val answer = defaultValue() + this.put(key, answer) + return answer + } +} diff --git a/libraries/stdlib/src/Standard.kt b/libraries/stdlib/src/Standard.kt new file mode 100644 index 00000000000..c575a484de6 --- /dev/null +++ b/libraries/stdlib/src/Standard.kt @@ -0,0 +1,71 @@ +package kotlin + +import java.util.Collection +import java.util.ArrayList +import java.util.LinkedList +import java.util.HashSet +import java.util.LinkedHashSet +import java.util.TreeSet + +/** +Helper to make jet.Iterator usable in for +*/ +inline fun jet.Iterator.iterator() = this + +/** +Helper to make java.util.Iterator usable in for +*/ +inline fun java.util.Iterator.iterator() = this + +/** +Helper to make java.util.Enumeration usable in for +*/ +fun java.util.Enumeration.iterator(): Iterator = object: Iterator { + override val hasNext: Boolean + get() = hasMoreElements() + + override fun next() = nextElement() +} + +/* + * Extension functions on the standard Kotlin types to behave like the java.lang.* and java.util.* collections + */ + +/** +Add iterated elements to given container +*/ +fun > Iterator.to(container: U) : U { + while(hasNext) + container.add(next()) + return container +} + +/** +Add iterated elements to java.util.ArrayList +*/ +inline fun Iterator.toArrayList() = to(ArrayList()) + +/** +Add iterated elements to java.util.LinkedList +*/ +inline fun Iterator.toLinkedList() = to(LinkedList()) + +/** +Add iterated elements to java.util.HashSet +*/ +inline fun Iterator.toHashSet() = to(HashSet()) + +/** +Add iterated elements to java.util.LinkedHashSet +*/ +inline fun Iterator.toLinkedHashSet() = to(LinkedHashSet()) + +/** +Add iterated elements to java.util.TreeSet +*/ +inline fun Iterator.toTreeSet() = to(TreeSet()) + +/** +Run function f +*/ +inline fun run(f: () -> T) = f() diff --git a/libraries/stdlib/src/String.kt b/libraries/stdlib/src/String.kt new file mode 100644 index 00000000000..6f6ac6540f0 --- /dev/null +++ b/libraries/stdlib/src/String.kt @@ -0,0 +1,167 @@ +package kotlin + +import java.io.StringReader + +inline fun String.lastIndexOf(str: String) = (this as java.lang.String).lastIndexOf(str) + +inline fun String.lastIndexOf(ch: Char) = (this as java.lang.String).lastIndexOf(ch.toString()) + +inline fun String.equalsIgnoreCase(anotherString: String) = (this as java.lang.String).equalsIgnoreCase(anotherString) + +inline fun String.indexOf(str : String) = (this as java.lang.String).indexOf(str) + +inline fun String.indexOf(str : String, fromIndex : Int) = (this as java.lang.String).indexOf(str, fromIndex) + +inline fun String.replace(oldChar: Char, newChar : Char) = (this as java.lang.String).replace(oldChar, newChar).sure() + +inline fun String.replaceAll(regex: String, replacement : String) = (this as java.lang.String).replaceAll(regex, replacement).sure() + +inline fun String.trim() = (this as java.lang.String).trim().sure() + +/** Returns the string with leading and trailing text matching the given string removed */ +inline fun String.trim(text: String) = trimLeading(text).trimTrailing(text) + +/** Returns the string with the prefix and postfix text trimmed */ +inline fun String.trim(prefix: String, postfix: String) = trimLeading(prefix).trimTrailing(postfix) + +/** Returns the string with the leading prefix of this string removed */ +inline fun String.trimLeading(prefix: String): String { + var answer = this + if (answer.startsWith(prefix)) { + answer = answer.substring(prefix.length()) + } + return answer +} + +/** Returns the string with the trailing postfix of this string removed */ +inline fun String.trimTrailing(postfix: String): String { + var answer = this + if (answer.endsWith(postfix)) { + answer = answer.substring(0, length() - postfix.length()) + } + return answer +} + +inline fun String.toUpperCase() = (this as java.lang.String).toUpperCase().sure() + +inline fun String.toLowerCase() = (this as java.lang.String).toLowerCase().sure() + +inline fun String.length() = (this as java.lang.String).length() + +inline fun String.getBytes() = (this as java.lang.String).getBytes().sure() + +inline fun String.toCharArray() = (this as java.lang.String).toCharArray().sure() + +inline fun String.format(format : String, vararg args : Any?) = java.lang.String.format(format, args).sure() + +inline fun String.split(regex : String) = (this as java.lang.String).split(regex) + +inline fun String.substring(beginIndex : Int) = (this as java.lang.String).substring(beginIndex).sure() + +inline fun String.substring(beginIndex : Int, endIndex : Int) = (this as java.lang.String).substring(beginIndex, endIndex).sure() + +inline fun String.startsWith(prefix: String) = (this as java.lang.String).startsWith(prefix) + +inline fun String.startsWith(prefix: String, toffset: Int) = (this as java.lang.String).startsWith(prefix, toffset) + +inline fun String.contains(seq: CharSequence) : Boolean = (this as java.lang.String).contains(seq) + +inline fun String.endsWith(suffix: String) : Boolean = (this as java.lang.String).endsWith(suffix) + +inline val String.size : Int +get() = length() + +inline val String.reader : StringReader +get() = StringReader(this) + +// "constructors" for String + +inline fun String(bytes : ByteArray, offset : Int, length : Int, charsetName : String) = java.lang.String(bytes, offset, length, charsetName) as String + +inline fun String(bytes : ByteArray, offset : Int, length : Int, charset : java.nio.charset.Charset) = java.lang.String(bytes, offset, length, charset) as String + +inline fun String(bytes : ByteArray, charsetName : String?) = java.lang.String(bytes, charsetName) as String + +inline fun String(bytes : ByteArray, charset : java.nio.charset.Charset) = java.lang.String(bytes, charset) as String + +inline fun String(bytes : ByteArray, i : Int, i1 : Int) = java.lang.String(bytes, i, i1) as String + +inline fun String(bytes : ByteArray) = java.lang.String(bytes) as String + +inline fun String(chars : CharArray) = java.lang.String(chars) as String + +inline fun String(stringBuffer : java.lang.StringBuffer) = java.lang.String(stringBuffer) as String + +inline fun String(stringBuilder : java.lang.StringBuilder) = java.lang.String(stringBuilder) as String + +/** Returns true if the string is not null and not empty */ +inline fun String?.notEmpty() : Boolean = this != null && this.length() > 0 + +/** +Iterator for characters of given CharSequence +*/ +inline fun CharSequence.iterator() : CharIterator = object: jet.CharIterator() { + private var index = 0 + + public override fun nextChar(): Char = get(index++) + + public override val hasNext: Boolean + get() = index < length +} + +inline fun String.replaceFirst(regex : String, replacement : String) = (this as java.lang.String).replaceFirst(regex, replacement).sure() + +inline fun String.charAt(index : Int) = (this as java.lang.String).charAt(index).sure() + +inline fun String.split(regex : String, limit : Int) = (this as java.lang.String).split(regex, limit).sure() + +inline fun String.codePointAt(index : Int) = (this as java.lang.String).codePointAt(index).sure() + +inline fun String.codePointBefore(index : Int) = (this as java.lang.String).codePointBefore(index).sure() + +inline fun String.codePointCount(beginIndex : Int, endIndex : Int) = (this as java.lang.String).codePointCount(beginIndex, endIndex) + +inline fun String.compareToIgnoreCase(str : String) = (this as java.lang.String).compareToIgnoreCase(str).sure() + +inline fun String.concat(str : String) = (this as java.lang.String).concat(str).sure() + +inline fun String.contentEquals(cs : CharSequence) = (this as java.lang.String).contentEquals(cs).sure() + +inline fun String.contentEquals(sb : StringBuffer) = (this as java.lang.String).contentEquals(sb).sure() + +inline fun String.getBytes(charset : java.nio.charset.Charset) = (this as java.lang.String).getBytes(charset).sure() + +inline fun String.getBytes(charsetName : String) = (this as java.lang.String).getBytes(charsetName).sure() + +inline fun String.getChars(srcBegin : Int, srcEnd : Int, dst : CharArray, dstBegin : Int) = (this as java.lang.String).getChars(srcBegin, srcEnd, dst, dstBegin).sure() + +inline fun String.indexOf(ch : Char) = (this as java.lang.String).indexOf(ch.toString()).sure() + +inline fun String.indexOf(ch : Char, fromIndex : Int) = (this as java.lang.String).indexOf(ch.toString(), fromIndex).sure() + +inline fun String.intern() = (this as java.lang.String).intern().sure() + +inline fun String.isEmpty() = (this as java.lang.String).isEmpty().sure() + +inline fun String.lastIndexOf(ch : Char, fromIndex : Int) = (this as java.lang.String).lastIndexOf(ch.toString(), fromIndex).sure() + +inline fun String.lastIndexOf(str : String, fromIndex : Int) = (this as java.lang.String).lastIndexOf(str, fromIndex).sure() + +inline fun String.matches(regex : String) = (this as java.lang.String).matches(regex).sure() + +inline fun String.offsetByCodePoints(index : Int, codePointOffset : Int) = (this as java.lang.String).offsetByCodePoints(index, codePointOffset).sure() + +inline fun String.regionMatches(ignoreCase : Boolean, toffset : Int, other : String, ooffset : Int, len : Int) = (this as java.lang.String).regionMatches(ignoreCase, toffset, other, ooffset, len).sure() + +inline fun String.regionMatches(toffset : Int, other : String, ooffset : Int, len : Int) = (this as java.lang.String).regionMatches(toffset, other, ooffset, len).sure() + +inline fun String.replace(target : CharSequence, replacement : CharSequence) = (this as java.lang.String).replace(target, replacement).sure() + +inline fun String.subSequence(beginIndex : Int, endIndex : Int) = (this as java.lang.String).subSequence(beginIndex, endIndex).sure() + +inline fun String.toLowerCase(locale : java.util.Locale) = (this as java.lang.String).toLowerCase(locale).sure() + +inline fun String.toUpperCase(locale : java.util.Locale) = (this as java.lang.String).toUpperCase(locale).sure() + +/** Returns the string if it is not null or the empty string if its null */ +inline fun String?.orEmpty(): String = this ?: "" \ No newline at end of file diff --git a/libraries/stdlib/src/System.kt b/libraries/stdlib/src/System.kt new file mode 100644 index 00000000000..af27fe41cd1 --- /dev/null +++ b/libraries/stdlib/src/System.kt @@ -0,0 +1,19 @@ +package kotlin.util + +/** +Executes current block and returns elapsed time in milliseconds +*/ +fun measureTimeMillis(block: () -> Unit) : Long { + val start = System.currentTimeMillis() + block() + return System.currentTimeMillis() - start +} + +/** +Executes current block and returns elapsed time in nanoseconds +*/ +fun measureTimeNano(block: () -> Unit) : Long { + val start = System.nanoTime() + block() + return System.nanoTime() - start +} diff --git a/libraries/stdlib/src/concurrent/FunctionalList.kt b/libraries/stdlib/src/concurrent/FunctionalList.kt new file mode 100644 index 00000000000..f441d73f47d --- /dev/null +++ b/libraries/stdlib/src/concurrent/FunctionalList.kt @@ -0,0 +1,57 @@ +package kotlin.concurrent + +abstract class FunctionalList(public val size: Int) { + public abstract val head: T + public abstract val tail: FunctionalList + + val empty : Boolean + get() = size == 0 + + fun add(element: T) : FunctionalList = FunctionalList.Standard(element, this) + + fun reversed() : FunctionalList { + if(empty) + return this + + var cur = tail + var new = of(head) + + while(!cur.empty) { + new = new.add(cur.head) + cur = cur.tail + } + return new + } + + fun iterator() = object: Iterator { + var cur = this@FunctionalList + + override fun next(): T { + if(cur.empty) + throw java.util.NoSuchElementException() + + val head = cur.head + cur = cur.tail + return head + } + + override val hasNext: Boolean + get() = !cur.empty + } + + class object { + class Empty() : FunctionalList(0) { + override val head: T + get() = throw java.util.NoSuchElementException() + override val tail: FunctionalList + get() = throw java.util.NoSuchElementException() + } + + class Standard(override val head: T, override val tail: FunctionalList) : FunctionalList(tail.size+1) + + fun emptyList() = Empty() + + fun of(element: T) : FunctionalList = FunctionalList.Standard(element,emptyList()) + } +} + diff --git a/libraries/stdlib/src/concurrent/FunctionalQueue.kt b/libraries/stdlib/src/concurrent/FunctionalQueue.kt new file mode 100644 index 00000000000..10c3eaf3b03 --- /dev/null +++ b/libraries/stdlib/src/concurrent/FunctionalQueue.kt @@ -0,0 +1,30 @@ +package kotlin.concurrent + +import java.util.concurrent.Executor +import jet.Iterator + +class FunctionalQueue ( + val input: FunctionalList = FunctionalList.emptyList(), + val output: FunctionalList = FunctionalList.emptyList()) { + + val size : Int + get() = input.size + output.size + + val empty : Boolean + get() = size == 0 + + fun add(element: T) = FunctionalQueue(input add element, output) + + fun addFirst(element: T) = FunctionalQueue(input, output add element) + + fun removeFirst() : #(T,FunctionalQueue) = + if(output.empty) { + if(input.empty) + throw java.util.NoSuchElementException() + else + FunctionalQueue(FunctionalList.emptyList(), input.reversed()).removeFirst() + } + else { + #(output.head, FunctionalQueue(input, output.tail)) + } +} diff --git a/libraries/stdlib/src/concurrent/Locks.kt b/libraries/stdlib/src/concurrent/Locks.kt new file mode 100644 index 00000000000..39d4609ea84 --- /dev/null +++ b/libraries/stdlib/src/concurrent/Locks.kt @@ -0,0 +1,58 @@ +package kotlin.concurrent + +import java.util.concurrent.locks.Lock +import java.util.concurrent.locks.ReadWriteLock +import java.util.concurrent.locks.ReentrantReadWriteLock +import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock + +/** +Executes given calculation under lock +Returns result of the calculation +*/ +inline fun Lock.withLock(action: ()->T) : T { + lock() + try { + return action() + } + finally { + unlock(); + } +} + +/** +Executes given calculation under read lock +Returns result of the calculation +*/ +inline fun ReentrantReadWriteLock.read(action: ()->T) : T { + val rl = readLock().sure() + rl.lock() + try { + return action() + } + finally { + rl.unlock() + } +} + +/** +Executes given calculation under write lock. +The method does upgrade from read to write lock if needed +If such write has been initiated by checking some condition, the condition must be rechecked inside the action to avoid possible races +Returns result of the calculation +*/ +inline fun ReentrantReadWriteLock.write(action: ()->T) : T { + val rl = readLock().sure() + + val readCount = if (getWriteHoldCount() == 0) getReadHoldCount() else 0 + readCount times { rl.unlock() } + + val wl = writeLock().sure() + wl.lock() + try { + return action() + } + finally { + readCount times { rl.lock() } + wl.unlock() + } +} diff --git a/libraries/stdlib/src/concurrent/Thread.kt b/libraries/stdlib/src/concurrent/Thread.kt new file mode 100644 index 00000000000..6a513291ead --- /dev/null +++ b/libraries/stdlib/src/concurrent/Thread.kt @@ -0,0 +1,53 @@ +package kotlin.concurrent + +import java.lang.* +import java.util.concurrent.Executor + +inline val currentThread : Thread + get() = Thread.currentThread().sure() + +inline var Thread.name : String + get() = getName().sure() + set(name: String) { setName(name) } + +inline var Thread.daemon : Boolean + get() = isDaemon() + set(on: Boolean) { setDaemon(on) } + +inline val Thread.alive : Boolean + get() = isAlive() + +inline var Thread.priority : Int + get() = getPriority() + set(prio: Int) { setPriority(prio) } + +inline var Thread.contextClassLoader : ClassLoader? + get() = getContextClassLoader() + set(loader: ClassLoader?) { setContextClassLoader(loader) } + +fun thread(start: Boolean = true, daemon: Boolean = false, contextClassLoader: ClassLoader? = null, name: String? = null, priority: Int = -1, block: ()->Unit) : Thread { + val thread = object: Thread() { + override fun run() { + block() + } + } + if(daemon) + thread.setDaemon(true) + if(priority > 0) + thread.setPriority(priority) + if(name != null) + thread.setName(name) + if(contextClassLoader != null) + thread.setContextClassLoader(contextClassLoader) + if(start) + thread.start() + return thread +} + +inline fun Executor.execute(action: ()->Unit) { + execute(object: Runnable{ + override fun run() { + action() + } + }) +} diff --git a/libraries/stdlib/src/concurrent/Timer.kt b/libraries/stdlib/src/concurrent/Timer.kt new file mode 100644 index 00000000000..d3ad1b68fc8 --- /dev/null +++ b/libraries/stdlib/src/concurrent/Timer.kt @@ -0,0 +1,71 @@ +package kotlin.concurrent + +import java.util.Timer +import java.util.TimerTask +import java.util.Date + +fun Timer.schedule(delay: Long, action: TimerTask.()->Unit) : TimerTask { + val task = createTask(action) + schedule(task, delay) + return task +} + +fun Timer.schedule(time: Date, action: TimerTask.()->Unit) : TimerTask { + val task = createTask(action) + schedule(task, time) + return task +} + +fun Timer.schedule(delay: Long, period: Long, action: TimerTask.()->Unit) : TimerTask { + val task = createTask(action) + schedule(task, delay, period) + return task +} + +fun Timer.schedule(time: Date, period: Long, action: TimerTask.()->Unit) : TimerTask { + val task = createTask(action) + schedule(task, time, period) + return task +} + +fun Timer.scheduleAtFixedRate(delay: Long, period: Long, action: TimerTask.()->Unit) : TimerTask { + val task = createTask(action) + scheduleAtFixedRate(task, delay, period) + return task +} + +fun Timer.scheduleAtFixedRate(time: Date, period: Long, action: TimerTask.()->Unit) : TimerTask { + val task = createTask(action) + scheduleAtFixedRate(task, time, period) + return task +} + +fun timer(name: String? = null, daemon: Boolean = false, initialDelay: Long = 0.toLong(), period: Long, action: TimerTask.()->Unit) : Timer { + val timer = if(name == null) Timer(daemon) else Timer(name, daemon) + timer.schedule(initialDelay, period, action) + return timer +} + +fun timer(name: String? = null, daemon: Boolean = false, startAt: Date, period: Long, action: TimerTask.()->Unit) : Timer { + val timer = if(name == null) Timer(daemon) else Timer(name, daemon) + timer.schedule(startAt, period, action) + return timer +} + +fun fixedRateTimer(name: String? = null, daemon: Boolean = false, initialDelay: Long = 0.toLong(), period: Long, action: TimerTask.()->Unit) : Timer { + val timer = if(name == null) Timer(daemon) else Timer(name, daemon) + timer.scheduleAtFixedRate(initialDelay, period, action) + return timer +} + +fun fixedRateTimer(name: String? = null, daemon: Boolean = false, startAt: Date, period : Long, action: TimerTask.()->Unit) : Timer { + val timer = if(name == null) Timer(daemon) else Timer(name, daemon) + timer.scheduleAtFixedRate(startAt, period, action) + return timer +} + +private fun createTask(action: TimerTask.()->Unit) : TimerTask = object: TimerTask() { + override fun run() { + action() + } +} \ No newline at end of file diff --git a/libraries/stdlib/src/dom/Dom.kt b/libraries/stdlib/src/dom/Dom.kt new file mode 100644 index 00000000000..e925b51d5d2 --- /dev/null +++ b/libraries/stdlib/src/dom/Dom.kt @@ -0,0 +1,384 @@ +package kotlin.dom + +import kotlin.* +import kotlin.util.* +import java.util.* +import org.w3c.dom.* + + +// Properties + +val Document?.rootElement : Element? +get() = if (this != null) this.getDocumentElement() else null + + +var Node.text : String +get() { + if (this is Element) { + return this.text + } else { + return this.getNodeValue() ?: "" + } +} +set(value) { + if (this is Element) { + this.text = value + } else { + this.setNodeValue(value) + } +} + +var Element.text : String +get() { + val buffer = StringBuilder() + val nodeList = this.getChildNodes() + if (nodeList != null) { + var i = 0 + val size = nodeList.getLength() + while (i < size) { + val node = nodeList.item(i) + if (node != null) { + if (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.CDATA_SECTION_NODE) { + buffer.append(node.getNodeValue()) + } + } + i++ + } + } + return buffer.toString().sure() +} +set(value) { + // lets remove all the previous text nodes first + this.setAttribute("id", value) +} + +var Element.id : String +get() = this.getAttribute("id")?: "" +set(value) { + this.setAttribute("id", value) + this.setIdAttribute("id", true) +} + +var Element.style : String +get() = this.getAttribute("style")?: "" +set(value) { + this.setAttribute("style", value) +} + +var Element.classes : String +get() = this.getAttribute("class")?: "" +set(value) { + this.setAttribute("class", value) +} + +var Element.classSet : Set +get() { + val answer = LinkedHashSet() + val array = this.classes.split("""\s""") + for (s in array) { + if (s != null && s.size > 0) { + answer.add(s) + } + } + return answer +} +set(value) { + this.classes = value.join(" ") +} + + +// Helper methods + +/** Returns true if the element has the given CSS class style in its 'class' attribute */ +fun Element.hasClass(cssClass: String): Boolean { + val c = this.classes + return if (c != null) + c.matches("""(^|.*\s+)$cssClass($|\s+.*)""") + else false +} + +/** Adds the given CSS class to this element's 'class' attribute */ +fun Element.addClass(cssClass: String): Boolean { + val classSet = this.classSet + val answer = classSet.add(cssClass) + if (answer) { + this.classSet = classSet + } + return answer +} + +/** Removes the given CSS class to this element's 'class' attribute */ +fun Element.removeClass(cssClass: String): Boolean { + val classSet = this.classSet + val answer = classSet.remove(cssClass) + if (answer) { + this.classSet = classSet + } + return answer +} + +/** TODO this approach generates compiler errors... + +fun Element.addClass(varargs cssClasses: Array): Boolean { + val set = this.classSet + var answer = false + for (cs in cssClasses) { + if (set.add(cs)) { + answer = true + } + } + if (answer) { + this.classSet = classSet + } + return answer +} + +fun Element.removeClass(varargs cssClasses: Array): Boolean { + val set = this.classSet + var answer = false + for (cs in cssClasses) { + if (set.remove(cs)) { + answer = true + } + } + if (answer) { + this.classSet = classSet + } + return answer +} +*/ + +/** Searches for elements using the element name, an element ID (if prefixed with dot) or element class (if prefixed with #) */ +fun Document?.get(selector: String): List { + val root = this?.getDocumentElement() + return if (root != null) { + if (selector == "*") { + elements + } else if (selector.startsWith(".")) { + elements.filter{ it.hasClass(selector.substring(1)) }.toList() + } else if (selector.startsWith("#")) { + val id = selector.substring(1) + val element = this?.getElementById(id) + return if (element != null) + Collections.singletonList(element).sure() as List + else + Collections.EMPTY_LIST.sure() as List + } else { + // assume its a vanilla element name + elements(selector) + } + } else { + Collections.EMPTY_LIST as List + } +} + +/** Searches for elements using the element name, an element ID (if prefixed with dot) or element class (if prefixed with #) */ +fun Element.get(selector: String): List { + return if (selector == "*") { + elements + } else if (selector.startsWith(".")) { + elements.filter{ it.hasClass(selector.substring(1)) }.toList() + } else if (selector.startsWith("#")) { + val element = this.getOwnerDocument()?.getElementById(selector.substring(1)) + return if (element != null) + Collections.singletonList(element).sure() as List + else + Collections.EMPTY_LIST.sure() as List + } else { + // assume its a vanilla element name + elements(selector) + } +} + +/** Returns the attribute value or empty string if its not present */ +inline fun Element.attribute(name: String): String { + return this.getAttribute(name) ?: "" +} + +/** Returns the children of the element as a list */ +inline fun Element?.children(): List { + return this?.getChildNodes().toList() +} + +/** The child elements of this document */ +val Document?.elements : List +get() = this?.getElementsByTagName("*").toElementList() + +/** The child elements of this elements */ +val Element?.elements : List +get() = this?.getElementsByTagName("*").toElementList() + + +/** Returns all the child elements given the local element name */ +inline fun Element?.elements(localName: String?): List { + return this?.getElementsByTagName(localName).toElementList() +} + +/** Returns all the elements given the local element name */ +inline fun Document?.elements(localName: String?): List { + return this?.getElementsByTagName(localName).toElementList() +} + +/** Returns all the child elements given the namespace URI and local element name */ +inline fun Element?.elements(namespaceUri: String?, localName: String?): List { + return this?.getElementsByTagNameNS(namespaceUri, localName).toElementList() +} + +/** Returns all the elements given the namespace URI and local element name */ +inline fun Document?.elements(namespaceUri: String?, localName: String?): List { + return this?.getElementsByTagNameNS(namespaceUri, localName).toElementList() +} + +val NodeList?.head : Node? +get() = if (this != null && this.getLength() > 0) this.item(0) else null + +val NodeList?.first : Node? +get() = this.head + +val NodeList?.tail : Node? +get() { + if (this == null) { + return null + } else { + val s = this.getLength() + return if (s > 0) this.item(s - 1) else null + } +} + +val NodeList?.last : Node? +get() = this.tail + + +inline fun NodeList?.toList(): List { + return if (this == null) { + Collections.EMPTY_LIST as List + } + else { + NodeListAsList(this) + } +} + +inline fun NodeList?.toElementList(): List { + return if (this == null) { + Collections.EMPTY_LIST as List + } + else { + ElementListAsList(this) + } +} + +/** Converts the node list to an XML String */ +fun NodeList?.toXmlString(xmlDeclaration: Boolean = false): String { + return if (this == null) + "" else { + this.toList().toXmlString(xmlDeclaration) + } +} + +class NodeListAsList(val nodeList: NodeList): AbstractList() { + override fun get(index: Int): Node { + val node = nodeList.item(index) + if (node == null) { + throw IndexOutOfBoundsException("NodeList does not contain a node at index: " + index) + } else { + return node + } + } + + override fun size(): Int = nodeList.getLength() +} + +class ElementListAsList(val nodeList: NodeList): AbstractList() { + override fun get(index: Int): Element { + val node = nodeList.item(index) + if (node is Element) { + return node + } else { + if (node == null) { + throw IndexOutOfBoundsException("NodeList does not contain a node at index: " + index) + } else { + throw IllegalArgumentException("Node is not an Element as expected but is $node") + } + } + } + + override fun size(): Int = nodeList.getLength() + +} + + +// Syntax sugar + +inline fun Node.plus(child: Node?): Node { + if (child != null) { + this.appendChild(child) + } + return this +} + +inline fun Element.plus(text: String?): Element = this.addText(text) + +inline fun Element.plusAssign(text: String?): Element = this.addText(text) + + +// Builder + +/** + * Creates a new element which can be configured via a function + */ +fun Document.createElement(name: String, init: Element.()-> Unit): Element { + val elem = this.createElement(name).sure() + elem.init() + return elem +} + +/** + * Creates a new element to an element which has an owner Document which can be configured via a function + */ +fun Element.createElement(name: String, doc: Document? = null, init: Element.()-> Unit): Element { + val elem = ownerDocument(doc).createElement(name).sure() + elem.init() + return elem +} + +/** Returns the owner document of the element or uses the provided document */ +fun Node.ownerDocument(doc: Document? = null): Document { + val answer = if (this is Document) this as Document + else if (doc == null) this.getOwnerDocument() + else doc + + if (answer == null) { + throw IllegalArgumentException("Element does not have an ownerDocument and none was provided for: ${this}") + } else { + return answer + } +} + +/** +Adds a newly created element which can be configured via a function +*/ +fun Document.addElement(name: String, init: Element.()-> Unit): Element { + val child = createElement(name, init) + this.appendChild(child) + return child +} + +/** +Adds a newly created element to an element which has an owner Document which can be configured via a function +*/ +fun Element.addElement(name: String, doc: Document? = null, init: Element.()-> Unit): Element { + val child = createElement(name, doc, init) + this.appendChild(child) + return child +} + +/** +Adds a newly created text node to an element which either already has an owner Document or one must be provided as a parameter +*/ +fun Element.addText(text: String?, doc: Document? = null): Element { + if (text != null) { + val child = ownerDocument(doc).createTextNode(text) + this.appendChild(child) + } + return this +} diff --git a/libraries/stdlib/src/dom/DomJVM.kt b/libraries/stdlib/src/dom/DomJVM.kt new file mode 100644 index 00000000000..31f6373e6f3 --- /dev/null +++ b/libraries/stdlib/src/dom/DomJVM.kt @@ -0,0 +1,73 @@ +/** + * JVM specific API implementations using JAXB and so forth which would not be used when compiling to JS + */ +package kotlin.dom + +import org.w3c.dom.* +import javax.xml.parsers.DocumentBuilder +import javax.xml.parsers.DocumentBuilderFactory +import javax.xml.transform.Transformer +import javax.xml.transform.TransformerFactory +import javax.xml.transform.Source +import javax.xml.transform.dom.DOMSource +import javax.xml.transform.stream.StreamResult + +import java.io.StringWriter +import javax.xml.transform.OutputKeys +import java.lang.Iterable +import java.util.List +import java.util.Collection + +/** Creates a new document with the given document builder*/ +fun createDocument(builder: DocumentBuilder): Document { + return builder.newDocument().sure() +} + +/** Creates a new document with an optional DocumentBuilderFactory */ +fun createDocument(builderFactory: DocumentBuilderFactory = DocumentBuilderFactory.newInstance().sure()): Document { + return createDocument(builderFactory.newDocumentBuilder().sure()) +} + +/** Creates a new TrAX transformer */ +fun createTransformer(source: Source? = null, factory: TransformerFactory = TransformerFactory.newInstance().sure()): Transformer { + val transformer = if (source != null) { + factory.newTransformer(source) + } else { + factory.newTransformer() + } + return transformer.sure() +} + +/** Converts the node to an XML String */ +fun Node.toXmlString(xmlDeclaration: Boolean = this is Document): String { + return nodeToXmlString(this, xmlDeclaration) +} + +/** Converts the collection of nodes to an XML String */ +fun java.lang.Iterable.toXmlString(xmlDeclaration: Boolean = false): String { + // TODO this should work... + // return this.map{it.toXmlString()}.join("") + val builder = StringBuilder() + for (n in this) { + builder.append(n.toXmlString(xmlDeclaration)) + } + return builder.toString().sure() +} + + +/* +fun Document.toXmlString(xmlDeclaration: Boolean = true): String { + return nodeToXmlString(this, xmlDeclaration) +} +*/ + +/** Converts the node to an XML String */ +fun nodeToXmlString(node: Node, xmlDeclaration: Boolean): String { + val transformer = createTransformer() + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, if (xmlDeclaration) "no" else "yes") + val buffer = StringWriter() + transformer.transform(DOMSource(node), StreamResult(buffer)) + return buffer.toString().sure() + +} + diff --git a/libraries/stdlib/src/generated/ArraysFromJavaCollections.kt b/libraries/stdlib/src/generated/ArraysFromJavaCollections.kt new file mode 100644 index 00000000000..d8b1c6e14ff --- /dev/null +++ b/libraries/stdlib/src/generated/ArraysFromJavaCollections.kt @@ -0,0 +1,16 @@ +// NOTE this file is auto-generated from stdlib/ktSrc/JavaCollections.kt +package kotlin + +import java.util.* + +/** Returns a new List containing the results of applying the given function to each element in this collection */ +inline fun Array.map(transform : (T) -> R) : java.util.List { + return mapTo(java.util.ArrayList(this.size), transform) +} + +/** Transforms each element of this collection with the given function then adds the results to the given collection */ +inline fun > Array.mapTo(result: C, transform : (T) -> R) : C { + for (item in this) + result.add(transform(item)) + return result +} diff --git a/libraries/stdlib/src/generated/ArraysFromJavaIterables.kt b/libraries/stdlib/src/generated/ArraysFromJavaIterables.kt new file mode 100644 index 00000000000..8d5a80aa89d --- /dev/null +++ b/libraries/stdlib/src/generated/ArraysFromJavaIterables.kt @@ -0,0 +1,200 @@ +// NOTE this file is auto-generated from stdlib/ktSrc/JavaIterables.kt +package kotlin + +import kotlin.util.* + +import java.util.* + +/** Returns true if any elements in the collection match the given predicate */ +inline fun Array.any(predicate: (T)-> Boolean) : Boolean { + for (elem in this) { + if (predicate(elem)) { + return true + } + } + return false +} + +/** Returns true if all elements in the collection match the given predicate */ +inline fun Array.all(predicate: (T)-> Boolean) : Boolean { + for (elem in this) { + if (!predicate(elem)) { + return false + } + } + return true +} + +/** Returns the number of items which match the given predicate */ +inline fun Array.count(predicate: (T)-> Boolean) : Int { + var answer = 0 + for (elem in this) { + if (predicate(elem)) + answer += 1 + } + return answer +} + +/** Returns the first item in the collection which matches the given predicate or null if none matched */ +inline fun Array.find(predicate: (T)-> Boolean) : T? { + for (elem in this) { + if (predicate(elem)) + return elem + } + return null +} + +/** Returns a new List containing all elements in this collection which match the given predicate */ +inline fun Array.filter(predicate: (T)-> Boolean) : Collection = filterTo(java.util.ArrayList(), predicate) + +/** Filters all elements in this collection which match the given predicate into the given result collection */ +inline fun > Array.filterTo(result: C, predicate: (T)-> Boolean) : C { + for (elem in this) { + if (predicate(elem)) + result.add(elem) + } + return result +} + +/** Returns a List containing all the non null elements in this collection */ +inline fun Array?.filterNulls() : Collection = filterNullsTo(java.util.ArrayList()) + +/** Filters all the null elements in this collection winto the given result collection */ +inline fun > Array?.filterNullsTo(result: C) : C { + if (this != null) { + for (elem in this) { + if (elem != null) + result.add(elem) + } + } + return result +} + +/** Returns a new collection containing all elements in this collection which do not match the given predicate */ +inline fun Array.filterNot(predicate: (T)-> Boolean) : Collection = filterNotTo(ArrayList(), predicate) + +/** Returns a new collection containing all elements in this collection which do not match the given predicate */ +inline fun > Array.filterNotTo(result: C, predicate: (T)-> Boolean) : C { + for (elem in this) { + if (!predicate(elem)) + result.add(elem) + } + return result +} + +/** + * Returns the result of transforming each item in the collection to a one or more values which + * are concatenated together into a single collection + */ +inline fun Array.flatMap(transform: (T)-> Collection) : Collection { + return flatMapTo(ArrayList(), transform) +} + +/** + * Returns the result of transforming each item in the collection to a one or more values which + * are concatenated together into a single collection + */ +inline fun Array.flatMapTo(result: Collection, transform: (T)-> Collection) : Collection { + for (elem in this) { + val coll = transform(elem) + if (coll != null) { + for (r in coll) { + result.add(r) + } + } + } + return result +} + +/** Performs the given operation on each element inside the collection */ +inline fun Array.foreach(operation: (element: T) -> Unit) { + for (elem in this) + operation(elem) +} + +/** + * Folds all the values from from left to right with the initial value to perform the operation on sequential pairs of values + * + * For example to sum together all numeric values in a collection of numbers it would be + * {code}val total = numbers.fold(0){(a, b) -> a + b}{code} + */ +inline fun Array.fold(initial: T, operation: (it: T, it2: T) -> T): T { + var answer = initial + for (elem in this) { + answer = operation(answer, elem) + } + return answer +} + +/** + * Folds all the values from right to left with the initial value to perform the operation on sequential pairs of values + */ +inline fun Array.foldRight(initial: T, operation: (it: T, it2: T) -> T): T { + val reversed = this.reverse() + return reversed.fold(initial, operation) +} + +/** + * Iterates through the collection performing the transformation on each element and using the result + * as the key in a map to group elements by the result + */ +inline fun Array.groupBy(result: Map> = HashMap>(), toKey: (T)-> K) : Map> { + for (elem in this) { + val key = toKey(elem) + val list = result.getOrPut(key){ ArrayList() } + list.add(elem) + } + return result +} + + +/** Creates a String from all the elements in the collection, using the seperator between them and using the given prefix and postfix if supplied */ +inline fun Array.join(separator: String, prefix: String = "", postfix: String = "") : String { + val buffer = StringBuilder(prefix) + var first = true + for (elem in this) { + if (first) + first = false + else + buffer.append(separator) + buffer.append(elem) + } + buffer.append(postfix) + return buffer.toString().sure() +} + +/** Returns a reversed List of this collection */ +inline fun Array.reverse() : List { + val answer = LinkedList() + for (elem in this) { + answer.addFirst(elem) + } + return answer +} + +/** Copies the collection into the given collection */ +inline fun > Array.to(result: C) : C { + for (elem in this) + result.add(elem) + return result +} + +/** Converts the collection into a LinkedList */ +inline fun Array.toLinkedList() : LinkedList = this.to(LinkedList()) + +/** Converts the collection into a List */ +inline fun Array.toList() : List = this.to(ArrayList()) + +/** Converts the collection into a Set */ +inline fun Array.toSet() : Set = this.to(HashSet()) + +/** Converts the collection into a SortedSet */ +inline fun Array.toSortedSet() : SortedSet = this.to(TreeSet()) +/** + TODO figure out necessary variance/generics ninja stuff... :) +inline fun Array.toSortedList(transform: fun(T) : java.lang.Comparable<*>) : List { + val answer = this.toList() + answer.sort(transform) + return answer +} +*/ diff --git a/libraries/stdlib/src/generated/JavaUtilIterablesFromJavaCollections.kt b/libraries/stdlib/src/generated/JavaUtilIterablesFromJavaCollections.kt new file mode 100644 index 00000000000..db9fa82bdef --- /dev/null +++ b/libraries/stdlib/src/generated/JavaUtilIterablesFromJavaCollections.kt @@ -0,0 +1,16 @@ +// NOTE this file is auto-generated from stdlib/ktSrc/JavaCollections.kt +package kotlin.util + +import java.util.* + +/** Returns a new List containing the results of applying the given function to each element in this collection */ +inline fun java.lang.Iterable.map(transform : (T) -> R) : java.util.List { + return mapTo(java.util.ArrayList(), transform) +} + +/** Transforms each element of this collection with the given function then adds the results to the given collection */ +inline fun > java.lang.Iterable.mapTo(result: C, transform : (T) -> R) : C { + for (item in this) + result.add(transform(item)) + return result +} diff --git a/libraries/stdlib/src/generated/StandardFromJavaCollections.kt b/libraries/stdlib/src/generated/StandardFromJavaCollections.kt new file mode 100644 index 00000000000..0421c4a631e --- /dev/null +++ b/libraries/stdlib/src/generated/StandardFromJavaCollections.kt @@ -0,0 +1,16 @@ +// NOTE this file is auto-generated from stdlib/ktSrc/JavaCollections.kt +package kotlin + +import java.util.* + +/** Returns a new List containing the results of applying the given function to each element in this collection */ +inline fun Iterable.map(transform : (T) -> R) : java.util.List { + return mapTo(java.util.ArrayList(), transform) +} + +/** Transforms each element of this collection with the given function then adds the results to the given collection */ +inline fun > Iterable.mapTo(result: C, transform : (T) -> R) : C { + for (item in this) + result.add(transform(item)) + return result +} diff --git a/libraries/stdlib/src/generated/StandardFromJavaIterables.kt b/libraries/stdlib/src/generated/StandardFromJavaIterables.kt new file mode 100644 index 00000000000..6f3470b2f73 --- /dev/null +++ b/libraries/stdlib/src/generated/StandardFromJavaIterables.kt @@ -0,0 +1,188 @@ +// NOTE this file is auto-generated from stdlib/ktSrc/JavaIterables.kt +package kotlin + +import kotlin.util.* + +import java.util.* + +/** Returns true if any elements in the collection match the given predicate */ +inline fun Iterable.any(predicate: (T)-> Boolean) : Boolean { + for (elem in this) { + if (predicate(elem)) { + return true + } + } + return false +} + +/** Returns true if all elements in the collection match the given predicate */ +inline fun Iterable.all(predicate: (T)-> Boolean) : Boolean { + for (elem in this) { + if (!predicate(elem)) { + return false + } + } + return true +} + +/** Returns the number of items which match the given predicate */ +inline fun Iterable.count(predicate: (T)-> Boolean) : Int { + var answer = 0 + for (elem in this) { + if (predicate(elem)) + answer += 1 + } + return answer +} + +/** Returns the first item in the collection which matches the given predicate or null if none matched */ +inline fun Iterable.find(predicate: (T)-> Boolean) : T? { + for (elem in this) { + if (predicate(elem)) + return elem + } + return null +} + +/** Returns a new List containing all elements in this collection which match the given predicate */ +inline fun Iterable.filter(predicate: (T)-> Boolean) : Collection = filterTo(java.util.ArrayList(), predicate) + +/** Filters all elements in this collection which match the given predicate into the given result collection */ +inline fun > Iterable.filterTo(result: C, predicate: (T)-> Boolean) : C { + for (elem in this) { + if (predicate(elem)) + result.add(elem) + } + return result +} + + + +/** Returns a new collection containing all elements in this collection which do not match the given predicate */ +inline fun Iterable.filterNot(predicate: (T)-> Boolean) : Collection = filterNotTo(ArrayList(), predicate) + +/** Returns a new collection containing all elements in this collection which do not match the given predicate */ +inline fun > Iterable.filterNotTo(result: C, predicate: (T)-> Boolean) : C { + for (elem in this) { + if (!predicate(elem)) + result.add(elem) + } + return result +} + +/** + * Returns the result of transforming each item in the collection to a one or more values which + * are concatenated together into a single collection + */ +inline fun Iterable.flatMap(transform: (T)-> Collection) : Collection { + return flatMapTo(ArrayList(), transform) +} + +/** + * Returns the result of transforming each item in the collection to a one or more values which + * are concatenated together into a single collection + */ +inline fun Iterable.flatMapTo(result: Collection, transform: (T)-> Collection) : Collection { + for (elem in this) { + val coll = transform(elem) + if (coll != null) { + for (r in coll) { + result.add(r) + } + } + } + return result +} + +/** Performs the given operation on each element inside the collection */ +inline fun Iterable.foreach(operation: (element: T) -> Unit) { + for (elem in this) + operation(elem) +} + +/** + * Folds all the values from from left to right with the initial value to perform the operation on sequential pairs of values + * + * For example to sum together all numeric values in a collection of numbers it would be + * {code}val total = numbers.fold(0){(a, b) -> a + b}{code} + */ +inline fun Iterable.fold(initial: T, operation: (it: T, it2: T) -> T): T { + var answer = initial + for (elem in this) { + answer = operation(answer, elem) + } + return answer +} + +/** + * Folds all the values from right to left with the initial value to perform the operation on sequential pairs of values + */ +inline fun Iterable.foldRight(initial: T, operation: (it: T, it2: T) -> T): T { + val reversed = this.reverse() + return reversed.fold(initial, operation) +} + +/** + * Iterates through the collection performing the transformation on each element and using the result + * as the key in a map to group elements by the result + */ +inline fun Iterable.groupBy(result: Map> = HashMap>(), toKey: (T)-> K) : Map> { + for (elem in this) { + val key = toKey(elem) + val list = result.getOrPut(key){ ArrayList() } + list.add(elem) + } + return result +} + + +/** Creates a String from all the elements in the collection, using the seperator between them and using the given prefix and postfix if supplied */ +inline fun Iterable.join(separator: String, prefix: String = "", postfix: String = "") : String { + val buffer = StringBuilder(prefix) + var first = true + for (elem in this) { + if (first) + first = false + else + buffer.append(separator) + buffer.append(elem) + } + buffer.append(postfix) + return buffer.toString().sure() +} + +/** Returns a reversed List of this collection */ +inline fun Iterable.reverse() : List { + val answer = LinkedList() + for (elem in this) { + answer.addFirst(elem) + } + return answer +} + +/** Copies the collection into the given collection */ +inline fun > Iterable.to(result: C) : C { + for (elem in this) + result.add(elem) + return result +} + +/** Converts the collection into a LinkedList */ +inline fun Iterable.toLinkedList() : LinkedList = this.to(LinkedList()) + +/** Converts the collection into a List */ +inline fun Iterable.toList() : List = this.to(ArrayList()) + +/** Converts the collection into a Set */ +inline fun Iterable.toSet() : Set = this.to(HashSet()) + +/** Converts the collection into a SortedSet */ +inline fun Iterable.toSortedSet() : SortedSet = this.to(TreeSet()) +/** + TODO figure out necessary variance/generics ninja stuff... :) +inline fun Iterable.toSortedList(transform: fun(T) : java.lang.Comparable<*>) : List { + val answer = this.toList() + answer.sort(transform) + return answer +} +*/ diff --git a/libraries/stdlib/src/modules/ModuleBuilder.kt b/libraries/stdlib/src/modules/ModuleBuilder.kt new file mode 100644 index 00000000000..301e41930a8 --- /dev/null +++ b/libraries/stdlib/src/modules/ModuleBuilder.kt @@ -0,0 +1,47 @@ +package kotlin.modules + +import java.util.* +import jet.modules.* + +fun module(name: String, callback: ModuleBuilder.() -> Unit) { + val builder = ModuleBuilder(name) + builder.callback() + AllModules.modules.sure().get()?.add(builder) +} + +class SourcesBuilder(val parent: ModuleBuilder) { + fun plusAssign(pattern: String) { + parent.addSourceFiles(pattern) + } +} + +class ClasspathBuilder(val parent: ModuleBuilder) { + fun plusAssign(name: String) { + parent.addClasspathEntry(name) + } +} + +open class ModuleBuilder(val name: String): Module { + // http://youtrack.jetbrains.net/issue/KT-904 + private val sourceFiles0: ArrayList = ArrayList() + private val classpathRoots0: ArrayList = ArrayList() + + val sources: SourcesBuilder + get() = SourcesBuilder(this) + + val classpath: ClasspathBuilder + get() = ClasspathBuilder(this) + + fun addSourceFiles(pattern: String) { + sourceFiles0.add(pattern) + } + + fun addClasspathEntry(name: String) { + classpathRoots0.add(name) + } + + override fun getSourceFiles(): List? = sourceFiles0 + override fun getClasspathRoots(): List? = classpathRoots0 + override fun getModuleName(): String? = name +} + diff --git a/libraries/stdlib/src/org/jetbrains/kotlin/support/AsserterLoader.kt b/libraries/stdlib/src/org/jetbrains/kotlin/support/AsserterLoader.kt new file mode 100644 index 00000000000..9720634c929 --- /dev/null +++ b/libraries/stdlib/src/org/jetbrains/kotlin/support/AsserterLoader.kt @@ -0,0 +1,6 @@ +package org.jetbrains.kotlin.support + +fun loadAsserter(): Unit { + val c = javaClass() + println("class is $c") +} \ No newline at end of file diff --git a/libraries/stdlib/src/properties/Properties.kt b/libraries/stdlib/src/properties/Properties.kt new file mode 100644 index 00000000000..3636d7bec01 --- /dev/null +++ b/libraries/stdlib/src/properties/Properties.kt @@ -0,0 +1,107 @@ +package kotlin.properties + +import kotlin.* +import kotlin.util.* +import java.util.List +import java.util.Map +import java.util.HashMap +import java.util.ArrayList + +class ChangeEvent(val source: Any, val name: String, val oldValue: Any?, val newValue: Any?) { + var propogationId: Any? = null + + fun toString() = "ChangeEvent($name, $oldValue, $newValue)" +} + +trait ChangeListener { + fun onPropertyChange(event: ChangeEvent): Unit +} + +/** + * Represents an object where properties can be listened to and notified on + * updates for easier binding to user interfaces, undo/redo command stacks and + * change tracking mechanisms for persistence or distributed change notifications. + */ +abstract class ChangeSupport { + private var allListeners: List? = null + private var nameListeners: Map>? = null + + + fun addChangeListener(listener: ChangeListener) { + if (allListeners == null) { + allListeners = ArrayList() + } + allListeners?.add(listener) + } + + fun addChangeListener(name: String, listener: ChangeListener) { + if (nameListeners == null) { + nameListeners = HashMap>() + } + var listeners = nameListeners?.get(name) + if (listeners == null) { + listeners = arrayList() + nameListeners?.put(name, listeners.sure()) + } + listeners?.add(listener) + } + + protected fun changeProperty(name: String, oldValue: T?, newValue: T?): Unit { + if (oldValue != newValue) { + firePropertyChanged(ChangeEvent(this, name, oldValue, newValue)) + } + } + + protected fun firePropertyChanged(event: ChangeEvent): Unit { + if (nameListeners != null) { + val listeners = nameListeners?.get(event.name) + if (listeners != null) { + for (listener in listeners) { + listener.onPropertyChange(event) + } + } + } + if (allListeners != null) { + for (listener in allListeners) { + listener.onPropertyChange(event) + } + } + } + + fun onPropertyChange(fn: (ChangeEvent) -> Unit) { + // TODO + //addChangeListener(DelegateChangeListener(fn)) + } + + fun onPropertyChange(name: String, fn: (ChangeEvent) -> Unit) { + // TODO + //addChangeListener(name, DelegateChangeListener(fn)) + } +} + +/* +TODO this seems to generate a compiler barf! +see http://youtrack.jetbrains.com/issue/KT-1362 + + protected fun createChangeListener(fn: (ChangeEvent) -> Unit): ChangeListener { + return DelegateChangeListener(fn) + } + + protected fun createChangeListener(fn: (ChangeEvent) -> Unit): ChangeListener { + return ChangeListener { + override fun onPropertyChange(event: ChangeEvent): Unit { + fn(event) + } + } + } + +} + + +class DelegateChangeListener(val f: (ChangeEvent) -> Unit) : ChangeListener { + override fun onPropertyChange(event: ChangeEvent): Unit { + f(event) + } +} + + diff --git a/libraries/stdlib/src/test/Test.kt b/libraries/stdlib/src/test/Test.kt new file mode 100644 index 00000000000..310cf5cf33f --- /dev/null +++ b/libraries/stdlib/src/test/Test.kt @@ -0,0 +1,163 @@ +/** + * A number of helper methods for writing Kool unit tests + */ +package kotlin.test + +import java.util.ServiceLoader + +private var _asserter: Asserter? = null + +fun asserter(): Asserter { + if (_asserter == null) { + /* TODO + val loader = ServiceLoader.load(javaClass) + for (a in loader) { + if (a != null) { + _asserter = a + break + } + } + */ + if (_asserter == null) { + _asserter = DefaultAsserter() + } + } + return _asserter.sure() +} + +/** Asserts that the given block returns true */ +inline fun assertTrue(message: String, block: ()-> Boolean) { + val actual = block() + asserter().assertTrue(message, actual) +} + +/** Asserts that the given block returns true */ +inline fun assertTrue(block: ()-> Boolean) = assertTrue(block.toString(), block) + +/** Asserts that the given block returns false */ +inline fun assertNot(message: String, block: ()-> Boolean) { + assertTrue(message){ !block() } +} + +/** Asserts that the given block returns true */ +inline fun assertNot(block: ()-> Boolean) = assertNot(block.toString(), block) + +/** Asserts that the expression is true with an optional message */ +inline fun assertTrue(actual: Boolean, message: String = "") { + return assertEquals(true, actual, message) +} + +/** Asserts that the expression is false with an optional message */ +inline fun assertFalse(actual: Boolean, message: String = "") { + return assertEquals(false, actual, message) +} + +/** Asserts that the expected value is equal to the actual value, with an optional message */ +inline fun assertEquals(expected: Any?, actual: Any?, message: String = "") { + asserter().assertEquals(message, expected, actual) +} + +/** Asserts that the expression is not null, with an optional message */ +inline fun assertNotNull(actual: Any?, message: String = "") { + asserter().assertNotNull(message, actual) +} + +/** Asserts that the expression is null, with an optional message */ +inline fun assertNull(actual: Any?, message: String = "") { + asserter().assertNull(message, actual) +} + +/** Marks a test as having failed if this point in the execution path is reached, with an optional message */ +inline fun fail(message: String = "") { + asserter().fail(message) +} + +/** Asserts that given function block returns the given expected value */ +inline fun expect(expected: T, block: ()-> T) { + expect(expected, block.toString(), block) +} + +/** Asserts that given function block returns the given expected value and use the given message if it fails */ +inline fun expect(expected: T, message: String, block: ()-> T) { + val actual = block() + assertEquals(expected, actual, message) +} + +/** Asserts that given function block fails by throwing an exception */ +fun fails(block: ()-> Unit): Exception? { + try { + block() + asserter().fail("Expected an exception to be thrown") + return null + } catch (e: Exception) { + println("Caught excepted exception: $e") + return e + } +} + +/** Asserts that a block fails with a specific exception being thrown */ +fun failsWith(block: ()-> Unit) { + try { + block() + asserter().fail("Expected an exception to be thrown") + } catch (e: T) { + println("Caught excepted exception: $e") + // OK + } +} + +/** + * Comments out a block of test code until it is implemented while keeping a link to the code + * to implement in your unit test output + */ +inline fun todo(block: ()-> Any) { + println("TODO at " + (Exception() as java.lang.Throwable).getStackTrace()?.get(1) + " for " + block) +} + +/** + * A plugin for performing assertions which can reuse JUnit or TestNG + */ +trait Asserter { + fun assertTrue(message: String, actual: Boolean): Unit + + fun assertEquals(message: String, expected: Any?, actual: Any?): Unit + + fun assertNotNull(message: String, actual: Any?): Unit + + fun assertNull(message: String, actual: Any?): Unit + + fun fail(message: String): Unit +} + +/** + * Default implementation to avoid dependency on JUnit or TestNG + */ +class DefaultAsserter() : Asserter { + + override fun assertTrue(message : String, actual : Boolean) { + if (!actual) { + fail(message) + } + } + + override fun assertEquals(message : String, expected : Any?, actual : Any?) { + if (expected != actual) { + fail("$message. Expected <$expected> actual <$actual>") + } + } + + override fun assertNotNull(message : String, actual : Any?) { + if (actual == null) { + fail(message) + } + } + + override fun assertNull(message : String, actual : Any?) { + if (actual != null) { + fail(message) + } + } + override fun fail(message : String) { + throw AssertionError(message) + } +} \ No newline at end of file