提交 1261d872 编写于 作者: M Maxim Shafirov

Assorted fixes to inheritance/delegation codegen

上级 42a36e0c
......@@ -179,6 +179,8 @@ public class ClassCodegen {
ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, typeMapper, Type.VOID_TYPE, classDescriptor, kind);
String classname = JetTypeMapper.jvmName(classDescriptor, kind);
final Type classType = Type.getType("L" + classname + ";");
if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
String interfaceDesc = JetTypeMapper.jetInterfaceType(classDescriptor).getDescriptor();
v.visitField(Opcodes.ACC_PRIVATE, "$this", interfaceDesc, /*TODO*/null, null);
......@@ -202,67 +204,85 @@ public class ClassCodegen {
int n = 0;
for (JetDelegationSpecifier specifier : specifiers) {
boolean instanceOnStack = pushDelegateInstance(specifier, kind, codegen, iv, n);
if (instanceOnStack) {
JetType superType = bindingContext.resolveTypeReference(specifier.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
String delegateField = "$delegate_" + n;
String fieldDesc = JetTypeMapper.jetInterfaceType(superClassDescriptor).getDescriptor();
v.visitField(Opcodes.ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null);
iv.putfield(classname, delegateField, fieldDesc);
}
boolean delegateOnStack = specifier instanceof JetDelegatorToSuperCall && n > 0 ||
specifier instanceof JetDelegatorByExpressionSpecifier ;
n++;
}
if (delegateOnStack) {
iv.load(0, classType);
}
generateInitializers(aClass, kind, codegen, iv);
if (specifier instanceof JetDelegatorToSuperCall) {
JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier;
ConstructorDescriptor constructorDescriptor1 = bindingContext.resolveSuperConstructor(superCall, this);
iv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
ClassDescriptor classDecl = constructorDescriptor1.getContainingDeclaration();
boolean isDelegating = kind == OwnerKind.DELEGATING_IMPLEMENTATION;
Type type = isDelegating ? JetTypeMapper.jetDelegatingImplementationType(classDecl) : JetTypeMapper.jetImplementationType(classDecl);
private boolean pushDelegateInstance(JetDelegationSpecifier specifier, OwnerKind kind, ExpressionCodegen codegen, InstructionAdapter v, int pos) {
boolean instanceOnStack = false;
if (specifier instanceof JetDelegatorToSuperCall) {
JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier;
ConstructorDescriptor constructorDescriptor = bindingContext.resolveSuperConstructor(superCall, this);
if (n > 0) {
if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
codegen.thisToStack();
}
}
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
boolean isDelegating = kind == OwnerKind.DELEGATING_IMPLEMENTATION;
Type type = isDelegating ? JetTypeMapper.jetDelegatingImplementationType(classDecl) : JetTypeMapper.jetImplementationType(classDecl);
if (n == 0) {
iv.load(0, type);
}
else {
iv.anew(type);
iv.dup();
}
if (pos > 0) {
if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
codegen.thisToStack();
Method method1 = typeMapper.mapConstructorSignature(constructorDescriptor1, kind);
final Type[] argTypes1 = method1.getArgumentTypes();
List<JetArgument> args = superCall.getValueArguments();
for (int i = 0, argsSize = args.size(); i < argsSize; i++) {
JetArgument arg = args.get(i);
codegen.gen(arg.getArgumentExpression(), argTypes1[i]);
}
}
Method method = typeMapper.mapConstructorSignature(constructorDescriptor, kind);
final Type[] argTypes = method.getArgumentTypes();
List<JetArgument> args = superCall.getValueArguments();
for (int i = 0, argsSize = args.size(); i < argsSize; i++) {
JetArgument arg = args.get(i);
codegen.gen(arg.getArgumentExpression(), argTypes[i]);
iv.invokespecial(type.getClassName(), "<init>", method1.getDescriptor());
}
if (pos == 0) {
v.load(0, type);
else if (specifier instanceof JetDelegatorByExpressionSpecifier) {
codegen.genToJVMStack(((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression());
}
else {
v.anew(type);
v.dup();
instanceOnStack = true;
if (delegateOnStack) {
JetType superType = bindingContext.resolveTypeReference(specifier.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
String delegateField = "$delegate_" + n;
Type fieldType = JetTypeMapper.jetInterfaceType(superClassDescriptor);
String fieldDesc = fieldType.getDescriptor();
v.visitField(Opcodes.ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null);
iv.putfield(classname, delegateField, fieldDesc);
JetClass superClass = (JetClass) bindingContext.getDeclarationPsiElement(superClassDescriptor);
generateDelegates(aClass, superClass, v,
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false),
JetTypeMapper.jvmNameForInterface(superClassDescriptor)));
}
v.invokespecial(type.getClassName(), "<init>", method.getDescriptor());
n++;
}
else if (specifier instanceof JetDelegatorByExpressionSpecifier) {
codegen.genToJVMStack(((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression());
instanceOnStack = true;
generateInitializers(aClass, kind, codegen, iv);
int curParam = 0;
List<JetParameter> constructorParameters = aClass.getPrimaryConstructorParameters();
for (JetParameter parameter : constructorParameters) {
if (parameter.getValOrVarNode() != null) {
VariableDescriptor descriptor = paramDescrs.get(curParam);
Type type = typeMapper.mapType(descriptor.getOutType());
iv.load(0, classType);
iv.load(frameMap.getIndex(descriptor), type);
iv.putfield(classname, descriptor.getName(), type.getDescriptor());
}
curParam++;
}
return instanceOnStack;
iv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
private void generateInitializers(JetClass aClass, OwnerKind kind, ExpressionCodegen codegen, InstructionAdapter iv) {
......@@ -295,5 +315,56 @@ public class ClassCodegen {
functionCodegen.gen((JetFunction) declaration, kind);
}
}
for (JetParameter p : aClass.getPrimaryConstructorParameters()) {
if (p.getValOrVarNode() != null) {
VariableDescriptor descriptor = bindingContext.getParameterDescriptor(p);
if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
if (propertyDescriptor.isVar()) {
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
}
if (!(kind instanceof OwnerKind.DelegateKind) && kind != OwnerKind.INTERFACE && bindingContext.hasBackingField(propertyDescriptor)) {
v.visitField(Opcodes.ACC_PRIVATE, p.getName(), typeMapper.mapType(propertyDescriptor.getOutType()).getDescriptor(), null, null);
}
}
}
}
}
private void generateDelegates(JetClass inClass, JetClass toClass, ClassVisitor v, OwnerKind kind) {
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, standardLibrary, bindingContext);
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, standardLibrary, bindingContext, functionCodegen);
/* TODO
for (JetDeclaration declaration : toClass.getDeclarations()) {
if (declaration instanceof JetProperty) {
propertyCodegen.gen((JetProperty) declaration, kind);
}
else if (declaration instanceof JetFunction) {
functionCodegen.gen((JetFunction) declaration, kind);
}
}
*/
for (JetParameter p : toClass.getPrimaryConstructorParameters()) {
if (p.getValOrVarNode() != null) {
VariableDescriptor descriptor = bindingContext.getParameterDescriptor(p);
if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
if (propertyDescriptor.isVar()) {
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
}
if (!(kind instanceof OwnerKind.DelegateKind) && kind != OwnerKind.INTERFACE && bindingContext.hasBackingField(propertyDescriptor)) {
v.visitField(Opcodes.ACC_PRIVATE, p.getName(), typeMapper.mapType(propertyDescriptor.getOutType()).getDescriptor(), null, null);
}
}
}
}
}
}
......@@ -4,6 +4,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import jet.IntRange;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.*;
......@@ -448,6 +449,23 @@ public class ExpressionCodegen extends JetVisitor {
}
else if (descriptor instanceof PropertyDescriptor) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
//TODO: hack, will not need if resolve goes to right descriptor itself
if (declaration instanceof JetParameter) {
if (PsiTreeUtil.getParentOfType(expression, JetDelegationSpecifier.class) != null) {
JetClass aClass = PsiTreeUtil.getParentOfType(expression, JetClass.class);
ConstructorDescriptor constructorDescriptor = bindingContext.getConstructorDescriptor(aClass);
List<ValueParameterDescriptor> parameters = constructorDescriptor.getUnsubstitutedValueParameters();
for (ValueParameterDescriptor parameter : parameters) {
if (parameter.getName().equals(descriptor.getName())) {
final JetType outType = ((VariableDescriptor) descriptor).getOutType();
myStack.push(StackValue.local(myMap.getIndex(parameter), typeMapper.mapType(outType)));
return;
}
}
}
}
boolean isStatic = descriptor.getContainingDeclaration() instanceof NamespaceDescriptor;
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField);
......
......@@ -32,18 +32,18 @@ public class JetTypeMapper {
}
static String jvmName(ClassDescriptor jetClass, OwnerKind kind) {
switch (kind) {
case INTERFACE:
return jvmNameForInterface(jetClass);
case IMPLEMENTATION:
return jvmNameForImplementation(jetClass);
case DELEGATING_IMPLEMENTATION:
return jvmNameForDelegatingImplementation(jetClass);
default:
assert false : "Unsuitable kind";
return "java/lang/Object";
if (kind == OwnerKind.INTERFACE) {
return jvmNameForInterface(jetClass);
}
else if (kind == OwnerKind.IMPLEMENTATION) {
return jvmNameForImplementation(jetClass);
}
else if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
return jvmNameForDelegatingImplementation(jetClass);
}
else {
assert false : "Unsuitable kind";
return "java/lang/Object";
}
}
......
package org.jetbrains.jet.codegen;
import org.objectweb.asm.Type;
/**
* @author max
*/
public enum OwnerKind {
NAMESPACE,
INTERFACE,
IMPLEMENTATION,
DELEGATING_IMPLEMENTATION
public class OwnerKind {
public static final OwnerKind NAMESPACE = new OwnerKind();
public static final OwnerKind INTERFACE = new OwnerKind();
public static final OwnerKind IMPLEMENTATION = new OwnerKind();
public static final OwnerKind DELEGATING_IMPLEMENTATION = new OwnerKind();
public static class DelegateKind extends OwnerKind {
private final StackValue delegate;
private final String ownerClass;
public DelegateKind(StackValue delegate, String ownerClass) {
this.delegate = delegate;
this.ownerClass = ownerClass;
}
public StackValue getDelegate() {
return delegate;
}
public String getOwnerClass() {
return ownerClass;
}
}
}
......@@ -122,49 +122,78 @@ public class PropertyCodegen {
private void generateDefaultGetter(JetProperty p, JetDeclaration declaration, OwnerKind kind) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) context.getVariableDescriptor(p);
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC);
generateDefaultGetter(propertyDescriptor, flags, kind);
}
public void generateDefaultGetter(PropertyDescriptor propertyDescriptor, int flags, OwnerKind kind) {
if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC;
}
else if (kind == OwnerKind.INTERFACE) {
flags |= Opcodes.ACC_ABSTRACT;
}
final String signature = mapper.mapGetterSignature(propertyDescriptor).getDescriptor();
MethodVisitor mv = v.visitMethod(flags, getterName(p.getName()), signature, null, null);
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
if (kind != OwnerKind.NAMESPACE) {
iv.load(0, JetTypeMapper.TYPE_OBJECT);
String getterName = getterName(propertyDescriptor.getName());
MethodVisitor mv = v.visitMethod(flags, getterName, signature, null, null);
if (kind != OwnerKind.INTERFACE) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
if (kind != OwnerKind.NAMESPACE) {
iv.load(0, JetTypeMapper.TYPE_OBJECT);
}
final Type type = mapper.mapType(propertyDescriptor.getOutType());
if (kind instanceof OwnerKind.DelegateKind) {
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv);
iv.invokeinterface(dk.getOwnerClass(), getterName, signature);
}
else {
iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.GETSTATIC : Opcodes.GETFIELD,
JetTypeMapper.getOwner(propertyDescriptor), propertyDescriptor.getName(),
type.getDescriptor());
}
iv.areturn(type);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
final Type type = mapper.mapType(propertyDescriptor.getOutType());
iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.GETSTATIC : Opcodes.GETFIELD,
JetTypeMapper.getOwner(propertyDescriptor), propertyDescriptor.getName(),
type.getDescriptor());
iv.areturn(type);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
private void generateDefaultSetter(JetProperty p, JetDeclaration declaration, OwnerKind kind) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) context.getVariableDescriptor(p);
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC);
generateDefaultSetter(propertyDescriptor, flags, kind);
}
public void generateDefaultSetter(PropertyDescriptor propertyDescriptor, int flags, OwnerKind kind) {
if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC;
}
final String signature = mapper.mapSetterSignature(propertyDescriptor).getDescriptor();
MethodVisitor mv = v.visitMethod(flags, setterName(p.getName()), signature, null, null);
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
final Type type = mapper.mapType(propertyDescriptor.getOutType());
if (kind != OwnerKind.NAMESPACE) {
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(1, type);
else if (kind == OwnerKind.INTERFACE) {
flags |= Opcodes.ACC_ABSTRACT;
}
else {
iv.load(0, type);
final String signature = mapper.mapSetterSignature(propertyDescriptor).getDescriptor();
MethodVisitor mv = v.visitMethod(flags, setterName(propertyDescriptor.getName()), signature, null, null);
if (kind != OwnerKind.INTERFACE) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
final Type type = mapper.mapType(propertyDescriptor.getOutType());
if (kind != OwnerKind.NAMESPACE) {
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(1, type);
}
else {
iv.load(0, type);
}
//TODO: kind inst Delegate
iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD,
JetTypeMapper.getOwner(propertyDescriptor), propertyDescriptor.getName(),
type.getDescriptor());
iv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD,
JetTypeMapper.getOwner(propertyDescriptor), propertyDescriptor.getName(),
type.getDescriptor());
iv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
public static String getterName(String propertyName) {
......
class X(val x : Int) {}
class Y(val y : Int) {}
class Point(x : Int, y : Int) : X(x), Y(y) {}
class Point(x : Int, y : Int) : X(x) , Y(y) {}
class Abstract {}
......@@ -18,10 +18,10 @@ fun box() : String {
if (p.x + p.y != 239) return "FAIL #3"
val y = new Y(-1)
/*
val p1 = new P1(240, y)
if (p1.x + p1.y != 239) return "FAIL #4"
val p2 = new P2(240, y)
if (p2.x + p2.y != 239) return "FAIL #5"
......@@ -30,6 +30,6 @@ fun box() : String {
val p4 = new P4(240, y)
if (p4.x + p4.y != 239) return "FAIL #7"
*/
"OK"
}
\ No newline at end of file
......@@ -40,6 +40,7 @@ public class ClassGenTest extends CodegenTestCase {
public void testNewInstanceExplicitConstructor() throws Exception {
loadFile("newInstanceDefaultConstructor.jet");
System.out.println(generateToText());
final Codegens codegens = generateClassesInFile();
loadImplementationClass(codegens, "SimpleClass");
Class ns = loadRootNamespaceClass(codegens);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册