initial version of codegen for objects

This commit is contained in:
Dmitry Jemerov
2011-06-16 18:26:01 +02:00
parent 67689f4ed2
commit a05b65f1a6
12 changed files with 151 additions and 61 deletions
@@ -8,6 +8,9 @@ import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import java.util.Collections;
import java.util.List;
/** /**
* @author max * @author max
* @author yole * @author yole
@@ -16,12 +19,12 @@ public abstract class ClassBodyCodegen {
protected final BindingContext bindingContext; protected final BindingContext bindingContext;
protected final JetStandardLibrary stdlib; protected final JetStandardLibrary stdlib;
protected final JetTypeMapper typeMapper; protected final JetTypeMapper typeMapper;
protected final JetClass myClass; protected final JetClassOrObject myClass;
protected final OwnerKind kind; protected final OwnerKind kind;
protected final ClassDescriptor descriptor; protected final ClassDescriptor descriptor;
protected final ClassVisitor v; protected final ClassVisitor v;
public ClassBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClass aClass, OwnerKind kind, ClassVisitor v) { public ClassBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, OwnerKind kind, ClassVisitor v) {
this.bindingContext = bindingContext; this.bindingContext = bindingContext;
this.stdlib = stdlib; this.stdlib = stdlib;
this.typeMapper = new JetTypeMapper(stdlib, bindingContext); this.typeMapper = new JetTypeMapper(stdlib, bindingContext);
@@ -47,7 +50,7 @@ public abstract class ClassBodyCodegen {
} }
private void generateClassBody() { private void generateClassBody() {
final FunctionCodegen functionCodegen = new FunctionCodegen(myClass, v, stdlib, bindingContext); final FunctionCodegen functionCodegen = new FunctionCodegen((JetDeclaration) myClass, v, stdlib, bindingContext);
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen); final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen);
for (JetDeclaration declaration : myClass.getDeclarations()) { for (JetDeclaration declaration : myClass.getDeclarations()) {
@@ -63,7 +66,11 @@ public abstract class ClassBodyCodegen {
} }
} }
for (JetParameter p : myClass.getPrimaryConstructorParameters()) { generatePrimaryConstructorProperties(propertyCodegen);
}
private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen) {
for (JetParameter p : getPrimaryConstructorParameters()) {
if (p.getValOrVarNode() != null) { if (p.getValOrVarNode() != null) {
PropertyDescriptor propertyDescriptor = bindingContext.getPropertyDescriptor(p); PropertyDescriptor propertyDescriptor = bindingContext.getPropertyDescriptor(p);
if (propertyDescriptor != null) { if (propertyDescriptor != null) {
@@ -80,4 +87,11 @@ public abstract class ClassBodyCodegen {
} }
} }
protected List<JetParameter> getPrimaryConstructorParameters() {
if (myClass instanceof JetClass) {
return ((JetClass) myClass).getPrimaryConstructorParameters();
}
return Collections.emptyList();
}
} }
@@ -3,7 +3,9 @@ package org.jetbrains.jet.codegen;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
@@ -17,21 +19,22 @@ public class ClassCodegen {
private final Project project; private final Project project;
private final BindingContext bindingContext; private final BindingContext bindingContext;
private final Codegens factory; private final Codegens factory;
private final JetTypeMapper typeMapper;
public ClassCodegen(Project project, Codegens factory, BindingContext bindingContext) { public ClassCodegen(Project project, Codegens factory, BindingContext bindingContext) {
this.project = project; this.project = project;
this.factory = factory; this.factory = factory;
this.bindingContext = bindingContext; this.bindingContext = bindingContext;
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
} }
public void generate(JetClass aClass) { public void generate(JetClassOrObject aClass) {
generateInterface(aClass); if (aClass instanceof JetObjectDeclaration) {
generateImplementation(aClass, OwnerKind.IMPLEMENTATION); generateImplementation(aClass, OwnerKind.IMPLEMENTATION);
generateImplementation(aClass, OwnerKind.DELEGATING_IMPLEMENTATION); }
else {
generateInterface(aClass);
generateImplementation(aClass, OwnerKind.IMPLEMENTATION);
generateImplementation(aClass, OwnerKind.DELEGATING_IMPLEMENTATION);
}
for (JetDeclaration declaration : aClass.getDeclarations()) { for (JetDeclaration declaration : aClass.getDeclarations()) {
if (declaration instanceof JetClass) { if (declaration instanceof JetClass) {
@@ -40,14 +43,16 @@ public class ClassCodegen {
} }
} }
private void generateInterface(JetClass aClass) { private void generateInterface(JetClassOrObject aClass) {
final ClassVisitor visitor = factory.forClassInterface(bindingContext.getClassDescriptor(aClass)); final ClassVisitor visitor = factory.forClassInterface(bindingContext.getClassDescriptor(aClass));
new InterfaceBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, visitor).generate(); new InterfaceBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, visitor).generate();
} }
private void generateImplementation(JetClass aClass, OwnerKind kind) { private void generateImplementation(JetClassOrObject aClass, OwnerKind kind) {
ClassDescriptor descriptor = bindingContext.getClassDescriptor(aClass); ClassDescriptor descriptor = bindingContext.getClassDescriptor(aClass);
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION ? factory.forClassImplementation(descriptor) : factory.forClassDelegatingImplementation(descriptor); ClassVisitor v = kind == OwnerKind.IMPLEMENTATION
? factory.forClassImplementation(descriptor)
: factory.forClassDelegatingImplementation(descriptor);
new ImplementationBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, kind, v).generate(); new ImplementationBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, kind, v).generate();
} }
@@ -597,6 +597,14 @@ public class ExpressionCodegen extends JetVisitor {
v.arraylength(); v.arraylength();
myStack.push(StackValue.onStack(Type.INT_TYPE)); myStack.push(StackValue.onStack(Type.INT_TYPE));
} }
else if (declaration instanceof JetObjectDeclarationName) {
JetObjectDeclaration objectDeclaration = PsiTreeUtil.getParentOfType(declaration, JetObjectDeclaration.class);
ClassDescriptor classDescriptor = bindingContext.getClassDescriptor(objectDeclaration);
myStack.push(StackValue.field(typeMapper.jvmType(classDescriptor, OwnerKind.IMPLEMENTATION),
typeMapper.jvmName(classDescriptor, OwnerKind.IMPLEMENTATION),
"$instance",
true));
}
else { else {
boolean isStatic = container instanceof NamespaceDescriptorImpl; boolean isStatic = container instanceof NamespaceDescriptorImpl;
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER; final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
@@ -614,9 +622,10 @@ public class ExpressionCodegen extends JetVisitor {
} }
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean directToField) { public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean directToField) {
boolean isStatic = propertyDescriptor.getContainingDeclaration() instanceof NamespaceDescriptorImpl; DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
final JetType outType = propertyDescriptor.getOutType(); final JetType outType = propertyDescriptor.getOutType();
boolean isInsideClass = propertyDescriptor.getContainingDeclaration() == contextType; boolean isInsideClass = containingDeclaration == contextType;
Method getter; Method getter;
Method setter; Method setter;
if (directToField) { if (directToField) {
@@ -628,17 +637,18 @@ public class ExpressionCodegen extends JetVisitor {
setter = isInsideClass && propertyDescriptor.getSetter() == null ? null : typeMapper.mapSetterSignature(propertyDescriptor); setter = isInsideClass && propertyDescriptor.getSetter() == null ? null : typeMapper.mapSetterSignature(propertyDescriptor);
} }
String fieldOwner; String owner;
String interfaceOwner; boolean isInterface;
if (isInsideClass || isStatic) { if (isInsideClass || isStatic) {
fieldOwner = interfaceOwner = typeMapper.getOwner(propertyDescriptor, contextKind); owner = typeMapper.getOwner(propertyDescriptor, contextKind);
isInterface = false;
} }
else { else {
fieldOwner = null; owner = typeMapper.getOwner(propertyDescriptor, OwnerKind.INTERFACE);
interfaceOwner = typeMapper.getOwner(propertyDescriptor, OwnerKind.INTERFACE); isInterface = !(containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).isObject());
} }
return StackValue.property(propertyDescriptor.getName(), fieldOwner, interfaceOwner, typeMapper.mapType(outType), isStatic, getter, setter); return StackValue.property(propertyDescriptor.getName(), owner, typeMapper.mapType(outType), isStatic, isInterface, getter, setter);
} }
@Nullable @Nullable
@@ -12,16 +12,15 @@ import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
import java.util.HashSet; import java.util.*;
import java.util.List;
import java.util.Set;
/** /**
* @author max * @author max
* @author yole * @author yole
*/ */
public class ImplementationBodyCodegen extends ClassBodyCodegen { public class ImplementationBodyCodegen extends ClassBodyCodegen {
public ImplementationBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClass aClass, OwnerKind kind, ClassVisitor v) { public ImplementationBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass,
OwnerKind kind, ClassVisitor v) {
super(bindingContext, stdlib, aClass, kind, v); super(bindingContext, stdlib, aClass, kind, v);
} }
@@ -29,17 +28,25 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
protected void generateDeclaration() { protected void generateDeclaration() {
String superClass = getSuperClass(); String superClass = getSuperClass();
final String defaultInterfaceName = JetTypeMapper.jvmNameForInterface(descriptor); List<String> interfaces = new ArrayList<String>();
interfaces.add("jet/JetObject");
if (!(myClass instanceof JetObjectDeclaration)) {
interfaces.add(JetTypeMapper.jvmNameForInterface(descriptor));
}
v.visit(Opcodes.V1_6, v.visit(Opcodes.V1_6,
Opcodes.ACC_PUBLIC, Opcodes.ACC_PUBLIC,
JetTypeMapper.jetJvmName(descriptor, kind), jvmName(),
null, null,
superClass, superClass,
new String[]{"jet/JetObject", defaultInterfaceName} interfaces.toArray(new String[interfaces.size()])
); );
} }
private String getSuperClass() { private String jvmName() {
return JetTypeMapper.jetJvmName(descriptor, kind);
}
protected String getSuperClass() {
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers(); List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
if (delegationSpecifiers.isEmpty()) return "java/lang/Object"; if (delegationSpecifiers.isEmpty()) return "java/lang/Object";
@@ -59,6 +66,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
int typeinfoStatic = descriptor.getTypeConstructor().getParameters().size() > 0 ? 0 : Opcodes.ACC_STATIC; int typeinfoStatic = descriptor.getTypeConstructor().getParameters().size() > 0 ? 0 : Opcodes.ACC_STATIC;
v.visitField(Opcodes.ACC_PRIVATE | typeinfoStatic, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null); v.visitField(Opcodes.ACC_PRIVATE | typeinfoStatic, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
if (myClass instanceof JetObjectDeclaration) {
Type type = JetTypeMapper.jetImplementationType(descriptor);
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$instance", type.getDescriptor(), null, null);
}
generateStaticInitializer(); generateStaticInitializer();
try { try {
@@ -71,17 +83,25 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateGetTypeInfo(); generateGetTypeInfo();
} }
private void generatePrimaryConstructor() { protected void generatePrimaryConstructor() {
ConstructorDescriptor constructorDescriptor = bindingContext.getConstructorDescriptor(myClass); ConstructorDescriptor constructorDescriptor = bindingContext.getConstructorDescriptor((JetElement) myClass);
if (constructorDescriptor == null) return; if (constructorDescriptor == null && !(myClass instanceof JetObjectDeclaration)) return;
Method method = typeMapper.mapConstructorSignature(constructorDescriptor, kind); Method method;
if (myClass instanceof JetObjectDeclaration) {
method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
}
else {
method = typeMapper.mapConstructorSignature(constructorDescriptor, kind);
}
int flags = Opcodes.ACC_PUBLIC; // TODO int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null); final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
mv.visitCode(); mv.visitCode();
Type[] argTypes = method.getArgumentTypes(); Type[] argTypes = method.getArgumentTypes();
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor.getUnsubstitutedValueParameters(); List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
? constructorDescriptor.getUnsubstitutedValueParameters()
: Collections.<ValueParameterDescriptor>emptyList();
FrameMap frameMap = new FrameMap(); FrameMap frameMap = new FrameMap();
frameMap.enterTemp(); // this frameMap.enterTemp(); // this
@@ -161,7 +181,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
int n = 0; int n = 0;
for (JetDelegationSpecifier specifier : specifiers) { for (JetDelegationSpecifier specifier : specifiers) {
boolean delegateOnStack = specifier instanceof JetDelegatorToSuperCall && n > 0 || boolean delegateOnStack = specifier instanceof JetDelegatorToSuperCall && n > 0 ||
specifier instanceof JetDelegatorByExpressionSpecifier ; specifier instanceof JetDelegatorByExpressionSpecifier;
if (delegateOnStack) { if (delegateOnStack) {
iv.load(0, classType); iv.load(0, classType);
@@ -233,7 +253,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateInitializers(codegen, iv); generateInitializers(codegen, iv);
int curParam = 0; int curParam = 0;
List<JetParameter> constructorParameters = myClass.getPrimaryConstructorParameters(); List<JetParameter> constructorParameters = getPrimaryConstructorParameters();
for (JetParameter parameter : constructorParameters) { for (JetParameter parameter : constructorParameters) {
if (parameter.getValOrVarNode() != null) { if (parameter.getValOrVarNode() != null) {
VariableDescriptor descriptor = paramDescrs.get(curParam); VariableDescriptor descriptor = paramDescrs.get(curParam);
@@ -250,7 +270,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitEnd(); mv.visitEnd();
} }
private void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) { protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
iv.load(0, JetTypeMapper.TYPE_OBJECT); iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.anew(JetTypeMapper.TYPE_TYPEINFO); iv.anew(JetTypeMapper.TYPE_TYPEINFO);
iv.dup(); iv.dup();
@@ -269,7 +289,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.putfield(typeMapper.jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$typeInfo", "Ljet/typeinfo/TypeInfo;"); iv.putfield(typeMapper.jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
} }
private void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) { protected void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) {
for (JetDeclaration declaration : myClass.getDeclarations()) { for (JetDeclaration declaration : myClass.getDeclarations()) {
if (declaration instanceof JetProperty) { if (declaration instanceof JetProperty) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.getVariableDescriptor((JetProperty) declaration); final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.getVariableDescriptor((JetProperty) declaration);
@@ -289,7 +309,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
} }
private void generateDelegates(JetClass inClass, JetClass toClass, OwnerKind kind, Set<FunctionDescriptor> overriden) { protected void generateDelegates(JetClassOrObject inClass, JetClass toClass, OwnerKind kind, Set<FunctionDescriptor> overriden) {
final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, stdlib, bindingContext); final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, stdlib, bindingContext);
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen); final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen);
@@ -318,7 +338,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
private void generateStaticInitializer() { private void generateStaticInitializer() {
if (descriptor.getTypeConstructor().getParameters().size() > 0) { boolean needTypeInfo = descriptor.getTypeConstructor().getParameters().size() == 0;
boolean needInstance = myClass instanceof JetObjectDeclaration;
if (!needTypeInfo && !needInstance) {
// we will have a dynamic type info field // we will have a dynamic type info field
return; return;
} }
@@ -327,8 +349,18 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitCode(); mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv); InstructionAdapter v = new InstructionAdapter(mv);
ClassCodegen.newTypeInfo(v, Type.getObjectType(JetTypeMapper.jvmNameForInterface(descriptor)));
v.putstatic(JetTypeMapper.jvmNameForImplementation(descriptor), "$typeInfo", "Ljet/typeinfo/TypeInfo;"); if (needTypeInfo) {
ClassCodegen.newTypeInfo(v, typeMapper.jvmType(descriptor, OwnerKind.INTERFACE));
v.putstatic(JetTypeMapper.jvmNameForImplementation(descriptor), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
}
if (needInstance) {
String name = jvmName();
v.anew(Type.getObjectType(name));
v.dup();
v.invokespecial(name, "<init>", "()V");
v.putstatic(name, "$instance", JetTypeMapper.jetImplementationType(descriptor).getDescriptor());
}
mv.visitInsn(Opcodes.RETURN); mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0); mv.visitMaxs(0, 0);
@@ -3,7 +3,7 @@ package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetDelegationSpecifier; import org.jetbrains.jet.lang.psi.JetDelegationSpecifier;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.jetbrains.jet.lang.types.JetStandardLibrary;
@@ -19,7 +19,7 @@ import java.util.Set;
* @author yole * @author yole
*/ */
public class InterfaceBodyCodegen extends ClassBodyCodegen { public class InterfaceBodyCodegen extends ClassBodyCodegen {
public InterfaceBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClass aClass, ClassVisitor v) { public InterfaceBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, ClassVisitor v) {
super(bindingContext, stdlib, aClass, OwnerKind.INTERFACE, v); super(bindingContext, stdlib, aClass, OwnerKind.INTERFACE, v);
} }
@@ -53,6 +53,9 @@ public class JetTypeMapper {
} }
public static String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) { public static String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) {
if (jetClass.isObject()) {
return jvmNameForImplementation(jetClass);
}
if (kind == OwnerKind.INTERFACE) { if (kind == OwnerKind.INTERFACE) {
return jvmNameForInterface(jetClass); return jvmNameForInterface(jetClass);
} }
@@ -118,7 +121,13 @@ public class JetTypeMapper {
} }
else if (descriptor.getContainingDeclaration() instanceof ClassDescriptor) { else if (descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration(); ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration();
owner = jvmName(classDescriptor, kind instanceof OwnerKind.DelegateKind ? OwnerKind.INTERFACE : kind); if (kind instanceof OwnerKind.DelegateKind) {
kind = OwnerKind.INTERFACE;
}
else if (classDescriptor.isObject()) {
kind = OwnerKind.IMPLEMENTATION;
}
owner = jvmName(classDescriptor, kind);
} }
else { else {
throw new UnsupportedOperationException("don't know how to generate owner for parent " + descriptor.getContainingDeclaration()); throw new UnsupportedOperationException("don't know how to generate owner for parent " + descriptor.getContainingDeclaration());
@@ -62,8 +62,8 @@ public class NamespaceCodegen {
throw new RuntimeException("Failed to generate function " + declaration.getName(), e); throw new RuntimeException("Failed to generate function " + declaration.getName(), e);
} }
} }
else if (declaration instanceof JetClass) { else if (declaration instanceof JetClassOrObject) {
classCodegen.generate((JetClass) declaration); classCodegen.generate((JetClassOrObject) declaration);
} }
} }
} }
@@ -108,7 +108,7 @@ public class PropertyCodegen {
} }
private static boolean isExternallyAccessible(JetProperty p) { private static boolean isExternallyAccessible(JetProperty p) {
return p.hasModifier(JetTokens.PUBLIC_KEYWORD); return !p.hasModifier(JetTokens.PRIVATE_KEYWORD);
} }
private void generateSetter(JetProperty p, OwnerKind kind, PropertyDescriptor propertyDescriptor) { private void generateSetter(JetProperty p, OwnerKind kind, PropertyDescriptor propertyDescriptor) {
@@ -71,8 +71,8 @@ public abstract class StackValue {
return new Field(type, owner, name, isStatic); return new Field(type, owner, name, isStatic);
} }
public static StackValue property(String name, String fieldOwner, String interfaceOwner, Type type, boolean isStatic, Method getter, Method setter) { public static StackValue property(String name, String owner, Type type, boolean isStatic, boolean isInterface, Method getter, Method setter) {
return new Property(name, fieldOwner, interfaceOwner, getter, setter, isStatic, type); return new Property(name, owner, getter, setter, isStatic, isInterface, type);
} }
private static void box(final Type type, final Type toType, InstructionAdapter v) { private static void box(final Type type, final Type toType, InstructionAdapter v) {
@@ -391,37 +391,37 @@ public abstract class StackValue {
private final String name; private final String name;
private final Method getter; private final Method getter;
private final Method setter; private final Method setter;
private final String owner;
private final boolean isStatic; private final boolean isStatic;
private final String fieldOwner; private final boolean isInterface;
private final String interfaceOwner;
public Property(String name, String fieldOwner, String interfaceOwner, Method getter, Method setter, boolean aStatic, Type type) { public Property(String name, String owner, Method getter, Method setter, boolean aStatic, boolean isInterface, Type type) {
super(type); super(type);
this.name = name; this.name = name;
this.fieldOwner = fieldOwner; this.owner = owner;
this.interfaceOwner = interfaceOwner;
this.getter = getter; this.getter = getter;
this.setter = setter; this.setter = setter;
isStatic = aStatic; isStatic = aStatic;
this.isInterface = isInterface;
} }
@Override @Override
public void put(Type type, InstructionAdapter v) { public void put(Type type, InstructionAdapter v) {
if (getter == null) { if (getter == null) {
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, fieldOwner, name, this.type.getDescriptor()); v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor());
} }
else { else {
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : fieldOwner == null ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, interfaceOwner, getter.getName(), getter.getDescriptor()); v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, getter.getName(), getter.getDescriptor());
} }
} }
@Override @Override
public void store(InstructionAdapter v) { public void store(InstructionAdapter v) {
if (setter == null) { if (setter == null) {
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, fieldOwner, name, this.type.getDescriptor()); v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
} }
else { else {
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : fieldOwner == null ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, interfaceOwner, setter.getName(), setter.getDescriptor()); v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, setter.getName(), setter.getDescriptor());
} }
} }
} }
@@ -0,0 +1,7 @@
object A {
val x: Int = 610
}
fun box() : String {
return if (A.x != 610) "fail" else "OK"
}
@@ -68,6 +68,9 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
String actual; String actual;
try { try {
actual = blackBox(); actual = blackBox();
} catch (NoClassDefFoundError e) {
System.out.println(generateToText());
throw e;
} catch (Exception e) { } catch (Exception e) {
System.out.println(generateToText()); System.out.println(generateToText());
throw e; throw e;
@@ -0,0 +1,10 @@
package org.jetbrains.jet.codegen;
/**
* @author yole
*/
public class ObjectGenTest extends CodegenTestCase {
public void testSimpleObject() throws Exception {
blackBoxFile("objects/simpleObject.jet");
}
}