generate initializers for namespace properties in <clinit> method
This commit is contained in:
@@ -191,8 +191,7 @@ public class ClassCodegen {
|
|||||||
if (initializer != null) {
|
if (initializer != null) {
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
codegen.genToJVMStack(initializer);
|
codegen.genToJVMStack(initializer);
|
||||||
iv.putfield(JetTypeMapper.getOwner(propertyDescriptor), propertyDescriptor.getName(),
|
codegen.intermediateValueForProperty(propertyDescriptor, false).store(iv);
|
||||||
typeMapper.mapType(propertyDescriptor.getOutType()).getDescriptor());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -371,22 +371,12 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
else if (descriptor instanceof PropertyDescriptor) {
|
else if (descriptor instanceof PropertyDescriptor) {
|
||||||
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||||
boolean isStatic = descriptor.getContainingDeclaration() instanceof NamespaceDescriptor;
|
boolean isStatic = descriptor.getContainingDeclaration() instanceof NamespaceDescriptor;
|
||||||
String owner = JetTypeMapper.getOwner(descriptor);
|
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
|
||||||
final JetType outType = ((VariableDescriptor) descriptor).getOutType();
|
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField);
|
||||||
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);
|
|
||||||
}
|
|
||||||
if (!isStatic) {
|
if (!isStatic) {
|
||||||
ensureReceiverOnStack(expression);
|
ensureReceiverOnStack(expression);
|
||||||
}
|
}
|
||||||
myStack.push(StackValue.property(descriptor.getName(), owner, typeMapper.mapType(outType), isStatic, getter, setter));
|
myStack.push(iValue);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
|
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
|
@Nullable
|
||||||
private static Type getCastType(String castMethodName) {
|
private static Type getCastType(String castMethodName) {
|
||||||
if ("dbl".equals(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.AnalyzingUtils;
|
||||||
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.jetbrains.jet.lang.types.PropertyDescriptor;
|
||||||
import org.objectweb.asm.ClassVisitor;
|
import org.objectweb.asm.ClassVisitor;
|
||||||
|
import org.objectweb.asm.MethodVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
import org.objectweb.asm.commons.Method;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author max
|
* @author max
|
||||||
@@ -40,6 +45,10 @@ public class NamespaceCodegen {
|
|||||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, standardLibrary, bindingContext, functionCodegen);
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, standardLibrary, bindingContext, functionCodegen);
|
||||||
final ClassCodegen classCodegen = codegens.forClass(bindingContext);
|
final ClassCodegen classCodegen = codegens.forClass(bindingContext);
|
||||||
|
|
||||||
|
if (hasNonConstantPropertyInitializers(namespace)) {
|
||||||
|
generateStaticInitializers(namespace, bindingContext);
|
||||||
|
}
|
||||||
|
|
||||||
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
||||||
if (declaration instanceof JetProperty) {
|
if (declaration instanceof JetProperty) {
|
||||||
propertyCodegen.genInNamespace((JetProperty) declaration);
|
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() {
|
public void done() {
|
||||||
v.visitEnd();
|
v.visitEnd();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,4 +82,11 @@ public class PropertyGenTest extends CodegenTestCase {
|
|||||||
assertEquals(349, getFoo.invoke(instance));
|
assertEquals(349, getFoo.invoke(instance));
|
||||||
assertNull(findMethodByName(aClass, "setFoo"));
|
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