Simplified intrinsics matching in JS backend.

This commit is contained in:
Evgeny Gerashchenko
2013-11-07 23:34:04 +04:00
parent 28ef7495af
commit aa2ff87b47
3 changed files with 39 additions and 96 deletions
@@ -109,21 +109,28 @@ public class OverridingUtil {
return candidates; return candidates;
} }
public static <Descriptor extends CallableDescriptor> boolean overrides(@NotNull Descriptor f, @NotNull Descriptor g) { public static <D extends CallableDescriptor> boolean overrides(@NotNull D f, @NotNull D g) {
Set<CallableDescriptor> overriddenDescriptors = Sets.newHashSet();
getAllOverriddenDescriptors(f.getOriginal(), overriddenDescriptors);
CallableDescriptor originalG = g.getOriginal(); CallableDescriptor originalG = g.getOriginal();
for (CallableDescriptor overriddenFunction : overriddenDescriptors) { for (CallableDescriptor overriddenFunction : getAllOverriddenDescriptors(f)) {
if (originalG.equals(overriddenFunction.getOriginal())) return true; if (originalG.equals(overriddenFunction.getOriginal())) return true;
} }
return false; return false;
} }
private static void getAllOverriddenDescriptors(@NotNull CallableDescriptor current, @NotNull Set<CallableDescriptor> overriddenDescriptors) { public static Set<CallableDescriptor> getAllOverriddenDescriptors(CallableDescriptor f) {
if (overriddenDescriptors.contains(current)) return; Set<CallableDescriptor> overriddenDescriptors = Sets.newHashSet();
collectAllOverriddenDescriptors(f.getOriginal(), overriddenDescriptors);
return overriddenDescriptors;
}
private static void collectAllOverriddenDescriptors(
@NotNull CallableDescriptor current,
@NotNull Set<CallableDescriptor> result
) {
if (result.contains(current)) return;
for (CallableDescriptor descriptor : current.getOriginal().getOverriddenDescriptors()) { for (CallableDescriptor descriptor : current.getOriginal().getOverriddenDescriptors()) {
getAllOverriddenDescriptors(descriptor, overriddenDescriptors); collectAllOverriddenDescriptors(descriptor, result);
overriddenDescriptors.add(descriptor); result.add(descriptor);
} }
} }
@@ -179,9 +179,8 @@ public final class TopLevelFIF extends CompositeFIF {
add(pattern("jet", "Map", "get").checkOverridden(), NATIVE_MAP_GET); add(pattern("jet", "Map", "get").checkOverridden(), NATIVE_MAP_GET);
add(pattern("js", "set").receiverExists(), NATIVE_MAP_SET); add(pattern("js", "set").receiverExists(), NATIVE_MAP_SET);
String[] javaUtil = {"java", "util"}; 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));
add(pattern("js", "Json", "get"), ArrayFIF.GET_INTRINSIC); add(pattern("js", "Json", "get"), ArrayFIF.GET_INTRINSIC);
add(pattern("js", "Json", "set"), ArrayFIF.SET_INTRINSIC); add(pattern("js", "Json", "set"), ArrayFIF.SET_INTRINSIC);
@@ -18,17 +18,17 @@ 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.CallableDescriptor;
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;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.OverridingUtil;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.Namer;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Set;
public final class PatternBuilder { public final class PatternBuilder {
@@ -127,13 +127,9 @@ 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);
} }
public static class DescriptorPredicateImpl implements DescriptorPredicate { public static class DescriptorPredicateImpl implements DescriptorPredicate {
@@ -141,7 +137,6 @@ public final class PatternBuilder {
private boolean receiverParameterExists; private boolean receiverParameterExists;
private String[] root;
private boolean checkOverridden; private boolean checkOverridden;
public DescriptorPredicateImpl(String... names) { public DescriptorPredicateImpl(String... names) {
@@ -153,30 +148,14 @@ public final class PatternBuilder {
return this; return this;
} }
public DescriptorPredicateImpl root(String... root) {
this.root = root;
return this;
}
public DescriptorPredicateImpl checkOverridden() { public DescriptorPredicateImpl checkOverridden() {
this.checkOverridden = true; this.checkOverridden = true;
return this; return this;
} }
private boolean check(FunctionDescriptor functionDescriptor) { private boolean matches(@NotNull CallableDescriptor callable) {
DeclarationDescriptor descriptor = functionDescriptor.getContainingDeclaration(); DeclarationDescriptor descriptor = callable;
String[] list; int nameIndex = names.length - 1;
int nameIndex;
if (root == null) {
list = names;
nameIndex = list.length - 2;
}
else {
assert names.length == 1;
list = root;
nameIndex = list.length - 1;
}
do { do {
if (nameIndex == -1) { if (nameIndex == -1) {
return isRootNamespace(descriptor); return isRootNamespace(descriptor);
@@ -185,12 +164,12 @@ public final class PatternBuilder {
return false; return false;
} }
if (!descriptor.getName().asString().equals(list[nameIndex--])) { if (!descriptor.getName().asString().equals(names[nameIndex--])) {
return false; return false;
} }
} }
while ((descriptor = descriptor.getContainingDeclaration()) != null); while ((descriptor = descriptor.getContainingDeclaration()) != null);
return false; return true;
} }
@Override @Override
@@ -199,66 +178,24 @@ public final class PatternBuilder {
return false; return false;
} }
// avoid unwrap FAKE_OVERRIDE if (!(functionDescriptor.getContainingDeclaration() instanceof ClassDescriptor)) {
int nameIndex = names.length - 1; return matches(functionDescriptor);
if (!functionDescriptor.getName().asString().equals(names[nameIndex--])) {
return false;
} }
DeclarationDescriptor descriptor; for (CallableMemberDescriptor real : OverridingUtil.getOverriddenDeclarations(functionDescriptor)) {
if (functionDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { if (matches(real)) {
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;
}
if (!descriptor.getName().asString().equals(list[nameIndex--])) {
// we check overridden on any mismatch - we can have classes with equal name from different packages
return checkOverridden && checkOverridden(functionDescriptor);
}
}
return false;
}
private boolean checkOverridden(FunctionDescriptor functionDescriptor) {
Set<? extends FunctionDescriptor> overriddenDescriptors = functionDescriptor.getOverriddenDescriptors();
if (overriddenDescriptors.isEmpty()) {
return false;
}
for (FunctionDescriptor overridden : overriddenDescriptors) {
if (overridden.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
for (FunctionDescriptor realOverridden : overridden.getOverriddenDescriptors()) {
if (check(realOverridden) || checkOverridden(realOverridden)) {
return true;
}
}
}
else if (check(overridden) || checkOverridden(overridden)) {
return true; return true;
} }
} }
if (checkOverridden) {
for (CallableDescriptor overridden : OverridingUtil.getAllOverriddenDescriptors(functionDescriptor)) {
if (matches(overridden)) {
return true;
}
}
}
return false; return false;
} }
} }