initial implementation of as?

This commit is contained in:
Dmitry Jemerov
2011-05-13 15:08:57 +02:00
parent 1966d6d12c
commit fa52f5f513
5 changed files with 62 additions and 12 deletions
@@ -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) {
@@ -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");
}
}
}
@@ -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());
@@ -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());
}
@@ -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));
}
}