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.*
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) {
@@ -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 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<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
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<GenericFunction> {
class GenericFunction(val signature: String, val keyword: String = "fun") {
open class SpecializedProperty<TKey: Any, TValue : Any>() {
private val values = HashMap<TKey?, TValue>()
@@ -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<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 {
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 {