fix for broken test. (this, receiver) handling normalized

This commit is contained in:
Alex Tkachman
2011-11-12 19:13:26 +02:00
parent 3fcb75ba1d
commit 396376c013
6 changed files with 121 additions and 77 deletions
@@ -1,7 +1,9 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
@@ -18,8 +20,9 @@ public class CallableMethod implements Callable {
private final Method signature;
private int invokeOpcode;
private final List<Type> valueParameterTypes;
private DeclarationDescriptor thisClass = null;
private DeclarationDescriptor receiverClass = null;
private ClassDescriptor thisClass = null;
private FunctionDescriptor receiverFunction = null;
private Type generateCalleeType = null;
public CallableMethod(String owner, Method signature, int invokeOpcode, List<Type> valueParameterTypes) {
@@ -45,11 +48,11 @@ public class CallableMethod implements Callable {
return valueParameterTypes;
}
public void setNeedsReceiver(@Nullable DeclarationDescriptor receiverClass) {
this.receiverClass = receiverClass;
public void setNeedsReceiver(@Nullable FunctionDescriptor receiverClass) {
this.receiverFunction = receiverClass;
}
public void setNeedsThis(@Nullable DeclarationDescriptor receiverClass) {
public void setNeedsThis(@Nullable ClassDescriptor receiverClass) {
this.thisClass = receiverClass;
}
@@ -78,10 +81,14 @@ public class CallableMethod implements Callable {
}
public boolean isNeedsReceiver() {
return receiverClass != null;
return receiverFunction != null;
}
public DeclarationDescriptor getThisClass() {
public ClassDescriptor getThisClass() {
return thisClass;
}
public FunctionDescriptor getReceiverFunction() {
return receiverFunction;
}
}
@@ -45,6 +45,17 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
return new Method("invoke", JetTypeMapper.TYPE_OBJECT, args);
}
public static CallableMethod asCallableMethod(FunctionDescriptor fd) {
Method descriptor = erasedInvokeSignature(fd);
String owner = getInternalClassName(fd);
final CallableMethod result = new CallableMethod(owner, descriptor, INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
if (fd.getReceiverParameter().exists()) {
result.setNeedsReceiver(fd);
}
result.requestGenerateCallee(Type.getObjectType(getInternalClassName(fd)));
return result;
}
public Method invokeSignature(FunctionDescriptor fd) {
return state.getTypeMapper().mapSignature("invoke", fd);
}
@@ -1,6 +1,7 @@
package org.jetbrains.jet.codegen;
import com.intellij.psi.util.PsiTreeUtil;
import gnu.trove.THashSet;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.JetClass;
@@ -13,6 +14,7 @@ import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* @author abreslav
@@ -142,4 +144,29 @@ public class CodegenUtil {
Modality.FINAL, Visibility.PUBLIC);
return invokeDescriptor;
}
public static boolean isSubclass(ClassDescriptor subClass, ClassDescriptor superClass) {
Set<JetType> allSuperTypes = new THashSet<JetType>();
addSuperTypes(subClass.getDefaultType(), allSuperTypes);
final DeclarationDescriptor superOriginal = superClass.getOriginal();
for (JetType superType : allSuperTypes) {
final DeclarationDescriptor descriptor = superType.getConstructor().getDeclarationDescriptor();
if (descriptor != null && superOriginal.equals(descriptor.getOriginal())) {
return true;
}
}
return false;
}
private static void addSuperTypes(JetType type, Set<JetType> set) {
set.add(type);
for (JetType jetType : type.getConstructor().getSupertypes()) {
addSuperTypes(jetType, set);
}
}
}
@@ -4,7 +4,6 @@ import com.intellij.openapi.editor.Document;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod;
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
@@ -15,7 +14,10 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.*;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.Label;
@@ -27,8 +29,6 @@ import org.objectweb.asm.commons.Method;
import java.util.*;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
/**
* @author max
* @author yole
@@ -79,17 +79,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
this.intrinsics = state.getIntrinsics();
}
private static CallableMethod asCallableMethod(FunctionDescriptor fd) {
Method descriptor = ClosureCodegen.erasedInvokeSignature(fd);
String owner = ClosureCodegen.getInternalClassName(fd);
final CallableMethod result = new CallableMethod(owner, descriptor, INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
if (fd.getReceiverParameter().exists()) {
result.setNeedsReceiver(fd.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor());
}
result.requestGenerateCallee(Type.getObjectType(ClosureCodegen.getInternalClassName(fd)));
return result;
}
public GenerationState getState() {
return state;
}
@@ -1021,7 +1010,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (expression.getParent() instanceof JetQualifiedExpression) {
final JetExpression receiverExpression = ((JetQualifiedExpression) expression.getParent()).getReceiverExpression();
if (receiverExpression instanceof JetSuperExpression) {
assert receiver == StackValue.none();
superCall = true;
receiver = StackValue.thisOrOuter(this, context.getThisDescriptor());
JetSuperExpression superExpression = (JetSuperExpression) receiverExpression;
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement);
@@ -1033,17 +1024,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
fd = c.getAccessor(fd);
superCall = false;
receiver = StackValue.thisOrOuter(this, enclosed);
}
}
}
}
Callable callableMethod = resolveToCallable(fd, superCall);
return invokeCallable(fd, callableMethod, expression, receiver);
}
@Nullable
private StackValue invokeCallable(DeclarationDescriptor fd, Callable callable, JetCallExpression expression, StackValue receiver) {
Callable callable = resolveToCallable(fd, superCall);
if (callable instanceof CallableMethod) {
final CallableMethod callableMethod = (CallableMethod) callable;
invokeMethodWithArguments(callableMethod, expression, receiver);
@@ -1079,11 +1066,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
CallableMethod callableMethod;
if (fd instanceof VariableAsFunctionDescriptor) {
assert !superCall;
callableMethod = asCallableMethod((FunctionDescriptor) fd);
callableMethod = ClosureCodegen.asCallableMethod((FunctionDescriptor) fd);
}
else if (fd instanceof ExpressionAsFunctionDescriptor) {
FunctionDescriptor invoke = CodegenUtil.createInvoke((ExpressionAsFunctionDescriptor) fd);
callableMethod = asCallableMethod(invoke);
callableMethod = ClosureCodegen.asCallableMethod(invoke);
}
else if (fd instanceof FunctionDescriptor) {
callableMethod = typeMapper.mapToCallableMethod((FunctionDescriptor) fd, superCall, OwnerKind.IMPLEMENTATION);
@@ -1108,17 +1095,30 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
public void invokeMethodWithArguments(CallableMethod callableMethod, JetCallElement expression, StackValue receiver) {
final Type calleeType = callableMethod.getGenerateCalleeType();
if (calleeType != null && expression instanceof JetCallExpression) {
assert !callableMethod.isNeedsThis();
gen(expression.getCalleeExpression(), calleeType);
}
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
assert resolvedCall != null;
FunctionDescriptor callableDescriptor = (FunctionDescriptor) resolvedCall.getResultingDescriptor();
boolean hasThis = resolvedCall.getThisObject().exists();
boolean hasReceiver = resolvedCall.getReceiverArgument().exists();
if (callableMethod.isNeedsThis()) {
if(callableMethod.isNeedsReceiver()) {
generateThisOrOuter((ClassDescriptor) callableMethod.getThisClass()).put(JetTypeMapper.TYPE_OBJECT, v);
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
generateFromResolvedCall(resolvedCall.getThisObject());
if(receiver == StackValue.none()) {
generateFromResolvedCall(resolvedCall.getReceiverArgument());
}
else {
receiver.put(typeMapper.mapType(callableMethod.getReceiverFunction().getReceiverParameter().getType()), v);
}
}
else {
if (receiver == StackValue.none()) {
generateThisOrOuter((ClassDescriptor) callableMethod.getThisClass()).put(JetTypeMapper.TYPE_OBJECT, v);
generateFromResolvedCall(resolvedCall.getThisObject());
}
else {
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
@@ -1128,13 +1128,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else {
if (callableMethod.isNeedsReceiver()) {
if (receiver == StackValue.none()) {
v.load(0, JetTypeMapper.TYPE_OBJECT);
generateFromResolvedCall(resolvedCall.getReceiverArgument());
}
else
receiver.put(callableMethod.getSignature().getArgumentTypes()[0], v);
}
}
int mask = pushMethodArguments(expression, callableMethod.getValueParameterTypes());
pushTypeArguments(expression);
if(mask == 0)
@@ -1143,6 +1143,24 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
callableMethod.invokeWithDefault(v, mask);
}
private void generateFromResolvedCall(ReceiverDescriptor descriptor) {
if(descriptor instanceof ClassReceiver) {
ClassReceiver classReceiver = (ClassReceiver) descriptor;
generateThisOrOuter((ClassDescriptor) classReceiver.getDeclarationDescriptor()).put(typeMapper.mapType(descriptor.getType()), v);
}
else if(descriptor instanceof ExtensionReceiver) {
ExtensionReceiver extensionReceiver = (ExtensionReceiver) descriptor;
generateReceiver((FunctionDescriptor) extensionReceiver.getDeclarationDescriptor()).put(typeMapper.mapType(descriptor.getType()), v);
}
else if(descriptor instanceof ExpressionReceiver) {
ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor;
genToJVMStack(expressionReceiver.getExpression());
}
else {
throw new UnsupportedOperationException();
}
}
private static JetExpression getReceiverForSelector(PsiElement expression) {
if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) {
final JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent();
@@ -1151,31 +1169,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return null;
}
private static boolean isSubclass(ClassDescriptor subClass, ClassDescriptor superClass) {
Set<JetType> allSuperTypes = new THashSet<JetType>();
addSuperTypes(subClass.getDefaultType(), allSuperTypes);
final DeclarationDescriptor superOriginal = superClass.getOriginal();
for (JetType superType : allSuperTypes) {
final DeclarationDescriptor descriptor = superType.getConstructor().getDeclarationDescriptor();
if (descriptor != null && superOriginal.equals(descriptor.getOriginal())) {
return true;
}
}
return false;
}
private static void addSuperTypes(JetType type, Set<JetType> set) {
set.add(type);
for (JetType jetType : type.getConstructor().getSupertypes()) {
addSuperTypes(jetType, set);
}
}
private StackValue generateReceiver(FunctionDescriptor descriptor) {
assert context instanceof CodegenContext.FunctionContext;
CodegenContext.FunctionContext cur = (CodegenContext.FunctionContext) context;
@@ -1184,21 +1177,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
return context.lookupInContext(descriptor, v, StackValue.local(0, JetTypeMapper.TYPE_OBJECT));
// assert context instanceof CodegenContext.FunctionContext;
// CodegenContext.FunctionContext cur = (CodegenContext.FunctionContext) context;
//
// StackValue result = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
// while (cur != null) {
//
// if (cur.getReceiverDescriptor() == descriptor) {
// return cur.getReceiverExpression(typeMapper);
// }
//
// result = cur.getOuterExpression(result);
// cur = cur.getOuterFunction();
// }
//
// throw new UnsupportedOperationException("Don't know how to generate receiver for " + descriptor);
}
public StackValue generateThisOrOuter(ClassDescriptor calleeContainingClass) {
@@ -1209,7 +1187,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if(cur instanceof CodegenContext.MethodContext && !(cur instanceof CodegenContext.ConstructorContext))
cur = cur.getParentContext();
if (isSubclass(cur.getThisDescriptor(), calleeContainingClass)) {
if (CodegenUtil.isSubclass(cur.getThisDescriptor(), calleeContainingClass)) {
Type type = typeMapper.mapType(calleeContainingClass.getDefaultType());
result.put(JetTypeMapper.TYPE_OBJECT, v);
return StackValue.onStack(type);
@@ -341,7 +341,7 @@ public class JetTypeMapper {
if(isInterface && superCall) {
descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, OwnerKind.TRAIT_IMPL);
}
thisClass = containingClass;
thisClass = (ClassDescriptor) functionParent;
}
else {
throw new UnsupportedOperationException("unknown function parent");
@@ -350,7 +350,7 @@ public class JetTypeMapper {
final CallableMethod result = new CallableMethod(owner, descriptor, invokeOpcode, valueParameterTypes);
result.setNeedsThis(thisClass);
if(functionDescriptor.getReceiverParameter().exists()) {
result.setNeedsReceiver(functionDescriptor.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor());
result.setNeedsReceiver(functionDescriptor);
}
return result;
@@ -1,6 +1,7 @@
package org.jetbrains.jet.codegen;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.Label;
@@ -239,6 +240,10 @@ public abstract class StackValue {
return new Composed(prefix, suffix);
}
public static StackValue thisOrOuter(ExpressionCodegen codegen, ClassDescriptor descriptor) {
return new ThisOuter(codegen, descriptor);
}
private static class None extends StackValue {
public static None INSTANCE = new None();
private None() {
@@ -817,4 +822,20 @@ public abstract class StackValue {
suffix.store(v);
}
}
private static class ThisOuter extends StackValue {
private ExpressionCodegen codegen;
private ClassDescriptor descriptor;
public ThisOuter(ExpressionCodegen codegen, ClassDescriptor descriptor) {
super(JetTypeMapper.TYPE_OBJECT);
this.codegen = codegen;
this.descriptor = descriptor;
}
@Override
public void put(Type type, InstructionAdapter v) {
codegen.generateThisOrOuter(descriptor);
}
}
}