diff --git a/stdlib/ktSrc/JavaIterables.kt b/stdlib/ktSrc/JavaIterables.kt new file mode 100644 index 00000000000..1bfecd5e104 --- /dev/null +++ b/stdlib/ktSrc/JavaIterables.kt @@ -0,0 +1,116 @@ +// Note: this file is used to generate methods on Array too +package std.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 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 collection containing all elements in this collection which match the given predicate */ +inline fun java.lang.Iterable.filter(result: Collection = ArrayList(), predicate: (T)-> Boolean) : Collection { + 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(result: Collection = ArrayList(), 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) +} + +/** 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 new collection containing the results of applying the given function to each element in this collection */ +/* +inline fun java.lang.Iterable.map(result: Collection = ArrayList(), transform : (T) -> R) : Collection { + for (item in this) + result.add(transform(item)) + return result +} +*/ + +/** Returns a new collection containing the results of applying the given function to each element in this collection */ +inline fun java.util.Collection.map(result: Collection = ArrayList(this.size), transform : (T) -> R) : Collection { + for (item in this) + result.add(transform(item)) + return result +} + +inline fun > java.lang.Iterable.to(result: C) : C { + for (elem in this) + result.add(elem) + return result +} + +inline fun java.lang.Iterable.toLinkedList() : LinkedList = this.to(LinkedList()) + +inline fun java.lang.Iterable.toList() : List = this.to(ArrayList()) + +inline fun java.lang.Iterable.toSet() : Set = this.to(HashSet()) + +/** + 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/stdlib/ktSrc/JavaUtil.kt b/stdlib/ktSrc/JavaUtil.kt index c54e9b1b6ef..f275339cbf2 100644 --- a/stdlib/ktSrc/JavaUtil.kt +++ b/stdlib/ktSrc/JavaUtil.kt @@ -19,127 +19,6 @@ inline fun linkedList(vararg values: T) : LinkedList = values.to(LinkedLi /** Returns a new HashSet with a variable number of initial elements */ inline fun hashSet(vararg values: T) : HashSet = values.to(HashSet(values.size)) -/** 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 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 collection containing all elements in this collection which match the given predicate */ -inline fun java.lang.Iterable.filter(result: Collection = ArrayList(), predicate: (T)-> Boolean) : Collection { - 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(result: Collection = ArrayList(), 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) -} - -/** 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 new collection containing the results of applying the given function to each element in this collection */ -inline fun java.lang.Iterable.map(result: Collection = ArrayList(), transform : (T) -> R) : Collection { - for (item in this) - result.add(transform(item)) - return result -} - -/** Returns a new collection containing the results of applying the given function to each element in this collection */ -inline fun java.util.Collection.map(result: Collection = ArrayList(this.size), transform : (T) -> R) : Collection { - for (item in this) - result.add(transform(item)) - return result -} - -// TODO would be nice to not have to write extension methods for Array, Iterable and Iterator - -inline fun > Array.to(result: C) : C { - for (elem in this) - result.add(elem) - return result -} - -inline fun > java.lang.Iterable.to(result: C) : C { - for (elem in this) - result.add(elem) - return result -} - -inline fun java.lang.Iterable.toLinkedList() : LinkedList = this.to(LinkedList()) - -inline fun java.lang.Iterable.toList() : List = this.to(ArrayList()) - -inline fun java.lang.Iterable.toSet() : Set = this.to(HashSet()) - -inline fun > java.lang.Iterable.toSortedList() : List = toList().sort() - -inline fun > java.lang.Iterable.toSortedList(comparator: java.util.Comparator) : List = toList().sort(comparator) - -/** - 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 -} -*/ inline fun java.util.Collection.toArray() : Array { val answer = Array(this.size) @@ -149,6 +28,12 @@ inline fun java.util.Collection.toArray() : Array { 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 diff --git a/stdlib/ktSrc/generated/ArraysGenerated.kt b/stdlib/ktSrc/generated/ArraysGenerated.kt new file mode 100644 index 00000000000..0e71d7b3739 --- /dev/null +++ b/stdlib/ktSrc/generated/ArraysGenerated.kt @@ -0,0 +1,117 @@ +// NOTE this file is auto-generated from stdlib/ktSrc/JavaIterables.kt +package std +// Note: this file is used to generate methods on Array too + +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 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 collection containing all elements in this collection which match the given predicate */ +inline fun Array.filter(result: Collection = ArrayList(), predicate: (T)-> Boolean) : Collection { + 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(result: Collection = ArrayList(), 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) +} + +/** 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 new collection containing the results of applying the given function to each element in this collection */ +/* +inline fun Array.map(result: Collection = ArrayList(), transform : (T) -> R) : Collection { + for (item in this) + result.add(transform(item)) + return result +} +*/ + +/** Returns a new collection containing the results of applying the given function to each element in this collection */ +inline fun Array.map(result: Collection = ArrayList(this.size), transform : (T) -> R) : Collection { + for (item in this) + result.add(transform(item)) + return result +} + +inline fun > Array.to(result: C) : C { + for (elem in this) + result.add(elem) + return result +} + +inline fun Array.toLinkedList() : LinkedList = this.to(LinkedList()) + +inline fun Array.toList() : List = this.to(ArrayList()) + +inline fun Array.toSet() : Set = this.to(HashSet()) + +/** + 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/testlib/test/GenerateStandardLib.kt b/testlib/test/GenerateStandardLib.kt new file mode 100644 index 00000000000..49671f40885 --- /dev/null +++ b/testlib/test/GenerateStandardLib.kt @@ -0,0 +1,59 @@ +namespace kotlin.tools + +import std.* +import std.io.* +import std.util.* +import java.io.* +import java.util.* + +fun generateFile(outFile: File, header: String, typeName: String, inputFile: File) { + println("Parsing $inputFile and writing $outFile") + + outFile.getParentFile()?.mkdirs() + val writer = PrintWriter(FileWriter(outFile)) + try { + writer.println("// NOTE this file is auto-generated from $inputFile") + writer.println(header) + + val reader = FileReader(inputFile).buffered() + try { + // TODO ideally we'd use a filterNot() here :) + val iter = reader.lineIterator() + while (iter.hasNext) { + val line = iter.next() + + if (line.startsWith("package")) continue + val xform = line.replaceAll("java.lang.Iterable", typeName).replaceAll("java.util.Collection", typeName) + writer.println(xform) + } + } finally { + reader.close() + reader.close() + } + } finally { + writer.close() + } +} + + +/** + * Generates methods in the standard library which are mostly identical + * but just using a different input kind. + * + * Kinda like mimicking source macros here, but this avoids the inefficiency of type conversions + * at runtime. + */ +fun main(args: Array) { + var stdlib = File("stdlib") + if (!stdlib.exists()) { + stdlib = File("../stdlib") + if (!stdlib.exists()) { + println("Cannot find stdlib!") + return + } + } + val srcDir = File(stdlib, "ktSrc") + val input = File(srcDir, "JavaIterables.kt") + val outDir = File(srcDir, "generated") + generateFile(File(outDir, "ArraysGenerated.kt"), "package std", "Array", input) +} \ No newline at end of file