From 67689f4ed2b4030c48918f09b60411e0b51a3edd Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 16 Jun 2011 17:41:08 +0200 Subject: [PATCH 1/9] check if element is valid --- .../jet/plugin/structureView/JetStructureViewElement.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewElement.java b/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewElement.java index 8a8d8e3b8d8..2f0c86f7e1e 100644 --- a/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewElement.java +++ b/idea/src/org/jetbrains/jet/plugin/structureView/JetStructureViewElement.java @@ -65,7 +65,9 @@ public class JetStructureViewElement implements StructureViewTreeElement { @Override public Icon getIcon(boolean open) { - return PsiIconUtil.getProvidersIcon(myElement, open ? Iconable.ICON_FLAG_OPEN : Iconable.ICON_FLAG_CLOSED); + return myElement.isValid() + ? PsiIconUtil.getProvidersIcon(myElement, open ? Iconable.ICON_FLAG_OPEN : Iconable.ICON_FLAG_CLOSED) + : null; } @Override From a05b65f1a68011ce0fb9e2e533e818739b4af18e Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 16 Jun 2011 18:26:01 +0200 Subject: [PATCH 2/9] initial version of codegen for objects --- .../jet/codegen/ClassBodyCodegen.java | 22 +++++- .../jetbrains/jet/codegen/ClassCodegen.java | 27 ++++--- .../jet/codegen/ExpressionCodegen.java | 26 +++++-- .../codegen/ImplementationBodyCodegen.java | 74 +++++++++++++------ .../jet/codegen/InterfaceBodyCodegen.java | 4 +- .../jetbrains/jet/codegen/JetTypeMapper.java | 11 ++- .../jet/codegen/NamespaceCodegen.java | 4 +- .../jet/codegen/PropertyCodegen.java | 2 +- .../org/jetbrains/jet/codegen/StackValue.java | 22 +++--- .../testData/codegen/objects/simpleObject.jet | 7 ++ .../jet/codegen/CodegenTestCase.java | 3 + .../jetbrains/jet/codegen/ObjectGenTest.java | 10 +++ 12 files changed, 151 insertions(+), 61 deletions(-) create mode 100644 idea/testData/codegen/objects/simpleObject.jet create mode 100644 idea/tests/org/jetbrains/jet/codegen/ObjectGenTest.java diff --git a/idea/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index 8b70b2f2ad5..cdf5e5d319f 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -8,6 +8,9 @@ import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Opcodes; +import java.util.Collections; +import java.util.List; + /** * @author max * @author yole @@ -16,12 +19,12 @@ public abstract class ClassBodyCodegen { protected final BindingContext bindingContext; protected final JetStandardLibrary stdlib; protected final JetTypeMapper typeMapper; - protected final JetClass myClass; + protected final JetClassOrObject myClass; protected final OwnerKind kind; protected final ClassDescriptor descriptor; 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.stdlib = stdlib; this.typeMapper = new JetTypeMapper(stdlib, bindingContext); @@ -47,7 +50,7 @@ public abstract class ClassBodyCodegen { } 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); 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) { PropertyDescriptor propertyDescriptor = bindingContext.getPropertyDescriptor(p); if (propertyDescriptor != null) { @@ -80,4 +87,11 @@ public abstract class ClassBodyCodegen { } } + protected List getPrimaryConstructorParameters() { + if (myClass instanceof JetClass) { + return ((JetClass) myClass).getPrimaryConstructorParameters(); + } + return Collections.emptyList(); + } + } diff --git a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java index 4bf390d8532..6595f171e96 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -3,7 +3,9 @@ package org.jetbrains.jet.codegen; import com.intellij.openapi.project.Project; 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.JetDeclaration; +import org.jetbrains.jet.lang.psi.JetObjectDeclaration; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.objectweb.asm.ClassVisitor; @@ -17,21 +19,22 @@ public class ClassCodegen { private final Project project; private final BindingContext bindingContext; private final Codegens factory; - private final JetTypeMapper typeMapper; public ClassCodegen(Project project, Codegens factory, BindingContext bindingContext) { this.project = project; this.factory = factory; this.bindingContext = bindingContext; - - final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project); - typeMapper = new JetTypeMapper(standardLibrary, bindingContext); } - public void generate(JetClass aClass) { - generateInterface(aClass); - generateImplementation(aClass, OwnerKind.IMPLEMENTATION); - generateImplementation(aClass, OwnerKind.DELEGATING_IMPLEMENTATION); + public void generate(JetClassOrObject aClass) { + if (aClass instanceof JetObjectDeclaration) { + generateImplementation(aClass, OwnerKind.IMPLEMENTATION); + } + else { + generateInterface(aClass); + generateImplementation(aClass, OwnerKind.IMPLEMENTATION); + generateImplementation(aClass, OwnerKind.DELEGATING_IMPLEMENTATION); + } for (JetDeclaration declaration : aClass.getDeclarations()) { 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)); 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); - 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(); } diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 85aabb3e97d..6b3650925f0 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -597,6 +597,14 @@ public class ExpressionCodegen extends JetVisitor { v.arraylength(); 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 { boolean isStatic = container instanceof NamespaceDescriptorImpl; 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) { - boolean isStatic = propertyDescriptor.getContainingDeclaration() instanceof NamespaceDescriptorImpl; + DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); + boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl; final JetType outType = propertyDescriptor.getOutType(); - boolean isInsideClass = propertyDescriptor.getContainingDeclaration() == contextType; + boolean isInsideClass = containingDeclaration == contextType; Method getter; Method setter; if (directToField) { @@ -628,17 +637,18 @@ public class ExpressionCodegen extends JetVisitor { setter = isInsideClass && propertyDescriptor.getSetter() == null ? null : typeMapper.mapSetterSignature(propertyDescriptor); } - String fieldOwner; - String interfaceOwner; + String owner; + boolean isInterface; if (isInsideClass || isStatic) { - fieldOwner = interfaceOwner = typeMapper.getOwner(propertyDescriptor, contextKind); + owner = typeMapper.getOwner(propertyDescriptor, contextKind); + isInterface = false; } else { - fieldOwner = null; - interfaceOwner = typeMapper.getOwner(propertyDescriptor, OwnerKind.INTERFACE); + owner = 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 diff --git a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 47fcc302105..62a252d7c80 100644 --- a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -12,16 +12,15 @@ import org.objectweb.asm.Type; import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.Method; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** * @author max * @author yole */ 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); } @@ -29,17 +28,25 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { protected void generateDeclaration() { String superClass = getSuperClass(); - final String defaultInterfaceName = JetTypeMapper.jvmNameForInterface(descriptor); + List interfaces = new ArrayList(); + interfaces.add("jet/JetObject"); + if (!(myClass instanceof JetObjectDeclaration)) { + interfaces.add(JetTypeMapper.jvmNameForInterface(descriptor)); + } v.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, - JetTypeMapper.jetJvmName(descriptor, kind), + jvmName(), null, 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 delegationSpecifiers = myClass.getDelegationSpecifiers(); 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; 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(); try { @@ -71,17 +83,25 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { generateGetTypeInfo(); } - private void generatePrimaryConstructor() { - ConstructorDescriptor constructorDescriptor = bindingContext.getConstructorDescriptor(myClass); - if (constructorDescriptor == null) return; + protected void generatePrimaryConstructor() { + ConstructorDescriptor constructorDescriptor = bindingContext.getConstructorDescriptor((JetElement) myClass); + if (constructorDescriptor == null && !(myClass instanceof JetObjectDeclaration)) return; - Method method = typeMapper.mapConstructorSignature(constructorDescriptor, kind); + Method method; + if (myClass instanceof JetObjectDeclaration) { + method = new Method("", Type.VOID_TYPE, new Type[0]); + } + else { + method = typeMapper.mapConstructorSignature(constructorDescriptor, kind); + } int flags = Opcodes.ACC_PUBLIC; // TODO final MethodVisitor mv = v.visitMethod(flags, "", method.getDescriptor(), null, null); mv.visitCode(); Type[] argTypes = method.getArgumentTypes(); - List paramDescrs = constructorDescriptor.getUnsubstitutedValueParameters(); + List paramDescrs = constructorDescriptor != null + ? constructorDescriptor.getUnsubstitutedValueParameters() + : Collections.emptyList(); FrameMap frameMap = new FrameMap(); frameMap.enterTemp(); // this @@ -161,7 +181,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { int n = 0; for (JetDelegationSpecifier specifier : specifiers) { boolean delegateOnStack = specifier instanceof JetDelegatorToSuperCall && n > 0 || - specifier instanceof JetDelegatorByExpressionSpecifier ; + specifier instanceof JetDelegatorByExpressionSpecifier; if (delegateOnStack) { iv.load(0, classType); @@ -233,7 +253,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { generateInitializers(codegen, iv); int curParam = 0; - List constructorParameters = myClass.getPrimaryConstructorParameters(); + List constructorParameters = getPrimaryConstructorParameters(); for (JetParameter parameter : constructorParameters) { if (parameter.getValOrVarNode() != null) { VariableDescriptor descriptor = paramDescrs.get(curParam); @@ -250,7 +270,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { 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.anew(JetTypeMapper.TYPE_TYPEINFO); iv.dup(); @@ -269,7 +289,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { 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()) { if (declaration instanceof JetProperty) { 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 overriden) { + protected void generateDelegates(JetClassOrObject inClass, JetClass toClass, OwnerKind kind, Set overriden) { final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, stdlib, bindingContext); final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen); @@ -318,7 +338,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } 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 return; } @@ -327,8 +349,18 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { mv.visitCode(); 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, "", "()V"); + v.putstatic(name, "$instance", JetTypeMapper.jetImplementationType(descriptor).getDescriptor()); + } mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(0, 0); diff --git a/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java index d720062b7b4..5514043d665 100644 --- a/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java @@ -3,7 +3,7 @@ package org.jetbrains.jet.codegen; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; 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.resolve.BindingContext; import org.jetbrains.jet.lang.types.JetStandardLibrary; @@ -19,7 +19,7 @@ import java.util.Set; * @author yole */ 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); } diff --git a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 2e1c58c79c9..de54ff43817 100644 --- a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -53,6 +53,9 @@ public class JetTypeMapper { } public static String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) { + if (jetClass.isObject()) { + return jvmNameForImplementation(jetClass); + } if (kind == OwnerKind.INTERFACE) { return jvmNameForInterface(jetClass); } @@ -118,7 +121,13 @@ public class JetTypeMapper { } else if (descriptor.getContainingDeclaration() instanceof ClassDescriptor) { 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 { throw new UnsupportedOperationException("don't know how to generate owner for parent " + descriptor.getContainingDeclaration()); diff --git a/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index f8bbb64d0a5..8f7b3489733 100644 --- a/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -62,8 +62,8 @@ public class NamespaceCodegen { throw new RuntimeException("Failed to generate function " + declaration.getName(), e); } } - else if (declaration instanceof JetClass) { - classCodegen.generate((JetClass) declaration); + else if (declaration instanceof JetClassOrObject) { + classCodegen.generate((JetClassOrObject) declaration); } } } diff --git a/idea/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/idea/src/org/jetbrains/jet/codegen/PropertyCodegen.java index 36b9876354a..545b113470a 100644 --- a/idea/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -108,7 +108,7 @@ public class PropertyCodegen { } 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) { diff --git a/idea/src/org/jetbrains/jet/codegen/StackValue.java b/idea/src/org/jetbrains/jet/codegen/StackValue.java index 066cc83926c..6dbbe94b8a9 100644 --- a/idea/src/org/jetbrains/jet/codegen/StackValue.java +++ b/idea/src/org/jetbrains/jet/codegen/StackValue.java @@ -71,8 +71,8 @@ public abstract class StackValue { 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) { - return new Property(name, fieldOwner, interfaceOwner, getter, setter, isStatic, type); + 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); } 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 Method getter; private final Method setter; + private final String owner; private final boolean isStatic; - private final String fieldOwner; - private final String interfaceOwner; + private final boolean isInterface; - 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); this.name = name; - this.fieldOwner = fieldOwner; - this.interfaceOwner = interfaceOwner; + this.owner = owner; this.getter = getter; this.setter = setter; isStatic = aStatic; + this.isInterface = isInterface; } @Override public void put(Type type, InstructionAdapter v) { 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 { - 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 public void store(InstructionAdapter v) { 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 { - 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()); } } } diff --git a/idea/testData/codegen/objects/simpleObject.jet b/idea/testData/codegen/objects/simpleObject.jet new file mode 100644 index 00000000000..5b78c077a6e --- /dev/null +++ b/idea/testData/codegen/objects/simpleObject.jet @@ -0,0 +1,7 @@ +object A { + val x: Int = 610 +} + +fun box() : String { + return if (A.x != 610) "fail" else "OK" +} diff --git a/idea/tests/org/jetbrains/jet/codegen/CodegenTestCase.java b/idea/tests/org/jetbrains/jet/codegen/CodegenTestCase.java index 8e7f4f832a4..29d32ce1b0d 100644 --- a/idea/tests/org/jetbrains/jet/codegen/CodegenTestCase.java +++ b/idea/tests/org/jetbrains/jet/codegen/CodegenTestCase.java @@ -68,6 +68,9 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase { String actual; try { actual = blackBox(); + } catch (NoClassDefFoundError e) { + System.out.println(generateToText()); + throw e; } catch (Exception e) { System.out.println(generateToText()); throw e; diff --git a/idea/tests/org/jetbrains/jet/codegen/ObjectGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ObjectGenTest.java new file mode 100644 index 00000000000..16e69b485cb --- /dev/null +++ b/idea/tests/org/jetbrains/jet/codegen/ObjectGenTest.java @@ -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"); + } +} From 90c5a66362e7a01f880775e7b3fd533208423bc1 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 16 Jun 2011 19:04:35 +0200 Subject: [PATCH 3/9] allow namespace-qualified references; generate nested namespaces --- .../src/org/jetbrains/jet/codegen/ExpressionCodegen.java | 2 +- idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java | 9 ++++++--- idea/testData/codegen/namespaceQualifiedMethod.jet | 7 +++++++ .../org/jetbrains/jet/codegen/NamespaceGenTest.java | 4 ++++ 4 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 idea/testData/codegen/namespaceQualifiedMethod.jet diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 6b3650925f0..8c74d403175 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -615,7 +615,7 @@ public class ExpressionCodegen extends JetVisitor { myStack.push(iValue); } } - else { + else if (!(descriptor instanceof NamespaceDescriptor)) { throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); } } diff --git a/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 8f7b3489733..80d5e22c87e 100644 --- a/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -38,9 +38,8 @@ public class NamespaceCodegen { } public void generate(JetNamespace namespace) { - BindingContext bindingContext1 = AnalyzingUtils.analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY); - AnalyzingUtils.applyHandler(ErrorHandler.THROW_EXCEPTION, bindingContext1); - BindingContext bindingContext = bindingContext1; + BindingContext bindingContext = AnalyzingUtils.analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY); + AnalyzingUtils.applyHandler(ErrorHandler.THROW_EXCEPTION, bindingContext); final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project); final FunctionCodegen functionCodegen = new FunctionCodegen(namespace, v, standardLibrary, bindingContext); @@ -65,6 +64,10 @@ public class NamespaceCodegen { else if (declaration instanceof JetClassOrObject) { classCodegen.generate((JetClassOrObject) declaration); } + else if (declaration instanceof JetNamespace) { + JetNamespace childNamespace = (JetNamespace) declaration; + codegens.forNamespace(childNamespace).generate(childNamespace); + } } } diff --git a/idea/testData/codegen/namespaceQualifiedMethod.jet b/idea/testData/codegen/namespaceQualifiedMethod.jet new file mode 100644 index 00000000000..b532836e3e2 --- /dev/null +++ b/idea/testData/codegen/namespaceQualifiedMethod.jet @@ -0,0 +1,7 @@ +namespace Foo { + fun bar() = 610 +} + +fun box(): String { + return if (Foo.bar() == 610) "OK" else "fail" +} diff --git a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java index 95093596439..cc597b51ca2 100644 --- a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java @@ -400,4 +400,8 @@ public class NamespaceGenTest extends CodegenTestCase { final StringBuilder sb = new StringBuilder("x"); assertEquals('x', ((Character) main.invoke(null, sb)).charValue()); } + + public void testNamespaceQualifiedMethod() throws Exception { + blackBoxFile("namespaceQualifiedMethod.jet"); + } } From e6fc0a316f5f088ce82207dbc2a843f2b75584f1 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 16 Jun 2011 19:10:05 +0200 Subject: [PATCH 4/9] pass our binding context when generating nested namespace --- idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 80d5e22c87e..1f95548c87a 100644 --- a/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -38,7 +38,10 @@ public class NamespaceCodegen { } public void generate(JetNamespace namespace) { - BindingContext bindingContext = AnalyzingUtils.analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY); + generate(namespace, AnalyzingUtils.analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY)); + } + + public void generate(JetNamespace namespace, BindingContext bindingContext) { AnalyzingUtils.applyHandler(ErrorHandler.THROW_EXCEPTION, bindingContext); final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project); @@ -66,7 +69,7 @@ public class NamespaceCodegen { } else if (declaration instanceof JetNamespace) { JetNamespace childNamespace = (JetNamespace) declaration; - codegens.forNamespace(childNamespace).generate(childNamespace); + codegens.forNamespace(childNamespace).generate(childNamespace, bindingContext); } } } From 4b5fd5556ad643e86d633054c585d1895503148d Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 16 Jun 2011 19:19:04 +0200 Subject: [PATCH 5/9] implement JetNamespace.getFQName() for nested namespaces --- idea/src/org/jetbrains/jet/lang/psi/JetNamespace.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetNamespace.java b/idea/src/org/jetbrains/jet/lang/psi/JetNamespace.java index ef249cb50b1..32ab88d7aa2 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetNamespace.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetNamespace.java @@ -49,6 +49,10 @@ public class JetNamespace extends JetNamedDeclaration { } public String getFQName() { - return getName(); // TODO: Must include container namespace names, module root namespace + JetNamespace parent = PsiTreeUtil.getParentOfType(this, JetNamespace.class); + if (parent != null) { + return parent.getFQName() + "." + getName(); + } + return getName(); // TODO: Must include module root namespace } } From 392dce3207f29076c97537318272130d178b87b8 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 17 Jun 2011 12:10:40 +0200 Subject: [PATCH 6/9] JetClass -> JetClassOrObject --- idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 5b6dbe8696a..3423fc8fe14 100644 --- a/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -58,8 +58,8 @@ public class FunctionCodegen { return; } - DeclarationDescriptor contextDescriptor = owner instanceof JetClass - ? bindingContext.getClassDescriptor((JetClass) owner) + DeclarationDescriptor contextDescriptor = owner instanceof JetClassOrObject + ? bindingContext.getClassDescriptor((JetClassOrObject) owner) : bindingContext.getNamespaceDescriptor((JetNamespace) owner); final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null); From 1e0eb7692ea69a59a4662033dd4c0d4443fde830 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 17 Jun 2011 12:48:01 +0200 Subject: [PATCH 7/9] avoid NPE in reference --- .../jet/lang/psi/JetArrayAccessExpression.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java index a1e1dff7dfa..4df3429fe9f 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java @@ -24,7 +24,8 @@ public class JetArrayAccessExpression extends JetReferenceExpression { @Override public PsiReference getReference() { - return new JetArrayAccessReference(); + JetContainerNode indicesNode = getIndicesNode(); + return indicesNode == null ? null : new JetArrayAccessReference(); } @Override @@ -41,11 +42,15 @@ public class JetArrayAccessExpression extends JetReferenceExpression { @NotNull public List getIndexExpressions() { - PsiElement container = findChildByType(JetNodeTypes.INDICES); + PsiElement container = getIndicesNode(); if (container == null) return Collections.emptyList(); return PsiTreeUtil.getChildrenOfTypeAsList(container, JetExpression.class); } + private JetContainerNode getIndicesNode() { + return (JetContainerNode) findChildByType(JetNodeTypes.INDICES); + } + private class JetArrayAccessReference extends JetPsiReference implements MultiRangeReference { @Override @@ -62,7 +67,7 @@ public class JetArrayAccessExpression extends JetReferenceExpression { public List getRanges() { List list = new ArrayList(); - JetContainerNode indices = (JetContainerNode) findChildByType(JetNodeTypes.INDICES); + JetContainerNode indices = getIndicesNode(); TextRange textRange = indices.getNode().findChildByType(JetTokens.LBRACKET).getTextRange(); TextRange lBracketRange = textRange.shiftRight(-getTextOffset()); From ddecfcb5b6f569876171315c2324e0d04d67b1ac Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 17 Jun 2011 12:53:04 +0200 Subject: [PATCH 8/9] test fix --- .../org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java index 4df3429fe9f..255c5617042 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java @@ -47,7 +47,7 @@ public class JetArrayAccessExpression extends JetReferenceExpression { return PsiTreeUtil.getChildrenOfTypeAsList(container, JetExpression.class); } - private JetContainerNode getIndicesNode() { + public JetContainerNode getIndicesNode() { return (JetContainerNode) findChildByType(JetNodeTypes.INDICES); } From f234961baae014bbfccd78c69079a22eb6c38d5b Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 17 Jun 2011 12:54:19 +0200 Subject: [PATCH 9/9] another test fix --- idea/src/org/jetbrains/jet/lang/psi/JetNamespace.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetNamespace.java b/idea/src/org/jetbrains/jet/lang/psi/JetNamespace.java index 32ab88d7aa2..178b05bd771 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetNamespace.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetNamespace.java @@ -51,7 +51,10 @@ public class JetNamespace extends JetNamedDeclaration { public String getFQName() { JetNamespace parent = PsiTreeUtil.getParentOfType(this, JetNamespace.class); if (parent != null) { - return parent.getFQName() + "." + getName(); + String parentFQName = parent.getFQName(); + if (parentFQName.length() > 0) { + return parentFQName + "." + getName(); + } } return getName(); // TODO: Must include module root namespace }