New stdlib generators

This commit is contained in:
Ilya Ryzhenkov
2014-03-18 13:45:31 +04:00
committed by Andrey Breslav
parent 0980f5e40a
commit e37d8174c3
109 changed files with 13317 additions and 7735 deletions
@@ -0,0 +1,35 @@
package generators
import java.io.*
import templates.Family.*
import templates.*
import templates.PrimitiveType.*
fun generateCollectionsAPI(outDir : File) {
elements().writeTo(File(outDir, "_Elements.kt")) { build() }
filtering().writeTo(File(outDir, "_Filtering.kt")) { build() }
ordering().writeTo(File(outDir, "_Ordering.kt")) { build() }
arrays().writeTo(File(outDir, "_Arrays.kt")) { build() }
snapshots().writeTo(File(outDir, "_Snapshots.kt")) { build() }
mapping().writeTo(File(outDir, "_Mapping.kt")) { build() }
aggregates().writeTo(File(outDir, "_Aggregates.kt")) { build() }
guards().writeTo(File(outDir, "_Guards.kt")) { build() }
generators().writeTo(File(outDir, "_Generators.kt")) { build() }
strings().writeTo(File(outDir, "_Strings.kt")) { build() }
specialJVM().writeTo(File(outDir, "_SpecialJVM.kt")) { build() }
numeric().writeTo(File(outDir, "_Numeric.kt")) {
val builder = StringBuilder()
// TODO: decide if sum for byte and short is needed and how to make it work
for(numeric in listOf(Int, Long, /*Byte, Short, */ Double, Float)) {
build(builder, Iterables, numeric)
}
for(numeric in listOf(Int, Long, Byte, Short, Double, Float)) {
build(builder, ArraysOfObjects, numeric)
build(builder, ArraysOfPrimitives, numeric)
}
builder.toString()
}
}
@@ -28,29 +28,7 @@ fun main(args: Array<String>) {
generateDomAPI(File(jsCoreDir, "dom.kt"))
generateDomEventsAPI(File(jsCoreDir, "domEvents.kt"))
iterators().writeTo(File(outDir, "_Iterators.kt")) {
buildFor(Iterators, null)
}
val arrays = arrays()
val sumFunctions = PrimitiveType.values().map(::sumFunction).filterNotNull()
(arrays + sumFunctions).writeTo(File(outDir, "_Arrays.kt")) {
buildFor(Arrays, null)
}
for (primitive in PrimitiveType.values()) {
(arrays + sumFunction(primitive)).filterNotNull().writeTo(File(outDir, "_${primitive.name}Arrays.kt")) {
buildFor(PrimitiveArrays, primitive)
}
}
(iterables().sort() + sumFunctions).writeTo(File(outDir, "_Iterables.kt")) {
buildFor(Iterables, null)
}
collections().writeTo(File(outDir, "_Collections.kt")) {
buildFor(Collections, null)
}
generateCollectionsAPI(outDir)
generateDownTos(File(outDir, "_DownTo.kt"), "package kotlin")
}
@@ -65,20 +43,8 @@ fun List<GenericFunction>.writeTo(file: File, builder: GenericFunction.() -> Str
its.append("package kotlin\n\n")
its.append("$COMMON_AUTOGENERATED_WARNING\n\n")
its.append("import java.util.*\n\n")
for (t in this) {
for (t in this.sort()) {
its.append(t.builder())
}
}
}
// Pretty hacky way to code generate; ideally we'd be using the AST and just changing the function prototypes
fun replaceGenerics(arrayName: String, it: String): String {
return it.replaceAll(" <in T>", " ").replaceAll("<in T, ", "<").replaceAll("<T, ", "<").replaceAll("<T,", "<").
replaceAll(" <T> ", " ").
replaceAll("<T>", "<${arrayName}>").replaceAll("<in T>", "<${arrayName}>").
replaceAll("\\(T\\)", "(${arrayName})").replaceAll("T\\?", "${arrayName}?").
replaceAll("T,", "${arrayName},").
replaceAll("T\\)", "${arrayName})").
replaceAll(" T ", " ${arrayName} ")
}
@@ -0,0 +1,399 @@
package templates
import templates.Family.*
fun aggregates(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
templates add f("all(predicate: (T) -> Boolean)") {
inline(true)
doc { "Returns *true* if all elements match the given *predicate*" }
returns("Boolean")
body {
"""
for (element in this) if (!predicate(element)) return false
return true
"""
}
include(Maps)
}
templates add f("none(predicate: (T) -> Boolean)") {
inline(true)
doc { "Returns *true* if no elements match the given *predicate*" }
returns("Boolean")
body {
"""
for (element in this) if (predicate(element)) return false
return true
"""
}
include(Maps)
}
templates add f("none()") {
doc { "Returns *true* if collection has no elements" }
returns("Boolean")
body {
"""
for (element in this) return false
return true
"""
}
include(Maps)
}
templates add f("any(predicate: (T) -> Boolean)") {
inline(true)
doc { "Returns *true* if any element matches the given *predicate*" }
returns("Boolean")
body {
"""
for (element in this) if (predicate(element)) return true
return false
"""
}
include(Maps)
}
templates add f("any()") {
doc { "Returns *true* if collection has at least one element" }
returns("Boolean")
body {
"""
for (element in this) return true
return false
"""
}
include(Maps)
}
templates add f("count(predicate: (T) -> Boolean)") {
inline(true)
doc { "Returns the number of elements matching the given *predicate*" }
returns("Int")
body {
"""
var count = 0
for (element in this) if (predicate(element)) count++
return count
"""
}
include(Maps)
}
templates add f("count()") {
doc { "Returns the number of elements" }
returns("Int")
body {
"""
var count = 0
for (element in this) count++
return count
"""
}
body(Maps, Collections, ArraysOfObjects, ArraysOfPrimitives) {
"return size"
}
}
templates add f("min()") {
doc { "Returns the smallest element or null if there are no elements" }
returns("T?")
exclude(PrimitiveType.Boolean)
typeParam("T: Comparable<T>")
body {
"""
val iterator = iterator()
if (!iterator.hasNext()) return null
var min = iterator.next()
while (iterator.hasNext()) {
val e = iterator.next()
if (min > e) min = e
}
return min
"""
}
body(ArraysOfObjects, ArraysOfPrimitives) {
"""
if (isEmpty()) return null
var min = this[0]
for (i in 1..lastIndex) {
val e = this[i]
if (min > e) min = e
}
return min
"""
}
}
templates add f("minBy(f: (T) -> R)") {
inline(true)
doc { "Returns the first element yielding the smallest value of the given function or null if there are no elements" }
typeParam("R: Comparable<R>")
typeParam("T: Any")
returns("T?")
body {
"""
val iterator = iterator()
if (!iterator.hasNext()) return null
var minElem = iterator.next()
var minValue = f(minElem)
while (iterator.hasNext()) {
val e = iterator.next()
val v = f(e)
if (minValue > v) {
minElem = e
minValue = v
}
}
return minElem
"""
}
body(ArraysOfObjects, ArraysOfPrimitives) {
"""
if (size == 0) return null
var minElem = this[0]
var minValue = f(minElem)
for (i in 1..lastIndex) {
val e = this[i]
val v = f(e)
if (minValue > v) {
minElem = e
minValue = v
}
}
return minElem
"""
}
}
templates add f("minBy(f: (T) -> R)") {
inline(true)
only(Maps)
doc { "Returns the first element yielding the smallest value of the given function or null if there are no elements" }
typeParam("R: Comparable<R>")
returns("T?")
body {
"""
val iterator = iterator()
if (!iterator.hasNext()) return null
var minElem = iterator.next()
var minValue = f(minElem)
while (iterator.hasNext()) {
val e = iterator.next()
val v = f(e)
if (minValue > v) {
minElem = e
minValue = v
}
}
return minElem
"""
}
}
templates add f("max()") {
doc { "Returns the largest element or null if there are no elements" }
returns("T?")
exclude(PrimitiveType.Boolean)
typeParam("T: Comparable<T>")
body {
"""
val iterator = iterator()
if (!iterator.hasNext()) return null
var max = iterator.next()
while (iterator.hasNext()) {
val e = iterator.next()
if (max < e) max = e
}
return max
"""
}
body(ArraysOfObjects, ArraysOfPrimitives) {
"""
if (isEmpty()) return null
var max = this[0]
for (i in 1..lastIndex) {
val e = this[i]
if (max < e) max = e
}
return max
"""
}
}
templates add f("maxBy(f: (T) -> R)") {
inline(true)
doc { "Returns the first element yielding the largest value of the given function or null if there are no elements" }
typeParam("R: Comparable<R>")
typeParam("T: Any")
returns("T?")
body {
"""
val iterator = iterator()
if (!iterator.hasNext()) return null
var maxElem = iterator.next()
var maxValue = f(maxElem)
while (iterator.hasNext()) {
val e = iterator.next()
val v = f(e)
if (maxValue < v) {
maxElem = e
maxValue = v
}
}
return maxElem
"""
}
body(ArraysOfObjects, ArraysOfPrimitives) {
"""
if (isEmpty()) return null
var maxElem = this[0]
var maxValue = f(maxElem)
for (i in 1..lastIndex) {
val e = this[i]
val v = f(e)
if (maxValue < v) {
maxElem = e
maxValue = v
}
}
return maxElem
"""
}
}
templates add f("maxBy(f: (T) -> R)") {
inline(true)
only(Maps)
doc { "Returns the first element yielding the largest value of the given function or null if there are no elements" }
typeParam("R: Comparable<R>")
returns("T?")
body {
"""
val iterator = iterator()
if (!iterator.hasNext()) return null
var maxElem = iterator.next()
var maxValue = f(maxElem)
while (iterator.hasNext()) {
val e = iterator.next()
val v = f(e)
if (maxValue < v) {
maxElem = e
maxValue = v
}
}
return maxElem
"""
}
}
templates add f("fold(initial: R, operation: (R, T) -> R)") {
inline(true)
doc { "Accumulates value starting with *initial* value and applying *operation* from left to right to current accumulator value and each element" }
typeParam("R")
returns("R")
body {
"""
var accumulator = initial
for (element in this) accumulator = operation(accumulator, element)
return accumulator
"""
}
}
templates add f("foldRight(initial: R, operation: (T, R) -> R)") {
inline(true)
only(Lists, ArraysOfObjects, ArraysOfPrimitives)
doc { "Accumulates value starting with *initial* value and applying *operation* from right to left to each element and current accumulator value" }
typeParam("R")
returns("R")
body {
"""
var index = size - 1
var accumulator = initial
while (index >= 0) {
accumulator = operation(get(index--), accumulator)
}
return accumulator
"""
}
}
templates add f("reduce(operation: (T, T) -> T)") {
inline(true)
doc { "Accumulates value starting with the first element and applying *operation* from left to right to current accumulator value and each element" }
returns("T")
body {
"""
val iterator = this.iterator()
if (!iterator.hasNext()) throw UnsupportedOperationException("Empty iterable can't be reduced")
var accumulator = iterator.next()
while (iterator.hasNext()) {
accumulator = operation(accumulator, iterator.next())
}
return accumulator
"""
}
}
templates add f("reduceRight(operation: (T, T) -> T)") {
inline(true)
only(Lists, ArraysOfObjects, ArraysOfPrimitives)
doc { "Accumulates value starting with last element and applying *operation* from right to left to each element and current accumulator value" }
returns("T")
body {
"""
var index = size - 1
if (index < 0) throw UnsupportedOperationException("Empty iterable can't be reduced")
var accumulator = get(index--)
while (index >= 0) {
accumulator = operation(get(index--), accumulator)
}
return accumulator
"""
}
}
templates add f("forEach(operation: (T) -> Unit)") {
inline(true)
doc { "Performs the given *operation* on each element" }
returns("Unit")
body {
"""
for (element in this) operation(element)
"""
}
include(Maps)
}
return templates
}
@@ -3,12 +3,11 @@ package templates
import templates.Family.*
fun arrays(): List<GenericFunction> {
val templates = iterables()
val templates = arrayListOf<GenericFunction>()
templates add f("isEmpty()") {
absentFor(Arrays)
isInline = false
doc = "Returns true if the array is empty"
only(ArraysOfObjects, ArraysOfPrimitives)
doc { "Returns true if the array is empty" }
returns("Boolean")
body {
"return size == 0"
@@ -16,57 +15,13 @@ fun arrays(): List<GenericFunction> {
}
templates add f("isNotEmpty()") {
absentFor(Arrays)
isInline = false
doc = "Returns true if the array is empty"
only(ArraysOfObjects, ArraysOfPrimitives)
doc { "Returns true if the array is not empty" }
returns("Boolean")
body {
"return !isEmpty()"
}
}
templates add f("indexOf(item: T)") {
absentFor(PrimitiveArrays)
isInline = false
doc = "Returns first index of item, or -1 if the array does not contain item"
returns("Int")
body {
"""
if (item == null) {
for (i in indices) {
if (this[i] == null) {
return i
}
}
} else {
for (i in indices) {
if (item == this[i]) {
return i
}
}
}
return -1
"""
}
}
// implementation for PrimitiveArrays is separate from Arrays, because they cannot hold null elements
templates add f("indexOf(item: T)") {
absentFor(Arrays)
isInline = false
doc = "Returns first index of item, or -1 if the array does not contain item"
returns("Int")
body {
"""
for (i in indices) {
if (item == this[i]) {
return i
}
}
return -1
"""
}
}
return templates.sort()
return templates
}
@@ -1,33 +0,0 @@
package templates
import java.util.ArrayList
import templates.Family.*
fun collections(): List<GenericFunction> {
val templates = ArrayList<GenericFunction>()
templates add f("requireNoNulls()") {
isInline = false
absentFor(PrimitiveArrays) // Those are inherently non-nulls
doc = "Returns a original Iterable containing all the non-*null* elements, throwing an [[IllegalArgumentException]] if there are any null elements"
typeParam("T:Any")
toNullableT = true
returns("SELF")
body {
val THIS = "\$this"
"""
for (element in this) {
if (element == null) {
throw IllegalArgumentException("null element found in $THIS")
}
}
return this as SELF
"""
}
}
return templates.sort()
}
@@ -1,467 +0,0 @@
package templates
import java.util.ArrayList
import templates.Family.*
fun commons(): ArrayList<GenericFunction> {
val templates = ArrayList<GenericFunction>()
templates add f("all(predicate: (T) -> Boolean)") {
doc = "Returns *true* if all elements match the given *predicate*"
returns("Boolean")
body {
"""
for (element in this) if (!predicate(element)) return false
return true
"""
}
}
templates add f("any(predicate: (T) -> Boolean)") {
doc = "Returns *true* if any elements match the given *predicate*"
returns("Boolean")
body {
"""
for (element in this) if (predicate(element)) return true
return false
"""
}
}
templates add f("count(predicate: (T) -> Boolean)") {
doc = "Returns the number of elements which match the given *predicate*"
returns("Int")
body {
"""
var count = 0
for (element in this) if (predicate(element)) count++
return count
"""
}
}
templates add f("find(predicate: (T) -> Boolean)") {
doc = "Returns the first element which matches the given *predicate* or *null* if none matched"
typeParam("T:Any")
returns("T?")
body {
"""
for (element in this) if (predicate(element)) return element
return null
"""
}
}
templates add f("filterTo(result: C, predicate: (T) -> Boolean)") {
doc = "Filters all elements which match the given predicate into the given list"
typeParam("C: MutableCollection<in T>")
returns("C")
body {
"""
for (element in this) if (predicate(element)) result.add(element)
return result
"""
}
}
templates add f("filterNotTo(result: C, predicate: (T) -> Boolean)") {
doc = "Returns a list containing all elements which do not match the given *predicate*"
typeParam("C: MutableCollection<in T>")
returns("C")
body {
"""
for (element in this) if (!predicate(element)) result.add(element)
return result
"""
}
}
templates add f("filterNotNullTo(result: C)") {
isInline = false
absentFor(PrimitiveArrays) // Those are inherently non-nulls
doc = "Filters all non-*null* elements into the given list"
typeParam("T:Any")
toNullableT = true
typeParam("C: MutableCollection<in T>")
returns("C")
body {
"""
for (element in this) if (element != null) result.add(element)
return result
"""
}
}
templates add f("partition(predicate: (T) -> Boolean)") {
doc = "Partitions this collection into a pair of collections"
returns("Pair<List<T>, List<T>>")
body {
"""
val first = ArrayList<T>()
val second = ArrayList<T>()
for (element in this) {
if (predicate(element)) {
first.add(element)
} else {
second.add(element)
}
}
return Pair(first, second)
"""
}
}
templates add f("mapTo(result: C, transform : (T) -> R)") {
doc = """
Transforms each element of this collection with the given *transform* function and
adds each return value to the given *results* collection
"""
typeParam("R")
typeParam("C: MutableCollection<in R>")
returns("C")
body {
"""
for (item in this)
result.add(transform(item))
return result
"""
}
}
templates add f("flatMapTo(result: C, transform: (T) -> Iterable<R>)") {
doc = "Returns the result of transforming each element to one or more values which are concatenated together into a single collection"
typeParam("R")
typeParam("C: MutableCollection<in R>")
returns("C")
body {
"""
for (element in this) {
val list = transform(element)
for (r in list) result.add(r)
}
return result
"""
}
}
templates add f("forEach(operation: (T) -> Unit)") {
doc = "Performs the given *operation* on each element"
returns("Unit")
body {
"""
for (element in this) operation(element)
"""
}
}
templates add f("fold(initial: R, operation: (R, T) -> R)") {
doc = "Folds all elements from from left to right with the *initial* value to perform the operation on sequential pairs of elements"
typeParam("R")
returns("R")
body {
"""
var answer = initial
for (element in this) answer = operation(answer, element)
return answer
"""
}
}
templates add f("foldRight(initial: R, operation: (T, R) -> R)") {
doc = "Folds all elements from right to left with the *initial* value to perform the operation on sequential pairs of elements"
typeParam("R")
returns("R")
absentFor(Iterators, Iterables, Collections)
body {
"""
var r = initial
var index = size - 1
while (index >= 0) {
r = operation(get(index--), r)
}
return r
"""
}
}
templates add f("reduce(operation: (T, T) -> T)") {
doc = """
Applies binary operation to all elements of iterable, going from left to right.
Similar to fold function, but uses the first element as initial value
"""
returns("T")
body {
"""
val iterator = this.iterator()
if (!iterator.hasNext()) {
throw UnsupportedOperationException("Empty iterable can't be reduced")
}
var result: T = iterator.next() //compiler doesn't understand that result will initialized anyway
while (iterator.hasNext()) {
result = operation(result, iterator.next())
}
return result
"""
}
}
templates add f("reduceRight(operation: (T, T) -> T)") {
doc = """
Applies binary operation to all elements of iterable, going from right to left.
Similar to foldRight function, but uses the last element as initial value
"""
returns("T")
absentFor(Iterators, Iterables, Collections)
body {
"""
var index = size - 1
if (index < 0) {
throw UnsupportedOperationException("Empty iterable can't be reduced")
}
var r = get(index--)
while (index >= 0) {
r = operation(get(index--), r)
}
return r
"""
}
}
templates add f("groupBy(toKey: (T) -> K)") {
doc = "Groups the elements in the collection into a new [[Map]] using the supplied *toKey* function to calculate the key to group the elements by"
typeParam("K")
returns("Map<K, List<T>>")
body { "return groupByTo(HashMap<K, MutableList<T>>(), toKey)" }
}
templates add f("groupByTo(result: MutableMap<K, MutableList<T>>, toKey: (T) -> K)") {
typeParam("K")
returns("Map<K, MutableList<T>>")
body {
"""
for (element in this) {
val key = toKey(element)
val list = result.getOrPut(key) { ArrayList<T>() }
list.add(element)
}
return result
"""
}
}
templates add f("drop(n: Int)") {
isInline = false
doc = "Returns a list containing everything but the first *n* elements"
returns("List<T>")
body {
"return dropWhile(countTo(n))"
}
}
templates add f("dropWhile(predicate: (T) -> Boolean)") {
doc = "Returns a list containing the everything but the first elements that satisfy the given *predicate*"
returns("List<T>")
body {
"return dropWhileTo(ArrayList<T>(), predicate)"
}
}
templates add f("dropWhileTo(result: L, predicate: (T) -> Boolean)") {
doc = "Returns a list containing the everything but the first elements that satisfy the given *predicate*"
typeParam("L: MutableList<in T>")
returns("L")
body {
"""
var start = true
for (element in this) {
if (start && predicate(element)) {
// ignore
} else {
start = false
result.add(element)
}
}
return result
"""
}
}
templates add f("takeWhileTo(result: C, predicate: (T) -> Boolean)") {
doc = "Returns a list containing the first elements that satisfy the given *predicate*"
typeParam("C: MutableCollection<in T>")
returns("C")
body {
"""
for (element in this) if (predicate(element)) result.add(element) else break
return result
"""
}
}
templates add f("toCollection(result: C)") {
isInline = false
doc = "Copies all elements into the given collection"
typeParam("C: MutableCollection<in T>")
returns("C")
body {
"""
for (element in this) result.add(element)
return result
"""
}
}
templates add f("reverse()") {
isInline = false
doc = "Reverses the order the elements into a list"
returns("List<T>")
body {
"""
val list = toCollection(ArrayList<T>())
Collections.reverse(list)
return list
"""
}
}
templates add f("toLinkedList()") {
isInline = false
doc = "Copies all elements into a [[LinkedList]]"
returns("LinkedList<T>")
body { "return toCollection(LinkedList<T>())" }
}
templates add f("toList()") {
isInline = false
doc = "Copies all elements into a [[List]]"
returns("List<T>")
body { "return toCollection(ArrayList<T>())" }
}
templates add f("toSet()") {
isInline = false
doc = "Copies all elements into a [[Set]]"
returns("Set<T>")
body { "return toCollection(LinkedHashSet<T>())" }
}
templates add f("toSortedSet()") {
isInline = false
doc = "Copies all elements into a [[SortedSet]]"
returns("SortedSet<T>")
body { "return toCollection(TreeSet<T>())" }
}
templates add f("withIndices()") {
isInline = false
doc = "Returns an iterator of Pairs(index, data)"
returns("Iterator<Pair<Int, T>>")
body {
"return IndexIterator(iterator())"
}
}
templates add f("sortBy(f: (T) -> R)") {
doc = """
Copies all elements into a [[List]] and sorts it by value of compare_function(element)
E.g. arrayList("two" to 2, "one" to 1).sortBy({it.second}) returns list sorted by second element of pair
"""
returns("List<T>")
typeParam("R: Comparable<R>")
body {
"""
val sortedList = toCollection(ArrayList<T>())
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) ->
val xr = f(x)
val yr = f(y)
xr.compareTo(yr)
}
java.util.Collections.sort(sortedList, sortBy)
return sortedList
"""
}
}
templates add f("appendString(buffer: Appendable, separator: String = \", \", prefix: String =\"\", postfix: String = \"\", limit: Int = -1, truncated: String = \"...\")") {
isInline = false
doc =
"""
Appends the string from all the elements separated using the *separator* and using the given *prefix* and *postfix* if supplied
If a collection could be huge you can specify a non-negative value of *limit* which will only show a subset of the collection then it will
a special *truncated* separator (which defaults to "..."
"""
returns("Unit")
body {
"""
buffer.append(prefix)
var count = 0
for (element in this) {
if (++count > 1) buffer.append(separator)
if (limit < 0 || count <= limit) {
val text = if (element == null) "null" else element.toString()
buffer.append(text)
} else break
}
if (limit >= 0 && count > limit) buffer.append(truncated)
buffer.append(postfix)
"""
}
}
templates add f("makeString(separator: String = \", \", prefix: String = \"\", postfix: String = \"\", limit: Int = -1, truncated: String = \"...\")") {
isInline = false
doc = """
Creates a string from all the elements separated using the *separator* and using the given *prefix* and *postfix* if supplied.
If a collection could be huge you can specify a non-negative value of *limit* which will only show a subset of the collection then it will
a special *truncated* separator (which defaults to "..."
"""
returns("String")
body {
"""
val buffer = StringBuilder()
appendString(buffer, separator, prefix, postfix, limit, truncated)
return buffer.toString()
"""
}
}
return templates
}
@@ -0,0 +1,408 @@
package templates
import templates.Family.*
fun elements(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
templates add f("contains(element: T)") {
doc { "Returns true if *element* is found in the collection" }
returns("Boolean")
body {
"return indexOf(element) >= 0"
}
}
templates add f("indexOf(element: T)") {
doc { "Returns first index of *element*, or -1 if the collection does not contain element" }
returns("Int")
body {
"""
var index = 0
for (item in this) {
if (element == item)
return index
index++
}
return -1
"""
}
body(ArraysOfObjects) {
"""
if (element == null) {
for (index in indices) {
if (this[index] == null) {
return index
}
}
} else {
for (index in indices) {
if (element == this[index]) {
return index
}
}
}
return -1
"""
}
body(ArraysOfPrimitives) {
"""
for (index in indices) {
if (element == this[index]) {
return index
}
}
return -1
"""
}
}
templates add f("lastIndexOf(element: T)") {
doc { "Returns last index of *element*, or -1 if the collection does not contain element" }
returns("Int")
body {
"""
var lastIndex = -1
var index = 0
for (item in this) {
if (element == item)
lastIndex = index
index++
}
return lastIndex
"""
}
include(Lists)
body(Lists, ArraysOfObjects) {
"""
if (element == null) {
for (index in indices.reverse()) {
if (this[index] == null) {
return index
}
}
} else {
for (index in indices.reverse()) {
if (element == this[index]) {
return index
}
}
}
return -1
"""
}
body(ArraysOfPrimitives) {
"""
for (index in indices.reverse()) {
if (element == this[index]) {
return index
}
}
return -1
"""
}
}
templates add f("elementAt(index : Int)") {
doc { "Returns element at given *index*" }
returns("T")
body {
"""
if (this is List<*>)
return get(index) as T
val iterator = iterator()
var count = 0
while (iterator.hasNext()) {
val element = iterator.next()
if (index == count++)
return element
}
throw IndexOutOfBoundsException("Collection doesn't contain element at index")
"""
}
body(Streams) {
"""
val iterator = iterator()
var count = 0
while (iterator.hasNext()) {
val element = iterator.next()
if (index == count++)
return element
}
throw IndexOutOfBoundsException("Collection doesn't contain element at index")
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
return get(index)
"""
}
}
templates add f("first()") {
doc { "Returns first element" }
returns("T")
body {
"""
val iterator = iterator()
if (!iterator.hasNext())
throw IllegalArgumentException("Collection is empty")
return iterator.next()
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
return this[0]
"""
}
}
templates add f("firstOrNull()") {
doc { "Returns first elementm, or null if collection is empty" }
returns("T?")
body {
"""
val iterator = iterator()
if (!iterator.hasNext())
return null
return iterator.next()
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
return if (size > 0) this[0] else null
"""
}
}
templates add f("first(predicate: (T) -> Boolean)") {
inline(true)
doc { "Returns first element matching the given *predicate*" }
returns("T")
body {
"""
for (element in this) if (predicate(element)) return element
throw IllegalArgumentException("No element matching predicate was found")
"""
}
}
templates add f("firstOrNull(predicate: (T) -> Boolean)") {
inline(true)
doc { "Returns first element matching the given *predicate*, or *null* if element was not found" }
returns("T?")
body {
"""
for (element in this) if (predicate(element)) return element
return null
"""
}
}
templates add f("last()") {
doc { "Returns last element" }
returns("T")
body {
"""
when (this) {
is List<*> -> return this[size - 1] as T
else -> {
val iterator = iterator()
if (!iterator.hasNext())
throw IllegalArgumentException("Collection is empty")
var last = iterator.next()
while (iterator.hasNext())
last = iterator.next()
return last
}
}
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
if (size == 0)
throw IllegalArgumentException("Collection is empty")
return this[size - 1]
"""
}
}
templates add f("lastOrNull()") {
doc { "Returns last element, or null if collection is empty" }
returns("T?")
body {
"""
when (this) {
is List<*> -> return if (size > 0) this[size - 1] as T else null
else -> {
val iterator = iterator()
if (!iterator.hasNext())
return null
var last = iterator.next()
while (iterator.hasNext())
last = iterator.next()
return last
}
}
"""
}
include(Lists)
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
return if (size > 0) this[size - 1] else null
"""
}
}
templates add f("last(predicate: (T) -> Boolean)") {
doc { "Returns last element matching the given *predicate*" }
returns("T")
body {
"""
fun first(it : Iterator<T>) : T {
for (element in it) if (predicate(element)) return element
throw IllegalArgumentException("Collection doesn't contain any element matching predicate")
}
val iterator = iterator()
var last = first(iterator)
while (iterator.hasNext()) {
val element = iterator.next()
if (predicate(element))
last = element
}
return last
"""
}
}
templates add f("lastOrNull(predicate: (T) -> Boolean)") {
doc { "Returns last element matching the given *predicate*, or null if element was not found" }
returns("T?")
body {
"""
fun first(it : Iterator<T>) : T? {
for (element in it) if (predicate(element)) return element
return null
}
val iterator = iterator()
var last = first(iterator)
if (last == null)
return null
while (iterator.hasNext()) {
val element = iterator.next()
if (predicate(element))
last = element
}
return last
"""
}
}
val bucks = '$'
templates add f("single()") {
doc { "Returns single element, or throws exception if there is no or more than one element" }
returns("T")
body {
"""
when (this) {
is List<*> -> return if (size == 1) this[0] as T else throw IllegalArgumentException("Collection has ${bucks}size elements")
else -> {
val iterator = iterator()
if (!iterator.hasNext())
throw IllegalArgumentException("Collection is empty")
var single = iterator.next()
if (iterator.hasNext())
throw IllegalArgumentException("Collection has more than one element")
return single
}
}
"""
}
body(ArraysOfObjects, ArraysOfPrimitives) {
"""
if (size != 1)
throw IllegalArgumentException("Collection has ${bucks}size elements")
return this[0]
"""
}
}
templates add f("singleOrNull()") {
doc { "Returns single element, or null if collection is empty, or throws exception if there is more than one element" }
returns("T?")
body {
"""
when (this) {
is List<*> -> return if (size == 1) this[0] as T else if (size == 0) null else throw IllegalArgumentException("Collection has ${bucks}size elements")
else -> {
val iterator = iterator()
if (!iterator.hasNext())
return null
var single = iterator.next()
if (iterator.hasNext())
throw IllegalArgumentException("Collection has more than one element")
return single
}
}
"""
}
body(ArraysOfObjects, ArraysOfPrimitives) {
"""
if (size == 0)
return null
if (size != 1)
throw IllegalArgumentException("Collection has ${bucks}size elements")
return this[0]
"""
}
}
templates add f("single(predicate: (T) -> Boolean)") {
doc { "Returns single element matching the given *predicate*, or throws exception if there is no or more than one element" }
returns("T")
body {
"""
fun first(it : Iterator<T>) : T {
for (element in it) if (predicate(element)) return element
throw IllegalArgumentException("Collection doesn't have matching element")
}
val iterator = iterator()
var single = first(iterator)
while (iterator.hasNext()) {
val element = iterator.next()
if (predicate(element))
throw IllegalArgumentException("Collection has more than one matching element")
}
return single
"""
}
}
templates add f("singleOrNull(predicate: (T) -> Boolean)") {
doc { "Returns single element matching the given *predicate*, or null if element was not found or more than one elements were found" }
returns("T?")
body {
"""
fun first(it : Iterator<T>) : T? {
for (element in it) if (predicate(element)) return element
return null
}
val iterator = iterator()
var single = first(iterator)
if (single == null)
return null
while (iterator.hasNext()) {
val element = iterator.next()
if (predicate(element))
throw IllegalArgumentException("Collection has more than one matching element")
}
return single
"""
}
}
return templates
}
@@ -8,110 +8,206 @@ import java.io.StringReader
import java.util.StringTokenizer
enum class Family {
Iterators
Streams
Iterables
Collections
Arrays
PrimitiveArrays
Lists
Maps
ArraysOfObjects
ArraysOfPrimitives
}
class GenericFunction(val signature : String): Comparable<GenericFunction> {
var doc : String = ""
var toNullableT : Boolean = false
var isInline : Boolean = true;
private val customReceivers = HashMap<Family, String>()
val blockedFor = HashSet<Family>()
private val blockedForPrimitive = HashSet<PrimitiveType>()
enum class PrimitiveType(val name: String) {
Boolean: PrimitiveType("Boolean")
Byte: PrimitiveType("Byte")
Char: PrimitiveType("Char")
Short: PrimitiveType("Short")
Int: PrimitiveType("Int")
Long: PrimitiveType("Long")
Float: PrimitiveType("Float")
Double: PrimitiveType("Double")
}
class GenericFunction(val signature: String) : Comparable<GenericFunction> {
val defaultFamilies = array(Iterables, Streams, ArraysOfObjects, ArraysOfPrimitives)
var toNullableT: Boolean = false
var defaultInline = false
val inlineFamilies = HashMap<Family, Boolean>()
val buildFamilies = HashSet<Family>(defaultFamilies.toList())
private val buildPrimitives = HashSet<PrimitiveType>(PrimitiveType.values().toList())
var doc: String = ""
val docs = HashMap<Family, String>()
var defaultBody: String = ""
val bodies = HashMap<Family, String>()
var defaultReturnType = ""
val returnTypes = HashMap<Family, String>()
val typeParams = ArrayList<String>()
fun body(b : () -> String) {
for (f in Family.values()) {
if (bodies[f] == null) f.body(b)
fun body(vararg families: Family, b: () -> String) {
if (families.isEmpty())
defaultBody = b()
else {
for (f in families) {
include(f)
bodies[f] = b()
}
}
}
fun Family.body(b : () -> String) {
bodies[this] = b()
}
fun returns(r : String) {
for (f in Family.values()) {
if (returnTypes[f] == null) f.returns(r)
fun doc(vararg families: Family, b: () -> String) {
if (families.isEmpty())
doc = b()
else {
for (f in families) {
docs[f] = b()
}
}
}
fun Family.returns(r:String) {
returnTypes[this] = r
fun returns(vararg families: Family, b: () -> String) {
if (families.isEmpty())
defaultReturnType = b()
else {
for (f in families) {
returnTypes[f] = b()
}
}
}
fun Family.customReceiver(r: String) {
customReceivers[this] = r
fun returns(r: String) {
defaultReturnType = r
}
fun typeParam(t:String) {
fun typeParam(t: String) {
typeParams.add(t)
}
fun absentFor(vararg f : Family) {
blockedFor.addAll(f.toList())
fun inline(value : Boolean, vararg families: Family) {
if (families.isEmpty())
defaultInline = value
else
for (f in families)
inlineFamilies.put(f, value)
}
fun absentFor(vararg p: PrimitiveType) {
blockedForPrimitive.addAll(p.toList())
fun exclude(vararg families: Family) {
buildFamilies.removeAll(families.toList())
}
private fun effectiveTypeParams(f : Family) : List<String> {
val types = ArrayList(typeParams)
if (typeParams.find { it.startsWith("T") } == null && !customReceivers.containsKey(f)) {
types.add(0, "T")
fun only(vararg families: Family) {
buildFamilies.clear()
buildFamilies.addAll(families.toList())
}
fun include(vararg families: Family) {
buildFamilies.addAll(families.toList())
}
fun exclude(vararg p: PrimitiveType) {
buildPrimitives.removeAll(p.toList())
}
fun include(vararg p: PrimitiveType) {
buildPrimitives.addAll(p.toList())
}
fun build(vararg families: Family = Family.values()): String {
val builder = StringBuilder()
for (family in families.sortBy { it.name() }) {
if (buildFamilies.contains(family))
build(builder, family)
}
if (f == PrimitiveArrays) {
types.remove(types.find { it.startsWith("T") })
}
return types
return builder.toString()
}
fun build(builder: StringBuilder, f: Family) {
if (f == ArraysOfPrimitives) {
for (primitive in buildPrimitives.sortBy { it.name() })
build(builder, f, primitive)
} else {
build(builder, f, null)
}
}
fun build(builder: StringBuilder, f: Family, primitive: PrimitiveType?) {
val returnType = returnTypes[f] ?: defaultReturnType
if (returnType.isEmpty())
throw RuntimeException("No return type specified for $signature")
fun buildFor(f: Family, primitiveType: PrimitiveType?) : String {
if (blockedFor.contains(f)) return ""
if (primitiveType != null && blockedForPrimitive.contains(primitiveType)) return ""
if (returnTypes[f] == null) throw RuntimeException("No return type specified for $signature")
val retType = returnTypes[f]!!
val selftype = when (f) {
val receiver = when (f) {
Iterables -> "Iterable<T>"
Collections -> "Collection<T>"
Iterators -> "Iterator<T>"
Arrays -> "Array<out T>"
PrimitiveArrays -> "${primitiveType!!.name}Array"
Lists -> "List<T>"
Maps -> "Map<K,V>"
Streams -> "Stream<T>"
ArraysOfObjects -> "Array<T>"
ArraysOfPrimitives -> primitive?.let { it.name() + "Array" } ?: throw IllegalArgumentException("Primitive array should specify primitive type")
else -> throw IllegalStateException("Invalid family")
}
fun String.renderType() : String {
fun String.renderType(): String {
val t = StringTokenizer(this, " \t\n,:()<>?.", true)
val answer = StringBuilder()
while (t.hasMoreTokens()) {
val token = t.nextToken()
answer.append(when (token) {
"SELF" -> selftype
"T" -> if (f == Family.PrimitiveArrays) primitiveType!!.name else token
else -> token
})
"SELF" -> receiver
"PRIMITIVE" -> primitive?.name() ?: token
"SUM" -> {
when (primitive) {
PrimitiveType.Byte, PrimitiveType.Short -> "Int"
else -> primitive
}
}
"ZERO" -> when (primitive) {
PrimitiveType.Double -> "0.0"
PrimitiveType.Float -> "0.0f"
else -> "0"
}
"T" -> {
if (f == Maps)
"Map.Entry<K,V>"
else
primitive?.name() ?: token
}
else -> token
})
}
return answer.toString()
}
val builder = StringBuilder()
if (doc != "") {
fun effectiveTypeParams(): List<String> {
val types = ArrayList(typeParams)
if (primitive == null) {
val implicitTypeParameters = receiver.dropWhile { it != '<' }.drop(1).takeWhile { it != '>' }.split(",")
for (implicit in implicitTypeParameters.reverse()) {
if (!types.any { it.startsWith(implicit) }) {
types.add(0, implicit)
}
}
return types
} else {
// primitive type arrays should drop constraints
return typeParams.filter { !it.startsWith("T") }
}
}
val methodDoc = docs[f] ?: doc
if (methodDoc != "") {
builder.append("/**\n")
StringReader(doc).forEachLine {
StringReader(methodDoc).forEachLine {
val line = it.trim()
if (!line.isEmpty()) {
builder.append(" * ").append(line).append("\n")
@@ -121,56 +217,53 @@ class GenericFunction(val signature : String): Comparable<GenericFunction> {
}
builder.append("public ")
if (isInline) builder.append("inline ")
if (inlineFamilies[f] ?: defaultInline)
builder.append("inline ")
builder.append("fun ")
val types = effectiveTypeParams(f)
val types = effectiveTypeParams()
if (!types.isEmpty()) {
builder.append(types.makeString(separator = ", ", prefix = "<", postfix = "> ").renderType())
}
builder.append((customReceivers[f] ?:
val receiverType = (
if (toNullableT) {
selftype.replace("T>", "T?>")
}
else {
selftype
}).renderType())
receiver.replace("T>", "T?>")
} else {
if (receiver == "Array<T>")
"Array<out T>"
else
receiver
}).renderType()
builder.append(".${signature.renderType()} : ${retType.renderType()} {")
val body = bodies[f]!!.trim("\n")
val prefix : Int = body.takeWhile { it == ' ' }.length
builder.append(receiverType)
builder.append(".${signature.renderType()} : ${returnType.renderType()} {")
val body = (bodies[f] ?: defaultBody).trim("\n")
val prefix: Int = body.takeWhile { it == ' ' }.length
StringReader(body).forEachLine {
builder.append('\n')
var count = prefix
builder.append(" ").append(it.dropWhile {count-- > 0 && it == ' '} .renderType())
builder.append(" ").append(it.dropWhile { count-- > 0 && it == ' ' } .renderType())
}
return builder.toString().trimTrailingSpaces() + "\n}\n\n"
builder.append("\n}\n\n")
}
public override fun compareTo(other : GenericFunction) : Int = this.signature.compareTo(other.signature)
public override fun compareTo(other: GenericFunction): Int = this.signature.compareTo(other.signature)
}
fun String.trimTrailingSpaces() : String {
fun String.trimTrailingSpaces(): String {
var answer = this;
while (answer.endsWith(' ') || answer.endsWith('\n')) answer = answer.substring(0, answer.length() - 1)
return answer
}
fun f(signature : String, init : GenericFunction.() -> Unit): GenericFunction {
fun f(signature: String, init: GenericFunction.() -> Unit): GenericFunction {
val gf = GenericFunction(signature)
gf.init()
return gf
}
fun main(args : Array<String>) {
val templates = collections()
for (t in templates) {
print(t.buildFor(PrimitiveArrays, PrimitiveType.Byte))
}
}
@@ -0,0 +1,266 @@
package templates
import templates.Family.*
fun filtering(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
templates add f("drop(n: Int)") {
doc { "Returns a list containing all elements except first *n* elements" }
returns("List<T>")
body {
"""
var count = 0
val list = ArrayList<T>()
for (item in this) {
if (count++ >= n) list.add(item)
}
return list
"""
}
doc(Streams) { "Returns a stream containing all elements except first *n* elements" }
returns(Streams) { "Stream<T>" }
body(Streams) {
"""
var count = 0;
return FilteringStream(this) { count++ >= n }
"""
}
include(Collections)
body(Collections, ArraysOfObjects, ArraysOfPrimitives) {
"""
if (n >= size)
return ArrayList<T>()
var count = 0
val list = ArrayList<T>(size - n)
for (item in this) {
if (count++ >= n) list.add(item)
}
return list
"""
}
}
templates add f("take(n: Int)") {
doc { "Returns a list containing first *n* elements" }
returns("List<T>")
body {
"""
var count = 0
val list = ArrayList<T>(n)
for (item in this)
if (count++ >= n)
list.add(item)
return list
"""
}
doc(Streams) { "Returns a stream containing first *n* elements" }
returns(Streams) { "Stream<T>" }
body(Streams) {
"""
var count = 0
return LimitedStream(this) { count++ == n }
"""
}
include(Collections)
body(Collections, ArraysOfObjects, ArraysOfPrimitives) {
"""
var count = 0
val realN = if (n > size) size else n
val list = ArrayList<T>(realN)
for (item in this) {
if (count++ == realN)
break;
list.add(item)
}
return list
"""
}
}
templates add f("dropWhile(predicate: (T)->Boolean)") {
inline(true)
doc { "Returns a list containing all elements except first elements that satisfy the given *predicate*" }
returns("List<T>")
body {
"""
var yielding = false
val list = ArrayList<T>()
for (item in this)
if (yielding)
list.add(item)
else if(!predicate(item)) {
list.add(item)
yielding = true
}
return list
"""
}
inline(false, Streams)
doc(Streams) { "Returns a stream containing all elements except first elements that satisfy the given *predicate*" }
returns(Streams) { "Stream<T>" }
body(Streams) {
"""
var yielding = false
return FilteringStream(this) {
if (yielding)
true
else if (!predicate(it)) {
yielding = true
true
} else
false
}
"""
}
}
templates add f("takeWhile(predicate: (T)->Boolean)") {
inline(true)
doc { "Returns a list containing first elements satisfying the given *predicate*" }
returns("List<T>")
body {
"""
val list = ArrayList<T>()
for (item in this) {
if(!predicate(item))
break;
list.add(item)
}
return list
"""
}
inline(false, Streams)
doc(Streams) { "Returns a stream containing first elements satisfying the given *predicate*" }
returns(Streams) { "Stream<T>" }
body(Streams) {
"""
return LimitedStream(this, false, predicate)
"""
}
}
templates add f("filter(predicate: (T)->Boolean)") {
inline(true)
doc { "Returns a list containing all elements matching the given *predicate*" }
returns("List<T>")
body {
"""
return filterTo(ArrayList<T>(), predicate)
"""
}
inline(false, Streams)
doc(Streams) { "Returns a stream containing all elements matching the given *predicate*" }
returns(Streams) { "Stream<T>" }
body(Streams) {
"""
return FilteringStream(this, true, predicate)
"""
}
include(Maps)
}
templates add f("filterTo(collection: C, predicate: (T) -> Boolean)") {
inline(true)
doc { "Appends all elements matching the given *predicate* into the given *collection*" }
typeParam("C: MutableCollection<in T>")
returns("C")
body {
"""
for (element in this) if (predicate(element)) collection.add(element)
return collection
"""
}
include(Maps)
}
templates add f("filterNot(predicate: (T)->Boolean)") {
inline(true)
doc { "Returns a list containing all elements not matching the given *predicate*" }
returns("List<T>")
body {
"""
return filterNotTo(ArrayList<T>(), predicate)
"""
}
inline(false, Streams)
doc(Streams) { "Returns a stream containing all elements not matching the given *predicate*" }
returns(Streams) { "Stream<T>" }
body(Streams) {
"""
return FilteringStream(this, false, predicate)
"""
}
include(Maps)
}
templates add f("filterNotTo(collection: C, predicate: (T) -> Boolean)") {
inline(true)
doc { "Appends all elements not matching the given *predicate* to the given *collection*" }
typeParam("C: MutableCollection<in T>")
returns("C")
body {
"""
for (element in this) if (!predicate(element)) collection.add(element)
return collection
"""
}
include(Maps)
}
templates add f("filterNotNull()") {
exclude(ArraysOfPrimitives)
doc { "Returns a list containing all elements that are not null" }
typeParam("T: Any")
returns("List<T>")
toNullableT = true
body {
"""
return filterNotNullTo(ArrayList<T>())
"""
}
doc(Streams) { "Returns a stream containing all elements that are not null" }
returns(Streams) { "Stream<T>" }
body(Streams) {
"""
return FilteringStream(this, false, { it != null }) as Stream<T>
"""
}
}
templates add f("filterNotNullTo(collection: C)") {
exclude(ArraysOfPrimitives)
doc { "Appends all elements that are not null to the given *collection*" }
typeParam("C: MutableCollection<in T>")
typeParam("T: Any")
returns("C")
toNullableT = true
body {
"""
for (element in this) if (element != null) collection.add(element)
return collection
"""
}
}
return templates
}
@@ -0,0 +1,177 @@
package templates
import templates.Family.*
fun generators(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
templates add f("plus(element: T)") {
doc { "Returns a list containing all elements of original collection and then the given element" }
returns("List<T>")
body {
"""
val answer = toArrayList()
answer.add(element)
return answer
"""
}
doc(Streams) { "Returns a stream containing all elements of original stream and then the given element" }
returns(Streams) { "Stream<T>" }
// TODO: Implement lazy behavior
body(Streams) {
"""
val answer = toArrayList()
answer.add(element)
return answer.stream()
"""
}
}
templates add f("plus(collection: Iterable<T>)") {
exclude(Streams)
doc { "Returns a list containing all elements of original collection and then all elements of the given *collection*" }
returns("List<T>")
body {
"""
val answer = toArrayList()
answer.addAll(collection)
return answer
"""
}
}
templates add f("plus(array: Array<T>)") {
exclude(Streams)
doc { "Returns a list containing all elements of original collection and then all elements of the given *collection*" }
returns("List<T>")
body {
"""
val answer = toArrayList()
answer.addAll(array)
return answer
"""
}
}
templates add f("plus(collection: Iterable<T>)") {
only(Streams)
doc { "Returns a stream containing all elements of original stream and then all elements of the given *collection*" }
returns("Stream<T>")
// TODO: Implement lazy behavior
body {
"""
val answer = toArrayList()
answer.addAll(collection)
return answer.stream()
"""
}
}
templates add f("plus(stream: Stream<T>)") {
only(Streams)
doc { "Returns a stream containing all elements of original stream and then all elements of the given *stream*" }
returns("Stream<T>")
body {
// TODO: Implement lazy behavior
"""
val answer = toArrayList()
answer.addAll(stream)
return answer.stream()
"""
}
}
templates add f("partition(predicate: (T) -> Boolean)") {
inline(true)
doc {
"""
Splits original collection into pair of collections,
where *first* collection contains elements for which predicate yielded *true*,
while *second* collection contains elements for which predicate yielded *false*
"""
}
// TODO: Stream variant
returns("Pair<List<T>, List<T>>")
body {
"""
val first = ArrayList<T>()
val second = ArrayList<T>()
for (element in this) {
if (predicate(element)) {
first.add(element)
} else {
second.add(element)
}
}
return Pair(first, second)
"""
}
}
templates add f("zip(collection: Iterable<R>)") {
exclude(Streams)
doc {
"""
Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
"""
}
typeParam("R")
returns("List<Pair<T,R>>")
body {
"""
val first = iterator()
val second = collection.iterator()
val list = ArrayList<Pair<T,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
}
return list
"""
}
}
templates add f("zip(array: Array<R>)") {
exclude(Streams)
doc {
"""
Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection.
"""
}
typeParam("R")
returns("List<Pair<T,R>>")
body {
"""
val first = iterator()
val second = array.iterator()
val list = ArrayList<Pair<T,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
}
return list
"""
}
}
templates add f("zip(stream: Stream<R>)") {
only(Streams)
doc {
"""
Returns a stream of pairs built from elements of both collections with same indexes. List has length of shortest collection.
"""
}
typeParam("R")
returns("Stream<Pair<T,R>>")
body {
"""
return ZippingStream(this, stream)
"""
}
}
return templates
}
@@ -0,0 +1,41 @@
package templates
import java.util.ArrayList
import templates.Family.*
fun guards(): List<GenericFunction> {
val THIS = "\$this"
val templates = ArrayList<GenericFunction>()
templates add f("requireNoNulls()") {
include(Lists)
exclude(ArraysOfPrimitives)
doc { "Returns an original collection containing all the non-*null* elements, throwing an [[IllegalArgumentException]] if there are any null elements" }
typeParam("T:Any")
toNullableT = true
returns("SELF")
body {
"""
for (element in this) {
if (element == null) {
throw IllegalArgumentException("null element found in $THIS")
}
}
return this as SELF
"""
}
body(Streams) {
"""
return FilteringStream(this) {
if (it == null) {
throw IllegalArgumentException("null element found in $THIS")
}
true
} as Stream<T>
"""
}
}
return templates
}
@@ -1,308 +0,0 @@
package templates
import java.util.ArrayList
import templates.Family.*
fun iterables(): ArrayList<GenericFunction> {
val templates = commons()
templates add f("filter(predicate: (T) -> Boolean)") {
doc = "Returns a list containing all elements which match the given *predicate*"
returns("List<T>")
body {
"return filterTo(ArrayList<T>(), predicate)"
}
Iterators.returns("Iterator<T")
Iterators.body {
"return FilterIterator<T>(this, predicate)"
}
}
templates add f("filterNot(predicate: (T) -> Boolean)") {
doc = "Returns a list containing all elements which do not match the given *predicate*"
returns("List<T>")
body {
"return filterNotTo(ArrayList<T>(), predicate)"
}
}
templates add f("filterNotNull()") {
isInline = false
absentFor(PrimitiveArrays) // Those are inherently non-nulls
doc = "Returns a list containing all the non-*null* elements"
typeParam("T:Any")
toNullableT = true
returns("List<T>")
body {
"return filterNotNullTo<T, ArrayList<T>>(ArrayList<T>())"
}
}
templates add f("map(transform : (T) -> R)") {
doc = "Returns a new List containing the results of applying the given *transform* function to each element in this collection"
typeParam("R")
returns("List<R>")
body {
"return mapTo(ArrayList<R>(), transform)"
}
}
templates add f("flatMap(transform: (T)-> Iterable<R>)") {
doc = "Returns the result of transforming each element to one or more values which are concatenated together into a single list"
typeParam("R")
returns("List<R>")
body {
"return flatMapTo(ArrayList<R>(), transform)"
}
}
templates add f("take(n: Int)") {
isInline = false
doc = "Returns a list containing the first *n* elements"
returns("List<T>")
body {
"return takeWhile(countTo(n))"
}
}
templates add f("takeWhile(predicate: (T) -> Boolean)") {
doc = "Returns a list containing the first elements that satisfy the given *predicate*"
returns("List<T>")
body {
"return takeWhileTo(ArrayList<T>(), predicate)"
}
}
templates add f("requireNoNulls()") {
isInline = false
absentFor(PrimitiveArrays) // Those are inherently non-nulls
doc = "Returns a original Iterable containing all the non-*null* elements, throwing an [[IllegalArgumentException]] if there are any null elements"
typeParam("T:Any")
toNullableT = true
returns("SELF")
body {
val THIS = "\$this"
"""
for (element in this) {
if (element == null) {
throw IllegalArgumentException("null element found in $THIS")
}
}
return this as SELF
"""
}
}
templates add f("plus(element: T)") {
isInline = false
doc = "Creates an [[Iterator]] which iterates over this iterator then the given element at the end"
returns("List<T>")
body {
"""
val answer = ArrayList<T>()
toCollection(answer)
answer.add(element)
return answer
"""
}
}
templates add f("plus(iterator: Iterator<T>)") {
isInline = false
doc = "Creates an [[Iterator]] which iterates over this iterator then the following iterator"
returns("List<T>")
body {
"""
val answer = ArrayList<T>()
toCollection(answer)
for (element in iterator) {
answer.add(element)
}
return answer
"""
}
}
templates add f("plus(collection: Iterable<T>)") {
isInline = false
doc = "Creates an [[Iterator]] which iterates over this iterator then the following collection"
returns("List<T>")
body {
"return plus(collection.iterator())"
}
}
templates add f("min()") {
doc = "Returns the smallest element or null if there are no elements"
returns("T?")
absentFor(PrimitiveType.Boolean)
typeParam("T: Comparable<T>")
isInline = false
Iterables.body {
"""
val iterator = iterator()
if (!iterator.hasNext()) return null
var min = iterator.next()
while (iterator.hasNext()) {
val e = iterator.next()
if (min > e) min = e
}
return min
"""
}
listOf(Arrays, PrimitiveArrays).forEach {
it.body {
"""
if (isEmpty()) return null
var min = this[0]
for (i in 1..lastIndex) {
val e = this[i]
if (min > e) min = e
}
return min
"""
}
}
}
templates add f("max()") {
doc = "Returns the largest element or null if there are no elements"
returns("T?")
absentFor(PrimitiveType.Boolean)
typeParam("T: Comparable<T>")
isInline = false
Iterables.body {
"""
val iterator = iterator()
if (!iterator.hasNext()) return null
var max = iterator.next()
while (iterator.hasNext()) {
val e = iterator.next()
if (max < e) max = e
}
return max
"""
}
listOf(Arrays, PrimitiveArrays).forEach {
it.body {
"""
if (isEmpty()) return null
var max = this[0]
for (i in 1..lastIndex) {
val e = this[i]
if (max < e) max = e
}
return max
"""
}
}
}
templates add f("minBy(f: (T) -> R)") {
doc = "Returns the first element yielding the smallest value of the given function or null if there are no elements"
typeParam("R: Comparable<R>")
typeParam("T: Any")
returns("T?")
Iterables.body {
"""
val iterator = iterator()
if (!iterator.hasNext()) return null
var minElem = iterator.next()
var minValue = f(minElem)
while (iterator.hasNext()) {
val e = iterator.next()
val v = f(e)
if (minValue > v) {
minElem = e
minValue = v
}
}
return minElem
"""
}
listOf(Arrays, PrimitiveArrays).forEach {
it.body {
"""
if (size == 0) return null
var minElem = this[0]
var minValue = f(minElem)
for (i in 1..lastIndex) {
val e = this[i]
val v = f(e)
if (minValue > v) {
minElem = e
minValue = v
}
}
return minElem
"""
}
}
}
templates add f("maxBy(f: (T) -> R)") {
doc = "Returns the first element yielding the largest value of the given function or null if there are no elements"
typeParam("R: Comparable<R>")
typeParam("T: Any")
returns("T?")
Iterables.body {
"""
val iterator = iterator()
if (!iterator.hasNext()) return null
var maxElem = iterator.next()
var maxValue = f(maxElem)
while (iterator.hasNext()) {
val e = iterator.next()
val v = f(e)
if (maxValue < v) {
maxElem = e
maxValue = v
}
}
return maxElem
"""
}
listOf(Arrays, PrimitiveArrays).forEach {
it.body {
"""
if (isEmpty()) return null
var maxElem = this[0]
var maxValue = f(maxElem)
for (i in 1..lastIndex) {
val e = this[i]
val v = f(e)
if (maxValue < v) {
maxElem = e
maxValue = v
}
}
return maxElem
"""
}
}
}
return templates
}
@@ -1,222 +0,0 @@
package templates
import java.util.ArrayList
fun iterators(): List<GenericFunction> {
val templates = commons()
templates add f("filter(predicate: (T) -> Boolean)") {
isInline = false
doc = "Returns an iterator over elements which match the given *predicate*"
returns("Iterator<T>")
body {
"return FilterIterator<T>(this, predicate)"
}
}
templates add f("filterNot(predicate: (T) -> Boolean)") {
doc = "Returns an iterator over elements which don't match the given *predicate*"
returns("Iterator<T>")
body {
"return filter {!predicate(it)}"
}
}
templates add f("filterNotNull()") {
isInline = false
doc = "Returns an iterator over non-*null* elements"
typeParam("T:Any")
toNullableT = true
returns("Iterator<T>")
body {
"return FilterNotNullIterator(this)"
}
}
templates add f("map(transform : (T) -> R)") {
isInline = false
doc = "Returns an iterator obtained by applying *transform*, a function transforming an object of type *T* into an object of type *R*"
typeParam("R")
returns("Iterator<R>")
body {
"return MapIterator<T, R>(this, transform)"
}
}
templates add f("flatMap(transform: (T) -> Iterator<R>)") {
isInline = false
doc = "Returns an iterator over the concatenated results of transforming each element to one or more values"
typeParam("R")
returns("Iterator<R>")
body {
"return FlatMapIterator<T, R>(this, transform)"
}
}
templates add f("requireNoNulls()") {
isInline = false
doc = "Returns a original Iterable containing all the non-*null* elements, throwing an [[IllegalArgumentException]] if there are any null elements"
typeParam("T:Any")
toNullableT = true
returns("Iterator<T>")
body {
val THIS = "\$this"
"""
return map<T?, T>{
if (it == null) throw IllegalArgumentException("null element in iterator $THIS") else it
}
"""
}
}
templates add f("take(n: Int)") {
isInline = false
doc = "Returns an iterator restricted to the first *n* elements"
returns("Iterator<T>")
body {
"""
var count = n
return takeWhile{ --count >= 0 }
"""
}
}
templates add f("takeWhile(predicate: (T) -> Boolean)") {
isInline = false
doc = "Returns an iterator restricted to the first elements that match the given *predicate*"
returns("Iterator<T>")
body {
"return TakeWhileIterator<T>(this, predicate)"
}
}
// TODO: drop(n), dropWhile
templates add f("plus(element: T)") {
isInline = false
doc = "Creates an [[Iterator]] which iterates over this iterator then the given element at the end"
returns("Iterator<T>")
body {
"return CompositeIterator<T>(this, SingleIterator(element))"
}
}
templates add f("plus(iterator: Iterator<T>)") {
isInline = false
doc = "Creates an [[Iterator]] which iterates over this iterator then the following iterator"
returns("Iterator<T>")
body {
"return CompositeIterator<T>(this, iterator)"
}
}
templates add f("plus(collection: Iterable<T>)") {
isInline = false
doc = "Creates an [[Iterator]] which iterates over this iterator then the following collection"
returns("Iterator<T>")
body {
"return plus(collection.iterator())"
}
}
templates add f("min()") {
doc = "Returns the smallest element or null if there are no elements"
returns("T?")
typeParam("T: Comparable<T>")
isInline = false
body {
"""
if (!hasNext()) return null
var min = next()
while (hasNext()) {
val e = next()
if (min > e) min = e
}
return min
"""
}
}
templates add f("max()") {
doc = "Returns the largest element or null if there are no elements"
returns("T?")
typeParam("T: Comparable<T>")
isInline = false
body {
"""
if (!hasNext()) return null
var max = next()
while (hasNext()) {
val e = next()
if (max < e) max = e
}
return max
"""
}
}
templates add f("minBy(f: (T) -> R)") {
doc = "Returns the first element yielding the smallest value of the given function or null if there are no elements"
typeParam("R: Comparable<R>")
typeParam("T: Any")
returns("T?")
body {
"""
if (!hasNext()) return null
var minElem = next()
var minValue = f(minElem)
while (hasNext()) {
val e = next()
val v = f(e)
if (minValue > v) {
minElem = e
minValue = v
}
}
return minElem
"""
}
}
templates add f("maxBy(f: (T) -> R)") {
doc = "Returns the first element yielding the largest value of the given function or null if there are no elements"
typeParam("R: Comparable<R>")
typeParam("T: Any")
returns("T?")
body {
"""
if (!hasNext()) return null
var maxElem = next()
var maxValue = f(maxElem)
while (hasNext()) {
val e = next()
val v = f(e)
if (maxValue < v) {
maxElem = e
maxValue = v
}
}
return maxElem
"""
}
}
return templates.sort()
}
@@ -0,0 +1,208 @@
package templates
import templates.Family.*
fun mapping(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
templates add f("withIndices()") {
doc { "Returns a list containing pairs of each element of the original collection and their index" }
returns("List<Pair<Int, T>>")
body {
"""
var index = 0
return mapTo(ArrayList<Pair<Int, T>>(), { index++ to it })
"""
}
returns(Streams) { "Stream<Pair<Int, T>>" }
doc(Streams) { "Returns a stream containing pairs of each element of the original collection and their index" }
body(Streams) {
"""
var index = 0
return TransformingStream(this, { index++ to it })
"""
}
}
templates add f("map(transform : (T) -> R)") {
inline(true)
doc { "Returns a list containing the results of applying the given *transform* function to each element of the original collection" }
typeParam("R")
returns("List<R>")
body {
"return mapTo(ArrayList<R>(), transform)"
}
inline(false, Streams)
returns(Streams) { "Stream<R>" }
doc(Streams) { "Returns a stream containing the results of applying the given *transform* function to each element of the original stream" }
body(Streams) {
"return TransformingStream(this, transform) "
}
include(Maps)
}
templates add f("mapNotNull(transform : (T) -> R)") {
exclude(ArraysOfPrimitives)
doc { "Returns a list containing the results of applying the given *transform* function to each non-null element of the original collection" }
typeParam("T: Any")
typeParam("R")
returns("List<R>")
toNullableT = true
body {
"""
return mapNotNullTo(ArrayList<R>(), transform)
"""
}
doc(Streams) { "Returns a stream containing the results of applying the given *transform* function to each non-null element of the original stream" }
returns(Streams) { "Stream<R>" }
body(Streams) {
"""
return TransformingStream(FilteringStream(this, false, { it != null }) as Stream<T>, transform)
"""
}
}
templates add f("mapTo(collection: C, transform : (T) -> R)") {
inline(true)
doc {
"""
Appends transformed elements of original collection using the given *transform* function
to the given *collection*
"""
}
typeParam("R")
typeParam("C: MutableCollection<in R>")
returns("C")
body {
"""
for (item in this)
collection.add(transform(item))
return collection
"""
}
include(Maps)
}
templates add f("mapNotNullTo(collection: C, transform : (T) -> R)") {
inline(true)
exclude(ArraysOfPrimitives)
doc {
"""
Appends transformed non-null elements of original collection using the given *transform* function
to the given *collection*
"""
}
typeParam("T: Any")
typeParam("R")
typeParam("C: MutableCollection<in R>")
returns("C")
toNullableT = true
body {
"""
for (element in this) {
if (element != null) {
collection.add(transform(element))
}
}
return collection
"""
}
}
templates add f("flatMap(transform: (T)-> Iterable<R>)") {
inline(true)
exclude(Streams)
doc { "Returns a single list of all elements yielded from results of *transform* function being invoked on each element of original collection" }
typeParam("R")
returns("List<R>")
body {
"return flatMapTo(ArrayList<R>(), transform)"
}
include(Maps)
}
templates add f("flatMap(transform: (T)-> Stream<R>)") {
only(Streams)
doc { "Returns a single stream of all elements streamed from results of *transform* function being invoked on each element of original stream" }
typeParam("R")
returns("Stream<R>")
body {
"return FlatteningStream(this, transform)"
}
}
templates add f("flatMapTo(collection: C, transform: (T) -> Iterable<R>)") {
inline(true)
exclude(Streams)
doc { "Appends all elements yielded from results of *transform* function being invoked on each element of original collection, to the given *collection*" }
typeParam("R")
typeParam("C: MutableCollection<in R>")
returns("C")
body {
"""
for (element in this) {
val list = transform(element)
collection.addAll(list)
}
return collection
"""
}
include(Maps)
}
templates add f("flatMapTo(collection: C, transform: (T) -> Stream<R>)") {
inline(true)
only(Streams)
doc { "Appends all elements yielded from results of *transform* function being invoked on each element of original stream, to the given *collection*" }
typeParam("R")
typeParam("C: MutableCollection<in R>")
returns("C")
body {
"""
for (element in this) {
val list = transform(element)
collection.addAll(list)
}
return collection
"""
}
}
templates add f("groupBy(toKey: (T) -> K)") {
inline(true)
doc { "Returns a map of the elements in original collection grouped by the result of given *toKey* function" }
typeParam("K")
returns("Map<K, List<T>>")
body { "return groupByTo(HashMap<K, MutableList<T>>(), toKey)" }
include(Maps)
}
templates add f("groupByTo(map: MutableMap<K, MutableList<T>>, toKey: (T) -> K)") {
inline(true)
typeParam("K")
doc { "Appends elements from original collection grouped by the result of given *toKey* function to the given *map*" }
returns("Map<K, MutableList<T>>")
body {
"""
for (element in this) {
val key = toKey(element)
val list = map.getOrPut(key) { ArrayList<T>() }
list.add(element)
}
return map
"""
}
include(Maps)
}
return templates
}
@@ -0,0 +1,24 @@
package templates
import templates.Family.*
fun numeric(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
templates add f("sum()") {
doc { "Returns the sum of all elements in the collection" }
returns("SUM")
body {
"""
val iterator = iterator()
var sum : SUM = ZERO
while (iterator.hasNext()) {
sum += iterator.next()
}
return sum
"""
}
}
return templates
}
@@ -0,0 +1,131 @@
package templates
import templates.Family.*
fun ordering(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
templates add f("reverse()") {
doc { "Returns a list with elements in reversed order" }
returns { "List<T>" }
body {
"""
val list = toArrayList()
Collections.reverse(list)
return list
"""
}
exclude(Streams)
}
templates add f("sort()") {
doc {
"""
Returns a sorted list of all elements
"""
}
returns("List<T>")
typeParam("T: Comparable<T>")
body {
"""
val sortedList = toArrayList()
java.util.Collections.sort(sortedList)
return sortedList
"""
}
exclude(Streams)
exclude(ArraysOfPrimitives) // TODO: resolve collision between inplace sort and this function
exclude(ArraysOfObjects)
}
templates add f("sortDescending()") {
doc {
"""
Returns a sorted list of all elements
"""
}
returns("List<T>")
typeParam("T: Comparable<T>")
body {
"""
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> -x.compareTo(y)}
java.util.Collections.sort(sortedList, sortBy)
return sortedList
"""
}
exclude(Streams)
exclude(ArraysOfPrimitives) // TODO: resolve collision between inplace sort and this function
exclude(ArraysOfObjects)
}
templates add f("sortBy(order: (T) -> R)") {
inline(true)
doc {
"""
Returns a list of all elements, sorted by results of specified *order* function.
"""
}
returns("List<T>")
typeParam("R: Comparable<R>")
body {
"""
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> order(x).compareTo(order(y))}
java.util.Collections.sort(sortedList, sortBy)
return sortedList
"""
}
exclude(Streams)
exclude(ArraysOfPrimitives)
}
templates add f("sortDescendingBy(order: (T) -> R)") {
inline(true)
doc {
"""
Returns a list of all elements, sorted by results of specified *order* function.
"""
}
returns("List<T>")
typeParam("R: Comparable<R>")
body {
"""
val sortedList = toArrayList()
val sortBy: Comparator<T> = comparator<T> {(x: T, y: T) -> -order(x).compareTo(order(y))}
java.util.Collections.sort(sortedList, sortBy)
return sortedList
"""
}
exclude(Streams)
exclude(ArraysOfPrimitives)
}
templates add f("sortBy(comparator : Comparator<T>)") {
doc {
"""
Returns a list of all elements, sorted by the specified *comparator*
"""
}
returns("List<T>")
body {
"""
val sortedList = toArrayList()
java.util.Collections.sort(sortedList, comparator)
return sortedList
"""
}
exclude(Streams)
exclude(ArraysOfPrimitives)
}
return templates
}
@@ -1,47 +0,0 @@
package templates
import templates.Family.*
enum class PrimitiveType(val name: String) {
Boolean: PrimitiveType("Boolean")
Byte: PrimitiveType("Byte")
Char: PrimitiveType("Char")
Short: PrimitiveType("Short")
Int: PrimitiveType("Int")
Long: PrimitiveType("Long")
Float: PrimitiveType("Float")
Double: PrimitiveType("Double")
}
private fun PrimitiveType.zero() = when (this) {
PrimitiveType.Int -> "0"
PrimitiveType.Byte -> "0"
PrimitiveType.Short -> "0"
PrimitiveType.Long -> "0.toLong()"
PrimitiveType.Double -> "0.0"
PrimitiveType.Float -> "0.toFloat()"
else -> null
}
private fun returnTypeForSum(primitive: PrimitiveType) = when (primitive) {
PrimitiveType.Byte -> PrimitiveType.Int
PrimitiveType.Short -> PrimitiveType.Int
else -> primitive
}
fun sumFunction(primitive: PrimitiveType) = primitive.zero()?.let { zero ->
f("sum()") {
doc = "Sums up the elements"
isInline = false
if (returnTypeForSum(primitive) != primitive) {
//this is required to avoid clash of erasured method signatures (Iterables.sum(): Int)
absentFor(Iterables)
}
Iterables.customReceiver("Iterable<${primitive.name}>")
Arrays.customReceiver("Array<${primitive.name}>")
returns(returnTypeForSum(primitive).name)
body {
"return fold($zero, {a,b -> a+b})"
}
}
}
@@ -0,0 +1,104 @@
package templates
import templates.Family.*
fun snapshots(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
templates add f("toCollection(collection : C)") {
doc { "Appends all elements to the given *collection*" }
returns("C")
typeParam("C : MutableCollection<in T>")
body {
"""
for (item in this) {
collection.add(item)
}
return collection
"""
}
}
templates add f("toSet()") {
doc { "Returns a Set of all elements" }
returns("Set<T>")
body { "return toCollection(LinkedHashSet<T>())" }
}
templates add f("toHashSet()") {
doc { "Returns a HashSet of all elements" }
returns("HashSet<T>")
body { "return toCollection(HashSet<T>())" }
}
templates add f("toSortedSet()") {
doc { "Returns a SortedSet of all elements" }
returns("SortedSet<T>")
body { "return toCollection(TreeSet<T>())" }
}
templates add f("toArrayList()") {
doc { "Returns an ArrayList of all elements" }
returns("ArrayList<T>")
body { "return toCollection(ArrayList<T>())" }
// ISSUE: JavaScript can't perform this operation
/*
body(Collections) {
"""
return ArrayList<T>(this)
"""
}
*/
body(ArraysOfObjects, ArraysOfPrimitives) {
"""
val list = ArrayList<T>(size)
for (item in this) list.add(item)
return list
"""
}
}
templates add f("toList()") {
doc { "Returns a List containing all elements" }
returns("List<T>")
body { "return toCollection(ArrayList<T>())" }
// ISSUE: JavaScript can't perform this operations
/*
body(Collections) {
"""
return ArrayList<T>(this)
"""
}
body(ArraysOfObjects) {
"""
return ArrayList<T>(Arrays.asList(*this))
"""
}
*/
body(ArraysOfPrimitives) {
"""
val list = ArrayList<T>(size)
for (item in this) list.add(item)
return list
"""
}
}
templates add f("toLinkedList()") {
doc { "Returns a LinkedList containing all elements" }
returns("LinkedList<T>")
body { "return toCollection(LinkedList<T>())" }
}
templates add f("toSortedList()") {
doc { "Returns a sorted list of all elements" }
typeParam("T: Comparable<T>")
returns("List<T>")
body { "return toArrayList().sort()" }
body(Iterables) { "return sort()" }
}
return templates
}
@@ -0,0 +1,94 @@
package templates
import templates.Family.*
fun specialJVM(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
templates add f("copyOfRange(from: Int, to: Int)") {
only(ArraysOfObjects, ArraysOfPrimitives)
doc { "Returns new array which is a copy of range of original array" }
returns("SELF")
body {
"return Arrays.copyOfRange(this, from, to)"
}
}
// TODO: when newLength is larger than size, we can get null items
templates add f("copyOf(newSize: Int = size)") {
only(ArraysOfObjects, ArraysOfPrimitives)
doc { "Returns new array which is a copy of the riginal array" }
returns("SELF")
body {
"return Arrays.copyOf(this, newSize)"
}
body(ArraysOfObjects) {
"return Arrays.copyOf(this, newSize) as Array<T>"
}
}
templates add f("fill(element: T)") {
only(ArraysOfObjects, ArraysOfPrimitives)
doc { "Fills original array with the provided value" }
returns("Unit")
body {
"Arrays.fill(this, element)"
}
}
templates add f("binarySearch(element: T, fromIndex: Int = 0, toIndex: Int = size - 1)") {
only(ArraysOfObjects, ArraysOfPrimitives)
exclude(PrimitiveType.Boolean)
doc { "Searches array or range of array for provided element index using binary search algorithm. Array is expected to be sorted." }
returns("Int")
body {
"return Arrays.binarySearch(this, fromIndex, toIndex, element)"
}
}
templates add f("sort(fromIndex : Int = 0, toIndex : Int = size - 1)") {
only(ArraysOfObjects, ArraysOfPrimitives)
exclude(PrimitiveType.Boolean)
doc { "Sorts array or range in array inplace" }
returns("Unit")
body {
"Arrays.sort(this, fromIndex, toIndex)"
}
}
templates add f("filterIsInstanceTo(collection: C, klass: Class<R>)") {
doc { "Appends all elements that are instances of specified class into the given *collection*" }
typeParam("C: MutableCollection<in R>")
typeParam("R: T")
returns("C")
exclude(ArraysOfPrimitives)
body {
"""
for (element in this) if (klass.isInstance(element)) collection.add(element as R)
return collection
"""
}
}
templates add f("filterIsInstance(klass: Class<R>)") {
doc { "Returns a list containing all elements that are instances of specified class" }
typeParam("R: T")
returns("List<R>")
body {
"""
return filterIsInstanceTo(ArrayList<R>(), klass)
"""
}
exclude(ArraysOfPrimitives)
doc(Streams) { "Returns a stream containing all elements that are instances of specified class" }
returns(Streams) { "Stream<T>" }
body(Streams) {
"""
return FilteringStream(this, true, { klass.isInstance(it) })
"""
}
}
return templates
}
@@ -0,0 +1,56 @@
package templates
import templates.Family.*
fun strings(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
templates add f("appendString(buffer: Appendable, separator: String = \", \", prefix: String =\"\", postfix: String = \"\", limit: Int = -1, truncated: String = \"...\")") {
doc {
"""
Appends the string from all the elements separated using the *separator* and using the given *prefix* and *postfix* if supplied
If a collection could be huge you can specify a non-negative value of *limit* which will only show a subset of the collection then it will
a special *truncated* separator (which defaults to "..."
"""
}
returns { "Unit" }
body {
"""
buffer.append(prefix)
var count = 0
for (element in this) {
if (++count > 1) buffer.append(separator)
if (limit < 0 || count <= limit) {
val text = if (element == null) "null" else element.toString()
buffer.append(text)
} else break
}
if (limit >= 0 && count > limit) buffer.append(truncated)
buffer.append(postfix)
"""
}
}
templates add f("makeString(separator: String = \", \", prefix: String = \"\", postfix: String = \"\", limit: Int = -1, truncated: String = \"...\")") {
doc {
"""
Creates a string from all the elements separated using the *separator* and using the given *prefix* and *postfix* if supplied.
If a collection could be huge you can specify a non-negative value of *limit* which will only show a subset of the collection then it will
a special *truncated* separator (which defaults to "..."
"""
}
returns("String")
body {
"""
val buffer = StringBuilder()
appendString(buffer, separator, prefix, postfix, limit, truncated)
return buffer.toString()
"""
}
}
return templates
}