New stdlib generators
This commit is contained in:
committed by
Andrey Breslav
parent
0980f5e40a
commit
e37d8174c3
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user