Move builtins generators to their own source set
Make them depend on bootstrap stdlib. This is to prevent recompiling the entire project when we need just to generate builtins sources.
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.generators.builtins.arrayIterators
|
||||
|
||||
import org.jetbrains.kotlin.generators.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.generators.builtins.generateBuiltIns.*
|
||||
import java.io.PrintWriter
|
||||
|
||||
class GenerateArrayIterators(out: PrintWriter) : BuiltInsSourceGenerator(out) {
|
||||
override fun getPackage() = "kotlin.jvm.internal"
|
||||
|
||||
override fun generateBody() {
|
||||
for (kind in PrimitiveType.values()) {
|
||||
val s = kind.capitalized
|
||||
out.println("private class Array${s}Iterator(private val array: ${s}Array) : ${s}Iterator() {")
|
||||
out.println(" private var index = 0")
|
||||
out.println(" override fun hasNext() = index < array.size")
|
||||
out.println(" override fun next$s() = try { array[index++] } catch (e: ArrayIndexOutOfBoundsException) { index -= 1; throw NoSuchElementException(e.message) }")
|
||||
out.println("}")
|
||||
out.println()
|
||||
}
|
||||
for (kind in PrimitiveType.values()) {
|
||||
val s = kind.capitalized
|
||||
out.println("public fun iterator(array: ${s}Array): ${s}Iterator = Array${s}Iterator(array)")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.generators.builtins.arrays
|
||||
|
||||
import org.jetbrains.kotlin.generators.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.generators.builtins.generateBuiltIns.BuiltInsSourceGenerator
|
||||
import java.io.PrintWriter
|
||||
|
||||
class GenerateArrays(out: PrintWriter) : BuiltInsSourceGenerator(out) {
|
||||
override fun getPackage() = "kotlin"
|
||||
|
||||
override fun generateBody() {
|
||||
for (kind in PrimitiveType.values()) {
|
||||
val typeLower = kind.name.toLowerCase()
|
||||
val s = kind.capitalized
|
||||
val defaultValue = if (kind == PrimitiveType.BOOLEAN) "false" else "zero"
|
||||
out.println("/**")
|
||||
out.println(" * An array of ${typeLower}s. When targeting the JVM, instances of this class are represented as `$typeLower[]`.")
|
||||
out.println(" * @constructor Creates a new array of the specified [size], with all elements initialized to $defaultValue.")
|
||||
out.println(" */")
|
||||
out.println("public class ${s}Array(size: Int) {")
|
||||
out.println(" /**")
|
||||
out.println(" * Creates a new array of the specified [size], where each element is calculated by calling the specified")
|
||||
out.println(" * [init] function. The [init] function returns an array element given its index.")
|
||||
out.println(" */")
|
||||
out.println(" public inline constructor(size: Int, init: (Int) -> $s)")
|
||||
out.println()
|
||||
out.println(" /** Returns the array element at the given [index]. This method can be called using the index operator. */")
|
||||
out.println(" public operator fun get(index: Int): $s")
|
||||
out.println(" /** Sets the element at the given [index] to the given [value]. This method can be called using the index operator. */")
|
||||
out.println(" public operator fun set(index: Int, value: $s): Unit")
|
||||
out.println()
|
||||
out.println(" /** Returns the number of elements in the array. */")
|
||||
out.println(" public val size: Int")
|
||||
out.println()
|
||||
out.println(" /** Creates an iterator over the elements of the array. */")
|
||||
out.println(" public operator fun iterator(): ${s}Iterator")
|
||||
out.println("}")
|
||||
out.println()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.generators.builtins
|
||||
|
||||
import org.jetbrains.kotlin.generators.builtins.ProgressionKind.*
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
enum class PrimitiveType {
|
||||
BYTE,
|
||||
CHAR,
|
||||
SHORT,
|
||||
INT,
|
||||
LONG,
|
||||
FLOAT,
|
||||
DOUBLE,
|
||||
BOOLEAN;
|
||||
|
||||
val capitalized: String get() = name.toLowerCase().capitalize()
|
||||
companion object {
|
||||
val exceptBoolean = PrimitiveType.values().filterNot { it == BOOLEAN }
|
||||
val onlyNumeric = PrimitiveType.values().filterNot { it == BOOLEAN || it == CHAR }
|
||||
}
|
||||
}
|
||||
|
||||
enum class ProgressionKind {
|
||||
CHAR,
|
||||
INT,
|
||||
LONG;
|
||||
|
||||
val capitalized: String get() = name.toLowerCase().capitalize()
|
||||
}
|
||||
|
||||
fun progressionIncrementType(kind: ProgressionKind) = when (kind) {
|
||||
CHAR -> "Int"
|
||||
else -> kind.capitalized
|
||||
}
|
||||
|
||||
fun areEqualNumbers(v: String) = "$v == other.$v"
|
||||
|
||||
fun hashLong(v: String) = "($v xor ($v ushr 32))"
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.generators.builtins.functions
|
||||
|
||||
import org.jetbrains.kotlin.generators.builtins.generateBuiltIns.BuiltInsSourceGenerator
|
||||
import java.io.PrintWriter
|
||||
|
||||
val MAX_PARAM_COUNT = 22
|
||||
|
||||
class GenerateFunctions(out: PrintWriter) : BuiltInsSourceGenerator(out) {
|
||||
override fun getPackage() = "kotlin.jvm.functions"
|
||||
|
||||
fun generateTypeParameters(i: Int, variance: Boolean) {
|
||||
out.print("<")
|
||||
|
||||
for (j in 1..i) {
|
||||
if (variance) out.print("in ")
|
||||
out.print("P$j, ")
|
||||
}
|
||||
|
||||
generateReturnTypeParameter(variance)
|
||||
|
||||
out.print(">")
|
||||
}
|
||||
|
||||
fun generateReturnTypeParameter(variance: Boolean) {
|
||||
if (variance) out.print("out ")
|
||||
out.print("R")
|
||||
}
|
||||
|
||||
override fun generateBody() {
|
||||
for (i in 0..MAX_PARAM_COUNT) {
|
||||
generateDocumentation(i)
|
||||
out.print("public interface Function$i")
|
||||
generateTypeParameters(i, variance = true)
|
||||
generateSuperClass()
|
||||
generateFunctionClassBody(i)
|
||||
}
|
||||
}
|
||||
|
||||
fun generateDocumentation(i: Int) {
|
||||
val suffix = if (i == 1) "" else "s"
|
||||
out.println("/** A function that takes $i argument${suffix}. */")
|
||||
}
|
||||
|
||||
fun generateSuperClass() {
|
||||
out.print(" : Function<")
|
||||
generateReturnTypeParameter(variance = false)
|
||||
out.print(">")
|
||||
}
|
||||
|
||||
fun generateFunctionClassBody(i: Int) {
|
||||
out.println(" {")
|
||||
generateInvokeSignature(i)
|
||||
out.println("}")
|
||||
}
|
||||
|
||||
fun generateInvokeSignature(i: Int) {
|
||||
if (i == 0) {
|
||||
out.println(" /** Invokes the function. */")
|
||||
}
|
||||
else {
|
||||
val suffix = if (i == 1) "" else "s"
|
||||
out.println(" /** Invokes the function with the specified argument${suffix}. */")
|
||||
}
|
||||
out.print(" public operator fun invoke(")
|
||||
for (j in 1..i) {
|
||||
out.print("p$j: P$j")
|
||||
if (j < i) {
|
||||
out.print(", ")
|
||||
}
|
||||
}
|
||||
out.println("): R")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.generators.builtins.generateBuiltIns
|
||||
|
||||
import org.jetbrains.kotlin.generators.builtins.arrayIterators.GenerateArrayIterators
|
||||
import org.jetbrains.kotlin.generators.builtins.arrays.GenerateArrays
|
||||
import org.jetbrains.kotlin.generators.builtins.functions.GenerateFunctions
|
||||
import org.jetbrains.kotlin.generators.builtins.iterators.GenerateIterators
|
||||
import org.jetbrains.kotlin.generators.builtins.progressionIterators.GenerateProgressionIterators
|
||||
import org.jetbrains.kotlin.generators.builtins.progressions.GenerateProgressions
|
||||
import org.jetbrains.kotlin.generators.builtins.ranges.GeneratePrimitives
|
||||
import org.jetbrains.kotlin.generators.builtins.ranges.GenerateRanges
|
||||
import org.xml.sax.InputSource
|
||||
import java.io.File
|
||||
import java.io.PrintWriter
|
||||
import javax.xml.xpath.XPathFactory
|
||||
|
||||
fun assertExists(file: File) {
|
||||
if (!file.exists()) error("Output dir does not exist: ${file.absolutePath}")
|
||||
}
|
||||
|
||||
val BUILT_INS_NATIVE_DIR = File("core/builtins/native/")
|
||||
val BUILT_INS_SRC_DIR = File("core/builtins/src/")
|
||||
val RUNTIME_JVM_DIR = File("libraries/stdlib/jvm/runtime/")
|
||||
|
||||
abstract class BuiltInsSourceGenerator(val out: PrintWriter) {
|
||||
protected abstract fun generateBody(): Unit
|
||||
|
||||
protected open fun getPackage(): String = "kotlin"
|
||||
|
||||
enum class Language {
|
||||
KOTLIN,
|
||||
JAVA
|
||||
}
|
||||
|
||||
fun generate() {
|
||||
out.println(readCopyrightNoticeFromProfile(File(".idea/copyright/apache.xml")))
|
||||
// Don't include generator class name in the message: these are built-in sources,
|
||||
// and we don't want to scare users with any internal information about our project
|
||||
out.println("// Auto-generated file. DO NOT EDIT!")
|
||||
out.println()
|
||||
out.print("package ${getPackage()}")
|
||||
out.println()
|
||||
out.println()
|
||||
|
||||
generateBody()
|
||||
}
|
||||
}
|
||||
|
||||
fun readCopyrightNoticeFromProfile(copyrightProfile: File): String {
|
||||
val template = copyrightProfile.reader().use { reader ->
|
||||
XPathFactory.newInstance().newXPath().evaluate("/component/copyright/option[@name='notice']/@value", InputSource(reader))
|
||||
}
|
||||
val yearTemplate = "$today.year"
|
||||
val year = java.time.LocalDate.now().year.toString()
|
||||
assert(yearTemplate in template)
|
||||
|
||||
return template.replace(yearTemplate, year).lines().joinToString("", prefix = "/*\n", postfix = " */\n") { " * $it\n" }
|
||||
}
|
||||
|
||||
fun generateBuiltIns(generate: (File, (PrintWriter) -> BuiltInsSourceGenerator) -> Unit) {
|
||||
assertExists(BUILT_INS_NATIVE_DIR)
|
||||
assertExists(BUILT_INS_SRC_DIR)
|
||||
assertExists(RUNTIME_JVM_DIR)
|
||||
|
||||
generate(File(RUNTIME_JVM_DIR, "kotlin/jvm/functions/Functions.kt")) { GenerateFunctions(it) }
|
||||
generate(File(BUILT_INS_NATIVE_DIR, "kotlin/Arrays.kt")) { GenerateArrays(it) }
|
||||
generate(File(BUILT_INS_NATIVE_DIR, "kotlin/Primitives.kt")) { GeneratePrimitives(it) }
|
||||
generate(File(BUILT_INS_SRC_DIR, "kotlin/Iterators.kt")) { GenerateIterators(it) }
|
||||
generate(File(RUNTIME_JVM_DIR, "kotlin/jvm/internal/ArrayIterators.kt")) { GenerateArrayIterators(it) }
|
||||
generate(File(BUILT_INS_SRC_DIR, "kotlin/ProgressionIterators.kt")) { GenerateProgressionIterators(it) }
|
||||
generate(File(BUILT_INS_SRC_DIR, "kotlin/Progressions.kt")) { GenerateProgressions(it) }
|
||||
generate(File(BUILT_INS_SRC_DIR, "kotlin/Ranges.kt")) { GenerateRanges(it) }
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
generateBuiltIns { file, generator ->
|
||||
println("generating $file")
|
||||
file.parentFile?.mkdirs()
|
||||
PrintWriter(file).use {
|
||||
generator(it).generate()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.generators.builtins.iterators
|
||||
|
||||
import org.jetbrains.kotlin.generators.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.generators.builtins.generateBuiltIns.*
|
||||
import java.io.PrintWriter
|
||||
|
||||
class GenerateIterators(out: PrintWriter) : BuiltInsSourceGenerator(out) {
|
||||
override fun getPackage() = "kotlin.collections"
|
||||
override fun generateBody() {
|
||||
for (kind in PrimitiveType.values()) {
|
||||
val s = kind.capitalized
|
||||
out.println("/** An iterator over a sequence of values of type `$s`. */")
|
||||
out.println("public abstract class ${s}Iterator : Iterator<$s> {" )
|
||||
out.println(" override final fun next() = next$s()")
|
||||
out.println()
|
||||
out.println(" /** Returns the next value in the sequence without boxing. */")
|
||||
out.println(" public abstract fun next$s(): $s")
|
||||
out.println("}")
|
||||
out.println()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.generators.builtins.ranges
|
||||
|
||||
import org.jetbrains.kotlin.generators.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.generators.builtins.generateBuiltIns.BuiltInsSourceGenerator
|
||||
import java.io.PrintWriter
|
||||
|
||||
class GeneratePrimitives(out: PrintWriter) : BuiltInsSourceGenerator(out) {
|
||||
private val binaryOperators: Map<String, String> = mapOf(
|
||||
"plus" to "Adds the other value to this value.",
|
||||
"minus" to "Subtracts the other value from this value.",
|
||||
"times" to "Multiplies this value by the other value.",
|
||||
"div" to "Divides this value by the other value.",
|
||||
"mod" to "Calculates the remainder of dividing this value by the other value.",
|
||||
"rem" to "Calculates the remainder of dividing this value by the other value."
|
||||
)
|
||||
private val unaryOperators: Map<String, String> = mapOf(
|
||||
"inc" to "Increments this value.",
|
||||
"dec" to "Decrements this value.",
|
||||
"unaryPlus" to "Returns this value.",
|
||||
"unaryMinus" to "Returns the negative of this value.")
|
||||
private val shiftOperators: Map<String, String> = mapOf(
|
||||
"shl" to "Shifts this value left by the [bitCount] number of bits.",
|
||||
"shr" to "Shifts this value right by the [bitCount] number of bits, filling the leftmost bits with copies of the sign bit.",
|
||||
"ushr" to "Shifts this value right by the [bitCount] number of bits, filling the leftmost bits with zeros.")
|
||||
private val bitwiseOperators: Map<String, String> = mapOf(
|
||||
"and" to "Performs a bitwise AND operation between the two values.",
|
||||
"or" to "Performs a bitwise OR operation between the two values.",
|
||||
"xor" to "Performs a bitwise XOR operation between the two values.")
|
||||
private val typeDescriptions: Map<PrimitiveType, String> = mapOf(
|
||||
PrimitiveType.DOUBLE to "double-precision 64-bit IEEE 754 floating point number",
|
||||
PrimitiveType.FLOAT to "single-precision 32-bit IEEE 754 floating point number",
|
||||
PrimitiveType.LONG to "64-bit signed integer",
|
||||
PrimitiveType.INT to "32-bit signed integer",
|
||||
PrimitiveType.SHORT to "16-bit signed integer",
|
||||
PrimitiveType.BYTE to "8-bit signed integer",
|
||||
PrimitiveType.CHAR to "16-bit Unicode character"
|
||||
)
|
||||
|
||||
private fun primitiveConstants(type: PrimitiveType): List<Any> = when (type) {
|
||||
PrimitiveType.INT -> listOf(java.lang.Integer.MIN_VALUE, java.lang.Integer.MAX_VALUE)
|
||||
PrimitiveType.BYTE -> listOf(java.lang.Byte.MIN_VALUE, java.lang.Byte.MAX_VALUE)
|
||||
PrimitiveType.SHORT -> listOf(java.lang.Short.MIN_VALUE, java.lang.Short.MAX_VALUE)
|
||||
PrimitiveType.LONG -> listOf((java.lang.Long.MIN_VALUE + 1).toString() + "L - 1L", java.lang.Long.MAX_VALUE.toString() + "L")
|
||||
// PrimitiveType.DOUBLE -> listOf(java.lang.Double.MIN_VALUE, java.lang.Double.MAX_VALUE, "1.0/0.0", "-1.0/0.0", "0.0/0.0")
|
||||
// PrimitiveType.FLOAT -> listOf(java.lang.Float.MIN_VALUE, java.lang.Float.MAX_VALUE, "1.0F/0.0F", "-1.0F/0.0F", "0.0F/0.0F").map { it as? String ?: "${it}F" }
|
||||
else -> throw IllegalArgumentException("type: $type")
|
||||
}
|
||||
|
||||
override fun generateBody() {
|
||||
for (kind in PrimitiveType.onlyNumeric) {
|
||||
val className = kind.capitalized
|
||||
generateDoc(kind)
|
||||
out.println("public class $className private constructor() : Number(), Comparable<$className> {")
|
||||
|
||||
out.print(" companion object ")
|
||||
if (kind == PrimitiveType.FLOAT || kind == PrimitiveType.DOUBLE) {
|
||||
//val (minValue, maxValue, posInf, negInf, nan) = primitiveConstants(kind)
|
||||
out.println("""{
|
||||
/**
|
||||
* A constant holding the smallest *positive* nonzero value of $className.
|
||||
*/
|
||||
public val MIN_VALUE: $className
|
||||
|
||||
/**
|
||||
* A constant holding the largest positive finite value of $className.
|
||||
*/
|
||||
public val MAX_VALUE: $className
|
||||
|
||||
/**
|
||||
* A constant holding the positive infinity value of $className.
|
||||
*/
|
||||
public val POSITIVE_INFINITY: $className
|
||||
|
||||
/**
|
||||
* A constant holding the negative infinity value of $className.
|
||||
*/
|
||||
public val NEGATIVE_INFINITY: $className
|
||||
|
||||
/**
|
||||
* A constant holding the "not a number" value of $className.
|
||||
*/
|
||||
public val NaN: $className
|
||||
}""")
|
||||
}
|
||||
if (kind == PrimitiveType.INT || kind == PrimitiveType.LONG || kind == PrimitiveType.SHORT || kind == PrimitiveType.BYTE) {
|
||||
val (minValue, maxValue) = primitiveConstants(kind)
|
||||
out.println("""{
|
||||
/**
|
||||
* A constant holding the minimum value an instance of $className can have.
|
||||
*/
|
||||
public const val MIN_VALUE: $className = $minValue
|
||||
|
||||
/**
|
||||
* A constant holding the maximum value an instance of $className can have.
|
||||
*/
|
||||
public const val MAX_VALUE: $className = $maxValue
|
||||
}""")
|
||||
}
|
||||
|
||||
generateCompareTo(kind)
|
||||
|
||||
generateBinaryOperators(kind)
|
||||
generateUnaryOperators(kind)
|
||||
generateRangeTo(kind)
|
||||
|
||||
if (kind == PrimitiveType.INT || kind == PrimitiveType.LONG) {
|
||||
generateBitShiftOperators(className)
|
||||
}
|
||||
if (kind == PrimitiveType.INT || kind == PrimitiveType.LONG /* || kind == PrimitiveType.BYTE || kind == PrimitiveType.SHORT */) {
|
||||
generateBitwiseOperators(className, since = if (kind == PrimitiveType.BYTE || kind == PrimitiveType.SHORT) "1.1" else null)
|
||||
}
|
||||
|
||||
generateConversions()
|
||||
|
||||
out.println("}\n")
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateDoc(kind: PrimitiveType) {
|
||||
out.println("/**")
|
||||
out.println(" * Represents a ${typeDescriptions[kind]}.")
|
||||
out.println(" * On the JVM, non-nullable values of this type are represented as values of the primitive type `${kind.name.toLowerCase()}`.")
|
||||
out.println(" */")
|
||||
}
|
||||
|
||||
private fun generateCompareTo(thisKind: PrimitiveType) {
|
||||
for (otherKind in PrimitiveType.onlyNumeric) {
|
||||
out.println("""
|
||||
/**
|
||||
* Compares this value with the specified value for order.
|
||||
* Returns zero if this value is equal to the specified other value, a negative number if it's less than other,
|
||||
* or a positive number if it's greater than other.
|
||||
*/""")
|
||||
out.print(" public ")
|
||||
if (otherKind == thisKind) out.print("override ")
|
||||
out.println("operator fun compareTo(other: ${otherKind.capitalized}): Int")
|
||||
}
|
||||
out.println()
|
||||
}
|
||||
|
||||
private fun generateBinaryOperators(thisKind: PrimitiveType) {
|
||||
for ((name, doc) in binaryOperators) {
|
||||
generateOperator(name, doc, thisKind)
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateOperator(name: String, doc: String, thisKind: PrimitiveType) {
|
||||
for (otherKind in PrimitiveType.onlyNumeric) {
|
||||
val returnType = getOperatorReturnType(thisKind, otherKind)
|
||||
|
||||
out.println(" /** $doc */")
|
||||
when (name) {
|
||||
"rem" ->
|
||||
out.println(" @SinceKotlin(\"1.1\")")
|
||||
|
||||
"mod" ->
|
||||
out.println(" @Deprecated(\"Use rem(other) instead\", ReplaceWith(\"rem(other)\"), DeprecationLevel.WARNING)")
|
||||
}
|
||||
out.println(" public operator fun $name(other: ${otherKind.capitalized}): ${returnType.capitalized}")
|
||||
}
|
||||
out.println()
|
||||
}
|
||||
|
||||
private fun generateRangeTo(thisKind: PrimitiveType) {
|
||||
for (otherKind in PrimitiveType.onlyNumeric) {
|
||||
val returnType =
|
||||
maxByDomainCapacity(thisKind, otherKind)
|
||||
.let { if (it == PrimitiveType.CHAR) it else maxByDomainCapacity(it, PrimitiveType.INT) }
|
||||
if (returnType == PrimitiveType.DOUBLE || returnType == PrimitiveType.FLOAT)
|
||||
continue
|
||||
out.println(" /** Creates a range from this value to the specified [other] value. */")
|
||||
out.println(" public operator fun rangeTo(other: ${otherKind.capitalized}): ${returnType.capitalized}Range")
|
||||
}
|
||||
out.println()
|
||||
|
||||
}
|
||||
|
||||
private fun generateUnaryOperators(kind: PrimitiveType) {
|
||||
for ((name, doc) in unaryOperators) {
|
||||
val returnType = if (kind in listOf(PrimitiveType.SHORT, PrimitiveType.BYTE, PrimitiveType.CHAR) &&
|
||||
name in listOf("unaryPlus", "unaryMinus")) "Int" else kind.capitalized
|
||||
out.println(" /** $doc */")
|
||||
out.println(" public operator fun $name(): $returnType")
|
||||
}
|
||||
out.println()
|
||||
}
|
||||
|
||||
private fun generateBitShiftOperators(className: String) {
|
||||
for ((name, doc) in shiftOperators) {
|
||||
out.println(" /** $doc */")
|
||||
out.println(" public infix fun $name(bitCount: Int): $className")
|
||||
}
|
||||
}
|
||||
private fun generateBitwiseOperators(className: String, since: String?) {
|
||||
for ((name, doc) in bitwiseOperators) {
|
||||
out.println(" /** $doc */")
|
||||
since?.let { out.println(" @SinceKotlin(\"$it\")") }
|
||||
out.println(" public infix fun $name(other: $className): $className")
|
||||
}
|
||||
out.println(" /** Inverts the bits in this value. */")
|
||||
since?.let { out.println(" @SinceKotlin(\"$it\")") }
|
||||
out.println(" public fun inv(): $className")
|
||||
out.println()
|
||||
}
|
||||
|
||||
private fun generateConversions() {
|
||||
for (otherKind in PrimitiveType.exceptBoolean) {
|
||||
val name = otherKind.capitalized
|
||||
out.println(" public override fun to$name(): $name")
|
||||
}
|
||||
}
|
||||
|
||||
private fun maxByDomainCapacity(type1: PrimitiveType, type2: PrimitiveType): PrimitiveType
|
||||
= if (type1.ordinal > type2.ordinal) type1 else type2
|
||||
|
||||
private fun getOperatorReturnType(kind1: PrimitiveType, kind2: PrimitiveType): PrimitiveType {
|
||||
require(kind1 != PrimitiveType.BOOLEAN) { "kind1 must not be BOOLEAN" }
|
||||
require(kind2 != PrimitiveType.BOOLEAN) { "kind2 must not be BOOLEAN" }
|
||||
return maxByDomainCapacity(maxByDomainCapacity(kind1, kind2), PrimitiveType.INT)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.generators.builtins.progressionIterators
|
||||
|
||||
import org.jetbrains.kotlin.generators.builtins.*
|
||||
import org.jetbrains.kotlin.generators.builtins.generateBuiltIns.*
|
||||
import org.jetbrains.kotlin.generators.builtins.ProgressionKind.*
|
||||
import java.io.PrintWriter
|
||||
|
||||
fun integerProgressionIterator(kind: ProgressionKind): String {
|
||||
val t = kind.capitalized
|
||||
|
||||
val incrementType = progressionIncrementType(kind)
|
||||
|
||||
val (toInt, toType) = when (kind) {
|
||||
CHAR -> ".toInt()" to ".to$t()"
|
||||
else -> "" to ""
|
||||
}
|
||||
|
||||
return """/**
|
||||
* An iterator over a progression of values of type `$t`.
|
||||
* @property step the number by which the value is incremented on each step.
|
||||
*/
|
||||
internal class ${t}ProgressionIterator(first: $t, last: $t, val step: $incrementType) : ${t}Iterator() {
|
||||
private val finalElement = last$toInt
|
||||
private var hasNext: Boolean = if (step > 0) first <= last else first >= last
|
||||
private var next = if (hasNext) first$toInt else finalElement
|
||||
|
||||
override fun hasNext(): Boolean = hasNext
|
||||
|
||||
override fun next$t(): $t {
|
||||
val value = next
|
||||
if (value == finalElement) {
|
||||
if (!hasNext) throw kotlin.NoSuchElementException()
|
||||
hasNext = false
|
||||
}
|
||||
else {
|
||||
next += step
|
||||
}
|
||||
return value$toType
|
||||
}
|
||||
}"""
|
||||
}
|
||||
|
||||
|
||||
class GenerateProgressionIterators(out: PrintWriter) : BuiltInsSourceGenerator(out) {
|
||||
override fun getPackage() = "kotlin.ranges"
|
||||
override fun generateBody() {
|
||||
for (kind in ProgressionKind.values()) {
|
||||
out.println(integerProgressionIterator(kind))
|
||||
out.println()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.generators.builtins.progressions
|
||||
|
||||
import org.jetbrains.kotlin.generators.builtins.*
|
||||
import org.jetbrains.kotlin.generators.builtins.generateBuiltIns.*
|
||||
import org.jetbrains.kotlin.generators.builtins.ProgressionKind.*
|
||||
import java.io.PrintWriter
|
||||
|
||||
class GenerateProgressions(out: PrintWriter) : BuiltInsSourceGenerator(out) {
|
||||
|
||||
override fun getPackage() = "kotlin.ranges"
|
||||
private fun generateDiscreteBody(kind: ProgressionKind) {
|
||||
val t = kind.capitalized
|
||||
val progression = "${t}Progression"
|
||||
|
||||
val incrementType = progressionIncrementType(kind)
|
||||
fun compare(v: String) = areEqualNumbers(v)
|
||||
|
||||
val zero = when (kind) {
|
||||
LONG -> "0L"
|
||||
else -> "0"
|
||||
}
|
||||
val checkZero = "if (step == $zero) throw kotlin.IllegalArgumentException(\"Step must be non-zero\")"
|
||||
|
||||
val hashCode = "=\n" + when (kind) {
|
||||
CHAR ->
|
||||
" if (isEmpty()) -1 else (31 * (31 * first.toInt() + last.toInt()) + step)"
|
||||
INT ->
|
||||
" if (isEmpty()) -1 else (31 * (31 * first + last) + step)"
|
||||
LONG ->
|
||||
" if (isEmpty()) -1 else (31 * (31 * ${hashLong("first")} + ${hashLong("last")}) + ${hashLong("step")}).toInt()"
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
out.println(
|
||||
"""/**
|
||||
* A progression of values of type `$t`.
|
||||
*/
|
||||
public open class $progression
|
||||
internal constructor
|
||||
(
|
||||
start: $t,
|
||||
endInclusive: $t,
|
||||
step: $incrementType
|
||||
) : Iterable<$t> {
|
||||
init {
|
||||
$checkZero
|
||||
}
|
||||
|
||||
/**
|
||||
* The first element in the progression.
|
||||
*/
|
||||
public val first: $t = start
|
||||
|
||||
/**
|
||||
* The last element in the progression.
|
||||
*/
|
||||
public val last: $t = getProgressionLastElement(start.to$incrementType(), endInclusive.to$incrementType(), step).to$t()
|
||||
|
||||
/**
|
||||
* The step of the progression.
|
||||
*/
|
||||
public val step: $incrementType = step
|
||||
|
||||
override fun iterator(): ${t}Iterator = ${t}ProgressionIterator(first, last, step)
|
||||
|
||||
/** Checks if the progression is empty. */
|
||||
public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is $progression && (isEmpty() && other.isEmpty() ||
|
||||
${compare("first")} && ${compare("last")} && ${compare("step")})
|
||||
|
||||
override fun hashCode(): Int $hashCode
|
||||
|
||||
override fun toString(): String = ${"if (step > 0) \"\$first..\$last step \$step\" else \"\$first downTo \$last step \${-step}\""}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Creates $progression within the specified bounds of a closed range.
|
||||
|
||||
* The progression starts with the [rangeStart] value and goes toward the [rangeEnd] value not excluding it, with the specified [step].
|
||||
* In order to go backwards the [step] must be negative.
|
||||
*/
|
||||
public fun fromClosedRange(rangeStart: $t, rangeEnd: $t, step: $incrementType): $progression = $progression(rangeStart, rangeEnd, step)
|
||||
}
|
||||
}""")
|
||||
out.println()
|
||||
|
||||
}
|
||||
|
||||
override fun generateBody() {
|
||||
out.println("import kotlin.internal.getProgressionLastElement")
|
||||
out.println()
|
||||
for (kind in ProgressionKind.values()) {
|
||||
generateDiscreteBody(kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.generators.builtins.ranges
|
||||
|
||||
import org.jetbrains.kotlin.generators.builtins.*
|
||||
import org.jetbrains.kotlin.generators.builtins.generateBuiltIns.*
|
||||
import org.jetbrains.kotlin.generators.builtins.ProgressionKind.*
|
||||
import java.io.PrintWriter
|
||||
|
||||
class GenerateRanges(out: PrintWriter) : BuiltInsSourceGenerator(out) {
|
||||
override fun getPackage() = "kotlin.ranges"
|
||||
override fun generateBody() {
|
||||
for (kind in ProgressionKind.values()) {
|
||||
val t = kind.capitalized
|
||||
val range = "${t}Range"
|
||||
|
||||
val increment = "1"
|
||||
|
||||
val emptyBounds = when (kind) {
|
||||
CHAR -> "1.toChar(), 0.toChar()"
|
||||
else -> "1, 0"
|
||||
}
|
||||
|
||||
fun compare(v: String) = areEqualNumbers(v)
|
||||
|
||||
val hashCode = when (kind) {
|
||||
CHAR -> "=\n" +
|
||||
" if (isEmpty()) -1 else (31 * first.toInt() + last.toInt())"
|
||||
INT -> "=\n" +
|
||||
" if (isEmpty()) -1 else (31 * first + last)"
|
||||
LONG -> "=\n" +
|
||||
" if (isEmpty()) -1 else (31 * ${hashLong("first")} + ${hashLong("last")}).toInt()"
|
||||
}
|
||||
|
||||
val toString = "\"\$first..\$last\""
|
||||
|
||||
out.println(
|
||||
"""/**
|
||||
* A range of values of type `$t`.
|
||||
*/
|
||||
public class $range(start: $t, endInclusive: $t) : ${t}Progression(start, endInclusive, $increment), ClosedRange<$t> {
|
||||
override val start: $t get() = first
|
||||
override val endInclusive: $t get() = last
|
||||
|
||||
override fun contains(value: $t): Boolean = first <= value && value <= last
|
||||
|
||||
override fun isEmpty(): Boolean = first > last
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is $range && (isEmpty() && other.isEmpty() ||
|
||||
${compare("first")} && ${compare("last")})
|
||||
|
||||
override fun hashCode(): Int $hashCode
|
||||
|
||||
override fun toString(): String = $toString
|
||||
|
||||
companion object {
|
||||
/** An empty range of values of type $t. */
|
||||
public val EMPTY: $range = $range($emptyBounds)
|
||||
}
|
||||
}""")
|
||||
out.println()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user