JS backend: refactoring
- add KotlinFunctionIntrinsic; - remove CallStandardMethodIntrinsic - rename TranslationUtils#generateCallArgumentList to TranslationUtils#generateInvocationArguments; - add to PatternBuilder#pattern with root(prefix) parameter.
This commit is contained in:
-71
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.k2js.translate.intrinsic.functions.basic;
|
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsInvocation;
|
|
||||||
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
|
||||||
import com.intellij.util.SmartList;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.jetbrains.k2js.translate.utils.ErrorReportingUtils.atLocation;
|
|
||||||
|
|
||||||
public final class CallStandardMethodIntrinsic extends FunctionIntrinsic {
|
|
||||||
@NotNull
|
|
||||||
private final JsNameRef methodName;
|
|
||||||
|
|
||||||
private final boolean receiverShouldBeNotNull;
|
|
||||||
private final int expectedParamsNumber;
|
|
||||||
|
|
||||||
public CallStandardMethodIntrinsic(@NotNull JsNameRef methodName, boolean receiverShouldBeNotNull, int expectedParamsNumber) {
|
|
||||||
this.methodName = methodName;
|
|
||||||
this.receiverShouldBeNotNull = receiverShouldBeNotNull;
|
|
||||||
this.expectedParamsNumber = expectedParamsNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public JsExpression apply(@Nullable JsExpression receiver,
|
|
||||||
@NotNull List<JsExpression> arguments,
|
|
||||||
@NotNull TranslationContext context) {
|
|
||||||
assert (receiver != null == receiverShouldBeNotNull);
|
|
||||||
assert arguments.size() == expectedParamsNumber : errorMessage(receiver, arguments);
|
|
||||||
return new JsInvocation(methodName, composeArguments(receiver, arguments));
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private String errorMessage(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments) {
|
|
||||||
return "Incorrect number of arguments " + arguments.size() + " when expected " + expectedParamsNumber + " on method " + methodName + " " +
|
|
||||||
atLocation(receiver, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static List<JsExpression> composeArguments(@Nullable JsExpression receiver, @NotNull List<JsExpression> arguments) {
|
|
||||||
if (receiver != null) {
|
|
||||||
List<JsExpression> args = new SmartList<JsExpression>(receiver);
|
|
||||||
args.addAll(arguments);
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return arguments;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+6
-8
@@ -19,7 +19,6 @@ package org.jetbrains.k2js.translate.intrinsic.functions.factories;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsArrayAccess;
|
import com.google.dart.compiler.backend.js.ast.JsArrayAccess;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
@@ -27,7 +26,6 @@ import org.jetbrains.jet.lang.types.lang.PrimitiveType;
|
|||||||
import org.jetbrains.k2js.translate.context.Namer;
|
import org.jetbrains.k2js.translate.context.Namer;
|
||||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.k2js.translate.intrinsic.functions.basic.BuiltInPropertyIntrinsic;
|
import org.jetbrains.k2js.translate.intrinsic.functions.basic.BuiltInPropertyIntrinsic;
|
||||||
import org.jetbrains.k2js.translate.intrinsic.functions.basic.CallStandardMethodIntrinsic;
|
|
||||||
import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic;
|
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.DescriptorPredicate;
|
||||||
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate;
|
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate;
|
||||||
@@ -138,12 +136,12 @@ public final class ArrayFIF extends CompositeFIF {
|
|||||||
add(pattern(ARRAYS, "get"), GET_INTRINSIC);
|
add(pattern(ARRAYS, "get"), GET_INTRINSIC);
|
||||||
add(pattern(ARRAYS, "set"), SET_INTRINSIC);
|
add(pattern(ARRAYS, "set"), SET_INTRINSIC);
|
||||||
add(pattern(ARRAYS, "<get-size>"), ARRAY_LENGTH_INTRINSIC);
|
add(pattern(ARRAYS, "<get-size>"), ARRAY_LENGTH_INTRINSIC);
|
||||||
add(pattern(ARRAYS, "<get-indices>"), new CallStandardMethodIntrinsic(new JsNameRef("arrayIndices", "Kotlin"), true, 0));
|
add(pattern(ARRAYS, "<get-indices>"), new KotlinFunctionIntrinsic("arrayIndices"));
|
||||||
add(pattern(ARRAYS, "iterator"), new CallStandardMethodIntrinsic(new JsNameRef("arrayIterator", "Kotlin"), true, 0));
|
add(pattern(ARRAYS, "iterator"), new KotlinFunctionIntrinsic("arrayIterator"));
|
||||||
add(pattern(ARRAY, "<init>"), new CallStandardMethodIntrinsic(new JsNameRef("arrayFromFun", "Kotlin"), false, 2));
|
add(pattern(ARRAY, "<init>"), new KotlinFunctionIntrinsic("arrayFromFun"));
|
||||||
add(pattern(NUMBER_ARRAY, "<init>"), new CallStandardMethodIntrinsic(new JsNameRef("numberArrayOfSize", "Kotlin"), false, 1));
|
add(pattern(NUMBER_ARRAY, "<init>"),new KotlinFunctionIntrinsic("numberArrayOfSize"));
|
||||||
add(pattern(CHAR_ARRAY, "<init>"), new CallStandardMethodIntrinsic(new JsNameRef("charArrayOfSize", "Kotlin"), false, 1));
|
add(pattern(CHAR_ARRAY, "<init>"), new KotlinFunctionIntrinsic("charArrayOfSize"));
|
||||||
add(pattern(BOOLEAN_ARRAY, "<init>"), new CallStandardMethodIntrinsic(new JsNameRef("booleanArrayOfSize", "Kotlin"), false, 1));
|
add(pattern(BOOLEAN_ARRAY, "<init>"), new KotlinFunctionIntrinsic("booleanArrayOfSize"));
|
||||||
add(ARRAY_FACTORY_METHODS, ARRAY_INTRINSIC);
|
add(ARRAY_FACTORY_METHODS, ARRAY_INTRINSIC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
package org.jetbrains.k2js.translate.intrinsic.functions.factories;
|
||||||
|
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsInvocation;
|
||||||
|
import com.google.dart.compiler.backend.js.ast.JsNameRef;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.k2js.translate.context.Namer;
|
||||||
|
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||||
|
import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic;
|
||||||
|
import org.jetbrains.k2js.translate.utils.TranslationUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class KotlinFunctionIntrinsic extends FunctionIntrinsic {
|
||||||
|
@NotNull
|
||||||
|
private final JsNameRef function;
|
||||||
|
|
||||||
|
public KotlinFunctionIntrinsic(@NotNull String functionName) {
|
||||||
|
function = new JsNameRef(functionName, Namer.KOTLIN_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public JsExpression apply(
|
||||||
|
@Nullable JsExpression receiver,
|
||||||
|
@NotNull List<JsExpression> arguments,
|
||||||
|
@NotNull TranslationContext context
|
||||||
|
) {
|
||||||
|
return new JsInvocation(function, receiver == null ? arguments : TranslationUtils.generateInvocationArguments(receiver, arguments));
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-9
@@ -36,7 +36,6 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
|||||||
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
|
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
|
||||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.k2js.translate.intrinsic.functions.basic.BuiltInFunctionIntrinsic;
|
import org.jetbrains.k2js.translate.intrinsic.functions.basic.BuiltInFunctionIntrinsic;
|
||||||
import org.jetbrains.k2js.translate.intrinsic.functions.basic.CallStandardMethodIntrinsic;
|
|
||||||
import org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic;
|
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.DescriptorPredicate;
|
||||||
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate;
|
import org.jetbrains.k2js.translate.intrinsic.functions.patterns.NamePredicate;
|
||||||
@@ -49,11 +48,11 @@ import java.util.List;
|
|||||||
|
|
||||||
import static org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic.CallParametersAwareFunctionIntrinsic;
|
import static org.jetbrains.k2js.translate.intrinsic.functions.basic.FunctionIntrinsic.CallParametersAwareFunctionIntrinsic;
|
||||||
import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern;
|
import static org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder.pattern;
|
||||||
import static org.jetbrains.k2js.translate.utils.TranslationUtils.generateCallArgumentList;
|
import static org.jetbrains.k2js.translate.utils.TranslationUtils.generateInvocationArguments;
|
||||||
|
|
||||||
public final class TopLevelFIF extends CompositeFIF {
|
public final class TopLevelFIF extends CompositeFIF {
|
||||||
@NotNull
|
@NotNull
|
||||||
public static final CallStandardMethodIntrinsic EQUALS = new CallStandardMethodIntrinsic(new JsNameRef("equals", "Kotlin"), true, 1);
|
public static final KotlinFunctionIntrinsic EQUALS = new KotlinFunctionIntrinsic("equals");
|
||||||
@NotNull
|
@NotNull
|
||||||
private static final FunctionIntrinsic RETURN_RECEIVER_INTRINSIC = new FunctionIntrinsic() {
|
private static final FunctionIntrinsic RETURN_RECEIVER_INTRINSIC = new FunctionIntrinsic() {
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -124,7 +123,7 @@ public final class TopLevelFIF extends CompositeFIF {
|
|||||||
add(pattern("jet", "equals").receiverExists(true), EQUALS);
|
add(pattern("jet", "equals").receiverExists(true), EQUALS);
|
||||||
add(pattern(NamePredicate.PRIMITIVE_NUMBERS, "equals"), EQUALS);
|
add(pattern(NamePredicate.PRIMITIVE_NUMBERS, "equals"), EQUALS);
|
||||||
add(pattern("String|Boolean|Char|Number.equals"), EQUALS);
|
add(pattern("String|Boolean|Char|Number.equals"), EQUALS);
|
||||||
add(pattern("jet", "arrayOfNulls"), new CallStandardMethodIntrinsic(new JsNameRef("nullArray", "Kotlin"), false, 1));
|
add(pattern("jet", "arrayOfNulls"), new KotlinFunctionIntrinsic("nullArray"));
|
||||||
add(pattern("jet", "iterator").receiverExists(true), RETURN_RECEIVER_INTRINSIC);
|
add(pattern("jet", "iterator").receiverExists(true), RETURN_RECEIVER_INTRINSIC);
|
||||||
add(new DescriptorPredicate() {
|
add(new DescriptorPredicate() {
|
||||||
@Override
|
@Override
|
||||||
@@ -155,18 +154,19 @@ public final class TopLevelFIF extends CompositeFIF {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new JsInvocation(new JsNameRef("call", callTranslator.getCallParameters().getFunctionReference()),
|
return new JsInvocation(new JsNameRef("call", callTranslator.getCallParameters().getFunctionReference()),
|
||||||
generateCallArgumentList(thisExpression, arguments));
|
generateInvocationArguments(thisExpression, arguments));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
add(pattern("java", "util", "set").receiverExists(true), NATIVE_MAP_SET);
|
String[] javaUtil = {"java", "util"};
|
||||||
|
add(pattern(javaUtil, "set").receiverExists(true), NATIVE_MAP_SET);
|
||||||
add(pattern("jet", "Map", "get"), NATIVE_MAP_GET);
|
add(pattern("jet", "Map", "get"), NATIVE_MAP_GET);
|
||||||
add(pattern("java", "util", "HashMap", "get"), NATIVE_MAP_GET);
|
add(pattern(javaUtil, "HashMap", "get"), NATIVE_MAP_GET);
|
||||||
|
|
||||||
add(pattern("java", "util", "HashMap", "<init>"), new MapSelectImplementationIntrinsic(false));
|
add(pattern(javaUtil, "HashMap", "<init>"), new MapSelectImplementationIntrinsic(false));
|
||||||
add(pattern("java", "util", "HashSet", "<init>"), new MapSelectImplementationIntrinsic(true));
|
add(pattern(javaUtil, "HashSet", "<init>"), new MapSelectImplementationIntrinsic(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract static class NativeMapGetSet extends CallParametersAwareFunctionIntrinsic {
|
private abstract static class NativeMapGetSet extends CallParametersAwareFunctionIntrinsic {
|
||||||
|
|||||||
+45
-7
@@ -18,6 +18,7 @@ package org.jetbrains.k2js.translate.intrinsic.functions.patterns;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||||
@@ -125,6 +126,11 @@ public final class PatternBuilder {
|
|||||||
return new DescriptorPredicateImpl(names);
|
return new DescriptorPredicateImpl(names);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static DescriptorPredicateImpl pattern(@NotNull String[] root, @NotNull String... names) {
|
||||||
|
return new DescriptorPredicateImpl(names).root(root);
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean isRootNamespace(DeclarationDescriptor declarationDescriptor) {
|
private static boolean isRootNamespace(DeclarationDescriptor declarationDescriptor) {
|
||||||
return declarationDescriptor instanceof NamespaceDescriptor && DescriptorUtils.isRootNamespace((NamespaceDescriptor) declarationDescriptor);
|
return declarationDescriptor instanceof NamespaceDescriptor && DescriptorUtils.isRootNamespace((NamespaceDescriptor) declarationDescriptor);
|
||||||
}
|
}
|
||||||
@@ -134,6 +140,8 @@ public final class PatternBuilder {
|
|||||||
|
|
||||||
private boolean receiverParameterExists;
|
private boolean receiverParameterExists;
|
||||||
|
|
||||||
|
private String[] root;
|
||||||
|
|
||||||
public DescriptorPredicateImpl(String... names) {
|
public DescriptorPredicateImpl(String... names) {
|
||||||
this.names = names;
|
this.names = names;
|
||||||
}
|
}
|
||||||
@@ -143,24 +151,54 @@ public final class PatternBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DescriptorPredicateImpl root(String... root) {
|
||||||
|
this.root = root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(@NotNull FunctionDescriptor functionDescriptor) {
|
public boolean apply(@NotNull FunctionDescriptor functionDescriptor) {
|
||||||
if ((functionDescriptor.getReceiverParameter() == null) == receiverParameterExists) {
|
if ((functionDescriptor.getReceiverParameter() == null) == receiverParameterExists) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclarationDescriptor descriptor = functionDescriptor;
|
// avoid unwrap FAKE_OVERRIDE
|
||||||
int nameIndex = names.length - 1;
|
int nameIndex = names.length - 1;
|
||||||
do {
|
if (!functionDescriptor.getName().asString().equals(names[nameIndex--])) {
|
||||||
if (!descriptor.getName().asString().equals(names[nameIndex--])) {
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeclarationDescriptor descriptor;
|
||||||
|
if (functionDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||||
|
assert functionDescriptor.getOverriddenDescriptors().size() > 0;
|
||||||
|
descriptor = functionDescriptor.getOverriddenDescriptors().iterator().next();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
descriptor = functionDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] list = names;
|
||||||
|
while ((descriptor = descriptor.getContainingDeclaration()) != null) {
|
||||||
|
if (nameIndex == -1) {
|
||||||
|
if (isRootNamespace(descriptor)) {
|
||||||
|
return list == root || root == null;
|
||||||
|
}
|
||||||
|
else if (root == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nameIndex = root.length - 1;
|
||||||
|
list = root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (isRootNamespace(descriptor)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
descriptor = descriptor.getContainingDeclaration();
|
|
||||||
if (nameIndex == -1) {
|
if (!descriptor.getName().asString().equals(list[nameIndex--])) {
|
||||||
return isRootNamespace(descriptor);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (descriptor != null && !isRootNamespace(descriptor));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ public final class CallTranslator extends AbstractTranslator {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private List<JsExpression> generateCallArgumentList(@NotNull JsExpression receiver) {
|
private List<JsExpression> generateCallArgumentList(@NotNull JsExpression receiver) {
|
||||||
return TranslationUtils.generateCallArgumentList(receiver, arguments);
|
return TranslationUtils.generateInvocationArguments(receiver, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ public final class TranslationUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static List<JsExpression> generateCallArgumentList(@NotNull JsExpression receiver, @NotNull List<JsExpression> arguments) {
|
public static List<JsExpression> generateInvocationArguments(@NotNull JsExpression receiver, @NotNull List<JsExpression> arguments) {
|
||||||
if (arguments.isEmpty()) {
|
if (arguments.isEmpty()) {
|
||||||
return Collections.singletonList(receiver);
|
return Collections.singletonList(receiver);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user