提交 2c7500c6 编写于 作者: D Dmitry Jemerov

generate initializers for namespace properties in <clinit> method

上级 85f46abc
......@@ -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);
}
}
......
......@@ -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)) {
......
......@@ -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,
"<clinit>", new Method("<clinit>", 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();
}
......
......@@ -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));
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册