Generate Kotlin sources of progressions

The check in DoubleProgression "if (increment == 0.0 || increment == -0.0)"
(and similar in FloatProgression) was simplified to "if (increment == 0.0)"
because 0.0 == -0.0 on JVM
This commit is contained in:
Alexander Udalov
2014-01-14 22:24:54 +04:00
parent 87a6ca5910
commit d427fcc187
11 changed files with 260 additions and 634 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.jet.generators.runtime
import java.io.File
import kotlin.properties.Delegates
import java.io.PrintWriter
import org.jetbrains.jet.generators.runtime.ProgressionKind.*
enum class ProgressionKind {
BYTE
@@ -32,6 +33,23 @@ enum class ProgressionKind {
val capitalized = name().toLowerCase().capitalize()
}
fun progressionIncrementType(kind: ProgressionKind) = when (kind) {
BYTE, CHAR, SHORT -> "Int"
else -> kind.capitalized
}
fun areEqualNumbers(kind: ProgressionKind, v: String) = when (kind) {
FLOAT, DOUBLE -> "java.lang.${kind.capitalized}.compare($v, other.$v) == 0"
else -> "$v == other.$v"
}
fun hashLong(v: String) = "($v xor ($v ushr 32))"
fun floatToIntBits(v: String) = "(if ($v != 0.0f) java.lang.Float.floatToIntBits($v) else 0)"
fun doubleToLongBits(v: String) = "if ($v != 0.0) java.lang.Double.doubleToLongBits($v) else 0L"
val OUTPUT_DIR: File by Delegates.lazy {
val result = File("runtime/kt/")
if (!result.exists()) {
@@ -0,0 +1,92 @@
/*
* Copyright 2010-2014 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.jet.generators.runtime.progressions
import org.jetbrains.jet.generators.runtime.*
import org.jetbrains.jet.generators.runtime.ProgressionKind.*
import java.io.PrintWriter
class GenerateProgressions(val out: PrintWriter) {
fun generate() {
generatedBy(out, javaClass.getName())
for (kind in ProgressionKind.values()) {
val t = kind.capitalized
val progression = "${t}Progression"
val incrementType = progressionIncrementType(kind)
fun compare(v: String) = areEqualNumbers(kind, v)
val zero = when (kind) {
FLOAT -> "0.0f"
DOUBLE -> "0.0"
LONG -> "0L"
else -> "0"
}
val checkNaN =
if (kind == FLOAT || kind == DOUBLE)
"if (java.lang.$t.isNaN(increment)) throw IllegalArgumentException(\"Increment must be not NaN\")\n "
else ""
val checkZero = "if (increment == $zero) throw IllegalArgumentException(\"Increment must be non-zero\")"
val constructor = checkNaN + checkZero
val hashCode = when (kind) {
BYTE, CHAR, SHORT -> " = 31 * (31 * start.toInt() + end) + increment"
INT -> " = 31 * (31 * start + end) + increment"
LONG -> " = (31 * (31 * ${hashLong("start")} + ${hashLong("end")}) + ${hashLong("increment")}).toInt()"
FLOAT -> " = (31 * (31 * ${floatToIntBits("start")} +\n" +
" ${floatToIntBits("end")}) + \n" +
" ${floatToIntBits("increment")}).toInt()"
DOUBLE -> ": Int {\n" +
" var temp = ${doubleToLongBits("start")}\n" +
" var result = ${hashLong("temp")}\n" +
" temp = ${doubleToLongBits("end")}\n" +
" result = 31 * result + ${hashLong("temp")}\n" +
" temp = ${doubleToLongBits("increment")}\n" +
" return (31 * result + ${hashLong("temp")}).toInt()\n" +
" }"
}
out.println(
"""public class $progression(
public override val start: $t,
public override val end: $t,
public override val increment: $incrementType
) : Progression<$t> {
{
$constructor
}
override fun iterator(): ${t}Iterator = ${t}ProgressionIterator(start, end, increment)
fun equals(other: Any?): Boolean =
other is $progression && ${compare("start")} && ${compare("end")} && ${compare("increment")}
fun hashCode()$hashCode
fun toString() = ${"if (increment > 0) \"\$start..\$end step \$increment\" else \"\$start downTo \$end step \${-increment}\""}
}""")
out.println()
}
}
}
fun main(args: Array<String>) {
generateRuntimeFile("Progressions.kt") {
GenerateProgressions(it).generate()
}
}
@@ -20,12 +20,6 @@ import org.jetbrains.jet.generators.runtime.*
import org.jetbrains.jet.generators.runtime.ProgressionKind.*
import java.io.PrintWriter
fun hashLong(v: String) = "($v xor ($v ushr 32))"
fun floatToIntBits(v: String) = "(if ($v != 0.0f) java.lang.Float.floatToIntBits($v) else 0)"
fun doubleToLongBits(v: String) = "if ($v != 0.0) java.lang.Double.doubleToLongBits($v) else 0L"
class GenerateRanges(val out: PrintWriter) {
fun generate() {
generatedBy(out, javaClass.getName())
@@ -33,10 +27,7 @@ class GenerateRanges(val out: PrintWriter) {
val t = kind.capitalized
val range = "${t}Range"
val incrementType = when (kind) {
BYTE, CHAR, SHORT -> "Int"
else -> kind.capitalized
}
val incrementType = progressionIncrementType(kind)
val increment = when (kind) {
FLOAT -> "1.0f"
@@ -51,10 +42,7 @@ class GenerateRanges(val out: PrintWriter) {
else -> "1, 0"
}
fun compare(v: String) = when (kind) {
FLOAT, DOUBLE -> "java.lang.${kind.capitalized}.compare($v, other.$v) == 0"
else -> "$v == other.$v"
}
fun compare(v: String) = areEqualNumbers(kind, v)
val hashCode = when (kind) {
BYTE, CHAR, SHORT -> " = 31 * start.toInt() + end"