[Generator] Generate Boolean class

This commit is contained in:
Ivan Kylchik
2023-07-21 15:17:17 +02:00
committed by Space Team
parent 3f3cd2e87a
commit 38e434bc07
11 changed files with 410 additions and 101 deletions
@@ -244,6 +244,8 @@ abstract class BasePrimitivesGenerator(private val writer: PrintWriter) : BuiltI
klass {
appendDoc("Represents a ${typeDescriptions[thisKind]}.")
name = className
superType("Number()")
superType("Comparable<$name>")
generateCompanionObject(thisKind)
generateCompareTo(thisKind)
@@ -0,0 +1,310 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package primitives
import org.jetbrains.kotlin.generators.builtins.PrimitiveType
import org.jetbrains.kotlin.generators.builtins.generateBuiltIns.BuiltInsGenerator
import org.jetbrains.kotlin.generators.builtins.numbers.primitives.*
import org.jetbrains.kotlin.generators.builtins.numbers.primitives.NativePrimitivesGenerator.Companion.setAsExternal
import org.jetbrains.kotlin.generators.builtins.numbers.primitives.WasmPrimitivesGenerator.Companion.implementAsIntrinsic
import org.jetbrains.kotlin.generators.builtins.numbers.primitives.WasmPrimitivesGenerator.Companion.implementedAsIntrinsic
import java.io.PrintWriter
abstract class BooleanGenerator(private val writer: PrintWriter) : BuiltInsGenerator {
override fun generate() {
writer.print(generateFile().build())
}
private fun generateFile(): FileBuilder {
return file { generateClass() }.apply { this.modifyGeneratedFile() }
}
private fun FileBuilder.generateClass() {
klass {
appendDoc("Represents a value which is either `true` or `false`.")
name = PrimitiveType.BOOLEAN.capitalized
superType("Comparable<$name>")
generateCompanionObject()
generateNot()
generateAnd()
generateOr()
generateXor()
generateCompareTo()
generateToString()
generateEquals()
generateHashCode()
generateAdditionalMethods()
}.modifyGeneratedClass()
}
private fun ClassBuilder.generateCompanionObject() {
companionObject {
annotations += "SinceKotlin(\"1.3\")"
}.modifyGeneratedCompanionObject()
}
private fun ClassBuilder.generateNot() {
method {
appendDoc("Returns the inverse of this boolean.")
annotations += intrinsicConstEvaluationAnnotation
signature {
methodName = "not"
isOperator = true
returnType = PrimitiveType.BOOLEAN.capitalized
}
}.modifyGeneratedNot()
}
private fun ClassBuilder.generateBooleanMethod(giveMethodName: String, doc: String) = method {
appendDoc(doc)
annotations += intrinsicConstEvaluationAnnotation
signature {
methodName = giveMethodName
parameter {
name = "other"
type = PrimitiveType.BOOLEAN.capitalized
}
isInfix = true
returnType = PrimitiveType.BOOLEAN.capitalized
}
}
private fun ClassBuilder.generateAnd() {
val doc = """
Performs a logical `and` operation between this Boolean and the [other] one. Unlike the `&&` operator,
this function does not perform short-circuit evaluation. Both `this` and [other] will always be evaluated.
""".trimIndent()
generateBooleanMethod("and", doc).modifyGeneratedAnd()
}
private fun ClassBuilder.generateOr() {
val doc = """
Performs a logical `or` operation between this Boolean and the [other] one. Unlike the `||` operator,
this function does not perform short-circuit evaluation. Both `this` and [other] will always be evaluated.
""".trimIndent()
generateBooleanMethod("or", doc).modifyGeneratedOr()
}
private fun ClassBuilder.generateXor() {
val doc = "Performs a logical `xor` operation between this Boolean and the [other] one."
generateBooleanMethod("xor", doc).modifyGeneratedXor()
}
private fun ClassBuilder.generateCompareTo() {
method {
annotations += intrinsicConstEvaluationAnnotation
signature {
methodName = "compareTo"
parameter {
name = "other"
type = PrimitiveType.BOOLEAN.capitalized
}
isOverride = true
returnType = PrimitiveType.INT.capitalized
}
}.modifyGeneratedCompareTo()
}
private fun ClassBuilder.generateToString() {
method {
annotations += intrinsicConstEvaluationAnnotation
signature {
methodName = "toString"
isOverride = true
returnType = "String"
}
}.modifyGeneratedToString()
}
private fun ClassBuilder.generateEquals() {
method {
annotations += intrinsicConstEvaluationAnnotation
signature {
isOverride = true
methodName = "equals"
parameter {
name = "other"
type = "Any?"
}
returnType = PrimitiveType.BOOLEAN.capitalized
}
}.modifyGeneratedEquals()
}
private fun ClassBuilder.generateHashCode() {
method {
signature {
isOverride = true
methodName = "hashCode"
returnType = PrimitiveType.INT.capitalized
}
}.modifyGeneratedHashCode()
}
internal open fun FileBuilder.modifyGeneratedFile() {}
internal open fun ClassBuilder.modifyGeneratedClass() {}
internal open fun CompanionObjectBuilder.modifyGeneratedCompanionObject() {}
internal open fun MethodBuilder.modifyGeneratedNot() {}
internal open fun MethodBuilder.modifyGeneratedAnd() {}
internal open fun MethodBuilder.modifyGeneratedOr() {}
internal open fun MethodBuilder.modifyGeneratedXor() {}
internal open fun MethodBuilder.modifyGeneratedCompareTo() {}
internal open fun MethodBuilder.modifyGeneratedToString() {}
internal open fun MethodBuilder.modifyGeneratedEquals() {}
internal open fun MethodBuilder.modifyGeneratedHashCode() {}
internal open fun ClassBuilder.generateAdditionalMethods() {}
}
class JvmBooleanGenerator(writer: PrintWriter) : BooleanGenerator(writer) {
override fun ClassBuilder.modifyGeneratedClass() {
appendDoc("On the JVM, non-nullable values of this type are represented as values of the primitive type `boolean`.")
}
}
class JsBooleanGenerator(writer: PrintWriter) : BooleanGenerator(writer) {
override fun FileBuilder.modifyGeneratedFile() {
suppress("NON_ABSTRACT_FUNCTION_WITH_NO_BODY")
suppress("UNUSED_PARAMETER")
}
}
class WasmBooleanGenerator(writer: PrintWriter) : BooleanGenerator(writer) {
override fun FileBuilder.modifyGeneratedFile() {
suppress("UNUSED_PARAMETER")
import("kotlin.wasm.internal.*")
}
override fun ClassBuilder.modifyGeneratedClass() {
annotations += "WasmAutoboxed"
constructorParam {
name = "private val value"
type = PrimitiveType.BOOLEAN.capitalized
}
}
override fun CompanionObjectBuilder.modifyGeneratedCompanionObject() {
isPublic = true
}
override fun MethodBuilder.modifyGeneratedNot() {
implementAsIntrinsic(PrimitiveType.BOOLEAN, methodName)
}
override fun MethodBuilder.modifyGeneratedAnd() {
implementAsIntrinsic(PrimitiveType.BOOLEAN, methodName)
}
override fun MethodBuilder.modifyGeneratedOr() {
implementAsIntrinsic(PrimitiveType.BOOLEAN, methodName)
}
override fun MethodBuilder.modifyGeneratedXor() {
implementAsIntrinsic(PrimitiveType.BOOLEAN, methodName)
}
override fun MethodBuilder.modifyGeneratedCompareTo() {
"wasm_i32_compareTo(this.toInt(), other.toInt())".addAsSingleLineBody(bodyOnNewLine = true)
}
override fun MethodBuilder.modifyGeneratedToString() {
modifySignature { visibility = null }
"if (this) \"true\" else \"false\"".addAsSingleLineBody(bodyOnNewLine = true)
}
override fun MethodBuilder.modifyGeneratedEquals() {
modifySignature { visibility = null }
"""
return if (other !is Boolean) {
false
} else {
wasm_i32_eq(this.toInt(), other.toInt())
}
""".trimIndent().addAsMultiLineBody()
}
override fun MethodBuilder.modifyGeneratedHashCode() {
modifySignature { visibility = null }
"if (this) 1231 else 1237".addAsSingleLineBody(bodyOnNewLine = true)
}
override fun ClassBuilder.generateAdditionalMethods() {
method {
annotations += "WasmNoOpCast"
signature {
visibility = MethodVisibility.INTERNAL
methodName = "toInt"
returnType = PrimitiveType.INT.capitalized
}
implementedAsIntrinsic.addAsSingleLineBody(bodyOnNewLine = true)
}
}
}
class NativeBooleanGenerator(writer: PrintWriter) : BooleanGenerator(writer) {
override fun FileBuilder.modifyGeneratedFile() {
import("kotlin.native.internal.TypedIntrinsic")
import("kotlin.native.internal.IntrinsicType")
}
override fun MethodBuilder.modifyGeneratedNot() {
setAsExternal()
}
override fun MethodBuilder.modifyGeneratedAnd() {
setAsExternal()
}
override fun MethodBuilder.modifyGeneratedOr() {
setAsExternal()
}
override fun MethodBuilder.modifyGeneratedXor() {
setAsExternal()
}
override fun MethodBuilder.modifyGeneratedCompareTo() {
annotations += "TypedIntrinsic(IntrinsicType.UNSIGNED_COMPARE_TO)"
modifySignature { isExternal = true }
}
override fun MethodBuilder.modifyGeneratedToString() {
"if (this) \"true\" else \"false\"".addAsSingleLineBody()
}
override fun MethodBuilder.modifyGeneratedEquals() {
"other is Boolean && kotlin.native.internal.areEqualByValue(this, other)".addAsSingleLineBody(bodyOnNewLine = true)
}
private fun ClassBuilder.generateCustomEquals() {
method {
annotations += "Deprecated(\"Provided for binary compatibility\", level = DeprecationLevel.HIDDEN)"
annotations += intrinsicConstEvaluationAnnotation
signature {
methodName = "equals"
parameter {
name = "other"
type = PrimitiveType.BOOLEAN.capitalized
}
returnType = PrimitiveType.BOOLEAN.capitalized
}
"kotlin.native.internal.areEqualByValue(this, other)".addAsSingleLineBody(bodyOnNewLine = false)
}
}
override fun MethodBuilder.modifyGeneratedHashCode() {
modifySignature { visibility = MethodVisibility.PUBLIC }
"if (this) 1231 else 1237".addAsSingleLineBody(bodyOnNewLine = true)
}
override fun ClassBuilder.generateAdditionalMethods() {
generateCustomEquals()
}
}
@@ -241,7 +241,7 @@ class NativePrimitivesGenerator(writer: PrintWriter) : BasePrimitivesGenerator(w
return this.uppercase(Locale.getDefault())
}
private fun MethodBuilder.setAsExternal() {
internal fun MethodBuilder.setAsExternal() {
annotations += "TypedIntrinsic(IntrinsicType.${methodName.toNativeOperator()})"
modifySignature { isExternal = true }
}
@@ -279,11 +279,13 @@ class WasmPrimitivesGenerator(writer: PrintWriter) : BasePrimitivesGenerator(wri
methodName = "reinterpretAs${otherKind.capitalized}"
returnType = otherKind.capitalized
}
"implementedAsIntrinsic".addAsSingleLineBody(bodyOnNewLine = true)
implementedAsIntrinsic.addAsSingleLineBody(bodyOnNewLine = true)
}
}
companion object {
internal const val implementedAsIntrinsic = "implementedAsIntrinsic"
private fun String.toWasmOperator(): String {
return when (this) {
"plus" -> "ADD"
@@ -294,19 +296,20 @@ class WasmPrimitivesGenerator(writer: PrintWriter) : BasePrimitivesGenerator(wri
"shr" -> "SHR_S"
"ushr" -> "SHR_U"
"equals" -> "EQ"
"not" -> "EQZ"
else -> this.uppercase()
}
}
private fun MethodBuilder.implementAsIntrinsic(thisKind: PrimitiveType, methodName: String) {
internal fun MethodBuilder.implementAsIntrinsic(thisKind: PrimitiveType, methodName: String) {
modifySignature { isInline = false }
annotations += "WasmOp(WasmOp.${thisKind.prefixUppercase}_${methodName.toWasmOperator()})"
"implementedAsIntrinsic".addAsSingleLineBody(bodyOnNewLine = true)
implementedAsIntrinsic.addAsSingleLineBody(bodyOnNewLine = true)
}
private val PrimitiveType.prefixUppercase: String
get() = when (this) {
PrimitiveType.BYTE, PrimitiveType.SHORT, PrimitiveType.INT -> "I32"
PrimitiveType.BYTE, PrimitiveType.SHORT, PrimitiveType.INT, PrimitiveType.BOOLEAN -> "I32"
PrimitiveType.LONG -> "I64"
PrimitiveType.FLOAT -> "F32"
PrimitiveType.DOUBLE -> "F64"
+15 -6
View File
@@ -122,6 +122,7 @@ internal class ClassBuilder : AnnotatedAndDocumented(), PrimitiveBuilder {
var isFinal: Boolean = false
var name: String = ""
private var constructorParam: MethodParameterBuilder? = null
private var superTypes: List<String> = emptyList()
private var companionObject: CompanionObjectBuilder? = null
private val methods: MutableList<MethodBuilder> = mutableListOf()
@@ -130,6 +131,10 @@ internal class ClassBuilder : AnnotatedAndDocumented(), PrimitiveBuilder {
constructorParam = MethodParameterBuilder().apply(init)
}
fun superType(type: String) {
superTypes += type
}
fun companionObject(init: CompanionObjectBuilder.() -> Unit): CompanionObjectBuilder {
throwIfAlreadyInitialized(companionObject, "companionObject", "ClassBuilder")
val companionObjectBuilder = CompanionObjectBuilder()
@@ -149,7 +154,7 @@ internal class ClassBuilder : AnnotatedAndDocumented(), PrimitiveBuilder {
append("public ")
if (isFinal) append("final ")
appendLine("class $name private constructor(${constructorParam?.build() ?: ""}) : Number(), Comparable<$name> {")
appendLine("class $name private constructor(${constructorParam?.build() ?: ""}) : ${superTypes.joinToString()} {")
companionObject?.let { appendLine(it.build().shift()) }
appendLine(methods.joinToString(separator = END_LINE + END_LINE) { it.build().shift() })
@@ -172,16 +177,20 @@ internal class CompanionObjectBuilder : AnnotatedAndDocumented(), PrimitiveBuild
return buildString {
printDocumentationAndAnnotations()
if (isPublic) append("public ")
appendLine("companion object {")
appendLine(properties.joinToString(separator = END_LINE + END_LINE) { it.build().shift() })
appendLine("}")
if (properties.isEmpty()) {
appendLine("companion object {}")
} else {
appendLine("companion object {")
appendLine(properties.joinToString(separator = END_LINE + END_LINE) { it.build().shift() })
appendLine("}")
}
}
}
}
internal class MethodSignatureBuilder : PrimitiveBuilder {
var isExternal: Boolean = false
var visibility: MethodVisibility = MethodVisibility.PUBLIC
var visibility: MethodVisibility? = MethodVisibility.PUBLIC
var isOverride: Boolean = false
var isInline: Boolean = false
var isInfix: Boolean = false
@@ -210,7 +219,7 @@ internal class MethodSignatureBuilder : PrimitiveBuilder {
return buildString {
if (isExternal) append("external ")
append("${visibility.name.lowercase()} ")
visibility?.let { append("${it.name.lowercase()} ") }
if (isOverride) append("override ")
if (isInline) append("inline ")
if (isInfix) append("infix ")