generate initializers for namespace properties in <clinit> method
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user