diff --git a/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt b/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt index 09e58ca95a2..692ecc0087c 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt @@ -17,7 +17,7 @@ private val COMMON_AUTOGENERATED_WARNING: String = """// * at runtime. */ fun main(args: Array) { - require(args.size == 1, "Expecting Kotlin project home path as an argument") + require(args.size() == 1, "Expecting Kotlin project home path as an argument") val outDir = File(File(args[0]), "libraries/stdlib/src/generated") require(outDir.exists(), "${outDir.getPath()} doesn't exist!") @@ -31,8 +31,6 @@ fun main(args: Array) { generateDownTos(File(outDir, "_DownTo.kt"), "package kotlin") } -fun String.flat() = this.replaceAll(" ", "") - fun List.writeTo(file: File, builder: GenericFunction.() -> String) { println("Generating file: ${file.getPath()}") val its = FileWriter(file) diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt index fda97e8d062..f6a3b8eb67e 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt @@ -7,7 +7,7 @@ fun comparables(): List { templates add f("coerceAtLeast(minimumValue: SELF)") { only(Primitives, Generic) - only(*numericPrimitives) + only(numericPrimitives) returns("SELF") typeParam("T: Comparable") doc { @@ -27,7 +27,7 @@ fun comparables(): List { templates add f("coerceAtMost(maximumValue: SELF)") { only(Primitives, Generic) - only(*numericPrimitives) + only(numericPrimitives) returns("SELF") typeParam("T: Comparable") doc { @@ -46,7 +46,7 @@ fun comparables(): List { templates add f("coerceIn(range: TRange)") { only(Primitives, Generic) - only(*numericPrimitives) + only(numericPrimitives) returns("SELF") typeParam("T: Comparable") doc { @@ -66,7 +66,7 @@ fun comparables(): List { templates add f("coerceIn(minimumValue: SELF?, maximumValue: SELF?)") { only(Primitives, Generic) - only(*numericPrimitives) + only(numericPrimitives) returns("SELF") typeParam("T: Comparable") doc { diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt index d271af9f2a5..a27564d565e 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt @@ -12,26 +12,40 @@ enum class Family { Collections, Lists, Maps, + Sets, ArraysOfObjects, ArraysOfPrimitives, + InvariantArraysOfObjects, Strings, RangesOfPrimitives, ProgressionsOfPrimitives, Primitives, Generic; - val isPrimitiveSpecialization: Boolean by Delegates.lazy { this in listOf(ArraysOfPrimitives, RangesOfPrimitives, ProgressionsOfPrimitives, Primitives) } + val isPrimitiveSpecialization: Boolean by lazy { this in primitiveSpecializations } + + companion object { + val primitiveSpecializations = setOf(ArraysOfPrimitives, RangesOfPrimitives, ProgressionsOfPrimitives, Primitives) + val defaultFamilies = setOf(Iterables, Sequences, ArraysOfObjects, ArraysOfPrimitives, Strings) + } } -enum class PrimitiveType(val name: String) { - Boolean("Boolean"), - Byte("Byte"), - Char("Char"), - Short("Short"), - Int("Int"), - Long("Long"), - Float("Float"), - Double("Double") +enum class PrimitiveType { + Boolean, + Byte, + Char, + Short, + Int, + Long, + Float, + Double; + + val name: String get() = this.name() + + companion object { + val defaultPrimitives = PrimitiveType.values().toSet() + val numericPrimitives = setOf(PrimitiveType.Int, PrimitiveType.Long, PrimitiveType.Byte, PrimitiveType.Short, PrimitiveType.Double, PrimitiveType.Float) + } } @@ -63,17 +77,18 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp open class PrimitiveProperty() : SpecializedProperty() - val defaultFamilies = array(Iterables, Sequences, ArraysOfObjects, ArraysOfPrimitives, Strings) - val defaultPrimitives = PrimitiveType.values() - val numericPrimitives = array(PrimitiveType.Int, PrimitiveType.Long, PrimitiveType.Byte, PrimitiveType.Short, PrimitiveType.Double, PrimitiveType.Float) + val defaultFamilies = Family.defaultFamilies + val defaultPrimitives = PrimitiveType.defaultPrimitives + val numericPrimitives = PrimitiveType.numericPrimitives var toNullableT: Boolean = false var receiverAsterisk = false - val buildFamilies = LinkedHashSet(defaultFamilies.toList()) - val buildPrimitives = LinkedHashSet(defaultPrimitives.toList()) + val buildFamilies = LinkedHashSet(defaultFamilies) + val buildPrimitives = LinkedHashSet(defaultPrimitives) + val customSignature = FamilyProperty() val deprecate = FamilyProperty() val deprecateReplacement = FamilyProperty() val doc = FamilyProperty() @@ -112,8 +127,12 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp } fun only(vararg primitives: PrimitiveType) { + only(primitives.asList()) + } + + fun only(primitives: Collection) { buildPrimitives.clear() - buildPrimitives.addAll(primitives.toList()) + buildPrimitives.addAll(primitives) } fun include(vararg families: Family) { @@ -156,15 +175,16 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp Collections -> "Collection<$isAsteriskOrT>" Lists -> "List<$isAsteriskOrT>" Maps -> "Map" + Sets -> "Set<$isAsteriskOrT>" Sequences -> "Sequence<$isAsteriskOrT>" - ArraysOfObjects -> "Array<$isAsteriskOrT>" + InvariantArraysOfObjects -> "Array" + ArraysOfObjects -> "Array<${isAsteriskOrT.replace("T", "out T")}>" Strings -> "String" ArraysOfPrimitives -> primitive?.let { it.name() + "Array" } ?: throw IllegalArgumentException("Primitive array should specify primitive type") RangesOfPrimitives -> primitive?.let { it.name() + "Range" } ?: throw IllegalArgumentException("Primitive range should specify primitive type") ProgressionsOfPrimitives -> primitive?.let { it.name() + "Progression" } ?: throw IllegalArgumentException("Primitive progression should specify primitive type") Primitives -> primitive?.let { it.name } ?: throw IllegalArgumentException("Primitive should specify primitive type") Generic -> "T" - else -> throw IllegalStateException("Invalid family") } @@ -175,7 +195,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp while (t.hasMoreTokens()) { val token = t.nextToken() answer.append(when (token) { - "SELF" -> if (receiver == "Array") "Array" else receiver + "SELF" -> receiver "PRIMITIVE" -> primitive?.name() ?: token "SUM" -> { when (primitive) { @@ -244,7 +264,8 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp return types } else if (primitive == null && f != Strings) { - val implicitTypeParameters = receiver.dropWhile { it != '<' }.drop(1).filterNot { it == ' ' }.takeWhile { it != '>' }.split(",") + val implicitTypeParameters = receiver.dropWhile { it != '<' }.drop(1).takeWhile { it != '>' }.split(",") + .map { it.removePrefix("out").removePrefix("in").trim() } for (implicit in implicitTypeParameters.reverse()) { if (implicit != "*" && !types.any { it.startsWith(implicit) || it.startsWith("reified " + implicit) }) { types.add(0, implicit) @@ -293,14 +314,10 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp builder.append(types.join(separator = ", ", prefix = "<", postfix = "> ").renderType()) } - val receiverType = (when (receiver) { - "Array" -> if (toNullableT) "Array" else "Array" - else -> if (toNullableT) receiver.replace("T>", "T?>") else receiver - }).renderType() - + val receiverType = (if (toNullableT) receiver.replace("T>", "T?>") else receiver).renderType() builder.append(receiverType) - builder.append(".${signature.renderType()}: ${returnType.renderType()}") + builder.append(".${(customSignature[f] ?: signature).renderType()}: ${returnType.renderType()}") if (keyword == "fun") builder.append(" {") val body = (customPrimitiveBodies[f to primitive] ?: body[f] ?: throw RuntimeException("No body specified for $signature for ${f to primitive}")).trim('\n')