@@ -26,20 +26,21 @@ fun main() {
26
26
fun generate (): String {
27
27
val sb = StringBuilder ()
28
28
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\" )" )
31
29
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)
40
37
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 >()
43
44
44
45
val builtIns = DefaultBuiltIns .Instance
45
46
@@ -56,45 +57,69 @@ fun generate(): String {
56
57
.filter { it is CallableDescriptor && ! EXCLUDED_FUNCTIONS .contains(it.getName().asString()) } as List <CallableDescriptor >
57
58
58
59
for (function in functions) {
59
- val parametersTypes = function.getParametersTypes()
60
+ val parametersTypes = function.getParametersTypes().map { it.typeName }
60
61
61
62
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) )
64
65
else -> throw IllegalStateException (
65
66
" Couldn't add following method from builtins to operations map: ${function.name} in class ${descriptor.name} "
66
67
)
67
68
}
68
69
}
69
70
}
70
71
71
- unaryOperationsMap.add(Triple (" code" , listOf (builtIns.charType ), false ))
72
+ unaryOperationsMap.add(Operation (" code" , listOf (" Char " ), false ))
72
73
73
74
for (type in integerTypes) {
74
75
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) )
78
79
}
79
80
}
80
81
81
82
for (type in fpTypes) {
82
83
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) )
85
86
}
86
87
}
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
+ }
87
104
105
+ private fun generateUnaryOp (
106
+ p : Printer ,
107
+ unaryOperationsMap : ArrayList <Operation >,
108
+ ) {
88
109
p.println (" fun evalUnaryOp(name: String, type: CompileTimeType, value: Any): Any? {" )
89
110
p.pushIndent()
90
111
p.println (" when (type) {" )
91
112
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) {" )
94
115
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
+ }
96
121
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 " )
98
123
}
99
124
p.popIndent()
100
125
p.println (" }" )
@@ -106,20 +131,25 @@ fun generate(): String {
106
131
p.popIndent()
107
132
p.println (" }" )
108
133
p.println ()
134
+ }
109
135
136
+ private fun generateBinaryOp (
137
+ p : Printer ,
138
+ binaryOperationsMap : ArrayList <Operation >,
139
+ ) {
110
140
p.println (" fun evalBinaryOp(name: String, leftType: CompileTimeType, left: Any, rightType: CompileTimeType, right: Any): Any? {" )
111
141
p.pushIndent()
112
142
p.println (" when (leftType) {" )
113
143
p.pushIndent()
114
144
for ((leftType, operationsOnThisLeftType) in binaryOperationsMap.groupBy { (_, parameters) -> parameters.first() }) {
115
- p.println (" ${leftType.asString ()} -> when (rightType) {" )
145
+ p.println (" ${leftType.toCompilTimeTypeFormat ()} -> when (rightType) {" )
116
146
p.pushIndent()
117
147
for ((rightType, operations) in operationsOnThisLeftType.groupBy { (_, parameters) -> parameters[1 ] }) {
118
- p.println (" ${rightType.asString ()} -> when (name) {" )
148
+ p.println (" ${rightType.toCompilTimeTypeFormat ()} -> when (name) {" )
119
149
p.pushIndent()
120
150
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 )" )
123
153
}
124
154
p.popIndent()
125
155
p.println (" }" )
@@ -135,7 +165,13 @@ fun generate(): String {
135
165
p.popIndent()
136
166
p.println (" }" )
137
167
p.println ()
168
+ }
138
169
170
+ // TODO, KT-75372: Can be dropped with K1
171
+ private fun generateBinaryOpCheck (
172
+ p : Printer ,
173
+ binaryOperationsMap : ArrayList <Operation >,
174
+ ) {
139
175
p.println (" fun checkBinaryOp(" )
140
176
p.println (" name: String, leftType: CompileTimeType, left: BigInteger, rightType: CompileTimeType, right: BigInteger" )
141
177
p.println (" ): BigInteger? {" )
@@ -145,10 +181,10 @@ fun generate(): String {
145
181
val checkedBinaryOperations =
146
182
binaryOperationsMap.filter { (name, parameters) -> getBinaryCheckerName(name, parameters[0 ], parameters[1 ]) != null }
147
183
for ((leftType, operationsOnThisLeftType) in checkedBinaryOperations.groupBy { (_, parameters) -> parameters.first() }) {
148
- p.println (" ${leftType.asString ()} -> when (rightType) {" )
184
+ p.println (" ${leftType.toCompilTimeTypeFormat ()} -> when (rightType) {" )
149
185
p.pushIndent()
150
186
for ((rightType, operations) in operationsOnThisLeftType.groupBy { (_, parameters) -> parameters[1 ] }) {
151
- p.println (" ${rightType.asString ()} -> when (name) {" )
187
+ p.println (" ${rightType.toCompilTimeTypeFormat ()} -> when (name) {" )
152
188
p.pushIndent()
153
189
for ((name, _) in operations) {
154
190
val checkerName = getBinaryCheckerName(name, leftType, rightType)!!
@@ -167,12 +203,11 @@ fun generate(): String {
167
203
p.println (" return null" )
168
204
p.popIndent()
169
205
p.println (" }" )
170
-
171
- return sb.toString()
172
206
}
173
207
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
176
211
177
212
return when (name) {
178
213
" plus" -> " add"
@@ -184,6 +219,13 @@ private fun getBinaryCheckerName(name: String, leftType: KotlinType, rightType:
184
219
}
185
220
}
186
221
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
+
187
229
private fun KotlinType.isIntegerType (): Boolean =
188
230
KotlinBuiltIns .isInt(this ) || KotlinBuiltIns .isShort(this ) || KotlinBuiltIns .isByte(this ) || KotlinBuiltIns .isLong(this )
189
231
@@ -194,7 +236,11 @@ private fun CallableDescriptor.getParametersTypes(): List<KotlinType> =
194
236
listOf ((containingDeclaration as ClassDescriptor ).defaultType) +
195
237
valueParameters.map { it.type.makeNotNullable() }
196
238
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
+ }
198
244
199
245
private val KotlinType .typeName: String
200
246
get(): String = constructor .declarationDescriptor!! .name.asString()
0 commit comments