diff --git a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java index 36975870014..92af8158517 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -73,7 +73,7 @@ public class ClassCodegen { ClassVisitor v = kind == OwnerKind.IMPLEMENTATION ? factory.forClassImplementation(descriptor) : factory.forClassDelegatingImplementation(descriptor); v.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, - JetTypeMapper.jvmName(descriptor, kind), + JetTypeMapper.jetJvmName(descriptor, kind), null, superClass, new String[] { "jet/JetObject", JetTypeMapper.jvmNameForInterface(descriptor) } @@ -113,7 +113,7 @@ public class ClassCodegen { else if (first instanceof JetDelegatorToSuperCall) { JetType superType = bindingContext.resolveTypeReference(first.getTypeReference()); ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); - return JetTypeMapper.jvmName(superClassDescriptor, kind); + return typeMapper.jvmName(superClassDescriptor, kind); } return "java/lang/Object"; @@ -177,7 +177,7 @@ public class ClassCodegen { final InstructionAdapter iv = new InstructionAdapter(mv); ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE, classDescriptor, kind); - String classname = JetTypeMapper.jvmName(classDescriptor, kind); + String classname = typeMapper.jvmName(classDescriptor, kind); final Type classType = Type.getType("L" + classname + ";"); if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) { diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 4260ee3e098..2071803269d 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -43,6 +43,7 @@ public class ExpressionCodegen extends JetVisitor { private static final String ITERATOR_NEXT_DESCRIPTOR = "()Ljava/lang/Object;"; private static final String INT_RANGE_CONSTRUCTOR_DESCRIPTOR = "(II)V"; + private static final Type OBJECT_TYPE = Type.getType(Object.class); private static final Type ITERATOR_TYPE = Type.getType(Iterator.class); private static final Type INT_RANGE_TYPE = Type.getType(IntRange.class); private static final Type JET_OBJECT_TYPE = Type.getType(JetObject.class); @@ -501,11 +502,11 @@ public class ExpressionCodegen extends JetVisitor { String fieldOwner; String interfaceOwner; if (isInsideClass || isStatic) { - fieldOwner = interfaceOwner = JetTypeMapper.getOwner(propertyDescriptor, contextKind); + fieldOwner = interfaceOwner = typeMapper.getOwner(propertyDescriptor, contextKind); } else { fieldOwner = null; - interfaceOwner = JetTypeMapper.getOwner(propertyDescriptor, OwnerKind.INTERFACE); + interfaceOwner = typeMapper.getOwner(propertyDescriptor, OwnerKind.INTERFACE); } return StackValue.property(propertyDescriptor.getName(), fieldOwner, interfaceOwner, typeMapper.mapType(outType), isStatic, getter, setter); @@ -1201,7 +1202,7 @@ public class ExpressionCodegen extends JetVisitor { v.load(0, JetTypeMapper.jetImplementationType(contextClass)); } else if (contextKind == OwnerKind.DELEGATING_IMPLEMENTATION) { - v.getfield(JetTypeMapper.jvmName(contextClass, contextKind), "$this", JetTypeMapper.jetInterfaceType(contextClass).getDescriptor()); + v.getfield(typeMapper.jvmName(contextClass, contextKind), "$this", JetTypeMapper.jetInterfaceType(contextClass).getDescriptor()); } else { throw new UnsupportedOperationException("Unknown kind: " + contextKind); @@ -1242,11 +1243,35 @@ public class ExpressionCodegen extends JetVisitor { @Override public void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression) { JetSimpleNameExpression operationSign = expression.getOperationSign(); - if (operationSign.getReferencedNameElementType() == JetTokens.COLON) { + IElementType opToken = operationSign.getReferencedNameElementType(); + if (opToken == JetTokens.COLON) { gen(expression.getLeft()); } else { - throw new UnsupportedOperationException("should generate a cast, but don't know how"); + 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?"); + } + Type type = typeMapper.jvmType((ClassDescriptor) descriptor, OwnerKind.INTERFACE); + gen(expression.getLeft(), OBJECT_TYPE); + if (opToken == JetTokens.AS_SAFE) { + v.dup(); + v.instanceOf(type); + Label isInstance = new Label(); + v.ifne(isInstance); + v.pop(); + v.aconst(null); + v.mark(isInstance); + myStack.push(StackValue.onStack(type)); + } + else { + throw new UnsupportedOperationException("as not yet implemented"); + } } } diff --git a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java index c7cb69c4c82..a32aefb4913 100644 --- a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -32,7 +32,15 @@ public class JetTypeMapper { return psiClass.getQualifiedName().replace(".", "/"); } - static String jvmName(ClassDescriptor jetClass, OwnerKind kind) { + public String jvmName(ClassDescriptor jetClass, OwnerKind kind) { + PsiElement declaration = bindingContext.getDeclarationPsiElement(jetClass); + if (declaration instanceof PsiClass) { + return jvmName((PsiClass) declaration); + } + return jetJvmName(jetClass, kind); + } + + public static String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) { if (kind == OwnerKind.INTERFACE) { return jvmNameForInterface(jetClass); } @@ -48,6 +56,10 @@ public class JetTypeMapper { } } + public Type jvmType(ClassDescriptor jetClass, OwnerKind kind) { + return Type.getType("L" + jvmName(jetClass, kind) + ";"); + } + static Type psiClassType(PsiClass psiClass) { return Type.getType("L" + jvmName(psiClass) + ";"); } @@ -84,7 +96,7 @@ public class JetTypeMapper { return jvmNameForInterface(descriptor) + "$$DImpl"; } - static String getOwner(DeclarationDescriptor descriptor, OwnerKind kind) { + public String getOwner(DeclarationDescriptor descriptor, OwnerKind kind) { String owner; if (descriptor.getContainingDeclaration() instanceof NamespaceDescriptor) { owner = jvmName((NamespaceDescriptor) descriptor.getContainingDeclaration()); diff --git a/idea/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/idea/src/org/jetbrains/jet/codegen/PropertyCodegen.java index 3efba079165..dcdead60d80 100644 --- a/idea/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -160,7 +160,7 @@ public class PropertyCodegen { } else { iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.GETSTATIC : Opcodes.GETFIELD, - JetTypeMapper.getOwner(propertyDescriptor, kind), propertyDescriptor.getName(), + mapper.getOwner(propertyDescriptor, kind), propertyDescriptor.getName(), type.getDescriptor()); } iv.areturn(type); @@ -206,7 +206,7 @@ public class PropertyCodegen { else { iv.load(paramCode, type); iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, - JetTypeMapper.getOwner(propertyDescriptor, kind), propertyDescriptor.getName(), + mapper.getOwner(propertyDescriptor, kind), propertyDescriptor.getName(), type.getDescriptor()); } diff --git a/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java b/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java index bc316608e86..cd9773c6beb 100644 --- a/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/TypeInfoTest.java @@ -28,5 +28,18 @@ public class TypeInfoTest extends CodegenTestCase { TypeInfo typeInfo = (TypeInfo) foo.invoke(null); assertNotNull(typeInfo); } + + public void testAsSafeOperator() throws Exception { + loadText("fun foo(x: Any) = x as? Runnable"); + System.out.println(generateToText()); + Method foo = generateFunction(); + assertNull(foo.invoke(null, new Object())); + Runnable r = new Runnable() { + @Override + public void run() { + } + }; + assertSame(r, foo.invoke(null, r)); + } }