diff --git a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java index 6c0b10e9afb..c62c45cd104 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -191,8 +191,7 @@ public class ClassCodegen { if (initializer != null) { iv.load(0, JetTypeMapper.TYPE_OBJECT); codegen.genToJVMStack(initializer); - iv.putfield(JetTypeMapper.getOwner(propertyDescriptor), propertyDescriptor.getName(), - typeMapper.mapType(propertyDescriptor.getOutType()).getDescriptor()); + codegen.intermediateValueForProperty(propertyDescriptor, false).store(iv); } } diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 0abae876181..1852765c617 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -371,22 +371,12 @@ public class ExpressionCodegen extends JetVisitor { else if (descriptor instanceof PropertyDescriptor) { final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; boolean isStatic = descriptor.getContainingDeclaration() instanceof NamespaceDescriptor; - String owner = JetTypeMapper.getOwner(descriptor); - final JetType outType = ((VariableDescriptor) descriptor).getOutType(); - Method getter; - Method setter; - if (expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) { - getter = null; - setter = null; - } - else { - getter = propertyDescriptor.getGetter() == null ? null : typeMapper.mapGetterSignature(propertyDescriptor); - setter = propertyDescriptor.getSetter() == null ? null : typeMapper.mapSetterSignature(propertyDescriptor); - } + final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER; + final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField); if (!isStatic) { ensureReceiverOnStack(expression); } - myStack.push(StackValue.property(descriptor.getName(), owner, typeMapper.mapType(outType), isStatic, getter, setter)); + myStack.push(iValue); } else { throw new UnsupportedOperationException("don't know how to generate reference " + descriptor); @@ -394,6 +384,23 @@ public class ExpressionCodegen extends JetVisitor { } } + public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean directToField) { + boolean isStatic = propertyDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor; + String owner = JetTypeMapper.getOwner(propertyDescriptor); + final JetType outType = propertyDescriptor.getOutType(); + Method getter; + Method setter; + if (directToField) { + getter = null; + setter = null; + } + else { + getter = propertyDescriptor.getGetter() == null ? null : typeMapper.mapGetterSignature(propertyDescriptor); + setter = propertyDescriptor.getSetter() == null ? null : typeMapper.mapSetterSignature(propertyDescriptor); + } + return StackValue.property(propertyDescriptor.getName(), owner, typeMapper.mapType(outType), isStatic, getter, setter); + } + @Nullable private static Type getCastType(String castMethodName) { if ("dbl".equals(castMethodName)) { diff --git a/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 5168804035b..6bc2993f05c 100644 --- a/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -6,8 +6,13 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.types.JetStandardLibrary; +import org.jetbrains.jet.lang.types.PropertyDescriptor; import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.InstructionAdapter; +import org.objectweb.asm.commons.Method; /** * @author max @@ -40,6 +45,10 @@ public class NamespaceCodegen { final PropertyCodegen propertyCodegen = new PropertyCodegen(v, standardLibrary, bindingContext, functionCodegen); final ClassCodegen classCodegen = codegens.forClass(bindingContext); + if (hasNonConstantPropertyInitializers(namespace)) { + generateStaticInitializers(namespace, bindingContext); + } + for (JetDeclaration declaration : namespace.getDeclarations()) { if (declaration instanceof JetProperty) { propertyCodegen.genInNamespace((JetProperty) declaration); @@ -53,6 +62,45 @@ public class NamespaceCodegen { } } + private void generateStaticInitializers(JetNamespace namespace, BindingContext bindingContext) { + MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, + "", new Method("", Type.VOID_TYPE, new Type[0]).getDescriptor(), + null, null); + mv.visitCode(); + + FrameMap frameMap = new FrameMap(); + JetTypeMapper typeMapper = new JetTypeMapper(JetStandardLibrary.getJetStandardLibrary(namespace.getProject()), bindingContext); + ExpressionCodegen codegen = new ExpressionCodegen(mv, bindingContext, frameMap, + typeMapper, Type.VOID_TYPE); + + for (JetDeclaration declaration : namespace.getDeclarations()) { + if (declaration instanceof JetProperty) { + final JetExpression initializer = ((JetProperty) declaration).getInitializer(); + if (initializer != null && !(initializer instanceof JetConstantExpression)) { + final PropertyDescriptor descriptor = (PropertyDescriptor) bindingContext.getVariableDescriptor((JetProperty) declaration); + codegen.genToJVMStack(initializer); + codegen.intermediateValueForProperty(descriptor, false).store(new InstructionAdapter(mv)); + } + } + } + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + private static boolean hasNonConstantPropertyInitializers(JetNamespace namespace) { + for (JetDeclaration declaration : namespace.getDeclarations()) { + if (declaration instanceof JetProperty) { + final JetExpression initializer = ((JetProperty) declaration).getInitializer(); + if (initializer != null && !(initializer instanceof JetConstantExpression)) { + return true; + } + + } + } + return false; + } + public void done() { v.visitEnd(); } diff --git a/idea/tests/org/jetbrains/jet/codegen/PropertyGenTest.java b/idea/tests/org/jetbrains/jet/codegen/PropertyGenTest.java index ddd812664f7..51c0b72c24b 100644 --- a/idea/tests/org/jetbrains/jet/codegen/PropertyGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/PropertyGenTest.java @@ -82,4 +82,11 @@ public class PropertyGenTest extends CodegenTestCase { assertEquals(349, getFoo.invoke(instance)); assertNull(findMethodByName(aClass, "setFoo")); } + + public void testInitializersForNamespaceProperties() throws Exception { + loadText("public val x = System.currentTimeMillis()"); + System.out.println(generateToText()); + final Method method = generateFunction("getX"); + assertIsCurrentTime((Long) method.invoke(null)); + } }