Merge remote branch 'origin/master'
This commit is contained in:
@@ -6,7 +6,8 @@ import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@@ -14,6 +15,7 @@ import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -210,6 +212,14 @@ public class ClassCodegen {
|
||||
iv.invokespecial(superClass, "<init>", /* TODO super constructor descriptor */"()V");
|
||||
}
|
||||
|
||||
HashSet<FunctionDescriptor> overriden = new HashSet<FunctionDescriptor>();
|
||||
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
||||
if (declaration instanceof JetFunction) {
|
||||
overriden.addAll(bindingContext.getFunctionDescriptor((JetFunction) declaration).getOverriddenFunctions());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int n = 0;
|
||||
for (JetDelegationSpecifier specifier : specifiers) {
|
||||
boolean delegateOnStack = specifier instanceof JetDelegatorToSuperCall && n > 0 ||
|
||||
@@ -267,7 +277,7 @@ public class ClassCodegen {
|
||||
JetClass superClass = (JetClass) bindingContext.getDeclarationPsiElement(superClassDescriptor);
|
||||
generateDelegates(aClass, superClass, v,
|
||||
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false),
|
||||
JetTypeMapper.jvmNameForInterface(superClassDescriptor)));
|
||||
JetTypeMapper.jvmNameForInterface(superClassDescriptor)), overriden);
|
||||
}
|
||||
|
||||
n++;
|
||||
@@ -364,7 +374,7 @@ public class ClassCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private void generateDelegates(JetClass inClass, JetClass toClass, ClassVisitor v, OwnerKind kind) {
|
||||
private void generateDelegates(JetClass inClass, JetClass toClass, ClassVisitor v, OwnerKind kind, Set<FunctionDescriptor> overriden) {
|
||||
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, standardLibrary, bindingContext);
|
||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, standardLibrary, bindingContext, functionCodegen);
|
||||
@@ -374,7 +384,9 @@ public class ClassCodegen {
|
||||
propertyCodegen.gen((JetProperty) declaration, kind);
|
||||
}
|
||||
else if (declaration instanceof JetFunction) {
|
||||
functionCodegen.gen((JetFunction) declaration, kind);
|
||||
if (!overriden.contains(bindingContext.getFunctionDescriptor((JetFunction) declaration))) {
|
||||
functionCodegen.gen((JetFunction) declaration, kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1268,9 +1268,6 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
else {
|
||||
JetTypeReference typeReference = expression.getRight();
|
||||
JetType jetType = bindingContext.resolveTypeReference(typeReference);
|
||||
if (jetType.getArguments().size() > 0) {
|
||||
throw new UnsupportedOperationException("don't know how to handle type arguments in as/as?");
|
||||
}
|
||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if (!(descriptor instanceof ClassDescriptor)) {
|
||||
throw new UnsupportedOperationException("don't know how to handle non-class types in as/as?");
|
||||
@@ -1278,8 +1275,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
Type type = typeMapper.jvmType((ClassDescriptor) descriptor, OwnerKind.INTERFACE);
|
||||
gen(expression.getLeft(), OBJECT_TYPE);
|
||||
if (opToken == JetTokens.AS_SAFE) {
|
||||
v.dup();
|
||||
v.instanceOf(type);
|
||||
generateInstanceOf(expression.getLeft(), jetType, true);
|
||||
Label isInstance = new Label();
|
||||
v.ifne(isInstance);
|
||||
v.pop();
|
||||
@@ -1288,7 +1284,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
myStack.push(StackValue.onStack(type));
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("as not yet implemented");
|
||||
throw new UnsupportedOperationException("'as' not yet implemented");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1307,22 +1303,32 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
}
|
||||
JetTypeReference typeReference = ((JetTypePattern) pattern).getTypeReference();
|
||||
JetType jetType = bindingContext.resolveTypeReference(typeReference);
|
||||
generateInstanceOf(expression.getLeftHandSide(), jetType, false);
|
||||
StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE);
|
||||
myStack.push(expression.isNot() ? StackValue.not(value) : value);
|
||||
}
|
||||
|
||||
private void generateInstanceOf(JetExpression expression, JetType jetType, boolean leaveExpressionOnStack) {
|
||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if (!(descriptor instanceof ClassDescriptor)) {
|
||||
throw new UnsupportedOperationException("don't know how to handle non-class types in is");
|
||||
throw new UnsupportedOperationException("don't know how to handle non-class types");
|
||||
}
|
||||
if (jetType.getArguments().size() > 0) {
|
||||
generateTypeInfo(jetType);
|
||||
gen(expression.getLeftHandSide(), OBJECT_TYPE);
|
||||
gen(expression, OBJECT_TYPE);
|
||||
if (leaveExpressionOnStack) {
|
||||
v.dupX1();
|
||||
}
|
||||
v.invokevirtual("jet/typeinfo/TypeInfo", "isInstance", "(Ljava/lang/Object;)Z");
|
||||
}
|
||||
else {
|
||||
gen(expression.getLeftHandSide(), OBJECT_TYPE);
|
||||
gen(expression, OBJECT_TYPE);
|
||||
if (leaveExpressionOnStack) {
|
||||
v.dup();
|
||||
}
|
||||
Type type = typeMapper.jvmType((ClassDescriptor) descriptor, OwnerKind.INTERFACE);
|
||||
v.instanceOf(type);
|
||||
}
|
||||
StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE);
|
||||
myStack.push(expression.isNot() ? StackValue.not(value) : value);
|
||||
}
|
||||
|
||||
private void generateTypeInfo(JetType jetType) {
|
||||
@@ -1330,9 +1336,8 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
if (declarationDescriptor instanceof TypeParameterDescriptor) {
|
||||
DeclarationDescriptor containingDeclaration = declarationDescriptor.getContainingDeclaration();
|
||||
if (containingDeclaration == contextType && contextType instanceof ClassDescriptor) {
|
||||
int index = indexOfTypeParameter((ClassDescriptor) contextType, (TypeParameterDescriptor) declarationDescriptor);
|
||||
loadTypeInfo((ClassDescriptor) contextType, v);
|
||||
v.iconst(index);
|
||||
v.iconst(((TypeParameterDescriptor) declarationDescriptor).getIndex());
|
||||
v.invokevirtual("jet/typeinfo/TypeInfo", "getTypeParameter", "(I)Ljet/typeinfo/TypeInfo;");
|
||||
return;
|
||||
}
|
||||
@@ -1361,15 +1366,6 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private int indexOfTypeParameter(ClassDescriptor classDescriptor, TypeParameterDescriptor typeParameterDescriptor) {
|
||||
List<TypeParameterDescriptor> parameters = classDescriptor.getTypeConstructor().getParameters();
|
||||
int index = parameters.indexOf(typeParameterDescriptor);
|
||||
if (index < 0) {
|
||||
throw new UnsupportedOperationException("can't find type parameter index");
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
private static class CompilationException extends RuntimeException {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
class Base() {
|
||||
public var v : Int
|
||||
}
|
||||
|
||||
class Left() : Base() {}
|
||||
class Right() : Base() {}
|
||||
|
||||
class D() : Left(), Right()
|
||||
|
||||
fun vl(l : Left) : Int = l.v
|
||||
fun vr(r : Right) : Int = r.v
|
||||
|
||||
fun box() : String {
|
||||
val d = new D()
|
||||
d.v = 42
|
||||
|
||||
if (d.v != 42) return "Fail #1"
|
||||
if (vl(d) != 42) return "Fail #2"
|
||||
if (vr(d) != 42) return "Fail #3"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
class Left() {}
|
||||
class Right() {
|
||||
virtual fun f() = 42
|
||||
}
|
||||
|
||||
class D() : Left(), Right() {
|
||||
override fun f() = 239
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
val r : Right = new Right()
|
||||
val d : D = new D()
|
||||
|
||||
if (r.f() != 42) return "Fail #1"
|
||||
if (d.f() != 239) return "Fail #2"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class Wrapper<T>() {
|
||||
fun castToSelf(wrapper: Any) = wrapper as? Wrapper<T>
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
val wrapper = new Wrapper<Int>()
|
||||
return wrapper.castToSelf(new Wrapper<String>())
|
||||
}
|
||||
@@ -36,6 +36,14 @@ public class ClassGenTest extends CodegenTestCase {
|
||||
blackBoxFile("classes/propertyDelegation.jet");
|
||||
}
|
||||
|
||||
public void testDiamondInheritance() throws Exception {
|
||||
blackBoxFile("classes/diamondInheritance.jet");
|
||||
}
|
||||
|
||||
public void testRightHandOverride() throws Exception {
|
||||
blackBoxFile("classes/rightHandOverride.jet");
|
||||
}
|
||||
|
||||
private static void checkInterface(Class aClass, Class ifs) {
|
||||
for (Class anInterface : aClass.getInterfaces()) {
|
||||
if (anInterface == ifs) return;
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.parsing.JetParsingTest;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.channels.NonWritableChannelException;
|
||||
import java.util.HashMap;
|
||||
|
||||
@@ -65,6 +65,12 @@ public class TypeInfoTest extends CodegenTestCase {
|
||||
assertFalse((Boolean) foo.invoke(null));
|
||||
}
|
||||
|
||||
public void testAsSafeWithGenerics() throws Exception {
|
||||
loadFile();
|
||||
Method foo = generateFunction();
|
||||
assertNull(foo.invoke(null));
|
||||
}
|
||||
|
||||
private Runnable newRunnable() {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user