From 2985e8bcd35ad024c676470380b3f0a4545d800c Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Mon, 3 Feb 2020 20:05:32 +0300 Subject: [PATCH] Clean up code of ir builtins map generator --- generators/evaluate/GenerateBuiltInsMap.kt | 216 +++++++++++---------- 1 file changed, 116 insertions(+), 100 deletions(-) diff --git a/generators/evaluate/GenerateBuiltInsMap.kt b/generators/evaluate/GenerateBuiltInsMap.kt index 7129c4448fd..a221a55baf1 100644 --- a/generators/evaluate/GenerateBuiltInsMap.kt +++ b/generators/evaluate/GenerateBuiltInsMap.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.generators.evaluate import org.jetbrains.kotlin.backend.common.interpreter.builtins.compileTimeAnnotation import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor import org.jetbrains.kotlin.builtins.DefaultBuiltIns -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageVersion @@ -25,7 +24,6 @@ import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.TypeTranslator import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.storage.LockBasedStorageManager -import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.utils.Printer import java.io.File @@ -46,116 +44,25 @@ fun generateMap(): String { p.println("/** This file is generated by org.jetbrains.kotlin.backend.common.interpreter.builtins.GenerateBuiltInsMap.generateMap(). DO NOT MODIFY MANUALLY */") p.println() - val unaryOperationsMap = mutableMapOf>() - val binaryOperationsMap = mutableMapOf>() - val ternaryOperationsMap = mutableMapOf>() - val builtIns = DefaultBuiltIns.Instance + val unaryOperationsMap = getOperationMap(1) + val binaryOperationsMap = getOperationMap(2) + val ternaryOperationsMap = getOperationMap(3) - //save common builtins - val allPrimitiveTypes = PrimitiveType.values().map { builtIns.getBuiltInClassByFqName(it.typeFqName) } - val arrays = PrimitiveType.values().map { builtIns.getPrimitiveArrayClassDescriptor(it) } + builtIns.array - - for (descriptor in allPrimitiveTypes + builtIns.string + arrays + builtIns.any) { - val typeParameters = descriptor.typeConstructor.parameters.map { it.name.asString() } - val typeParametersAsAny = if (typeParameters.isNotEmpty()) typeParameters.joinToString(prefix = "<", postfix = ">") { "Any?" } else "" - val descriptorType = descriptor.defaultType - - @Suppress("UNCHECKED_CAST") - val functions = descriptor.getMemberScope(listOf()).getContributedDescriptors() - .filter { - it is CallableDescriptor && - (it as? FunctionDescriptor)?.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && - (it.annotations.hasAnnotation(compileTimeAnnotation) || descriptor.annotations.hasAnnotation(compileTimeAnnotation)) - } as List - - for (function in functions) { - val operationArguments = (listOf(descriptorType) + function.valueParameters.map { it.type }).joinToString { "\"" + it + "\"" } - - val functionTypeParameters = (listOf(descriptorType.constructor.toString() + typeParametersAsAny) + - function.valueParameters.map { if (typeParameters.contains(it.type.toString())) "Any?" else it.type.toString() }) - .joinToString(prefix = "<", postfix = ">") - - when (function.valueParameters.size + 1) { // +1 for receiver - 1 -> unaryOperationsMap[function] = functionTypeParameters to operationArguments - 2 -> binaryOperationsMap[function] = functionTypeParameters to operationArguments - 3 -> ternaryOperationsMap[function] = functionTypeParameters to operationArguments - else -> throw IllegalStateException("Couldn't add following method from builtins to operations map: ${function.name} in class ${descriptor.name}") - } - } - } - - //save ir builtins - val binaryIrOperationsMap = mutableMapOf>() - val irBuiltIns = getIrBuiltIns() - val irNullCheck = irBuiltIns.checkNotNullSymbol.descriptor - val irFunSymbols = - (irBuiltIns.lessFunByOperandType.values + - irBuiltIns.lessOrEqualFunByOperandType.values + - irBuiltIns.greaterFunByOperandType.values + - irBuiltIns.greaterOrEqualFunByOperandType.values + - irBuiltIns.eqeqSymbol + - irBuiltIns.eqeqeqSymbol + - irBuiltIns.ieee754equalsFunByOperandType.values + - irBuiltIns.andandSymbol + - irBuiltIns.ororSymbol) - .map { it.descriptor } - .filter { it.annotations.hasAnnotation(compileTimeAnnotation) } - - for (function in irFunSymbols) { - val parametersTypes = function.valueParameters.map { it.type } - val operationArguments = parametersTypes.joinToString { "\"" + it + "\"" } - val functionTypeParameters = parametersTypes.joinToString(prefix = "<", postfix = ">") - - check(parametersTypes.size == 2) { "Couldn't add following method from ir builtins to operations map: ${function.name}" } - binaryIrOperationsMap[function] = functionTypeParameters to operationArguments - } + val binaryIrOperationsMap = getBinaryIrOperationMap() //save to file p.println("val unaryFunctions = mapOf>(") - val unaryBody = unaryOperationsMap.entries.joinToString(",\n", postfix = ",\n") { (function, parameters) -> - val methodName = "${function.name}" - val parentheses = if (function is FunctionDescriptor) "()" else "" - val body = - if (methodName == "toString" && parameters.first == "") "a.defaultToString()" - else "a.$methodName$parentheses" - " unaryOperation${parameters.first}(\"$methodName\", ${parameters.second}) { a -> $body }" - } + " unaryOperation(\"${irNullCheck.name}\", \"${irNullCheck.valueParameters.first().type}\") { a -> a!! },\n" + - " unaryOperation(\"\", \"Throwable\") { a -> a.getMessage() },\n" + - " unaryOperation(\"\", \"Throwable\") { a -> a.getCause() }" - p.println(unaryBody) + p.println(generateUnaryBody(unaryOperationsMap)) p.println(")") p.println() p.println("val binaryFunctions = mapOf>(") - val binaryBody = binaryOperationsMap.entries.joinToString(",\n", postfix = ",\n") { (function, parameters) -> - val methodName = "${function.name}" - " binaryOperation${parameters.first}(\"$methodName\", ${parameters.second}) { a, b -> a.$methodName(b) }" - } + binaryIrOperationsMap.entries.joinToString(",\n") { (function, parameters) -> - val methodName = "${function.name}" - val methodSymbol = when (methodName) { - IrBuiltIns.OperatorNames.LESS -> "<" - IrBuiltIns.OperatorNames.LESS_OR_EQUAL -> "<=" - IrBuiltIns.OperatorNames.GREATER -> ">" - IrBuiltIns.OperatorNames.GREATER_OR_EQUAL -> ">=" - IrBuiltIns.OperatorNames.EQEQ -> "==" - IrBuiltIns.OperatorNames.EQEQEQ -> "===" - IrBuiltIns.OperatorNames.IEEE754_EQUALS -> "==" - IrBuiltIns.OperatorNames.ANDAND -> "&&" - IrBuiltIns.OperatorNames.OROR -> "||" - else -> throw UnsupportedOperationException("Unknown ir operation \"$methodName\"") - } - " binaryOperation${parameters.first}(\"$methodName\", ${parameters.second}) { a, b -> a $methodSymbol b }" - } - p.println(binaryBody) + p.println(generateBinaryBody(binaryOperationsMap, binaryIrOperationsMap)) p.println(")") p.println() p.println("val ternaryFunctions = mapOf>(") - val ternaryBody = ternaryOperationsMap.entries.joinToString(",\n") { (function, parameters) -> - val methodName = "${function.name}" - " ternaryOperation${parameters.first}(\"$methodName\", ${parameters.second}) { a, b, c -> a.$methodName(b, c) }" - } - p.println(ternaryBody) + p.println(generateTernaryBody(ternaryOperationsMap)) p.println(")") p.println() @@ -174,6 +81,115 @@ fun generateMap(): String { return sb.toString() } +private fun getOperationMap(argumentsCount: Int): MutableMap> { + val builtIns = DefaultBuiltIns.Instance + val operationMap = mutableMapOf>() + val allPrimitiveTypes = PrimitiveType.values().map { builtIns.getBuiltInClassByFqName(it.typeFqName) } + val arrays = PrimitiveType.values().map { builtIns.getPrimitiveArrayClassDescriptor(it) } + builtIns.array + + fun CallableDescriptor.isCompileTime(classDescriptor: ClassDescriptor): Boolean { + return (this as? FunctionDescriptor)?.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && + (this.annotations.hasAnnotation(compileTimeAnnotation) || classDescriptor.annotations.hasAnnotation(compileTimeAnnotation)) + } + + for (classDescriptor in allPrimitiveTypes + builtIns.string + arrays + builtIns.any) { + val classTypeParameters = classDescriptor.typeConstructor.parameters.map { it.name.asString() } + val typeParametersReplacedToAny = + if (classTypeParameters.isNotEmpty()) classTypeParameters.joinToString(prefix = "<", postfix = ">") { "Any?" } else "" + val classType = classDescriptor.defaultType + + val compileTimeFunctions = classDescriptor.getMemberScope(listOf()).getContributedDescriptors() + .filterIsInstance() + .filter { it.isCompileTime(classDescriptor) } + + for (function in compileTimeFunctions) { + val operationArguments = (listOf(classType) + function.valueParameters.map { it.type }).joinToString { "\"" + it + "\"" } + + val typeParametersOfFun = listOf(classType.constructor.toString() + typeParametersReplacedToAny) + + function.valueParameters.map { if (classTypeParameters.contains(it.type.toString())) "Any?" else it.type.toString() } + + if (function.valueParameters.size + 1 == argumentsCount) { // +1 for receiver + operationMap[function] = typeParametersOfFun.joinToString(prefix = "<", postfix = ">") to operationArguments + } + } + } + + return operationMap +} + +private fun getBinaryIrOperationMap(): MutableMap> { + val irBuiltIns = getIrBuiltIns() + val operationMap = mutableMapOf>() + val irFunSymbols = + (irBuiltIns.lessFunByOperandType.values + irBuiltIns.lessOrEqualFunByOperandType.values + + irBuiltIns.greaterFunByOperandType.values + irBuiltIns.greaterOrEqualFunByOperandType.values + + irBuiltIns.eqeqSymbol + irBuiltIns.eqeqeqSymbol + irBuiltIns.ieee754equalsFunByOperandType.values + + irBuiltIns.andandSymbol + irBuiltIns.ororSymbol) + .map { it.descriptor } + .filter { it.annotations.hasAnnotation(compileTimeAnnotation) } + + for (function in irFunSymbols) { + val parametersTypes = function.valueParameters.map { it.type } + val operationArguments = parametersTypes.joinToString { "\"" + it + "\"" } + val functionTypeParameters = parametersTypes.joinToString(prefix = "<", postfix = ">") + + check(parametersTypes.size == 2) { "Couldn't add following method from ir builtins to operations map: ${function.name}" } + operationMap[function] = functionTypeParameters to operationArguments + } + + return operationMap +} + +private fun generateUnaryBody(unaryOperationsMap: Map>): String { + val irNullCheck = getIrBuiltIns().checkNotNullSymbol.descriptor + return unaryOperationsMap.entries.joinToString(separator = ",\n", postfix = ",\n") { (function, parameters) -> + val methodName = "${function.name}" + val parentheses = if (function is FunctionDescriptor) "()" else "" + val body = + if (methodName == "toString" && parameters.first == "") "a.defaultToString()" + else "a.$methodName$parentheses" + " unaryOperation${parameters.first}(\"$methodName\", ${parameters.second}) { a -> $body }" + } + + " unaryOperation(\"${irNullCheck.name}\", \"${irNullCheck.valueParameters.first().type}\") { a -> a!! },\n" + + " unaryOperation(\"\", \"Throwable\") { a -> a.getMessage() },\n" + + " unaryOperation(\"\", \"Throwable\") { a -> a.getCause() }" +} + +private fun generateBinaryBody( + binaryOperationsMap: Map>, binaryIrOperationsMap: Map> +): String { + return binaryOperationsMap.entries.joinToString(separator = ",\n", postfix = ",\n") { (function, parameters) -> + val methodName = "${function.name}" + " binaryOperation${parameters.first}(\"$methodName\", ${parameters.second}) { a, b -> a.$methodName(b) }" + } + binaryIrOperationsMap.entries.joinToString(separator = ",\n") { (function, parameters) -> + val methodName = "${function.name}" + val methodSymbol = getIrMethodSymbolByName(methodName) + " binaryOperation${parameters.first}(\"$methodName\", ${parameters.second}) { a, b -> a $methodSymbol b }" + } +} + +private fun generateTernaryBody(ternaryOperationsMap: Map>): String { + return ternaryOperationsMap.entries.joinToString(separator = ",\n") { (function, parameters) -> + val methodName = "${function.name}" + " ternaryOperation${parameters.first}(\"$methodName\", ${parameters.second}) { a, b, c -> a.$methodName(b, c) }" + } +} + +private fun getIrMethodSymbolByName(methodName: String): String { + return when (methodName) { + IrBuiltIns.OperatorNames.LESS -> "<" + IrBuiltIns.OperatorNames.LESS_OR_EQUAL -> "<=" + IrBuiltIns.OperatorNames.GREATER -> ">" + IrBuiltIns.OperatorNames.GREATER_OR_EQUAL -> ">=" + IrBuiltIns.OperatorNames.EQEQ -> "==" + IrBuiltIns.OperatorNames.EQEQEQ -> "===" + IrBuiltIns.OperatorNames.IEEE754_EQUALS -> "==" + IrBuiltIns.OperatorNames.ANDAND -> "&&" + IrBuiltIns.OperatorNames.OROR -> "||" + else -> throw UnsupportedOperationException("Unknown ir operation \"$methodName\"") + } +} + private fun getIrBuiltIns(): IrBuiltIns { val builtIns = DefaultBuiltIns.Instance val languageSettings = LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_3, ApiVersion.KOTLIN_1_3)