From 2bc1fbab3f6297ff7b23d9b520aa8f6874bd5f64 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Fri, 11 Sep 2015 16:43:41 +0300 Subject: [PATCH] Allow stdlib generator to distribute concrete functions between different target files. --- .../src/generators/GenerateCollections.kt | 42 +++++++++++-------- .../src/generators/GenerateStandardLib.kt | 20 ++++++++- .../src/generators/SourceFile.kt | 20 +++++++++ .../kotlin-stdlib-gen/src/templates/Engine.kt | 37 ++++++++++++++-- 4 files changed, 98 insertions(+), 21 deletions(-) create mode 100644 libraries/tools/kotlin-stdlib-gen/src/generators/SourceFile.kt diff --git a/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateCollections.kt b/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateCollections.kt index 644cdb8b7c2..7bcf875bb6d 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateCollections.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateCollections.kt @@ -6,23 +6,31 @@ 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() } - sets().writeTo(File(outDir, "_Sets.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() } - sequences().writeTo(File(outDir, "_Sequences.kt")) { build() } - specialJVM().writeTo(File(outDir, "_SpecialJVM.kt")) { build() } - ranges().writeTo(File(outDir, "_Ranges.kt")) { build() } - toPrimitiveArrays().writeTo(File(outDir, "_ArraysToPrimitiveArrays.kt")) { build() } - numeric().writeTo(File(outDir, "_Numeric.kt")) { build() } - comparables().writeTo(File(outDir, "_Comparables.kt")) { build() } + val templates = sequenceOf( + ::elements, + ::filtering, + ::ordering, + ::arrays, + ::snapshots, + ::mapping, + ::sets, + ::aggregates, + ::guards, + ::generators, + ::strings, + ::sequences, + ::specialJVM, + ::ranges, + ::toPrimitiveArrays, + ::numeric, + ::comparables + ).flatMap { it().sortedBy { it.signature }.asSequence() } + + val groupedConcreteFunctions = templates.flatMap { it.instantiate().asSequence() }.groupBy { it.sourceFile } + + for ((sourceFile, functions) in groupedConcreteFunctions) { + functions.writeTo(outDir, sourceFile) + } } fun generateCollectionsJsAPI(outDir: File) { diff --git a/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt b/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt index 0dcc36ff8c0..f594bcbb229 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt @@ -40,8 +40,26 @@ fun List.writeTo(file: File, builder: GenericFunction.() -> Str its.append("import kotlin.platform.*\n") // TODO: Remove unneeded import its.append("import java.util.*\n\n") its.append("import java.util.Collections // TODO: it's temporary while we have java.util.Collections in js\n\n") - for (t in this.sorted()) { + for (t in this.sortedBy { it.signature }) { its.append(t.builder()) } } } + +fun List.writeTo(outDir: File, sourceFile: SourceFile) { + val file = File(outDir, sourceFile.fileName) + println("Generating file: $file") + val its = FileWriter(file) + + its.use { + its.append("@file:kotlin.jvm.JvmName(\"${sourceFile.jvmClassName}\")\n\n") + its.append("package kotlin\n\n") + its.append("$COMMON_AUTOGENERATED_WARNING\n\n") + its.append("import java.util.*\n\n") + its.append("import java.util.Collections // TODO: it's temporary while we have java.util.Collections in js\n\n") + + for (f in this) { + f.textBuilder(its) + } + } +} diff --git a/libraries/tools/kotlin-stdlib-gen/src/generators/SourceFile.kt b/libraries/tools/kotlin-stdlib-gen/src/generators/SourceFile.kt new file mode 100644 index 00000000000..b6560878635 --- /dev/null +++ b/libraries/tools/kotlin-stdlib-gen/src/generators/SourceFile.kt @@ -0,0 +1,20 @@ +package generators + +enum class SourceFile(jvmClassName: String? = null) { + + Arrays(), + Collections(), + Sets(), + Maps(), + Sequences(), + Ranges(), + Strings(), + Numbers(), + ; + + val name = this.name() + + val jvmClassName = jvmClassName ?: this.name().capitalize() + + val fileName: String get() = "_${name.capitalize()}.kt" +} diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt index a743e5a6ec4..5a4233ab107 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Engine.kt @@ -1,5 +1,6 @@ package templates +import generators.SourceFile import templates.Family.* import templates.Family.Collections import java.io.StringReader @@ -57,8 +58,9 @@ enum class PrimitiveType { fun PrimitiveType.isIntegral(): Boolean = this in PrimitiveType.integralPrimitives fun PrimitiveType.isNumeric(): Boolean = this in PrimitiveType.numericPrimitives +class ConcreteFunction(val textBuilder: (Appendable) -> Unit, val sourceFile: SourceFile) -class GenericFunction(val signature: String, val keyword: String = "fun") : Comparable { +class GenericFunction(val signature: String, val keyword: String = "fun") { open class SpecializedProperty() { private val values = HashMap() @@ -165,6 +167,36 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp buildPrimitives.addAll(p.toList()) } + fun instantiate(vararg families: Family = Family.values()): List { + return families + .sortedBy { it.name() } + .filter { buildFamilies.contains(it) } + .flatMap { family -> instantiate(family) } + } + + fun instantiate(f: Family): List { + val onlyPrimitives = buildFamilyPrimitives[f] + + if (f.isPrimitiveSpecialization || onlyPrimitives != null) { + return (onlyPrimitives ?: buildPrimitives).sortedBy { it.name() } + .map { primitive -> ConcreteFunction( { build(it, f, primitive) }, sourceFileFor(f) ) } + } else { + return listOf(ConcreteFunction( { build(it, f, null) }, sourceFileFor(f) )) + } + } + + private fun sourceFileFor(f: Family) = getDefaultSourceFile(f) + + private fun getDefaultSourceFile(f: Family): SourceFile = when (f) { + Iterables, Collections, Lists -> SourceFile.Collections + Sequences -> SourceFile.Sequences + Sets -> SourceFile.Sets + Ranges, RangesOfPrimitives, ProgressionsOfPrimitives -> SourceFile.Ranges + ArraysOfObjects, ArraysOfObjectsSubtype, InvariantArraysOfObjects, ArraysOfPrimitives -> SourceFile.Arrays + Maps -> SourceFile.Maps + Strings -> SourceFile.Strings + Primitives, Generic -> SourceFile.Numbers + } fun build(vararg families: Family = Family.values()): String { val builder = StringBuilder() @@ -185,7 +217,7 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp } } - fun build(builder: StringBuilder, f: Family, primitive: PrimitiveType?) { + fun build(builder: Appendable, f: Family, primitive: PrimitiveType?) { val returnType = returns[f] ?: throw RuntimeException("No return type specified for $signature") fun renderType(expression: String, receiver: String): String { @@ -368,7 +400,6 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp builder.append("\n") } - public override fun compareTo(other: GenericFunction): Int = this.signature.compareTo(other.signature) } fun f(signature: String, init: GenericFunction.() -> Unit): GenericFunction {