From dcb95eb9f0f67dff6f40e5029bb18fe32b474263 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Thu, 10 Nov 2016 15:08:54 +0300 Subject: [PATCH] JS: refactor range and progression related intrinsics --- .../kotlin/js/translate/context/Namer.java | 2 - .../functions/basic/FqnCallIntrinsic.kt | 50 ------------------- .../basic/LazyImportedCallIntrinsic.kt | 49 ------------------ .../functions/basic/RangeToIntrinsic.kt | 42 ++++++++++++++++ .../PrimitiveBinaryOperationFIF.java | 13 ++--- .../factories/ProgressionCompanionFIF.kt | 37 ++++++++------ 6 files changed, 67 insertions(+), 126 deletions(-) delete mode 100644 js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/basic/FqnCallIntrinsic.kt delete mode 100644 js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/basic/LazyImportedCallIntrinsic.kt create mode 100644 js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/basic/RangeToIntrinsic.kt diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java index 6bbb96a5435..fd00b89a9fe 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/Namer.java @@ -56,8 +56,6 @@ public final class Namer { public static final String EQUALS_METHOD_NAME = getStableMangledNameForDescriptor(JsPlatform.INSTANCE.getBuiltIns().getAny(), "equals"); public static final String COMPARE_TO_METHOD_NAME = getStableMangledNameForDescriptor(JsPlatform.INSTANCE.getBuiltIns().getComparable(), "compareTo"); - public static final String INT_RANGE = "kotlin.ranges.IntRange"; - public static final String CHAR_RANGE = "kotlin.ranges.CharRange"; public static final String LONG_FROM_NUMBER = "fromNumber"; public static final String LONG_TO_NUMBER = "toNumber"; public static final String LONG_FROM_INT = "fromInt"; diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/basic/FqnCallIntrinsic.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/basic/FqnCallIntrinsic.kt deleted file mode 100644 index d97ec665504..00000000000 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/basic/FqnCallIntrinsic.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2010-2016 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.kotlin.js.translate.intrinsic.functions.basic - -import com.google.dart.compiler.backend.js.ast.JsExpression -import org.jetbrains.kotlin.js.translate.context.Namer -import org.jetbrains.kotlin.js.translate.context.TranslationContext -import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator -import org.jetbrains.kotlin.js.translate.utils.JsAstUtils -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter - -class FqnCallIntrinsic( - simpleName: String, - fqn: String, - isConstructor: Boolean = false, - receiverAsArgument: Boolean = true -) : LazyImportedCallIntrinsic(simpleName, isConstructor = isConstructor, receiverAsArgument = receiverAsArgument) { - val fqn = FqName(fqn) - - override fun getExpression(context: TranslationContext): JsExpression { - val packageDescriptor = context.currentModule.getPackage(fqn.parent()) - - // Hack to compile stdlib - val descriptors = packageDescriptor.memberScope.getContributedDescriptors(DescriptorKindFilter.ALL) { - it.asString() == fqn.shortName().asString() - } - - return if (descriptors.size == 1) { - JsAstUtils.replaceRootReference(context.getQualifiedReference(fqn), Namer.kotlinObject()) - } - else { - ReferenceTranslator.translateAsValueReference(descriptors.first(), context) - } - } -} \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/basic/LazyImportedCallIntrinsic.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/basic/LazyImportedCallIntrinsic.kt deleted file mode 100644 index 642d34937af..00000000000 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/basic/LazyImportedCallIntrinsic.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2010-2016 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.kotlin.js.translate.intrinsic.functions.basic - -import com.google.dart.compiler.backend.js.ast.* -import org.jetbrains.kotlin.js.translate.context.TranslationContext -import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn -import org.jetbrains.kotlin.utils.singletonOrEmptyList -import java.util.* - -abstract class LazyImportedCallIntrinsic( - val simpleName: String, - val isConstructor: Boolean = false, - val receiverAsArgument: Boolean = true -) : FunctionIntrinsic() { - private val internalNameMap = WeakHashMap() - - override fun apply(receiver: JsExpression?, arguments: MutableList, context: TranslationContext): JsExpression { - val rootContext = generateSequence(context) { it.parent }.last() - val functionName = internalNameMap.getOrPut(rootContext) { - val declaration = getExpression(rootContext) - if (declaration is JsNameRef && declaration.name != null && declaration.qualifier == null) { - declaration.name!! - } - else { - rootContext.importDeclaration(simpleName, declaration) - } - } - val allArguments = (if (receiverAsArgument) receiver else null).singletonOrEmptyList() + arguments - val function = pureFqn(functionName, null) - return if (isConstructor) JsNew(function, allArguments) else JsInvocation(function, allArguments) - } - - abstract fun getExpression(context: TranslationContext): JsExpression -} \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/basic/RangeToIntrinsic.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/basic/RangeToIntrinsic.kt new file mode 100644 index 00000000000..391bb4f87d8 --- /dev/null +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/basic/RangeToIntrinsic.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2016 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.kotlin.js.translate.intrinsic.functions.basic + +import com.google.dart.compiler.backend.js.ast.JsExpression +import com.google.dart.compiler.backend.js.ast.JsNew +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor +import org.jetbrains.kotlin.js.translate.context.TranslationContext +import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.utils.singletonOrEmptyList + +class RangeToIntrinsic(function: FunctionDescriptor) : FunctionIntrinsic() { + val rangeTypeDescriptor = function.returnType!!.constructor.declarationDescriptor as ClassDescriptor + + override fun apply(receiver: JsExpression?, arguments: MutableList, context: TranslationContext): JsExpression { + val packageName = (rangeTypeDescriptor.containingDeclaration as PackageFragmentDescriptor).fqName + val packageDescriptor = context.currentModule.getPackage(packageName) + val existingClasses = packageDescriptor.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) { + it == rangeTypeDescriptor.name + } + val finalClass = (existingClasses.firstOrNull() as? ClassDescriptor) ?: rangeTypeDescriptor + val constructor = ReferenceTranslator.translateAsTypeReference(finalClass, context) + return JsNew(constructor, receiver.singletonOrEmptyList() + arguments) + } +} \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/PrimitiveBinaryOperationFIF.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/PrimitiveBinaryOperationFIF.java index 469edb8177a..bad606150e4 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/PrimitiveBinaryOperationFIF.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/PrimitiveBinaryOperationFIF.java @@ -28,10 +28,9 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.js.patterns.DescriptorPredicate; import org.jetbrains.kotlin.js.patterns.NamePredicate; -import org.jetbrains.kotlin.js.translate.context.Namer; import org.jetbrains.kotlin.js.translate.context.TranslationContext; -import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FqnCallIntrinsic; import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic; +import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.RangeToIntrinsic; import org.jetbrains.kotlin.js.translate.operation.OperatorTable; import org.jetbrains.kotlin.js.translate.utils.JsAstUtils; import org.jetbrains.kotlin.lexer.KtToken; @@ -62,12 +61,6 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory { } } - @NotNull - private static final FunctionIntrinsic RANGE_TO_INTRINSIC = new FqnCallIntrinsic("IntRange", Namer.INT_RANGE, true, true); - - @NotNull - private static final FunctionIntrinsic CHAR_RANGE_TO_INTRINSIC = new FqnCallIntrinsic("CharRange", Namer.CHAR_RANGE, true, true); - @NotNull private static final BinaryOperationIntrinsicBase INTEGER_DIVISION_INTRINSIC = new BinaryOperationIntrinsicBase() { @NotNull @@ -127,7 +120,7 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory { @Override public FunctionIntrinsic getIntrinsic(@NotNull FunctionDescriptor descriptor) { if (pattern("Char.rangeTo(Char)").apply(descriptor)) { - return CHAR_RANGE_TO_INTRINSIC; + return new RangeToIntrinsic(descriptor); } if (PRIMITIVE_NUMBERS_COMPARE_TO_OPERATIONS.apply(descriptor)) { @@ -148,7 +141,7 @@ public enum PrimitiveBinaryOperationFIF implements FunctionIntrinsicFactory { return INTEGER_DIVISION_INTRINSIC; } if (descriptor.getName().equals(Name.identifier("rangeTo"))) { - return RANGE_TO_INTRINSIC; + return new RangeToIntrinsic(descriptor); } if (INT_WITH_BIT_OPERATIONS.apply(descriptor)) { JsBinaryOperator op = BINARY_BITWISE_OPERATIONS.get(descriptor.getName().asString()); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/ProgressionCompanionFIF.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/ProgressionCompanionFIF.kt index 4d93d06f931..34b8cff9a4b 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/ProgressionCompanionFIF.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/ProgressionCompanionFIF.kt @@ -18,26 +18,33 @@ package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories import com.google.dart.compiler.backend.js.ast.JsExpression import com.google.dart.compiler.backend.js.ast.JsNew -import org.jetbrains.kotlin.builtins.PrimitiveType +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.js.patterns.PatternBuilder.pattern import org.jetbrains.kotlin.js.translate.context.TranslationContext -import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FqnCallIntrinsic import org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic +import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator - -object ProgressionCompanionFIF : CompositeFIF() { - init { - val numberProgressionConstructor = FqnCallIntrinsic("IntProgression", "kotlin.ranges.IntProgression", isConstructor = true, - receiverAsArgument = false) - for (type in arrayOf(PrimitiveType.INT)) { - add(methodPattern("${type.typeName}Progression"), numberProgressionConstructor) - } - add(methodPattern("LongProgression"), FqnCallIntrinsic("LongProgression", "kotlin.ranges.LongProgression", isConstructor = true, - receiverAsArgument = false)) - add(methodPattern("CharProgression"), FqnCallIntrinsic("CharProgression", "kotlin.ranges.CharProgression", isConstructor = true, - receiverAsArgument = false)) - } +object ProgressionCompanionFIF : FunctionIntrinsicFactory { + val patterns = listOf(methodPattern("IntProgression"), methodPattern("LongProgression"), methodPattern("CharProgression")) private fun methodPattern(builtinProgressionName: String) = pattern("kotlin.ranges", builtinProgressionName, "Companion", "fromClosedRange") + + override fun getIntrinsic(descriptor: FunctionDescriptor): FunctionIntrinsic? = + if (patterns.any { it.apply(descriptor) }) { + FromClosedRangeIntrinsic(descriptor) + } + else { + null + } + + private class FromClosedRangeIntrinsic(descriptor: FunctionDescriptor) : FunctionIntrinsic() { + val progressionType = descriptor.containingDeclaration.containingDeclaration as ClassDescriptor + + override fun apply(receiver: JsExpression?, arguments: MutableList, context: TranslationContext): JsExpression { + val constructor = ReferenceTranslator.translateAsTypeReference(progressionType, context) + return JsNew(constructor, arguments) + } + } } \ No newline at end of file