Skip to content

Commit 07cb0dd

Browse files
flofridaySpace Team
authored andcommitted
[FIR] Refactor builtin operations map generator into multiple functions
This is now also closer to how the backend builtin map generator is written and easier to read. The base datatype used is now also the Operation data class instead of unnamed Tuple and Tripple. The Operation doesn't use KotlinType to represent types as there aren't any simple constructors available to represent unsigned types and this brings it closer to the backend builtin map generator. KT-51065 # Conflicts: # generators/evaluate/GenerateOperationsMap.kt
1 parent 9e16cd2 commit 07cb0dd

File tree

1 file changed

+82
-36
lines changed

1 file changed

+82
-36
lines changed

generators/evaluate/GenerateOperationsMap.kt

Lines changed: 82 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,21 @@ fun main() {
2626
fun generate(): String {
2727
val sb = StringBuilder()
2828
val p = Printer(sb)
29-
p.println(File("license/COPYRIGHT_HEADER.txt").readText())
30-
p.println("@file:Suppress(\"DEPRECATION\", \"DEPRECATION_ERROR\", \"REDUNDANT_CALL_OF_CONVERSION_METHOD\")")
3129

32-
p.println()
33-
p.println("package org.jetbrains.kotlin.resolve.constants.evaluate")
34-
p.println()
35-
p.println("import org.jetbrains.kotlin.resolve.constants.evaluate.CompileTimeType.*")
36-
p.println("import java.math.BigInteger")
37-
p.println()
38-
p.println("/** This file is generated by `./gradlew generateOperationsMap`. DO NOT MODIFY MANUALLY */")
39-
p.println()
30+
generateHeader(p)
31+
32+
val (unaryOperationsMap, binaryOperationsMap) = getOperationMaps()
33+
34+
generateUnaryOp(p, unaryOperationsMap)
35+
generateBinaryOp(p, binaryOperationsMap)
36+
generateBinaryOpCheck(p, binaryOperationsMap)
4037

41-
val unaryOperationsMap = arrayListOf<Triple<String, List<KotlinType>, Boolean>>()
42-
val binaryOperationsMap = arrayListOf<Pair<String, List<KotlinType>>>()
38+
return sb.toString()
39+
}
40+
41+
private fun getOperationMaps(): Pair<ArrayList<Operation>, ArrayList<Operation>> {
42+
val unaryOperationsMap = arrayListOf<Operation>()
43+
val binaryOperationsMap = arrayListOf<Operation>()
4344

4445
val builtIns = DefaultBuiltIns.Instance
4546

@@ -56,45 +57,69 @@ fun generate(): String {
5657
.filter { it is CallableDescriptor && !EXCLUDED_FUNCTIONS.contains(it.getName().asString()) } as List<CallableDescriptor>
5758

5859
for (function in functions) {
59-
val parametersTypes = function.getParametersTypes()
60+
val parametersTypes = function.getParametersTypes().map { it.typeName }
6061

6162
when (parametersTypes.size) {
62-
1 -> unaryOperationsMap.add(Triple(function.name.asString(), parametersTypes, function is FunctionDescriptor))
63-
2 -> binaryOperationsMap.add(function.name.asString() to parametersTypes)
63+
1 -> unaryOperationsMap.add(Operation(function.name.asString(), parametersTypes, function is FunctionDescriptor))
64+
2 -> binaryOperationsMap.add(Operation(function.name.asString(), parametersTypes))
6465
else -> throw IllegalStateException(
6566
"Couldn't add following method from builtins to operations map: ${function.name} in class ${descriptor.name}"
6667
)
6768
}
6869
}
6970
}
7071

71-
unaryOperationsMap.add(Triple("code", listOf(builtIns.charType), false))
72+
unaryOperationsMap.add(Operation("code", listOf("Char"), false))
7273

7374
for (type in integerTypes) {
7475
for (otherType in integerTypes) {
75-
val parameters = listOf(type, otherType)
76-
binaryOperationsMap.add("mod" to parameters)
77-
binaryOperationsMap.add("floorDiv" to parameters)
76+
val parameters = listOf(type, otherType).map { it.typeName }
77+
binaryOperationsMap.add(Operation("mod", parameters))
78+
binaryOperationsMap.add(Operation("floorDiv", parameters))
7879
}
7980
}
8081

8182
for (type in fpTypes) {
8283
for (otherType in fpTypes) {
83-
val parameters = listOf(type, otherType)
84-
binaryOperationsMap.add("mod" to parameters)
84+
val parameters = listOf(type, otherType).map { it.typeName }
85+
binaryOperationsMap.add(Operation("mod", parameters))
8586
}
8687
}
88+
return Pair(unaryOperationsMap, binaryOperationsMap)
89+
}
90+
91+
private fun generateHeader(p: Printer) {
92+
p.println(File("license/COPYRIGHT_HEADER.txt").readText())
93+
p.println("@file:Suppress(\"DEPRECATION\", \"DEPRECATION_ERROR\", \"REDUNDANT_CALL_OF_CONVERSION_METHOD\")")
94+
95+
p.println()
96+
p.println("package org.jetbrains.kotlin.resolve.constants.evaluate")
97+
p.println()
98+
p.println("import org.jetbrains.kotlin.resolve.constants.evaluate.CompileTimeType.*")
99+
p.println("import java.math.BigInteger")
100+
p.println()
101+
p.println("/** This file is generated by `./gradlew generateOperationsMap`. DO NOT MODIFY MANUALLY */")
102+
p.println()
103+
}
87104

105+
private fun generateUnaryOp(
106+
p: Printer,
107+
unaryOperationsMap: ArrayList<Operation>,
108+
) {
88109
p.println("fun evalUnaryOp(name: String, type: CompileTimeType, value: Any): Any? {")
89110
p.pushIndent()
90111
p.println("when (type) {")
91112
p.pushIndent()
92-
for ((type, operations) in unaryOperationsMap.groupBy { (_, parameters, _) -> parameters.single() }) {
93-
p.println("${type.asString()} -> when (name) {")
113+
for ((type, operations) in unaryOperationsMap.groupBy { it.parameterTypes.single() }) {
114+
p.println("${type.toCompilTimeTypeFormat()} -> when (name) {")
94115
p.pushIndent()
95-
for ((name, _, isFunction) in operations) {
116+
for ((name, _, isFunction, customExpr) in operations) {
117+
if (customExpr != null) {
118+
p.println("\"$name\" -> return $customExpr")
119+
continue
120+
}
96121
val parenthesesOrBlank = if (isFunction) "()" else ""
97-
p.println("\"$name\" -> return (value as ${type.typeName}).$name$parenthesesOrBlank")
122+
p.println("\"$name\" -> return (value as ${type}).$name$parenthesesOrBlank")
98123
}
99124
p.popIndent()
100125
p.println("}")
@@ -106,20 +131,25 @@ fun generate(): String {
106131
p.popIndent()
107132
p.println("}")
108133
p.println()
134+
}
109135

136+
private fun generateBinaryOp(
137+
p: Printer,
138+
binaryOperationsMap: ArrayList<Operation>,
139+
) {
110140
p.println("fun evalBinaryOp(name: String, leftType: CompileTimeType, left: Any, rightType: CompileTimeType, right: Any): Any? {")
111141
p.pushIndent()
112142
p.println("when (leftType) {")
113143
p.pushIndent()
114144
for ((leftType, operationsOnThisLeftType) in binaryOperationsMap.groupBy { (_, parameters) -> parameters.first() }) {
115-
p.println("${leftType.asString()} -> when (rightType) {")
145+
p.println("${leftType.toCompilTimeTypeFormat()} -> when (rightType) {")
116146
p.pushIndent()
117147
for ((rightType, operations) in operationsOnThisLeftType.groupBy { (_, parameters) -> parameters[1] }) {
118-
p.println("${rightType.asString()} -> when (name) {")
148+
p.println("${rightType.toCompilTimeTypeFormat()} -> when (name) {")
119149
p.pushIndent()
120150
for ((name, _) in operations) {
121-
val castToRightType = if (rightType.typeName == "Any") "" else " as ${rightType.typeName}"
122-
p.println("\"$name\" -> return (left as ${leftType.typeName}).$name(right$castToRightType)")
151+
val castToRightType = if (rightType == "Any") "" else " as ${rightType}"
152+
p.println("\"$name\" -> return (left as ${leftType}).$name(right$castToRightType)")
123153
}
124154
p.popIndent()
125155
p.println("}")
@@ -135,7 +165,13 @@ fun generate(): String {
135165
p.popIndent()
136166
p.println("}")
137167
p.println()
168+
}
138169

170+
// TODO, KT-75372: Can be dropped with K1
171+
private fun generateBinaryOpCheck(
172+
p: Printer,
173+
binaryOperationsMap: ArrayList<Operation>,
174+
) {
139175
p.println("fun checkBinaryOp(")
140176
p.println(" name: String, leftType: CompileTimeType, left: BigInteger, rightType: CompileTimeType, right: BigInteger")
141177
p.println("): BigInteger? {")
@@ -145,10 +181,10 @@ fun generate(): String {
145181
val checkedBinaryOperations =
146182
binaryOperationsMap.filter { (name, parameters) -> getBinaryCheckerName(name, parameters[0], parameters[1]) != null }
147183
for ((leftType, operationsOnThisLeftType) in checkedBinaryOperations.groupBy { (_, parameters) -> parameters.first() }) {
148-
p.println("${leftType.asString()} -> when (rightType) {")
184+
p.println("${leftType.toCompilTimeTypeFormat()} -> when (rightType) {")
149185
p.pushIndent()
150186
for ((rightType, operations) in operationsOnThisLeftType.groupBy { (_, parameters) -> parameters[1] }) {
151-
p.println("${rightType.asString()} -> when (name) {")
187+
p.println("${rightType.toCompilTimeTypeFormat()} -> when (name) {")
152188
p.pushIndent()
153189
for ((name, _) in operations) {
154190
val checkerName = getBinaryCheckerName(name, leftType, rightType)!!
@@ -167,12 +203,11 @@ fun generate(): String {
167203
p.println("return null")
168204
p.popIndent()
169205
p.println("}")
170-
171-
return sb.toString()
172206
}
173207

174-
private fun getBinaryCheckerName(name: String, leftType: KotlinType, rightType: KotlinType): String? {
175-
if (!leftType.isIntegerType() || !rightType.isIntegerType()) return null
208+
private fun getBinaryCheckerName(name: String, leftType: String, rightType: String): String? {
209+
val integerTypes = listOf("Int", "Short", "Byte", "Long")
210+
if (!integerTypes.contains(leftType) || !integerTypes.contains(rightType)) return null
176211

177212
return when (name) {
178213
"plus" -> "add"
@@ -184,6 +219,13 @@ private fun getBinaryCheckerName(name: String, leftType: KotlinType, rightType:
184219
}
185220
}
186221

222+
private data class Operation(
223+
val name: String,
224+
val parameterTypes: List<String>,
225+
val isFunction: Boolean = true,
226+
val customExpression: String? = null,
227+
) {}
228+
187229
private fun KotlinType.isIntegerType(): Boolean =
188230
KotlinBuiltIns.isInt(this) || KotlinBuiltIns.isShort(this) || KotlinBuiltIns.isByte(this) || KotlinBuiltIns.isLong(this)
189231

@@ -194,7 +236,11 @@ private fun CallableDescriptor.getParametersTypes(): List<KotlinType> =
194236
listOf((containingDeclaration as ClassDescriptor).defaultType) +
195237
valueParameters.map { it.type.makeNotNullable() }
196238

197-
private fun KotlinType.asString(): String = typeName.uppercase()
239+
// Formats the type to fit the Enum kotlin.resolve.constants.evaluateCompileTimeType which is all uppercase and doesn't have the concept of
240+
// nullability.
241+
private fun String.toCompilTimeTypeFormat(): String {
242+
return this.uppercase().removeSuffix("?")
243+
}
198244

199245
private val KotlinType.typeName: String
200246
get(): String = constructor.declarationDescriptor!!.name.asString()

0 commit comments

Comments
 (0)