From 678f6601dd080c123c9c722d4559c929338cc59e Mon Sep 17 00:00:00 2001 From: develar Date: Tue, 6 Aug 2013 17:24:48 +0400 Subject: [PATCH] JS backend: made as intrinsic map accessing methods and fixed accessing to native map. --- .../test/semantics/NativeInteropTest.java | 4 + .../functions/factories/ArrayFIF.java | 4 +- .../functions/factories/TopLevelFIF.java | 115 ++++++++++++++++-- .../testFiles/native/cases/kt2323.kt | 13 ++ .../testFiles/native/native/kt2323.js | 16 +++ 5 files changed, 141 insertions(+), 11 deletions(-) create mode 100644 js/js.translator/testFiles/native/cases/kt2323.kt create mode 100644 js/js.translator/testFiles/native/native/kt2323.js diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/NativeInteropTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/NativeInteropTest.java index 6c67e4f7f88..d9657d1e6e6 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/NativeInteropTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/NativeInteropTest.java @@ -80,4 +80,8 @@ public final class NativeInteropTest extends SingleFileTranslationTest { public void testKt_2388() throws Exception { fooBoxTest(); } + + public void testKt2323() throws Exception { + fooBoxTest(); + } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/ArrayFIF.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/ArrayFIF.java index 92161cd83bd..601683c9475 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/ArrayFIF.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/ArrayFIF.java @@ -99,7 +99,7 @@ public final class ArrayFIF extends CompositeFIF { }; @NotNull - private static final FunctionIntrinsic GET_INTRINSIC = new FunctionIntrinsic() { + public static final FunctionIntrinsic GET_INTRINSIC = new FunctionIntrinsic() { @NotNull @Override public JsExpression apply(@Nullable JsExpression receiver, @@ -113,7 +113,7 @@ public final class ArrayFIF extends CompositeFIF { }; @NotNull - private static final FunctionIntrinsic SET_INTRINSIC = new FunctionIntrinsic() { + public static final FunctionIntrinsic SET_INTRINSIC = new FunctionIntrinsic() { @NotNull @Override public JsExpression apply(@Nullable JsExpression receiver, diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/TopLevelFIF.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/TopLevelFIF.java index 7ad6599c655..314f234bd6f 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/TopLevelFIF.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/functions/factories/TopLevelFIF.java @@ -23,6 +23,13 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetQualifiedExpression; +import org.jetbrains.jet.lang.psi.JetReferenceExpression; +import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.intrinsic.functions.basic.BuiltInFunctionIntrinsic; @@ -31,6 +38,8 @@ import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic; import org.jetbrains.k2js.translate.intrinsic.functions.patterns.DescriptorPredicate; import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate; import org.jetbrains.k2js.translate.reference.CallTranslator; +import org.jetbrains.k2js.translate.utils.AnnotationsUtils; +import org.jetbrains.k2js.translate.utils.BindingUtils; import java.util.List; @@ -54,6 +63,100 @@ public final class TopLevelFIF extends CompositeFIF { return receiver; } }; + + private static final FunctionIntrinsic NATIVE_MAP_GET = new NativeMapGetSet() { + @NotNull + @Override + protected String operation() { + return "get"; + } + + @Nullable + @Override + protected ExpressionReceiver getExpressionReceiver(@NotNull ResolvedCall resolvedCall) { + ReceiverValue result = resolvedCall.getThisObject(); + return result instanceof ExpressionReceiver ? (ExpressionReceiver) result : null; + } + + @Override + protected JsExpression asArrayAccess( + @NotNull JsExpression receiver, + @NotNull List arguments, + @NotNull TranslationContext context + ) { + return ArrayFIF.GET_INTRINSIC.apply(receiver, arguments, context); + } + }; + + private static final FunctionIntrinsic NATIVE_MAP_SET = new NativeMapGetSet() { + @NotNull + @Override + protected String operation() { + return "put"; + } + + @Nullable + @Override + protected ExpressionReceiver getExpressionReceiver(@NotNull ResolvedCall resolvedCall) { + ReceiverValue result = resolvedCall.getReceiverArgument(); + return result instanceof ExpressionReceiver ? (ExpressionReceiver) result : null; + } + + @Override + protected JsExpression asArrayAccess( + @NotNull JsExpression receiver, + @NotNull List arguments, + @NotNull TranslationContext context + ) { + return ArrayFIF.SET_INTRINSIC.apply(receiver, arguments, context); + } + }; + + private abstract static class NativeMapGetSet extends CallParametersAwareFunctionIntrinsic { + @NotNull + protected abstract String operation(); + + @Nullable + protected abstract ExpressionReceiver getExpressionReceiver(@NotNull ResolvedCall resolvedCall); + + protected abstract JsExpression asArrayAccess( + @NotNull JsExpression receiver, + @NotNull List arguments, + @NotNull TranslationContext context + ); + + @NotNull + @Override + public JsExpression apply(@NotNull CallTranslator callTranslator, @NotNull List arguments, @NotNull TranslationContext context) { + ExpressionReceiver expressionReceiver = getExpressionReceiver(callTranslator.getResolvedCall()); + JsExpression thisOrReceiver = callTranslator.getCallParameters().getThisOrReceiverOrNull(); + assert thisOrReceiver != null; + if (expressionReceiver != null) { + JetExpression expression = expressionReceiver.getExpression(); + JetReferenceExpression referenceExpression = null; + if (expression instanceof JetReferenceExpression) { + referenceExpression = (JetReferenceExpression) expression; + } + else if (expression instanceof JetQualifiedExpression) { + JetExpression candidate = ((JetQualifiedExpression) expression).getReceiverExpression(); + if (candidate instanceof JetReferenceExpression) { + referenceExpression = (JetReferenceExpression) candidate; + } + } + + if (referenceExpression != null) { + DeclarationDescriptor candidate = BindingUtils.getDescriptorForReferenceExpression(context.bindingContext(), + referenceExpression); + if (candidate instanceof PropertyDescriptor && AnnotationsUtils.isNativeObject(candidate)) { + return asArrayAccess(thisOrReceiver, arguments, context); + } + } + } + + return new JsInvocation(new JsNameRef(operation(), thisOrReceiver), arguments); + } + } + @NotNull public static final FunctionIntrinsicFactory INSTANCE = new TopLevelFIF(); @@ -95,14 +198,8 @@ public final class TopLevelFIF extends CompositeFIF { } ); - add(pattern("java", "util", "set").receiverExists(true), new FunctionIntrinsic() { - @NotNull - @Override - public JsExpression apply( - @Nullable JsExpression receiver, @NotNull List arguments, @NotNull TranslationContext context - ) { - return new JsInvocation(new JsNameRef("put", receiver), arguments); - } - }); + add(pattern("java", "util", "set").receiverExists(true), NATIVE_MAP_SET); + add(pattern("jet", "Map", "get"), NATIVE_MAP_GET); + add(pattern("java", "util", "HashMap", "get"), NATIVE_MAP_GET); } } diff --git a/js/js.translator/testFiles/native/cases/kt2323.kt b/js/js.translator/testFiles/native/cases/kt2323.kt new file mode 100644 index 00000000000..cb120f4b580 --- /dev/null +++ b/js/js.translator/testFiles/native/cases/kt2323.kt @@ -0,0 +1,13 @@ +package foo + +import java.util.* + +native +val classes: Map = noImpl +native +val classesMutable: HashMap = noImpl + +fun box(): Boolean { + classesMutable["why"] = "?" + return classes["answer"] == 42 && classesMutable["why"] == "?" +} diff --git a/js/js.translator/testFiles/native/native/kt2323.js b/js/js.translator/testFiles/native/native/kt2323.js new file mode 100644 index 00000000000..bb266af9a59 --- /dev/null +++ b/js/js.translator/testFiles/native/native/kt2323.js @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2013 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. + */ +var classes = {"answer": 42}, classesMutable = {};