提交 d6611e49 编写于 作者: D Dmitry Jemerov

initial support for properties backed by instance fields; some dummy code to...

initial support for properties backed by instance fields; some dummy code to generate primary constructor
上级 433c0737
......@@ -9,9 +9,12 @@ import org.jetbrains.jet.lang.types.ClassDescriptor;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType;
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;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
......@@ -41,7 +44,7 @@ public class ClassCodegen {
Set<String> superInterfaces = getSuperInterfaces(aClass);
String fqName = CodeGenUtil.getInternalInterfaceName(descriptor);
String fqName = JetTypeMapper.jvmNameForInterface(descriptor);
ClassVisitor v = factory.forClassInterface(descriptor);
v.visit(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT,
......@@ -64,12 +67,14 @@ public class ClassCodegen {
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION ? factory.forClassImplementation(descriptor) : factory.forClassDelegatingImplementation(descriptor);
v.visit(Opcodes.V1_6,
Opcodes.ACC_PUBLIC,
CodeGenUtil.getInternalImplementationName(descriptor),
JetTypeMapper.jvmNameForImplementation(descriptor),
null,
superClass,
new String[] {CodeGenUtil.getInternalInterfaceName(descriptor)}
new String[] {JetTypeMapper.jvmNameForInterface(descriptor)}
);
generatePrimaryConstructor(aClass, v, kind);
generateClassBody(aClass, v, kind);
v.visitEnd();
......@@ -107,7 +112,7 @@ public class ClassCodegen {
if (superInterfaces.size() > 0) {
ClassDescriptor first = superInterfaces.iterator().next();
return kind == OwnerKind.IMPLEMENTATION ? CodeGenUtil.getInternalImplementationName(first) : CodeGenUtil.getInternalDelegatingImplementationName(first);
return kind == OwnerKind.IMPLEMENTATION ? JetTypeMapper.jvmNameForImplementation(first) : JetTypeMapper.jvmNameForDelegatingImplementation(first);
}
return "java/lang/Object";
......@@ -145,12 +150,26 @@ public class ClassCodegen {
}
}
else {
superInterfaces.add(CodeGenUtil.getInternalInterfaceName(superClassDescriptor));
superInterfaces.add(JetTypeMapper.jvmNameForInterface(superClassDescriptor));
}
}
return superInterfaces;
}
private void generatePrimaryConstructor(JetClass aClass, ClassVisitor v, OwnerKind kind) {
int flags = Opcodes.ACC_PUBLIC; // TODO
Method method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
mv.visitCode();
final InstructionAdapter iv = new InstructionAdapter(mv);
String superClass = getSuperClass(aClass, kind);
iv.load(0, Type.getType("L" + superClass + ";"));
iv.invokespecial(superClass, "<init>", method.getDescriptor());
iv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
private void generateClassBody(JetClass aClass, ClassVisitor v, OwnerKind kind) {
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
final FunctionCodegen functionCodegen = new FunctionCodegen(v, standardLibrary, bindingContext);
......
package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.types.ClassDescriptor;
import org.jetbrains.jet.resolve.DescriptorUtil;
/**
* @author max
*/
public class CodeGenUtil {
public static String getInternalInterfaceName(ClassDescriptor descriptor) {
return DescriptorUtil.getFQName(descriptor).replace('.', '/');
}
public static String getInternalImplementationName(ClassDescriptor descriptor) {
return getInternalInterfaceName(descriptor) + "$$Impl";
}
public static String getInternalDelegatingImplementationName(ClassDescriptor descriptor) {
return getInternalInterfaceName(descriptor) + "$$DImpl";
}
}
package org.jetbrains.jet.codegen;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.ClassDescriptor;
......@@ -45,7 +44,7 @@ public class Codegens {
}
public ClassVisitor forClassInterface(ClassDescriptor aClass) {
return newVisitor(CodeGenUtil.getInternalInterfaceName(aClass) + ".class");
return newVisitor(JetTypeMapper.jvmNameForInterface(aClass) + ".class");
}
public ClassCodegen forClass(BindingContext bindingContext) {
......@@ -53,11 +52,11 @@ public class Codegens {
}
public ClassVisitor forClassImplementation(ClassDescriptor aClass) {
return newVisitor(CodeGenUtil.getInternalImplementationName(aClass) + ".class");
return newVisitor(JetTypeMapper.jvmNameForImplementation(aClass) + ".class");
}
public ClassVisitor forClassDelegatingImplementation(ClassDescriptor aClass) {
return newVisitor(CodeGenUtil.getInternalDelegatingImplementationName(aClass) + ".class");
return newVisitor(JetTypeMapper.jvmNameForDelegatingImplementation(aClass) + ".class");
}
public NamespaceCodegen forNamespace(JetNamespace namespace) {
......
......@@ -372,25 +372,36 @@ public class ExpressionCodegen extends JetVisitor {
}
else if (descriptor instanceof PropertyDescriptor) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
String owner;
boolean isStatic;
if (descriptor.getContainingDeclaration() instanceof NamespaceDescriptor) {
JetNamespace ns = (JetNamespace) bindingContext.getDeclarationPsiElement(descriptor.getContainingDeclaration());
String owner = JetTypeMapper.jvmName(ns);
final JetType outType = ((VariableDescriptor) descriptor).getOutType();
Method getter;
Method setter;
if (expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
getter = null;
setter = null;
}
else {
getter = typeMapper.mapGetterSignature(propertyDescriptor);
setter = typeMapper.mapSetterSignature(propertyDescriptor);
}
myStack.push(StackValue.property(descriptor.getName(), owner, typeMapper.mapType(outType), getter, setter));
owner = JetTypeMapper.jvmName(ns);
isStatic = true;
}
else if (descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration();
owner = JetTypeMapper.jvmNameForImplementation(classDescriptor);
isStatic = false;
}
else {
throw new UnsupportedOperationException("don't know how to generate property reference with parent " + descriptor.getContainingDeclaration());
}
final JetType outType = ((VariableDescriptor) descriptor).getOutType();
Method getter;
Method setter;
if (expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
getter = null;
setter = null;
}
else {
throw new UnsupportedOperationException("don't know how to generate non-namespace property reference " + descriptor);
getter = typeMapper.mapGetterSignature(propertyDescriptor);
setter = typeMapper.mapSetterSignature(propertyDescriptor);
}
if (!isStatic) {
ensureReceiverOnStack(expression);
}
myStack.push(StackValue.property(descriptor.getName(), owner, typeMapper.mapType(outType), isStatic, getter, setter));
}
else {
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
......@@ -489,6 +500,9 @@ public class ExpressionCodegen extends JetVisitor {
myStack.pop().put(TYPE_OBJECT, v);
}
}
else if (!(expression.getParent() instanceof JetSafeQualifiedExpression)) {
v.load(0, TYPE_OBJECT); // TODO hope it works; really need more checks here :)
}
}
private void pushMethodArguments(JetCall expression, Method method) {
......
......@@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.psi.JetParameter;
import org.jetbrains.jet.lang.psi.JetTypeReference;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.resolve.DescriptorUtil;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;
......@@ -38,6 +39,18 @@ public class JetTypeMapper {
return NamespaceCodegen.getJVMClassName(namespace.getFQName());
}
public static String jvmNameForInterface(ClassDescriptor descriptor) {
return DescriptorUtil.getFQName(descriptor).replace('.', '/');
}
public static String jvmNameForImplementation(ClassDescriptor descriptor) {
return jvmNameForInterface(descriptor) + "$$Impl";
}
public static String jvmNameForDelegatingImplementation(ClassDescriptor descriptor) {
return jvmNameForInterface(descriptor) + "$$DImpl";
}
public Type mapType(final JetType jetType) {
if (jetType.equals(JetStandardClasses.getUnitType())) {
return Type.VOID_TYPE;
......@@ -112,7 +125,7 @@ public class JetTypeMapper {
if (declaration instanceof PsiClass) {
return psiClassType((PsiClass) declaration);
}
return Type.getObjectType(CodeGenUtil.getInternalInterfaceName((ClassDescriptor) descriptor));
return Type.getObjectType(jvmNameForInterface((ClassDescriptor) descriptor));
}
throw new UnsupportedOperationException("Unknown type " + jetType);
......
......@@ -71,8 +71,8 @@ public abstract class StackValue {
return new Field(type, owner, name, isStatic);
}
public static StackValue property(String name, String owner, Type type, Method getter, Method setter) {
return new Property(name, owner, getter, setter, type);
public static StackValue property(String name, String owner, Type type, boolean isStatic, Method getter, Method setter) {
return new Property(name, owner, getter, setter, isStatic, type);
}
private static void box(final Type type, InstructionAdapter v) {
......@@ -379,32 +379,34 @@ public abstract class StackValue {
private final String owner;
private final Method getter;
private final Method setter;
private final boolean isStatic;
public Property(String name, String owner, Method getter, Method setter, Type type) {
public Property(String name, String owner, Method getter, Method setter, boolean aStatic, Type type) {
super(type);
this.name = name;
this.owner = owner;
this.getter = getter;
this.setter = setter;
isStatic = aStatic;
}
@Override
public void put(Type type, InstructionAdapter v) {
if (getter == null) {
v.visitFieldInsn(Opcodes.GETSTATIC, owner, name, type.getDescriptor());
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, type.getDescriptor());
}
else {
v.invokestatic(owner, getter.getName(), getter.getDescriptor());
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL, owner, getter.getName(), getter.getDescriptor());
}
}
@Override
public void store(InstructionAdapter v) {
if (setter == null) {
v.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, type.getDescriptor());
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, type.getDescriptor());
}
else {
v.invokestatic(owner, setter.getName(), setter.getDescriptor());
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL, owner, setter.getName(), setter.getDescriptor());
}
}
}
......
class PrivateVar {
private var x = 0;
fun setValueOfX(val: Int) { x = val }
fun setValueOfX(aValue: Int) { x = aValue }
fun getValueOfX() = x
}
......@@ -20,6 +20,7 @@ public class PropertyGenTest extends CodegenTestCase {
public void testPrivateVar() throws Exception {
loadFile("privateVar.jet");
System.out.println(generateToText());
final Class aClass = loadImplementationClass(generateClassesInFile(), "PrivateVar");
final Object instance = aClass.newInstance();
Method setter = findMethodByName(aClass, "setValueOfX");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册