From 37dfa58cd328f96d03799962829163ad4f871868 Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Thu, 7 May 2015 21:34:54 +0300 Subject: [PATCH] JS: expand calls, generated to curry reified is checks --- .../js/ast/metadata/metadataProperties.kt | 6 +++ .../kotlin/js/inline/util/sideEffectUtils.kt | 2 + .../kotlin/js/facade/K2JSTranslator.java | 2 + .../kotlin/js/translate/context/Namer.java | 15 +++++- .../js/translate/utils/expandIsCalls.kt | 48 +++++++++++++++++++ 5 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/expandIsCalls.kt diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/metadataProperties.kt b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/metadataProperties.kt index 6d4ab195c5c..d7c7ee8f53b 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/metadataProperties.kt +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/metadata/metadataProperties.kt @@ -34,3 +34,9 @@ public var JsFunction.isLocal: Boolean by MetadataProperty(default = false) public var JsParameter.hasDefaultValue: Boolean by MetadataProperty(default = false) +public var JsInvocation.typeCheck: TypeCheck? by MetadataProperty(default = null) + +public enum class TypeCheck { + TYPEOF + INSTANCEOF +} \ No newline at end of file diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/sideEffectUtils.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/sideEffectUtils.kt index 4bfeeadd175..6d9d99bd5a2 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/sideEffectUtils.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/sideEffectUtils.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.js.inline.util import com.google.dart.compiler.backend.js.ast.JsLiteral.* import com.google.dart.compiler.backend.js.ast.* +import com.google.dart.compiler.backend.js.ast.metadata.typeCheck import org.jetbrains.kotlin.js.translate.utils.ast.any public fun JsExpression.canHaveSideEffect(): Boolean = @@ -44,5 +45,6 @@ public fun JsExpression.shouldHaveOwnAlias(): Boolean = is JsConditional, is JsBinaryOperation, is JsArrayLiteral -> true + is JsInvocation -> if (typeCheck == null) canHaveSideEffect() else false else -> canHaveOwnSideEffect() } \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java index 7c8d6bc9115..f3b813c6778 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/facade/K2JSTranslator.java @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics; import java.util.List; import static org.jetbrains.kotlin.diagnostics.DiagnosticUtils.hasError; +import static org.jetbrains.kotlin.js.translate.utils.UtilsPackage.expandIsCalls; /** * An entry point of translator. @@ -79,6 +80,7 @@ public final class K2JSTranslator { JsProgram program = JsInliner.process(context); if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics); + expandIsCalls(program, context); return new TranslationResult.Success(config, files, program, diagnostics, moduleDescriptor); } } 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 0f509f48576..5a7e116312a 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 @@ -17,6 +17,8 @@ package org.jetbrains.kotlin.js.translate.context; import com.google.dart.compiler.backend.js.ast.*; +import com.google.dart.compiler.backend.js.ast.metadata.TypeCheck; +import com.google.dart.compiler.backend.js.ast.metadata.MetadataPackage; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; @@ -375,12 +377,21 @@ public final class Namer { @NotNull public JsExpression isTypeOf(@NotNull JsExpression type) { - return new JsInvocation(kotlin("isTypeOf"), type); + JsInvocation invocation = new JsInvocation(kotlin("isTypeOf"), type); + MetadataPackage.setTypeCheck(invocation, TypeCheck.TYPEOF); + return invocation; } @NotNull public JsExpression isInstanceOf(@NotNull JsExpression type) { - return new JsInvocation(kotlin("isInstanceOf"), type); + JsInvocation invocation = new JsInvocation(kotlin("isInstanceOf"), type); + MetadataPackage.setTypeCheck(invocation, TypeCheck.INSTANCEOF); + return invocation; + } + + @NotNull + public JsExpression isInstanceOf(@NotNull JsExpression instance, @NotNull JsExpression type) { + return new JsInvocation(kotlin(isTypeName), instance, type); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/expandIsCalls.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/expandIsCalls.kt new file mode 100644 index 00000000000..28173a5d34f --- /dev/null +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/expandIsCalls.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2015 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.utils + +import com.google.dart.compiler.backend.js.ast.* +import com.google.dart.compiler.backend.js.ast.metadata.TypeCheck +import com.google.dart.compiler.backend.js.ast.metadata.typeCheck +import org.jetbrains.kotlin.js.translate.context.TranslationContext +import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.* + +public fun expandIsCalls(node: JsNode, context: TranslationContext) { + val visitor = object : JsVisitorWithContextImpl() { + override fun visit(x: JsInvocation, ctx: JsContext<*>): Boolean { + val callee = x.getQualifier() as? JsInvocation + val instance = x.getArguments().firstOrNull() + val type = callee?.getArguments()?.firstOrNull() + + val replacement = when (callee?.typeCheck) { + TypeCheck.TYPEOF -> typeof(instance!!, type as JsStringLiteral) + TypeCheck.INSTANCEOF -> context.namer().isInstanceOf(instance!!, type!!) + else -> null + } + + if (replacement != null) { + ctx.replaceMe(replacement) + return false + } + + return super.visit(x, ctx) + } + } + + visitor.accept(node) +}