initial super.property

This commit is contained in:
Alex Tkachman
2011-11-04 13:11:41 +01:00
parent 2755fb8538
commit df87493e4d
12 changed files with 204 additions and 38 deletions
@@ -69,7 +69,7 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
signatureWriter.visitEnd();
cv.defineClass(V1_6,
ACC_PUBLIC,
ACC_PUBLIC/*|ACC_SUPER*/,
name,
null,
funClass,
@@ -128,6 +128,23 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
throw new UnsupportedOperationException("Codegen for " + expression + " is not yet implemented");
}
@Override
public StackValue visitNamedFunction(JetNamedFunction function, StackValue data) {
throw new UnsupportedOperationException("Codegen for named functions is not yet implemented");
}
@Override
public StackValue visitSuperExpression(JetSuperExpression expression, StackValue data) {
// final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
// if (descriptor instanceof ClassDescriptor) {
// return generateThisOrOuter((ClassDescriptor) descriptor);
// }
// else {
// return thisExpression();
// }
return StackValue.none();
}
@Override
public StackValue visitParenthesizedExpression(JetParenthesizedExpression expression, StackValue receiver) {
return genQualified(receiver, expression.getExpression());
@@ -285,7 +302,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
// if(hND != null)
// invokeFunctionNoParams(hND, Type.BOOLEAN_TYPE, v);
// else
intermediateValueForProperty((PropertyDescriptor) hasNextDescriptor, false, false).put(Type.BOOLEAN_TYPE, v);
intermediateValueForProperty((PropertyDescriptor) hasNextDescriptor, false, false, false).put(Type.BOOLEAN_TYPE, v);
}
v.ifeq(end);
@@ -793,16 +810,17 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
else {
boolean isStatic = container instanceof NamespaceDescriptorImpl;
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL ;
JetExpression r = getReceiverForSelector(expression);
final boolean forceInterface = r != null && !(r instanceof JetThisExpression);
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField, forceInterface);
final boolean isSuper = r instanceof JetSuperExpression;
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField, forceInterface, isSuper);
if (!isStatic) {
if (receiver == StackValue.none()) {
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
}
JetType receiverType = bindingContext.get(BindingContext.EXPRESSION_TYPE, r);
receiver.put(receiverType != null ? typeMapper.mapType(receiverType) : JetTypeMapper.TYPE_OBJECT, v);
receiver.put(receiverType != null && !isSuper? typeMapper.mapType(receiverType) : JetTypeMapper.TYPE_OBJECT, v);
if(receiverType != null) {
ClassDescriptor propReceiverDescriptor = (ClassDescriptor) propertyDescriptor.getContainingDeclaration();
if(!CodegenUtil.isInterface(propReceiverDescriptor) && CodegenUtil.isInterface(receiverType.getConstructor().getDeclarationDescriptor())) {
@@ -895,11 +913,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
StackValue.onStack(typeMapper.mapType(functionDescriptor.getReturnType())).coerce(type, v);
}
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, boolean forceInterface) {
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, boolean forceInterface, boolean isSuper) {
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
propertyDescriptor = propertyDescriptor.getOriginal();
boolean isInsideClass = !forceInterface && containingDeclaration == context.getContextClass();
boolean isInsideClass = !forceInterface && containingDeclaration == context.getContextClass() && contextKind() != OwnerKind.TRAIT_IMPL;
Method getter;
Method setter;
if (forceField) {
@@ -909,10 +927,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else {
//noinspection ConstantConditions
getter = isInsideClass && (propertyDescriptor.getGetter() == null || propertyDescriptor.getGetter().isDefault())
? null : typeMapper.mapGetterSignature(propertyDescriptor);
? null : typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
//noinspection ConstantConditions
setter = isInsideClass && (propertyDescriptor.getSetter() == null || propertyDescriptor.getSetter().isDefault())
? null : typeMapper.mapSetterSignature(propertyDescriptor);
? null : typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
}
String owner;
@@ -931,7 +949,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
}
return StackValue.property(propertyDescriptor.getName(), owner, typeMapper.mapType(propertyDescriptor.getOutType()), isStatic, isInterface, getter, setter);
return StackValue.property(propertyDescriptor.getName(), owner, typeMapper.mapType(propertyDescriptor.getOutType()), isStatic, isInterface, isSuper, getter, setter);
}
@Override
@@ -1009,10 +1027,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private DeclarationDescriptor resolveCalleeDescriptor(JetCallExpression call) {
JetExpression callee = call.getCalleeExpression();
if (!(callee instanceof JetSimpleNameExpression)) {
if (!(callee instanceof JetReferenceExpression)) {
throw new UnsupportedOperationException("Don't know how to generate a call to " + callee);
}
DeclarationDescriptor funDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) callee);
DeclarationDescriptor funDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetReferenceExpression) callee);
if (funDescriptor == null) {
throw new CompilationException("Cannot resolve: " + callee.getText());
}
@@ -1883,7 +1901,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Type type = JetTypeMapper.psiClassType(javaClass);
v.anew(type);
v.dup();
final CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructor);
final CallableMethod callableMethod = JetTypeMapper.mapToCallableMethod(constructor);
invokeMethodWithArguments(callableMethod, expression, StackValue.none());
return type;
}
@@ -2071,6 +2089,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return generateThisOrOuter((ClassDescriptor) descriptor);
}
else {
// estension function or ???
return thisExpression();
}
}
@@ -2481,7 +2500,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) call);
if (descriptor instanceof PropertyDescriptor) {
v.load(subjectLocal, subjectType);
conditionValue = intermediateValueForProperty((PropertyDescriptor) descriptor, false, false);
conditionValue = intermediateValueForProperty((PropertyDescriptor) descriptor, false, false, false);
}
else {
throw new UnsupportedOperationException("unknown simple name resolve result: " + descriptor);
@@ -95,7 +95,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
v.defineClass(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface
? Opcodes.ACC_INTERFACE
: 0),
: 0/*Opcodes.ACC_SUPER*/),
jvmName(),
null,
superClass,
@@ -652,7 +652,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if(propertyDescriptor.getOutType().isNullable())
type = JetTypeMapper.boxType(type);
codegen.gen(initializer, type);
codegen.intermediateValueForProperty(propertyDescriptor, false, false).store(iv);
codegen.intermediateValueForProperty(propertyDescriptor, false, false, false).store(iv);
}
}
@@ -627,18 +627,29 @@ public class JetTypeMapper {
answer.append(p.getName()); // TODO: BOUND!
}
public Method mapGetterSignature(PropertyDescriptor descriptor) {
public Method mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
Type returnType = mapType(descriptor.getOutType());
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[0]);
if(kind != OwnerKind.TRAIT_IMPL)
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[0]);
else {
ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[] { mapType(containingDeclaration.getDefaultType()) });
}
}
public Method mapSetterSignature(PropertyDescriptor descriptor) {
public Method mapSetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
final JetType inType = descriptor.getInType();
if (inType == null) {
return null;
}
Type paramType = mapType(inType);
return new Method(PropertyCodegen.setterName(descriptor.getName()), Type.VOID_TYPE, new Type[] { paramType });
if(kind != OwnerKind.TRAIT_IMPL) {
return new Method(PropertyCodegen.setterName(descriptor.getName()), Type.VOID_TYPE, new Type[] { paramType });
}
else {
ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
return new Method(PropertyCodegen.setterName(descriptor.getName()), Type.VOID_TYPE, new Type[] { mapType(containingDeclaration.getDefaultType()), paramType });
}
}
private Method mapConstructorSignature(ConstructorDescriptor descriptor, List<Type> valueParameterTypes) {
@@ -32,7 +32,7 @@ public class NamespaceCodegen {
this.state = state;
v.defineClass(V1_6,
ACC_PUBLIC,
ACC_PUBLIC/*|ACC_SUPER*/,
getJVMClassName(fqName),
null,
//"jet/lang/Namespace",
@@ -93,7 +93,7 @@ public class NamespaceCodegen {
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
codegen.genToJVMStack(initializer);
codegen.intermediateValueForProperty(descriptor, true, false).store(new InstructionAdapter(mv));
codegen.intermediateValueForProperty(descriptor, true, false, false).store(new InstructionAdapter(mv));
}
}
}
@@ -37,8 +37,9 @@ public class PropertyCodegen {
throw new UnsupportedOperationException("expect a property to have a property descriptor");
}
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
if (kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION) {
generateBackingField(p, propertyDescriptor);
if (kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION || kind ==OwnerKind.TRAIT_IMPL ) {
if(kind != OwnerKind.TRAIT_IMPL)
generateBackingField(p, propertyDescriptor);
generateGetter(p, propertyDescriptor);
generateSetter(p, propertyDescriptor);
}
@@ -81,7 +82,7 @@ public class PropertyCodegen {
final JetPropertyAccessor getter = p.getGetter();
if (getter != null) {
if (getter.getBodyExpression() != null) {
functionCodegen.generateMethod(getter, state.getTypeMapper().mapGetterSignature(propertyDescriptor), propertyDescriptor.getGetter());
functionCodegen.generateMethod(getter, state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind), propertyDescriptor.getGetter());
}
else if (!getter.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
generateDefaultGetter(p, getter);
@@ -102,7 +103,7 @@ public class PropertyCodegen {
if (setter.getBodyExpression() != null) {
final PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
assert setterDescriptor != null;
functionCodegen.generateMethod(setter, state.getTypeMapper().mapSetterSignature(propertyDescriptor), setterDescriptor);
functionCodegen.generateMethod(setter, state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind), setterDescriptor);
}
else if (!p.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
generateDefaultSetter(p, setter);
@@ -120,6 +121,10 @@ public class PropertyCodegen {
}
public void generateDefaultGetter(PropertyDescriptor propertyDescriptor, int flags, PsiElement origin) {
if (kind == OwnerKind.TRAIT_IMPL) {
return;
}
if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC;
}
@@ -129,7 +134,7 @@ public class PropertyCodegen {
if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
flags |= Opcodes.ACC_ABSTRACT;
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor();
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind).getDescriptor();
String getterName = getterName(propertyDescriptor.getName());
MethodVisitor mv = v.newMethod(origin, flags, getterName, signature, null, null);
if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
@@ -162,6 +167,10 @@ public class PropertyCodegen {
}
public void generateDefaultSetter(PropertyDescriptor propertyDescriptor, int flags, PsiElement origin) {
if (kind == OwnerKind.TRAIT_IMPL) {
return;
}
if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC;
}
@@ -171,7 +180,7 @@ public class PropertyCodegen {
if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
flags |= Opcodes.ACC_ABSTRACT;
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor();
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind).getDescriptor();
MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), signature, null, null);
if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
mv.visitCode();
@@ -96,8 +96,8 @@ public abstract class StackValue {
return new InstanceField(type, owner, name);
}
public static StackValue property(String name, String owner, Type type, boolean isStatic, boolean isInterface, Method getter, Method setter) {
return new Property(name, owner, getter, setter, isStatic, isInterface, type);
public static StackValue property(String name, String owner, Type type, boolean isStatic, boolean isInterface, boolean isSuper, Method getter, Method setter) {
return new Property(name, owner, getter, setter, isStatic, isInterface, isSuper, type);
}
public static StackValue expression(Type type, JetExpression expression, ExpressionCodegen generator) {
@@ -623,8 +623,9 @@ public abstract class StackValue {
private final String owner;
private final boolean isStatic;
private final boolean isInterface;
private boolean isSuper;
public Property(String name, String owner, Method getter, Method setter, boolean aStatic, boolean isInterface, Type type) {
public Property(String name, String owner, Method getter, Method setter, boolean aStatic, boolean isInterface, boolean isSuper, Type type) {
super(type);
this.name = name;
this.owner = owner;
@@ -632,26 +633,37 @@ public abstract class StackValue {
this.setter = setter;
isStatic = aStatic;
this.isInterface = isInterface;
this.isSuper = isSuper;
}
@Override
public void put(Type type, InstructionAdapter v) {
if (getter == null) {
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor());
if(isSuper && isInterface) {
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + "$$TImpl", getter.getName(), getter.getDescriptor().replace("(","(L" + owner + ";"));
}
else {
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, getter.getName(), getter.getDescriptor());
if (getter == null) {
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor());
}
else {
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, getter.getName(), getter.getDescriptor());
}
}
coerce(type, v);
}
@Override
public void store(InstructionAdapter v) {
if (setter == null) {
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
if(isSuper && isInterface) {
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + "$$TImpl", setter.getName(), setter.getDescriptor().replace("(","(L" + owner + ";"));
}
else {
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, setter.getName(), setter.getDescriptor());
if (setter == null) {
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
}
else {
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, setter.getName(), setter.getDescriptor());
}
}
}
@@ -46,7 +46,7 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateDeclaration() {
v.defineClass(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL,
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL/*| Opcodes.ACC_SUPER*/,
jvmName(),
null,
"java/lang/Object",
@@ -0,0 +1,22 @@
open class M() {
open var b: Int = 0
}
class N() : M() {
val a : Int
get() {
super.b = super.b + 1
return super.b + 1
}
override var b: Int = a + 1
val superb : Int
get() = super.b
}
fun box(): String {
val n = N()
System.out?.println("a: " + n.a + " b: " + n.b + " superb: " + n.superb)
if (n.b == 3 && n.a == 4 && n.superb == 3) return "OK";
return "fail";
}
@@ -0,0 +1,29 @@
trait M {
var backingB : Int
var b : Int
get() = backingB
set(value: Int) {
backingB = value
}
}
class N() : M {
override var backingB : Int = 0
val a : Int
get() {
super.b = super.b + 1
return super.b + 1
}
override var b: Int = a + 1
val superb : Int
get() = super.b
}
fun box(): String {
val n = N()
System.out?.println("a: " + n.a + " b: " + n.b + " superb: " + n.superb)
if (n.b == 3 && n.a == 4 && n.superb == 3) return "OK";
return "fail";
}
@@ -80,4 +80,55 @@ public class FunctionGenTest extends CodegenTestCase {
public void testKt395 () {
blackBoxFile("regressions/kt395.jet");
}
/*
public void testFunction () throws InvocationTargetException, IllegalAccessException {
loadText("fun Any.foo() : fun(): String {\n" +
" return { \"239\" + this }\n" +
"}\n" +
"fun box() : String {\n" +
" return if((10.foo())() == \"23910\") \"OK\" else \"fail\"" +
"}" +
"");
System.out.println(generateToText());
Method foo = generateFunction();
assertTrue((Boolean) foo.invoke(null, "lala"));
assertFalse((Boolean) foo.invoke(null, "mama"));
}
fun Any.foo() : fun() : Unit {
return {}
}
fun Any.foo1() : fun(i : Int) : Unit {
return {}
}
fun foo2() : fun(i : fun()) : Unit {
return {}
}
fun fooT1<T>(t : T) : fun() : T {
return {t}
}
fun fooT2<T>() : fun(t : T) : T {
return {it}
}
fun main(args : Array<String>) {
args.foo()()
args.foo1()(1)
foo2()({})
(foo2()){}
val a = fooT1(1)()
a : Int
val b = fooT2<Int>()(1)
b : Int
fooT2()(1) // : Any?
}
*/
}
@@ -0,0 +1,13 @@
package org.jetbrains.jet.codegen;
public class SuperGenTest extends CodegenTestCase {
public void testBasicProperty () {
blackBoxFile("/super/basicproperty.jet");
System.out.println(generateToText());
}
public void testTraitProperty () {
blackBoxFile("/super/traitproperty.jet");
System.out.println(generateToText());
}
}