Allow stdlib generator to distribute concrete functions between different target files.

This commit is contained in:
Ilya Gorbunov
2015-09-11 16:43:41 +03:00
parent 947b8ac428
commit 2bc1fbab3f
4 changed files with 98 additions and 21 deletions
@@ -6,23 +6,31 @@ import templates.*
import templates.PrimitiveType.* import templates.PrimitiveType.*
fun generateCollectionsAPI(outDir: File) { fun generateCollectionsAPI(outDir: File) {
elements().writeTo(File(outDir, "_Elements.kt")) { build() } val templates = sequenceOf(
filtering().writeTo(File(outDir, "_Filtering.kt")) { build() } ::elements,
ordering().writeTo(File(outDir, "_Ordering.kt")) { build() } ::filtering,
arrays().writeTo(File(outDir, "_Arrays.kt")) { build() } ::ordering,
snapshots().writeTo(File(outDir, "_Snapshots.kt")) { build() } ::arrays,
mapping().writeTo(File(outDir, "_Mapping.kt")) { build() } ::snapshots,
sets().writeTo(File(outDir, "_Sets.kt")) { build() } ::mapping,
aggregates().writeTo(File(outDir, "_Aggregates.kt")) { build() } ::sets,
guards().writeTo(File(outDir, "_Guards.kt")) { build() } ::aggregates,
generators().writeTo(File(outDir, "_Generators.kt")) { build() } ::guards,
strings().writeTo(File(outDir, "_Strings.kt")) { build() } ::generators,
sequences().writeTo(File(outDir, "_Sequences.kt")) { build() } ::strings,
specialJVM().writeTo(File(outDir, "_SpecialJVM.kt")) { build() } ::sequences,
ranges().writeTo(File(outDir, "_Ranges.kt")) { build() } ::specialJVM,
toPrimitiveArrays().writeTo(File(outDir, "_ArraysToPrimitiveArrays.kt")) { build() } ::ranges,
numeric().writeTo(File(outDir, "_Numeric.kt")) { build() } ::toPrimitiveArrays,
comparables().writeTo(File(outDir, "_Comparables.kt")) { build() } ::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) { fun generateCollectionsJsAPI(outDir: File) {
@@ -40,8 +40,26 @@ fun List<GenericFunction>.writeTo(file: File, builder: GenericFunction.() -> Str
its.append("import kotlin.platform.*\n") // TODO: Remove unneeded import its.append("import kotlin.platform.*\n") // TODO: Remove unneeded import
its.append("import java.util.*\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") 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()) its.append(t.builder())
} }
} }
} }
fun List<ConcreteFunction>.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)
}
}
}
@@ -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"
}
@@ -1,5 +1,6 @@
package templates package templates
import generators.SourceFile
import templates.Family.* import templates.Family.*
import templates.Family.Collections import templates.Family.Collections
import java.io.StringReader import java.io.StringReader
@@ -57,8 +58,9 @@ enum class PrimitiveType {
fun PrimitiveType.isIntegral(): Boolean = this in PrimitiveType.integralPrimitives fun PrimitiveType.isIntegral(): Boolean = this in PrimitiveType.integralPrimitives
fun PrimitiveType.isNumeric(): Boolean = this in PrimitiveType.numericPrimitives 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<GenericFunction> { class GenericFunction(val signature: String, val keyword: String = "fun") {
open class SpecializedProperty<TKey: Any, TValue : Any>() { open class SpecializedProperty<TKey: Any, TValue : Any>() {
private val values = HashMap<TKey?, TValue>() private val values = HashMap<TKey?, TValue>()
@@ -165,6 +167,36 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp
buildPrimitives.addAll(p.toList()) buildPrimitives.addAll(p.toList())
} }
fun instantiate(vararg families: Family = Family.values()): List<ConcreteFunction> {
return families
.sortedBy { it.name() }
.filter { buildFamilies.contains(it) }
.flatMap { family -> instantiate(family) }
}
fun instantiate(f: Family): List<ConcreteFunction> {
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 { fun build(vararg families: Family = Family.values()): String {
val builder = StringBuilder() 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") val returnType = returns[f] ?: throw RuntimeException("No return type specified for $signature")
fun renderType(expression: String, receiver: String): String { fun renderType(expression: String, receiver: String): String {
@@ -368,7 +400,6 @@ class GenericFunction(val signature: String, val keyword: String = "fun") : Comp
builder.append("\n") builder.append("\n")
} }
public override fun compareTo(other: GenericFunction): Int = this.signature.compareTo(other.signature)
} }
fun f(signature: String, init: GenericFunction.() -> Unit): GenericFunction { fun f(signature: String, init: GenericFunction.() -> Unit): GenericFunction {