Merge remote branch 'origin/master'
This commit is contained in:
@@ -3,7 +3,6 @@ package org.jetbrains.jet.codegen;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import jet.typeinfo.TypeInfo;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -28,8 +27,6 @@ public class ClassCodegen {
|
||||
private final Codegens factory;
|
||||
private final JetTypeMapper typeMapper;
|
||||
|
||||
private static final Type TYPEINFO_TYPE = Type.getType(TypeInfo.class);
|
||||
|
||||
public ClassCodegen(Project project, Codegens factory, BindingContext bindingContext) {
|
||||
this.project = project;
|
||||
this.factory = factory;
|
||||
@@ -73,19 +70,20 @@ 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) }
|
||||
);
|
||||
|
||||
v.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
||||
int typeinfoStatic = descriptor.getTypeConstructor().getParameters().size() > 0 ? 0 : Opcodes.ACC_STATIC;
|
||||
v.visitField(Opcodes.ACC_PRIVATE | typeinfoStatic, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
||||
|
||||
generateStaticInitializer(descriptor, v);
|
||||
|
||||
generatePrimaryConstructor(aClass, v, kind);
|
||||
|
||||
generateGetTypeInfo(aClass, v);
|
||||
generateGetTypeInfo(descriptor, v);
|
||||
|
||||
generateClassBody(aClass, v, kind);
|
||||
|
||||
@@ -113,7 +111,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 +175,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) {
|
||||
@@ -193,6 +191,17 @@ public class ClassCodegen {
|
||||
frameMap.enter(parameter, argTypes[i].getSize());
|
||||
}
|
||||
|
||||
int firstTypeParameter = -1;
|
||||
int typeParamCount = classDescriptor.getTypeConstructor().getParameters().size();
|
||||
if (kind == OwnerKind.IMPLEMENTATION) {
|
||||
if (typeParamCount > 0) {
|
||||
firstTypeParameter = frameMap.enterTemp();
|
||||
for (int i = 1; i < typeParamCount; i++) {
|
||||
frameMap.enterTemp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<JetDelegationSpecifier> specifiers = aClass.getDelegationSpecifiers();
|
||||
|
||||
if (specifiers.isEmpty() || !(specifiers.get(0) instanceof JetDelegatorToSuperCall)) {
|
||||
@@ -264,6 +273,10 @@ public class ClassCodegen {
|
||||
n++;
|
||||
}
|
||||
|
||||
if (firstTypeParameter > 0 && kind == OwnerKind.IMPLEMENTATION) {
|
||||
generateTypeInfoInitializer(classDescriptor, firstTypeParameter, typeParamCount, iv);
|
||||
}
|
||||
|
||||
generateInitializers(aClass, kind, codegen, iv);
|
||||
|
||||
int curParam = 0;
|
||||
@@ -284,6 +297,25 @@ public class ClassCodegen {
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void generateTypeInfoInitializer(ClassDescriptor classDescriptor, int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
iv.anew(JetTypeMapper.TYPE_TYPEINFO);
|
||||
iv.dup();
|
||||
|
||||
iv.aconst(typeMapper.jvmType(classDescriptor, OwnerKind.INTERFACE));
|
||||
iv.iconst(typeParamCount);
|
||||
iv.newarray(JetTypeMapper.TYPE_TYPEINFO);
|
||||
|
||||
for (int i = 0; i < typeParamCount; i++) {
|
||||
iv.dup();
|
||||
iv.iconst(i);
|
||||
iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT);
|
||||
iv.astore(JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
iv.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;[Ljet/typeinfo/TypeInfo;)V");
|
||||
iv.putfield(typeMapper.jvmName(classDescriptor, OwnerKind.IMPLEMENTATION), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
|
||||
private void generateInitializers(JetClass aClass, OwnerKind kind, ExpressionCodegen codegen, InstructionAdapter iv) {
|
||||
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
@@ -360,15 +392,16 @@ public class ClassCodegen {
|
||||
}
|
||||
|
||||
private void generateStaticInitializer(ClassDescriptor descriptor, ClassVisitor cv) {
|
||||
if (descriptor.getTypeConstructor().getParameters().size() > 0) {
|
||||
// we will have a dynamic type info field
|
||||
return;
|
||||
}
|
||||
final MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
|
||||
"<clinit>", "()V", null, null);
|
||||
mv.visitCode();
|
||||
|
||||
InstructionAdapter v = new InstructionAdapter(mv);
|
||||
v.anew(TYPEINFO_TYPE);
|
||||
v.dup();
|
||||
v.aconst(Type.getObjectType(JetTypeMapper.jvmNameForInterface(descriptor)));
|
||||
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;)V");
|
||||
newTypeInfo(v, Type.getObjectType(JetTypeMapper.jvmNameForInterface(descriptor)));
|
||||
v.putstatic(JetTypeMapper.jvmNameForImplementation(descriptor), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
@@ -377,7 +410,14 @@ public class ClassCodegen {
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void generateGetTypeInfo(JetClass aClass, ClassVisitor cv) {
|
||||
public static void newTypeInfo(InstructionAdapter v, Type asmType) {
|
||||
v.anew(JetTypeMapper.TYPE_TYPEINFO);
|
||||
v.dup();
|
||||
v.aconst(asmType);
|
||||
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;)V");
|
||||
}
|
||||
|
||||
private void generateGetTypeInfo(ClassDescriptor descriptor, ClassVisitor cv) {
|
||||
final MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC,
|
||||
"getTypeInfo",
|
||||
"()Ljet/typeinfo/TypeInfo;",
|
||||
@@ -385,9 +425,15 @@ public class ClassCodegen {
|
||||
null);
|
||||
mv.visitCode();
|
||||
InstructionAdapter v = new InstructionAdapter(mv);
|
||||
ClassDescriptor descriptor = bindingContext.getClassDescriptor(aClass);
|
||||
v.getstatic(JetTypeMapper.jvmNameForImplementation(descriptor), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
v.areturn(TYPEINFO_TYPE);
|
||||
String owner = JetTypeMapper.jvmNameForImplementation(descriptor);
|
||||
if (descriptor.getTypeConstructor().getParameters().size() > 0) {
|
||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
v.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
else {
|
||||
v.getstatic(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -1146,6 +1147,13 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
|
||||
Method method = typeMapper.mapConstructorSignature((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
pushMethodArguments(expression, method);
|
||||
|
||||
for (JetTypeReference typeArgumentReference : constructorType.getTypeArgumentsAsTypes()) {
|
||||
JetType typeArgument = bindingContext.resolveTypeReference(typeArgumentReference);
|
||||
// TODO is the makeNullable() call correct here?
|
||||
ClassCodegen.newTypeInfo(v, typeMapper.mapType(TypeUtils.makeNullable(typeArgument)));
|
||||
}
|
||||
|
||||
v.invokespecial(JetTypeMapper.jvmNameForImplementation(classDecl), "<init>", method.getDescriptor());
|
||||
myStack.push(StackValue.onStack(type));
|
||||
return;
|
||||
@@ -1201,7 +1209,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 +1250,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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1256,6 +1288,56 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIsExpression(JetIsExpression expression) {
|
||||
JetPattern pattern = expression.getPattern();
|
||||
if (!(pattern instanceof JetTypePattern)) {
|
||||
throw new UnsupportedOperationException("can only generate a type pattern with 'is'");
|
||||
}
|
||||
JetTypeReference typeReference = ((JetTypePattern) pattern).getTypeReference();
|
||||
JetType jetType = bindingContext.resolveTypeReference(typeReference);
|
||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if (!(descriptor instanceof ClassDescriptor)) {
|
||||
throw new UnsupportedOperationException("don't know how to handle non-class types in is");
|
||||
}
|
||||
if (jetType.getArguments().size() > 0) {
|
||||
newTypeInfo(jetType);
|
||||
gen(expression.getLeftHandSide(), OBJECT_TYPE);
|
||||
v.invokevirtual("jet/typeinfo/TypeInfo", "isInstance", "(Ljava/lang/Object;)Z");
|
||||
}
|
||||
else {
|
||||
gen(expression.getLeftHandSide(), OBJECT_TYPE);
|
||||
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 newTypeInfo(JetType jetType) {
|
||||
v.anew(JetTypeMapper.TYPE_TYPEINFO);
|
||||
v.dup();
|
||||
|
||||
v.aconst(typeMapper.jvmType((ClassDescriptor) jetType.getConstructor().getDeclarationDescriptor(), OwnerKind.INTERFACE));
|
||||
List<TypeProjection> arguments = jetType.getArguments();
|
||||
if (arguments.size() > 0) {
|
||||
v.iconst(arguments.size());
|
||||
v.newarray(JetTypeMapper.TYPE_TYPEINFO);
|
||||
|
||||
for (int i = 0, argumentsSize = arguments.size(); i < argumentsSize; i++) {
|
||||
TypeProjection argument = arguments.get(i);
|
||||
v.dup();
|
||||
v.iconst(i);
|
||||
newTypeInfo(argument.getType());
|
||||
v.astore(JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;[Ljet/typeinfo/TypeInfo;)V");
|
||||
}
|
||||
else {
|
||||
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;)V");
|
||||
}
|
||||
}
|
||||
|
||||
private static class CompilationException extends RuntimeException {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import jet.typeinfo.TypeInfo;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -12,6 +13,7 @@ import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -19,6 +21,7 @@ import java.util.List;
|
||||
*/
|
||||
public class JetTypeMapper {
|
||||
static final Type TYPE_OBJECT = Type.getObjectType("java/lang/Object");
|
||||
static final Type TYPE_TYPEINFO = Type.getType(TypeInfo.class);
|
||||
|
||||
private final JetStandardLibrary standardLibrary;
|
||||
private final BindingContext bindingContext;
|
||||
@@ -32,7 +35,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 +59,13 @@ public class JetTypeMapper {
|
||||
}
|
||||
}
|
||||
|
||||
public Type jvmType(ClassDescriptor jetClass, OwnerKind kind) {
|
||||
if (jetClass == standardLibrary.getString()) {
|
||||
return Type.getType(String.class);
|
||||
}
|
||||
return Type.getType("L" + jvmName(jetClass, kind) + ";");
|
||||
}
|
||||
|
||||
static Type psiClassType(PsiClass psiClass) {
|
||||
return Type.getType("L" + jvmName(psiClass) + ";");
|
||||
}
|
||||
@@ -84,7 +102,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 NamespaceDescriptorImpl) {
|
||||
owner = jvmName((NamespaceDescriptor) descriptor.getContainingDeclaration());
|
||||
@@ -215,17 +233,21 @@ public class JetTypeMapper {
|
||||
public Method mapConstructorSignature(ConstructorDescriptor descriptor, OwnerKind kind) {
|
||||
boolean delegate = kind == OwnerKind.DELEGATING_IMPLEMENTATION;
|
||||
List<ValueParameterDescriptor> parameters = descriptor.getUnsubstitutedValueParameters();
|
||||
int count = parameters.size();
|
||||
int first = delegate ? 1 : 0;
|
||||
Type[] parameterTypes = new Type[count + first];
|
||||
List<Type> parameterTypes = new ArrayList<Type>();
|
||||
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
|
||||
if (delegate) {
|
||||
parameterTypes[0] = jetInterfaceType(descriptor.getContainingDeclaration());
|
||||
parameterTypes.add(jetInterfaceType(classDescriptor));
|
||||
}
|
||||
for (ValueParameterDescriptor parameter : parameters) {
|
||||
parameterTypes.add(mapType(parameter.getOutType()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
parameterTypes[i + first] = mapType(parameters.get(i).getOutType());
|
||||
List<TypeParameterDescriptor> typeParameters = classDescriptor.getTypeConstructor().getParameters();
|
||||
for (TypeParameterDescriptor typeParameter : typeParameters) {
|
||||
parameterTypes.add(TYPE_TYPEINFO);
|
||||
}
|
||||
return new Method("<init>", Type.VOID_TYPE, parameterTypes);
|
||||
|
||||
return new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||
}
|
||||
|
||||
static int getAccessModifiers(JetDeclaration p, int defaultFlags) {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@ public class ErrorHandler {
|
||||
public static final ErrorHandler THROW_EXCEPTION = new ErrorHandler() {
|
||||
@Override
|
||||
public void unresolvedReference(@NotNull JetReferenceExpression referenceExpression) {
|
||||
throw new IllegalStateException("Unresolved reference: " + referenceExpression.getText());
|
||||
throw new IllegalStateException("Unresolved reference: " + referenceExpression.getText() +
|
||||
" at offset " + referenceExpression.getTextRange().getStartOffset());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,6 +3,8 @@ package org.jetbrains.jet.lang.psi;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -27,4 +29,13 @@ public class JetIsExpression extends JetExpression {
|
||||
return findChildByClass(JetPattern.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetSimpleNameExpression getOperationReference() {
|
||||
return (JetSimpleNameExpression) findChildByType(JetNodeTypes.OPERATION_REFERENCE);
|
||||
}
|
||||
|
||||
public boolean isNot() {
|
||||
return getOperationReference().getReferencedNameElementType() == JetTokens.NOT_IS;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
class Wrapper<T>() {
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
val wrapper = new Wrapper<Int>()
|
||||
return wrapper is Wrapper<String>
|
||||
}
|
||||
@@ -28,5 +28,43 @@ 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 = newRunnable();
|
||||
assertSame(r, foo.invoke(null, r));
|
||||
}
|
||||
|
||||
public void testIsOperator() throws Exception {
|
||||
loadText("fun foo(x: Any) = x is Runnable");
|
||||
Method foo = generateFunction();
|
||||
assertFalse((Boolean) foo.invoke(null, new Object()));
|
||||
assertTrue((Boolean) foo.invoke(null, newRunnable()));
|
||||
}
|
||||
|
||||
public void testIsWithGenerics() throws Exception {
|
||||
loadFile();
|
||||
System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
assertFalse((Boolean) foo.invoke(null));
|
||||
}
|
||||
|
||||
public void testNotIsOperator() throws Exception {
|
||||
loadText("fun foo(x: Any) = x !is Runnable");
|
||||
Method foo = generateFunction();
|
||||
assertTrue((Boolean) foo.invoke(null, new Object()));
|
||||
assertFalse((Boolean) foo.invoke(null, newRunnable()));
|
||||
}
|
||||
|
||||
private Runnable newRunnable() {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,29 +2,49 @@ package jet.typeinfo;
|
||||
|
||||
import jet.JetObject;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TypeInfo<T> implements JetObject {
|
||||
|
||||
private TypeInfo<?> typeInfo;
|
||||
private TypeInfo<?> typeArgument;
|
||||
private Class<T> theClass;
|
||||
private final Class<T> theClass;
|
||||
private final TypeInfo[] typeParameters;
|
||||
|
||||
public TypeInfo(Class<T> theClass) {
|
||||
this.theClass = theClass;
|
||||
this.typeParameters = null;
|
||||
}
|
||||
|
||||
private TypeInfo(TypeInfo<?> typeArgument) {
|
||||
this.typeArgument = typeArgument;
|
||||
public TypeInfo(Class<T> theClass, TypeInfo[] typeParameters) {
|
||||
this.theClass = theClass;
|
||||
this.typeParameters = typeParameters;
|
||||
}
|
||||
|
||||
public boolean isInstance(Object obj) {
|
||||
if (obj instanceof JetObject) {
|
||||
return isSubtypeOf(((JetObject) obj).getTypeInfo());
|
||||
}
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
public boolean isSubtypeOf(TypeInfo<?> other) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
if (!theClass.isAssignableFrom(other.theClass)) {
|
||||
return false;
|
||||
}
|
||||
if (typeParameters != null) {
|
||||
if (other.typeParameters == null || other.typeParameters.length != typeParameters.length) {
|
||||
throw new IllegalArgumentException("inconsistent type infos for the same class");
|
||||
}
|
||||
for (int i = 0; i < typeParameters.length; i++) {
|
||||
// TODO handle variance here
|
||||
if (!typeParameters [i].equals(other.typeParameters [i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -35,4 +55,24 @@ public class TypeInfo<T> implements JetObject {
|
||||
}
|
||||
return typeInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
TypeInfo typeInfo = (TypeInfo) o;
|
||||
|
||||
if (!theClass.equals(typeInfo.theClass)) return false;
|
||||
if (!Arrays.equals(typeParameters, typeInfo.typeParameters)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = theClass.hashCode();
|
||||
result = 31 * result + (typeParameters != null ? Arrays.hashCode(typeParameters) : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user