Support String in generators, and migrate generated functions.

This commit is contained in:
Ilya Ryzhenkov
2014-04-08 15:40:53 +04:00
committed by Andrey Breslav
parent d9d5631a16
commit cbc0e6404e
22 changed files with 971 additions and 454 deletions
@@ -95,7 +95,7 @@ fun aggregates(): List<GenericFunction> {
return count
"""
}
body(Maps, Collections, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Maps, Collections, ArraysOfObjects, ArraysOfPrimitives) {
"return size"
}
}
@@ -324,7 +324,7 @@ fun aggregates(): List<GenericFunction> {
templates add f("foldRight(initial: R, operation: (T, R) -> R)") {
inline(true)
only(Lists, ArraysOfObjects, ArraysOfPrimitives)
only(Strings, 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")
@@ -363,7 +363,7 @@ fun aggregates(): List<GenericFunction> {
templates add f("reduceRight(operation: (T, T) -> T)") {
inline(true)
only(Lists, ArraysOfObjects, ArraysOfPrimitives)
only(Strings, 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 {
@@ -15,7 +15,7 @@ fun elements(): List<GenericFunction> {
return indexOf(element) >= 0
"""
}
exclude(Lists, Collections)
exclude(Strings, Lists, Collections)
body(ArraysOfPrimitives, ArraysOfObjects) {
"""
return indexOf(element) >= 0
@@ -24,6 +24,7 @@ fun elements(): List<GenericFunction> {
}
templates add f("indexOf(element: T)") {
exclude(Strings)
doc { "Returns first index of *element*, or -1 if the collection does not contain element" }
returns("Int")
body {
@@ -69,6 +70,7 @@ fun elements(): List<GenericFunction> {
}
templates add f("lastIndexOf(element: T)") {
exclude(Strings) // has native implementation
doc { "Returns last index of *element*, or -1 if the collection does not contain element" }
returns("Int")
body {
@@ -143,7 +145,7 @@ fun elements(): List<GenericFunction> {
throw IndexOutOfBoundsException("Collection doesn't contain element at index")
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
return get(index)
"""
@@ -171,7 +173,7 @@ fun elements(): List<GenericFunction> {
}
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
if (size == 0)
throw IllegalArgumentException("Collection is empty")
@@ -200,7 +202,7 @@ fun elements(): List<GenericFunction> {
}
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
return if (size > 0) this[0] else null
"""
@@ -255,7 +257,7 @@ fun elements(): List<GenericFunction> {
}
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
if (size == 0)
throw IllegalArgumentException("Collection is empty")
@@ -283,8 +285,7 @@ fun elements(): List<GenericFunction> {
}
"""
}
include(Lists)
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
return if (size > 0) this[size - 1] else null
"""
@@ -348,7 +349,7 @@ fun elements(): List<GenericFunction> {
}
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
if (size != 1)
throw IllegalArgumentException("Collection has ${bucks}size elements")
@@ -376,7 +377,7 @@ fun elements(): List<GenericFunction> {
}
"""
}
body(Lists, ArraysOfObjects, ArraysOfPrimitives) {
body(Strings, Lists, ArraysOfObjects, ArraysOfPrimitives) {
"""
if (size == 0)
return null
@@ -15,6 +15,7 @@ enum class Family {
Maps
ArraysOfObjects
ArraysOfPrimitives
Strings
}
enum class PrimitiveType(val name: String) {
@@ -30,7 +31,7 @@ enum class PrimitiveType(val name: String) {
class GenericFunction(val signature: String) : Comparable<GenericFunction> {
val defaultFamilies = array(Iterables, Streams, ArraysOfObjects, ArraysOfPrimitives)
val defaultFamilies = array(Iterables, Streams, ArraysOfObjects, ArraysOfPrimitives, Strings)
var toNullableT: Boolean = false
@@ -150,10 +151,12 @@ class GenericFunction(val signature: String) : Comparable<GenericFunction> {
Maps -> "Map<K,V>"
Streams -> "Stream<T>"
ArraysOfObjects -> "Array<T>"
Strings -> "String"
ArraysOfPrimitives -> primitive?.let { it.name() + "Array" } ?: throw IllegalArgumentException("Primitive array should specify primitive type")
else -> throw IllegalStateException("Invalid family")
}
fun String.renderType(): String {
val t = StringTokenizer(this, " \t\n,:()<>?.", true)
val answer = StringBuilder()
@@ -174,11 +177,18 @@ class GenericFunction(val signature: String) : Comparable<GenericFunction> {
PrimitiveType.Float -> "0.0f"
else -> "0"
}
"TCollection" -> {
when (f) {
Strings -> "Appendable"
else -> "MutableCollection<in T>".renderType()
}
}
"T" -> {
if (f == Maps)
"Map.Entry<K,V>"
else
primitive?.name() ?: token
when (f) {
Strings -> "Char"
Maps -> "Map.Entry<K,V>"
else -> primitive?.name() ?: token
}
}
else -> token
})
@@ -189,7 +199,7 @@ class GenericFunction(val signature: String) : Comparable<GenericFunction> {
fun effectiveTypeParams(): List<String> {
val types = ArrayList(typeParams)
if (primitive == null) {
if (primitive == null && f != Strings) {
val implicitTypeParameters = receiver.dropWhile { it != '<' }.drop(1).takeWhile { it != '>' }.split(",")
for (implicit in implicitTypeParameters.reverse()) {
if (!types.any { it.startsWith(implicit) }) {
@@ -28,7 +28,9 @@ fun filtering(): List<GenericFunction> {
"""
}
include(Collections)
body(Strings) { "return substring(Math.min(n, size))" }
returns(Strings) { "String"}
body(Collections, ArraysOfObjects, ArraysOfPrimitives) {
"""
if (n >= size)
@@ -60,6 +62,9 @@ fun filtering(): List<GenericFunction> {
"""
}
body(Strings) { "return substring(0, Math.min(n, size))" }
returns(Strings) { "String"}
doc(Streams) { "Returns a stream containing first *n* elements" }
returns(Streams) { "Stream<T>" }
body(Streams) {
@@ -105,6 +110,17 @@ fun filtering(): List<GenericFunction> {
"""
}
returns(Strings) { "String"}
body(Strings) {
"""
for (index in 0..length)
if (!predicate(get(index))) {
return substring(index)
}
return ""
"""
}
inline(false, Streams)
doc(Streams) { "Returns a stream containing all elements except first elements that satisfy the given *predicate*" }
returns(Streams) { "Stream<T>" }
@@ -142,6 +158,17 @@ fun filtering(): List<GenericFunction> {
"""
}
returns(Strings) { "String"}
body(Strings) {
"""
for (index in 0..length)
if (!predicate(get(index))) {
return substring(0, index)
}
return ""
"""
}
inline(false, Streams)
doc(Streams) { "Returns a stream containing first elements satisfying the given *predicate*" }
returns(Streams) { "Stream<T>" }
@@ -163,6 +190,13 @@ fun filtering(): List<GenericFunction> {
"""
}
returns(Strings) { "String"}
body(Strings) {
"""
return filterTo(StringBuilder(), predicate).toString()
"""
}
inline(false, Streams)
doc(Streams) { "Returns a stream containing all elements matching the given *predicate*" }
returns(Streams) { "Stream<T>" }
@@ -178,7 +212,7 @@ fun filtering(): List<GenericFunction> {
inline(true)
doc { "Appends all elements matching the given *predicate* into the given *collection*" }
typeParam("C: MutableCollection<in T>")
typeParam("C: TCollection")
returns("C")
body {
@@ -187,6 +221,18 @@ fun filtering(): List<GenericFunction> {
return collection
"""
}
doc(Strings) { "Appends all characters matching the given *predicate* to the given *collection*" }
body(Strings) {
"""
for (index in 0..length - 1) {
val element = get(index)
if (predicate(element)) destination.append(element)
}
return destination
"""
}
include(Maps)
}
@@ -201,6 +247,13 @@ fun filtering(): List<GenericFunction> {
"""
}
returns(Strings) { "String"}
body(Strings) {
"""
return filterNotTo(StringBuilder(), predicate).toString()
"""
}
inline(false, Streams)
doc(Streams) { "Returns a stream containing all elements not matching the given *predicate*" }
returns(Streams) { "Stream<T>" }
@@ -216,7 +269,7 @@ fun filtering(): List<GenericFunction> {
inline(true)
doc { "Appends all elements not matching the given *predicate* to the given *collection*" }
typeParam("C: MutableCollection<in T>")
typeParam("C: TCollection")
returns("C")
body {
@@ -225,11 +278,19 @@ fun filtering(): List<GenericFunction> {
return collection
"""
}
doc(Strings) { "Appends all characters not matching the given *predicate* to the given *collection*" }
body(Strings) {
"""
for (element in this) if (!predicate(element)) collection.append(element)
return collection
"""
}
include(Maps)
}
templates add f("filterNotNull()") {
exclude(ArraysOfPrimitives)
exclude(ArraysOfPrimitives, Strings)
doc { "Returns a list containing all elements that are not null" }
typeParam("T: Any")
returns("List<T>")
@@ -250,11 +311,11 @@ fun filtering(): List<GenericFunction> {
}
templates add f("filterNotNullTo(collection: C)") {
exclude(ArraysOfPrimitives)
exclude(ArraysOfPrimitives, Strings)
doc { "Appends all elements that are not null to the given *collection*" }
typeParam("C: MutableCollection<in T>")
typeParam("T: Any")
returns("C")
typeParam("C: TCollection")
typeParam("T: Any")
toNullableT = true
body {
"""
@@ -265,7 +326,7 @@ fun filtering(): List<GenericFunction> {
}
templates add f("slice(indices: Iterable<Int>)") {
only(Lists, ArraysOfPrimitives, ArraysOfObjects)
only(Strings, Lists, ArraysOfPrimitives, ArraysOfObjects)
doc { "Returns a list containing elements at specified positions" }
returns("List<T>")
body {
@@ -277,6 +338,17 @@ fun filtering(): List<GenericFunction> {
return list
"""
}
returns(Strings) { "String" }
body(Strings) {
"""
val result = StringBuilder()
for (i in indices) {
result.append(get(i))
}
return result.toString()
"""
}
}
return templates
@@ -6,6 +6,7 @@ fun generators(): List<GenericFunction> {
val templates = arrayListOf<GenericFunction>()
templates add f("plus(element: T)") {
exclude(Strings)
doc { "Returns a list containing all elements of original collection and then the given element" }
returns("List<T>")
body {
@@ -26,7 +27,7 @@ fun generators(): List<GenericFunction> {
}
templates add f("plus(collection: Iterable<T>)") {
exclude(Streams)
exclude(Strings, Streams)
doc { "Returns a list containing all elements of original collection and then all elements of the given *collection*" }
returns("List<T>")
body {
@@ -39,7 +40,7 @@ fun generators(): List<GenericFunction> {
}
templates add f("plus(array: Array<T>)") {
exclude(Streams)
exclude(Strings, Streams)
doc { "Returns a list containing all elements of original collection and then all elements of the given *collection*" }
returns("List<T>")
body {
@@ -99,9 +100,25 @@ fun generators(): List<GenericFunction> {
return Pair(first, second)
"""
}
returns(Strings) { "Pair<String, String>" }
body(Strings) {
"""
val first = StringBuilder()
val second = StringBuilder()
for (element in this) {
if (predicate(element)) {
first.append(element)
} else {
second.append(element)
}
}
return Pair(first.toString(), second.toString())
"""
}
}
templates add f("zip(collection: Iterable<R>)") {
templates add f("zip(other: Iterable<R>)") {
exclude(Streams)
doc {
"""
@@ -113,7 +130,7 @@ fun generators(): List<GenericFunction> {
body {
"""
val first = iterator()
val second = collection.iterator()
val second = other.iterator()
val list = ArrayList<Pair<T,R>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
@@ -123,6 +140,27 @@ fun generators(): List<GenericFunction> {
}
}
templates add f("zip(other : String)") {
only(Strings)
doc {
"""
Returns a list of pairs built from characters of both strings with same indexes. List has length of shortest collection.
"""
}
returns("List<Pair<Char,Char>>")
body {
"""
val first = iterator()
val second = other.iterator()
val list = ArrayList<Pair<Char,Char>>()
while (first.hasNext() && second.hasNext()) {
list.add(first.next() to second.next())
}
return list
"""
}
}
templates add f("zip(array: Array<R>)") {
exclude(Streams)
doc {
@@ -10,7 +10,7 @@ fun guards(): List<GenericFunction> {
templates add f("requireNoNulls()") {
include(Lists)
exclude(ArraysOfPrimitives)
exclude(Strings, 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
@@ -45,7 +45,8 @@ fun mapping(): List<GenericFunction> {
}
templates add f("mapNotNull(transform : (T) -> R)") {
exclude(ArraysOfPrimitives)
inline(true)
exclude(Strings, 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")
@@ -59,6 +60,7 @@ fun mapping(): List<GenericFunction> {
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>" }
inline(false, Streams)
body(Streams) {
"""
return TransformingStream(FilteringStream(this, false, { it != null }) as Stream<T>, transform)
@@ -91,7 +93,7 @@ fun mapping(): List<GenericFunction> {
templates add f("mapNotNullTo(collection: C, transform : (T) -> R)") {
inline(true)
exclude(ArraysOfPrimitives)
exclude(Strings, ArraysOfPrimitives)
doc {
"""
Appends transformed non-null elements of original collection using the given *transform* function
@@ -16,6 +16,15 @@ fun ordering(): List<GenericFunction> {
"""
}
doc(Strings) { "Returns a string with characters in reversed order" }
returns(Strings) { "String"}
body(Strings) {
// TODO: Replace with StringBuilder(this) when JS can handle it
"""
return StringBuilder().append(this).reverse().toString()
"""
}
exclude(Streams)
}
@@ -38,6 +47,7 @@ fun ordering(): List<GenericFunction> {
exclude(Streams)
exclude(ArraysOfPrimitives) // TODO: resolve collision between inplace sort and this function
exclude(ArraysOfObjects)
exclude(Strings)
}
templates add f("sortDescending()") {
@@ -60,6 +70,7 @@ fun ordering(): List<GenericFunction> {
exclude(Streams)
exclude(ArraysOfPrimitives) // TODO: resolve collision between inplace sort and this function
exclude(ArraysOfObjects)
exclude(Strings)
}
templates add f("sortBy(order: (T) -> R)") {
@@ -83,6 +94,7 @@ fun ordering(): List<GenericFunction> {
exclude(Streams)
exclude(ArraysOfPrimitives)
exclude(Strings)
}
templates add f("sortDescendingBy(order: (T) -> R)") {
@@ -106,6 +118,7 @@ fun ordering(): List<GenericFunction> {
exclude(Streams)
exclude(ArraysOfPrimitives)
exclude(Strings)
}
templates add f("sortBy(comparator : Comparator<T>)") {
@@ -125,6 +138,7 @@ fun ordering(): List<GenericFunction> {
exclude(Streams)
exclude(ArraysOfPrimitives)
exclude(Strings)
}
return templates