more progress on traits
This commit is contained in:
@@ -1813,23 +1813,25 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference);
|
JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference);
|
||||||
assert jetType != null;
|
assert jetType != null;
|
||||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||||
if (!(descriptor instanceof ClassDescriptor)) {
|
if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) {
|
||||||
throw new UnsupportedOperationException("don't know how to handle non-class types in as/as?");
|
Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType));
|
||||||
}
|
generateInstanceOf(StackValue.expression(OBJECT_TYPE, expression.getLeft(), this), jetType, true);
|
||||||
Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType));
|
Label isInstance = new Label();
|
||||||
generateInstanceOf(StackValue.expression(OBJECT_TYPE, expression.getLeft(), this), jetType, true);
|
v.ifne(isInstance);
|
||||||
Label isInstance = new Label();
|
v.pop();
|
||||||
v.ifne(isInstance);
|
if (opToken == JetTokens.AS_SAFE) {
|
||||||
v.pop();
|
v.aconst(null);
|
||||||
if (opToken == JetTokens.AS_SAFE) {
|
}
|
||||||
v.aconst(null);
|
else {
|
||||||
|
throwNewException(CLASS_TYPE_CAST_EXCEPTION);
|
||||||
|
}
|
||||||
|
v.mark(isInstance);
|
||||||
|
v.checkcast(type);
|
||||||
|
return StackValue.onStack(type);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throwNewException(CLASS_TYPE_CAST_EXCEPTION);
|
throw new UnsupportedOperationException("don't know how to handle non-class types in as/as?");
|
||||||
}
|
}
|
||||||
v.mark(isInstance);
|
|
||||||
v.checkcast(type);
|
|
||||||
return StackValue.onStack(type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1962,7 +1964,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateTypeInfo(JetType jetType) {
|
void generateTypeInfo(JetType jetType) {
|
||||||
String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType);
|
String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType);
|
||||||
if(knownTypeInfo != null) {
|
if(knownTypeInfo != null) {
|
||||||
v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;");
|
v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;");
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
|
|||||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||||
import org.jetbrains.jet.lang.types.Variance;
|
import org.jetbrains.jet.lang.types.Variance;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
import org.objectweb.asm.ClassVisitor;
|
import org.objectweb.asm.ClassVisitor;
|
||||||
@@ -109,7 +110,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
protected void getSuperClass() {
|
protected void getSuperClass() {
|
||||||
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
|
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
|
||||||
|
|
||||||
if(myClass instanceof JetClass && ((JetClass)myClass).isTrait())
|
if(myClass instanceof JetClass && ((JetClass) myClass).isTrait())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
||||||
@@ -150,6 +151,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
generateGetTypeInfo();
|
generateGetTypeInfo();
|
||||||
|
//genGetSuperTypesTypeInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateFieldForTypeInfo() {
|
private void generateFieldForTypeInfo() {
|
||||||
@@ -240,6 +242,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
||||||
|
|
||||||
|
for(int slot = 0; slot != frameMap.getTypeParameterCount(); ++slot) {
|
||||||
|
codegen.addTypeParameter(constructorDescriptor.getTypeParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
|
||||||
|
}
|
||||||
|
|
||||||
String classname = state.getTypeMapper().jvmName(descriptor, kind);
|
String classname = state.getTypeMapper().jvmName(descriptor, kind);
|
||||||
final Type classType = Type.getType("L" + classname + ";");
|
final Type classType = Type.getType("L" + classname + ";");
|
||||||
|
|
||||||
@@ -348,7 +354,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
reg += argType.getSize();
|
reg += argType.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
String fdescriptor = function.getDescriptor().replace("(","(L" + state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(),OwnerKind.IMPLEMENTATION) + ";");
|
ClassDescriptor containingDeclaration = (ClassDescriptor) fun.getContainingDeclaration();
|
||||||
|
JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, state.getBindingContext());
|
||||||
|
Type type = state.getTypeMapper().mapType(jetType);
|
||||||
|
if(type.getInternalName().equals("java/lang/Object")) {
|
||||||
|
jetType = containingDeclaration.getDefaultType();
|
||||||
|
type = state.getTypeMapper().mapType(jetType);
|
||||||
|
}
|
||||||
|
|
||||||
|
String fdescriptor = function.getDescriptor().replace("(","(" + type.getDescriptor());
|
||||||
iv.invokestatic(state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(), OwnerKind.TRAIT_IMPL), function.getName(), fdescriptor);
|
iv.invokestatic(state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(), OwnerKind.TRAIT_IMPL), function.getName(), fdescriptor);
|
||||||
iv.areturn(function.getReturnType());
|
iv.areturn(function.getReturnType());
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
@@ -530,7 +544,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
iv.dup();
|
iv.dup();
|
||||||
iv.iconst(i);
|
iv.iconst(i);
|
||||||
iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT);
|
iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT);
|
||||||
ExpressionCodegen.genTypeInfoToProjection(iv, Variance.INVARIANT);
|
iv.checkcast(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
|
||||||
iv.astore(JetTypeMapper.TYPE_OBJECT);
|
iv.astore(JetTypeMapper.TYPE_OBJECT);
|
||||||
}
|
}
|
||||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
|
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
|
||||||
@@ -648,4 +662,50 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
private void generateClassObject(JetClassObject declaration) {
|
private void generateClassObject(JetClassObject declaration) {
|
||||||
state.forClass().generate(context, declaration.getObjectDeclaration());
|
state.forClass().generate(context, declaration.getObjectDeclaration());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void genGetSuperTypesTypeInfo() {
|
||||||
|
if(!(myClass instanceof JetClass) || ((JetClass)myClass).isTrait()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String sig = getGetSuperTypesTypeInfoSignature(descriptor.getDefaultType());
|
||||||
|
|
||||||
|
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC|Opcodes.ACC_STATIC,
|
||||||
|
"$$getSuperTypesTypeInfo",
|
||||||
|
sig,
|
||||||
|
null /* TODO */,
|
||||||
|
null);
|
||||||
|
mv.visitCode();
|
||||||
|
InstructionAdapter v = new InstructionAdapter(mv);
|
||||||
|
|
||||||
|
ExpressionCodegen codegen = new ExpressionCodegen(v, new FrameMap(), Type.VOID_TYPE, context, state);
|
||||||
|
|
||||||
|
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
|
||||||
|
int k = 1;
|
||||||
|
for (TypeParameterDescriptor parameterDescriptor : descriptor.getTypeConstructor().getParameters()) {
|
||||||
|
codegen.addTypeParameter(parameterDescriptor, StackValue.local(k++, JetTypeMapper.TYPE_TYPEINFO));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(JetType superType : descriptor.getTypeConstructor().getSupertypes()) {
|
||||||
|
for (TypeProjection typeProjection : superType.getArguments()) {
|
||||||
|
codegen.generateTypeInfo(typeProjection.getType());
|
||||||
|
}
|
||||||
|
v.invokestatic(state.getTypeMapper().mapType(superType).getInternalName(), "$$getSuperTypesTypeInfo", getGetSuperTypesTypeInfoSignature(superType));
|
||||||
|
}
|
||||||
|
|
||||||
|
v.areturn(Type.VOID_TYPE);
|
||||||
|
mv.visitMaxs(0, 0);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getGetSuperTypesTypeInfoSignature(JetType type) {
|
||||||
|
List<TypeParameterDescriptor> typeParameters = type.getConstructor().getParameters();
|
||||||
|
StringBuilder sb = new StringBuilder("(Ljava/util/Set;");
|
||||||
|
for(TypeParameterDescriptor tp : typeParameters)
|
||||||
|
sb.append("Ljet/typeinfo/TypeInfo;");
|
||||||
|
sb.append(")V");
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -439,8 +439,13 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f);
|
FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f);
|
||||||
if(kind == OwnerKind.TRAIT_IMPL) {
|
if(kind == OwnerKind.TRAIT_IMPL) {
|
||||||
JetType jetType = ((ClassDescriptor)functionDescriptor.getContainingDeclaration()).getDefaultType();
|
ClassDescriptor containingDeclaration = (ClassDescriptor) functionDescriptor.getContainingDeclaration();
|
||||||
final Type type = mapType(jetType);
|
JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, bindingContext);
|
||||||
|
Type type = mapType(jetType);
|
||||||
|
if(type.getInternalName().equals("java/lang/Object")) {
|
||||||
|
jetType = containingDeclaration.getDefaultType();
|
||||||
|
type = mapType(jetType);
|
||||||
|
}
|
||||||
valueParameterTypes.add(type);
|
valueParameterTypes.add(type);
|
||||||
parameterTypes.add(type);
|
parameterTypes.add(type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import org.jetbrains.jet.lang.psi.JetClass;
|
import com.intellij.psi.PsiClass;
|
||||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
import org.objectweb.asm.ClassVisitor;
|
import org.objectweb.asm.ClassVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
@@ -16,6 +18,33 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
|||||||
super(aClass, context, v, state);
|
super(aClass, context, v, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//todo not needed when frontend will be able to calculate properly
|
||||||
|
static JetType getSuperClass(ClassDescriptor myClassDescr, BindingContext bindingContext) {
|
||||||
|
JetClassOrObject myClass = (JetClassOrObject) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, myClassDescr);
|
||||||
|
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
|
||||||
|
|
||||||
|
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
||||||
|
if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) {
|
||||||
|
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
|
||||||
|
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||||
|
final PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
||||||
|
if (declaration != null) {
|
||||||
|
if (declaration instanceof PsiClass) {
|
||||||
|
if (!((PsiClass) declaration).isInterface()) {
|
||||||
|
return superClassDescriptor.getDefaultType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(declaration instanceof JetClass) {
|
||||||
|
if(!((JetClass) declaration).isTrait()) {
|
||||||
|
return superClassDescriptor.getDefaultType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generateDeclaration() {
|
protected void generateDeclaration() {
|
||||||
v.visit(Opcodes.V1_6,
|
v.visit(Opcodes.V1_6,
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
class A() {}
|
class A() {}
|
||||||
class B<T>() {
|
open class B<T>() {
|
||||||
fun isT (a : Any?) : Boolean {
|
fun isT (a : Any?) : Boolean {
|
||||||
return a is T
|
return a is T
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class C() : B<String>() {
|
||||||
|
}
|
||||||
|
|
||||||
|
class D<T>() : B<B<T>>() {
|
||||||
|
}
|
||||||
|
|
||||||
fun t1() : Boolean {
|
fun t1() : Boolean {
|
||||||
val a = A()
|
val a = A()
|
||||||
if(a !is A) return false
|
if(a !is A) return false
|
||||||
@@ -148,6 +154,18 @@ fun t24 () : Boolean {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun t25 () : Boolean {
|
||||||
|
val c = C()
|
||||||
|
if(!c.isT("aaa")) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun t26 () : Boolean {
|
||||||
|
val d = D<String>()
|
||||||
|
if(!d.isT(B<String>())) return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
fun box() : String {
|
fun box() : String {
|
||||||
if(!t1()) {
|
if(!t1()) {
|
||||||
return "t1 failed"
|
return "t1 failed"
|
||||||
@@ -221,5 +239,11 @@ fun box() : String {
|
|||||||
if(!t24()) {
|
if(!t24()) {
|
||||||
return "t24 failed"
|
return "t24 failed"
|
||||||
}
|
}
|
||||||
|
if(!t25()) {
|
||||||
|
return "t25 failed"
|
||||||
|
}
|
||||||
|
if(!t26()) {
|
||||||
|
return "t26 failed"
|
||||||
|
}
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
trait AL {
|
||||||
|
fun get(index: Int) : Any? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
trait ALE<T> : AL {
|
||||||
|
fun getOrNull(index: Int, value : T) = get(index) as? T ?: value
|
||||||
|
}
|
||||||
|
|
||||||
|
class SmartArrayList() : ALE<String> {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
val c = SmartArrayList()
|
||||||
|
return if("239" == c.getOrNull(0, "239")) "OK" else "fail"
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
open class AL<T> {
|
||||||
|
fun get(index: Int) : T? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
trait ALE<T> : AL<T> {
|
||||||
|
fun getOrValue(index: Int, value : T) : T = get(index) ?: value
|
||||||
|
}
|
||||||
|
|
||||||
|
class SmartArrayList() : ALE<String>, AL<String> {
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
val c = SmartArrayList()
|
||||||
|
return if("239" == c.getOrValue(0, "239")) "OK" else "fail"
|
||||||
|
}
|
||||||
@@ -10,4 +10,14 @@ public class TraitsTest extends CodegenTestCase {
|
|||||||
blackBoxFile("traits/simple.jet");
|
blackBoxFile("traits/simple.jet");
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testWithRequired () throws Exception {
|
||||||
|
blackBoxFile("traits/withRequired.jet");
|
||||||
|
System.out.println(generateToText());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMultiple () throws Exception {
|
||||||
|
// blackBoxFile("traits/multiple.jet");
|
||||||
|
// System.out.println(generateToText());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ public class TypeInfoTest extends CodegenTestCase {
|
|||||||
|
|
||||||
public void testKt259() throws Exception {
|
public void testKt259() throws Exception {
|
||||||
blackBoxFile("regressions/kt259.jet");
|
blackBoxFile("regressions/kt259.jet");
|
||||||
|
System.out.println(generateToText());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user