Merge remote branch 'origin/master'
This commit is contained in:
@@ -8,6 +8,9 @@ import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
|||||||
import org.objectweb.asm.ClassVisitor;
|
import org.objectweb.asm.ClassVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author max
|
* @author max
|
||||||
* @author yole
|
* @author yole
|
||||||
@@ -16,12 +19,12 @@ public abstract class ClassBodyCodegen {
|
|||||||
protected final BindingContext bindingContext;
|
protected final BindingContext bindingContext;
|
||||||
protected final JetStandardLibrary stdlib;
|
protected final JetStandardLibrary stdlib;
|
||||||
protected final JetTypeMapper typeMapper;
|
protected final JetTypeMapper typeMapper;
|
||||||
protected final JetClass myClass;
|
protected final JetClassOrObject myClass;
|
||||||
protected final OwnerKind kind;
|
protected final OwnerKind kind;
|
||||||
protected final ClassDescriptor descriptor;
|
protected final ClassDescriptor descriptor;
|
||||||
protected final ClassVisitor v;
|
protected final ClassVisitor v;
|
||||||
|
|
||||||
public ClassBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClass aClass, OwnerKind kind, ClassVisitor v) {
|
public ClassBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, OwnerKind kind, ClassVisitor v) {
|
||||||
this.bindingContext = bindingContext;
|
this.bindingContext = bindingContext;
|
||||||
this.stdlib = stdlib;
|
this.stdlib = stdlib;
|
||||||
this.typeMapper = new JetTypeMapper(stdlib, bindingContext);
|
this.typeMapper = new JetTypeMapper(stdlib, bindingContext);
|
||||||
@@ -47,7 +50,7 @@ public abstract class ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateClassBody() {
|
private void generateClassBody() {
|
||||||
final FunctionCodegen functionCodegen = new FunctionCodegen(myClass, v, stdlib, bindingContext);
|
final FunctionCodegen functionCodegen = new FunctionCodegen((JetDeclaration) myClass, v, stdlib, bindingContext);
|
||||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen);
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen);
|
||||||
|
|
||||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||||
@@ -63,7 +66,11 @@ public abstract class ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (JetParameter p : myClass.getPrimaryConstructorParameters()) {
|
generatePrimaryConstructorProperties(propertyCodegen);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen) {
|
||||||
|
for (JetParameter p : getPrimaryConstructorParameters()) {
|
||||||
if (p.getValOrVarNode() != null) {
|
if (p.getValOrVarNode() != null) {
|
||||||
PropertyDescriptor propertyDescriptor = bindingContext.getPropertyDescriptor(p);
|
PropertyDescriptor propertyDescriptor = bindingContext.getPropertyDescriptor(p);
|
||||||
if (propertyDescriptor != null) {
|
if (propertyDescriptor != null) {
|
||||||
@@ -80,4 +87,11 @@ public abstract class ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<JetParameter> getPrimaryConstructorParameters() {
|
||||||
|
if (myClass instanceof JetClass) {
|
||||||
|
return ((JetClass) myClass).getPrimaryConstructorParameters();
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package org.jetbrains.jet.codegen;
|
|||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetClass;
|
import org.jetbrains.jet.lang.psi.JetClass;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
|
||||||
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.objectweb.asm.ClassVisitor;
|
import org.objectweb.asm.ClassVisitor;
|
||||||
@@ -17,21 +19,22 @@ public class ClassCodegen {
|
|||||||
private final Project project;
|
private final Project project;
|
||||||
private final BindingContext bindingContext;
|
private final BindingContext bindingContext;
|
||||||
private final Codegens factory;
|
private final Codegens factory;
|
||||||
private final JetTypeMapper typeMapper;
|
|
||||||
|
|
||||||
public ClassCodegen(Project project, Codegens factory, BindingContext bindingContext) {
|
public ClassCodegen(Project project, Codegens factory, BindingContext bindingContext) {
|
||||||
this.project = project;
|
this.project = project;
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
this.bindingContext = bindingContext;
|
this.bindingContext = bindingContext;
|
||||||
|
|
||||||
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
|
|
||||||
typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generate(JetClass aClass) {
|
public void generate(JetClassOrObject aClass) {
|
||||||
generateInterface(aClass);
|
if (aClass instanceof JetObjectDeclaration) {
|
||||||
generateImplementation(aClass, OwnerKind.IMPLEMENTATION);
|
generateImplementation(aClass, OwnerKind.IMPLEMENTATION);
|
||||||
generateImplementation(aClass, OwnerKind.DELEGATING_IMPLEMENTATION);
|
}
|
||||||
|
else {
|
||||||
|
generateInterface(aClass);
|
||||||
|
generateImplementation(aClass, OwnerKind.IMPLEMENTATION);
|
||||||
|
generateImplementation(aClass, OwnerKind.DELEGATING_IMPLEMENTATION);
|
||||||
|
}
|
||||||
|
|
||||||
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
||||||
if (declaration instanceof JetClass) {
|
if (declaration instanceof JetClass) {
|
||||||
@@ -40,14 +43,16 @@ public class ClassCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateInterface(JetClass aClass) {
|
private void generateInterface(JetClassOrObject aClass) {
|
||||||
final ClassVisitor visitor = factory.forClassInterface(bindingContext.getClassDescriptor(aClass));
|
final ClassVisitor visitor = factory.forClassInterface(bindingContext.getClassDescriptor(aClass));
|
||||||
new InterfaceBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, visitor).generate();
|
new InterfaceBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, visitor).generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateImplementation(JetClass aClass, OwnerKind kind) {
|
private void generateImplementation(JetClassOrObject aClass, OwnerKind kind) {
|
||||||
ClassDescriptor descriptor = bindingContext.getClassDescriptor(aClass);
|
ClassDescriptor descriptor = bindingContext.getClassDescriptor(aClass);
|
||||||
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION ? factory.forClassImplementation(descriptor) : factory.forClassDelegatingImplementation(descriptor);
|
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION
|
||||||
|
? factory.forClassImplementation(descriptor)
|
||||||
|
: factory.forClassDelegatingImplementation(descriptor);
|
||||||
new ImplementationBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, kind, v).generate();
|
new ImplementationBodyCodegen(bindingContext, JetStandardLibrary.getJetStandardLibrary(project), aClass, kind, v).generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -597,6 +597,14 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
v.arraylength();
|
v.arraylength();
|
||||||
myStack.push(StackValue.onStack(Type.INT_TYPE));
|
myStack.push(StackValue.onStack(Type.INT_TYPE));
|
||||||
}
|
}
|
||||||
|
else if (declaration instanceof JetObjectDeclarationName) {
|
||||||
|
JetObjectDeclaration objectDeclaration = PsiTreeUtil.getParentOfType(declaration, JetObjectDeclaration.class);
|
||||||
|
ClassDescriptor classDescriptor = bindingContext.getClassDescriptor(objectDeclaration);
|
||||||
|
myStack.push(StackValue.field(typeMapper.jvmType(classDescriptor, OwnerKind.IMPLEMENTATION),
|
||||||
|
typeMapper.jvmName(classDescriptor, OwnerKind.IMPLEMENTATION),
|
||||||
|
"$instance",
|
||||||
|
true));
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
boolean isStatic = container instanceof NamespaceDescriptorImpl;
|
boolean isStatic = container instanceof NamespaceDescriptorImpl;
|
||||||
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
|
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
|
||||||
@@ -607,16 +615,17 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
myStack.push(iValue);
|
myStack.push(iValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else if (!(descriptor instanceof NamespaceDescriptor)) {
|
||||||
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
|
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean directToField) {
|
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean directToField) {
|
||||||
boolean isStatic = propertyDescriptor.getContainingDeclaration() instanceof NamespaceDescriptorImpl;
|
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||||
|
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
|
||||||
final JetType outType = propertyDescriptor.getOutType();
|
final JetType outType = propertyDescriptor.getOutType();
|
||||||
boolean isInsideClass = propertyDescriptor.getContainingDeclaration() == contextType;
|
boolean isInsideClass = containingDeclaration == contextType;
|
||||||
Method getter;
|
Method getter;
|
||||||
Method setter;
|
Method setter;
|
||||||
if (directToField) {
|
if (directToField) {
|
||||||
@@ -628,17 +637,18 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
setter = isInsideClass && propertyDescriptor.getSetter() == null ? null : typeMapper.mapSetterSignature(propertyDescriptor);
|
setter = isInsideClass && propertyDescriptor.getSetter() == null ? null : typeMapper.mapSetterSignature(propertyDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
String fieldOwner;
|
String owner;
|
||||||
String interfaceOwner;
|
boolean isInterface;
|
||||||
if (isInsideClass || isStatic) {
|
if (isInsideClass || isStatic) {
|
||||||
fieldOwner = interfaceOwner = typeMapper.getOwner(propertyDescriptor, contextKind);
|
owner = typeMapper.getOwner(propertyDescriptor, contextKind);
|
||||||
|
isInterface = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fieldOwner = null;
|
owner = typeMapper.getOwner(propertyDescriptor, OwnerKind.INTERFACE);
|
||||||
interfaceOwner = typeMapper.getOwner(propertyDescriptor, OwnerKind.INTERFACE);
|
isInterface = !(containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).isObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
return StackValue.property(propertyDescriptor.getName(), fieldOwner, interfaceOwner, typeMapper.mapType(outType), isStatic, getter, setter);
|
return StackValue.property(propertyDescriptor.getName(), owner, typeMapper.mapType(outType), isStatic, isInterface, getter, setter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ public class FunctionCodegen {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclarationDescriptor contextDescriptor = owner instanceof JetClass
|
DeclarationDescriptor contextDescriptor = owner instanceof JetClassOrObject
|
||||||
? bindingContext.getClassDescriptor((JetClass) owner)
|
? bindingContext.getClassDescriptor((JetClassOrObject) owner)
|
||||||
: bindingContext.getNamespaceDescriptor((JetNamespace) owner);
|
: bindingContext.getNamespaceDescriptor((JetNamespace) owner);
|
||||||
|
|
||||||
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
|
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
|
||||||
|
|||||||
@@ -12,16 +12,15 @@ import org.objectweb.asm.Type;
|
|||||||
import org.objectweb.asm.commons.InstructionAdapter;
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
import org.objectweb.asm.commons.Method;
|
import org.objectweb.asm.commons.Method;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author max
|
* @author max
|
||||||
* @author yole
|
* @author yole
|
||||||
*/
|
*/
|
||||||
public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||||
public ImplementationBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClass aClass, OwnerKind kind, ClassVisitor v) {
|
public ImplementationBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass,
|
||||||
|
OwnerKind kind, ClassVisitor v) {
|
||||||
super(bindingContext, stdlib, aClass, kind, v);
|
super(bindingContext, stdlib, aClass, kind, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,17 +28,25 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
protected void generateDeclaration() {
|
protected void generateDeclaration() {
|
||||||
String superClass = getSuperClass();
|
String superClass = getSuperClass();
|
||||||
|
|
||||||
final String defaultInterfaceName = JetTypeMapper.jvmNameForInterface(descriptor);
|
List<String> interfaces = new ArrayList<String>();
|
||||||
|
interfaces.add("jet/JetObject");
|
||||||
|
if (!(myClass instanceof JetObjectDeclaration)) {
|
||||||
|
interfaces.add(JetTypeMapper.jvmNameForInterface(descriptor));
|
||||||
|
}
|
||||||
v.visit(Opcodes.V1_6,
|
v.visit(Opcodes.V1_6,
|
||||||
Opcodes.ACC_PUBLIC,
|
Opcodes.ACC_PUBLIC,
|
||||||
JetTypeMapper.jetJvmName(descriptor, kind),
|
jvmName(),
|
||||||
null,
|
null,
|
||||||
superClass,
|
superClass,
|
||||||
new String[]{"jet/JetObject", defaultInterfaceName}
|
interfaces.toArray(new String[interfaces.size()])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getSuperClass() {
|
private String jvmName() {
|
||||||
|
return JetTypeMapper.jetJvmName(descriptor, kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getSuperClass() {
|
||||||
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
|
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
|
||||||
|
|
||||||
if (delegationSpecifiers.isEmpty()) return "java/lang/Object";
|
if (delegationSpecifiers.isEmpty()) return "java/lang/Object";
|
||||||
@@ -59,6 +66,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
int typeinfoStatic = descriptor.getTypeConstructor().getParameters().size() > 0 ? 0 : Opcodes.ACC_STATIC;
|
int typeinfoStatic = descriptor.getTypeConstructor().getParameters().size() > 0 ? 0 : Opcodes.ACC_STATIC;
|
||||||
v.visitField(Opcodes.ACC_PRIVATE | typeinfoStatic, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
v.visitField(Opcodes.ACC_PRIVATE | typeinfoStatic, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
||||||
|
|
||||||
|
if (myClass instanceof JetObjectDeclaration) {
|
||||||
|
Type type = JetTypeMapper.jetImplementationType(descriptor);
|
||||||
|
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$instance", type.getDescriptor(), null, null);
|
||||||
|
}
|
||||||
|
|
||||||
generateStaticInitializer();
|
generateStaticInitializer();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -71,17 +83,25 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
generateGetTypeInfo();
|
generateGetTypeInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generatePrimaryConstructor() {
|
protected void generatePrimaryConstructor() {
|
||||||
ConstructorDescriptor constructorDescriptor = bindingContext.getConstructorDescriptor(myClass);
|
ConstructorDescriptor constructorDescriptor = bindingContext.getConstructorDescriptor((JetElement) myClass);
|
||||||
if (constructorDescriptor == null) return;
|
if (constructorDescriptor == null && !(myClass instanceof JetObjectDeclaration)) return;
|
||||||
|
|
||||||
Method method = typeMapper.mapConstructorSignature(constructorDescriptor, kind);
|
Method method;
|
||||||
|
if (myClass instanceof JetObjectDeclaration) {
|
||||||
|
method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
method = typeMapper.mapConstructorSignature(constructorDescriptor, kind);
|
||||||
|
}
|
||||||
int flags = Opcodes.ACC_PUBLIC; // TODO
|
int flags = Opcodes.ACC_PUBLIC; // TODO
|
||||||
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
|
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
Type[] argTypes = method.getArgumentTypes();
|
Type[] argTypes = method.getArgumentTypes();
|
||||||
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor.getUnsubstitutedValueParameters();
|
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
|
||||||
|
? constructorDescriptor.getUnsubstitutedValueParameters()
|
||||||
|
: Collections.<ValueParameterDescriptor>emptyList();
|
||||||
|
|
||||||
FrameMap frameMap = new FrameMap();
|
FrameMap frameMap = new FrameMap();
|
||||||
frameMap.enterTemp(); // this
|
frameMap.enterTemp(); // this
|
||||||
@@ -161,7 +181,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
int n = 0;
|
int n = 0;
|
||||||
for (JetDelegationSpecifier specifier : specifiers) {
|
for (JetDelegationSpecifier specifier : specifiers) {
|
||||||
boolean delegateOnStack = specifier instanceof JetDelegatorToSuperCall && n > 0 ||
|
boolean delegateOnStack = specifier instanceof JetDelegatorToSuperCall && n > 0 ||
|
||||||
specifier instanceof JetDelegatorByExpressionSpecifier ;
|
specifier instanceof JetDelegatorByExpressionSpecifier;
|
||||||
|
|
||||||
if (delegateOnStack) {
|
if (delegateOnStack) {
|
||||||
iv.load(0, classType);
|
iv.load(0, classType);
|
||||||
@@ -233,7 +253,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
generateInitializers(codegen, iv);
|
generateInitializers(codegen, iv);
|
||||||
|
|
||||||
int curParam = 0;
|
int curParam = 0;
|
||||||
List<JetParameter> constructorParameters = myClass.getPrimaryConstructorParameters();
|
List<JetParameter> constructorParameters = getPrimaryConstructorParameters();
|
||||||
for (JetParameter parameter : constructorParameters) {
|
for (JetParameter parameter : constructorParameters) {
|
||||||
if (parameter.getValOrVarNode() != null) {
|
if (parameter.getValOrVarNode() != null) {
|
||||||
VariableDescriptor descriptor = paramDescrs.get(curParam);
|
VariableDescriptor descriptor = paramDescrs.get(curParam);
|
||||||
@@ -250,7 +270,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
|
protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
|
||||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
iv.anew(JetTypeMapper.TYPE_TYPEINFO);
|
iv.anew(JetTypeMapper.TYPE_TYPEINFO);
|
||||||
iv.dup();
|
iv.dup();
|
||||||
@@ -269,7 +289,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
iv.putfield(typeMapper.jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
iv.putfield(typeMapper.jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) {
|
protected void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) {
|
||||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||||
if (declaration instanceof JetProperty) {
|
if (declaration instanceof JetProperty) {
|
||||||
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.getVariableDescriptor((JetProperty) declaration);
|
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.getVariableDescriptor((JetProperty) declaration);
|
||||||
@@ -289,7 +309,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateDelegates(JetClass inClass, JetClass toClass, OwnerKind kind, Set<FunctionDescriptor> overriden) {
|
protected void generateDelegates(JetClassOrObject inClass, JetClass toClass, OwnerKind kind, Set<FunctionDescriptor> overriden) {
|
||||||
final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, stdlib, bindingContext);
|
final FunctionCodegen functionCodegen = new FunctionCodegen(toClass, v, stdlib, bindingContext);
|
||||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen);
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(v, stdlib, bindingContext, functionCodegen);
|
||||||
|
|
||||||
@@ -318,7 +338,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateStaticInitializer() {
|
private void generateStaticInitializer() {
|
||||||
if (descriptor.getTypeConstructor().getParameters().size() > 0) {
|
boolean needTypeInfo = descriptor.getTypeConstructor().getParameters().size() == 0;
|
||||||
|
boolean needInstance = myClass instanceof JetObjectDeclaration;
|
||||||
|
if (!needTypeInfo && !needInstance) {
|
||||||
// we will have a dynamic type info field
|
// we will have a dynamic type info field
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -327,8 +349,18 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
|
|
||||||
InstructionAdapter v = new InstructionAdapter(mv);
|
InstructionAdapter v = new InstructionAdapter(mv);
|
||||||
ClassCodegen.newTypeInfo(v, Type.getObjectType(JetTypeMapper.jvmNameForInterface(descriptor)));
|
|
||||||
v.putstatic(JetTypeMapper.jvmNameForImplementation(descriptor), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
if (needTypeInfo) {
|
||||||
|
ClassCodegen.newTypeInfo(v, typeMapper.jvmType(descriptor, OwnerKind.INTERFACE));
|
||||||
|
v.putstatic(JetTypeMapper.jvmNameForImplementation(descriptor), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||||
|
}
|
||||||
|
if (needInstance) {
|
||||||
|
String name = jvmName();
|
||||||
|
v.anew(Type.getObjectType(name));
|
||||||
|
v.dup();
|
||||||
|
v.invokespecial(name, "<init>", "()V");
|
||||||
|
v.putstatic(name, "$instance", JetTypeMapper.jetImplementationType(descriptor).getDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
mv.visitInsn(Opcodes.RETURN);
|
mv.visitInsn(Opcodes.RETURN);
|
||||||
mv.visitMaxs(0, 0);
|
mv.visitMaxs(0, 0);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package org.jetbrains.jet.codegen;
|
|||||||
import com.intellij.psi.PsiClass;
|
import com.intellij.psi.PsiClass;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetClass;
|
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||||
import org.jetbrains.jet.lang.psi.JetDelegationSpecifier;
|
import org.jetbrains.jet.lang.psi.JetDelegationSpecifier;
|
||||||
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;
|
||||||
@@ -19,7 +19,7 @@ import java.util.Set;
|
|||||||
* @author yole
|
* @author yole
|
||||||
*/
|
*/
|
||||||
public class InterfaceBodyCodegen extends ClassBodyCodegen {
|
public class InterfaceBodyCodegen extends ClassBodyCodegen {
|
||||||
public InterfaceBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClass aClass, ClassVisitor v) {
|
public InterfaceBodyCodegen(BindingContext bindingContext, JetStandardLibrary stdlib, JetClassOrObject aClass, ClassVisitor v) {
|
||||||
super(bindingContext, stdlib, aClass, OwnerKind.INTERFACE, v);
|
super(bindingContext, stdlib, aClass, OwnerKind.INTERFACE, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) {
|
public static String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) {
|
||||||
|
if (jetClass.isObject()) {
|
||||||
|
return jvmNameForImplementation(jetClass);
|
||||||
|
}
|
||||||
if (kind == OwnerKind.INTERFACE) {
|
if (kind == OwnerKind.INTERFACE) {
|
||||||
return jvmNameForInterface(jetClass);
|
return jvmNameForInterface(jetClass);
|
||||||
}
|
}
|
||||||
@@ -118,7 +121,13 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
else if (descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
|
else if (descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||||
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration();
|
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration();
|
||||||
owner = jvmName(classDescriptor, kind instanceof OwnerKind.DelegateKind ? OwnerKind.INTERFACE : kind);
|
if (kind instanceof OwnerKind.DelegateKind) {
|
||||||
|
kind = OwnerKind.INTERFACE;
|
||||||
|
}
|
||||||
|
else if (classDescriptor.isObject()) {
|
||||||
|
kind = OwnerKind.IMPLEMENTATION;
|
||||||
|
}
|
||||||
|
owner = jvmName(classDescriptor, kind);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("don't know how to generate owner for parent " + descriptor.getContainingDeclaration());
|
throw new UnsupportedOperationException("don't know how to generate owner for parent " + descriptor.getContainingDeclaration());
|
||||||
|
|||||||
@@ -38,9 +38,11 @@ public class NamespaceCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void generate(JetNamespace namespace) {
|
public void generate(JetNamespace namespace) {
|
||||||
BindingContext bindingContext1 = AnalyzingUtils.analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY);
|
generate(namespace, AnalyzingUtils.analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY));
|
||||||
AnalyzingUtils.applyHandler(ErrorHandler.THROW_EXCEPTION, bindingContext1);
|
}
|
||||||
BindingContext bindingContext = bindingContext1;
|
|
||||||
|
public void generate(JetNamespace namespace, BindingContext bindingContext) {
|
||||||
|
AnalyzingUtils.applyHandler(ErrorHandler.THROW_EXCEPTION, bindingContext);
|
||||||
|
|
||||||
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
|
final JetStandardLibrary standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
|
||||||
final FunctionCodegen functionCodegen = new FunctionCodegen(namespace, v, standardLibrary, bindingContext);
|
final FunctionCodegen functionCodegen = new FunctionCodegen(namespace, v, standardLibrary, bindingContext);
|
||||||
@@ -62,8 +64,12 @@ public class NamespaceCodegen {
|
|||||||
throw new RuntimeException("Failed to generate function " + declaration.getName(), e);
|
throw new RuntimeException("Failed to generate function " + declaration.getName(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (declaration instanceof JetClass) {
|
else if (declaration instanceof JetClassOrObject) {
|
||||||
classCodegen.generate((JetClass) declaration);
|
classCodegen.generate((JetClassOrObject) declaration);
|
||||||
|
}
|
||||||
|
else if (declaration instanceof JetNamespace) {
|
||||||
|
JetNamespace childNamespace = (JetNamespace) declaration;
|
||||||
|
codegens.forNamespace(childNamespace).generate(childNamespace, bindingContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ public class PropertyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isExternallyAccessible(JetProperty p) {
|
private static boolean isExternallyAccessible(JetProperty p) {
|
||||||
return p.hasModifier(JetTokens.PUBLIC_KEYWORD);
|
return !p.hasModifier(JetTokens.PRIVATE_KEYWORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateSetter(JetProperty p, OwnerKind kind, PropertyDescriptor propertyDescriptor) {
|
private void generateSetter(JetProperty p, OwnerKind kind, PropertyDescriptor propertyDescriptor) {
|
||||||
|
|||||||
@@ -71,8 +71,8 @@ public abstract class StackValue {
|
|||||||
return new Field(type, owner, name, isStatic);
|
return new Field(type, owner, name, isStatic);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StackValue property(String name, String fieldOwner, String interfaceOwner, Type type, boolean isStatic, Method getter, Method setter) {
|
public static StackValue property(String name, String owner, Type type, boolean isStatic, boolean isInterface, Method getter, Method setter) {
|
||||||
return new Property(name, fieldOwner, interfaceOwner, getter, setter, isStatic, type);
|
return new Property(name, owner, getter, setter, isStatic, isInterface, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void box(final Type type, final Type toType, InstructionAdapter v) {
|
private static void box(final Type type, final Type toType, InstructionAdapter v) {
|
||||||
@@ -391,37 +391,37 @@ public abstract class StackValue {
|
|||||||
private final String name;
|
private final String name;
|
||||||
private final Method getter;
|
private final Method getter;
|
||||||
private final Method setter;
|
private final Method setter;
|
||||||
|
private final String owner;
|
||||||
private final boolean isStatic;
|
private final boolean isStatic;
|
||||||
private final String fieldOwner;
|
private final boolean isInterface;
|
||||||
private final String interfaceOwner;
|
|
||||||
|
|
||||||
public Property(String name, String fieldOwner, String interfaceOwner, Method getter, Method setter, boolean aStatic, Type type) {
|
public Property(String name, String owner, Method getter, Method setter, boolean aStatic, boolean isInterface, Type type) {
|
||||||
super(type);
|
super(type);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.fieldOwner = fieldOwner;
|
this.owner = owner;
|
||||||
this.interfaceOwner = interfaceOwner;
|
|
||||||
this.getter = getter;
|
this.getter = getter;
|
||||||
this.setter = setter;
|
this.setter = setter;
|
||||||
isStatic = aStatic;
|
isStatic = aStatic;
|
||||||
|
this.isInterface = isInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void put(Type type, InstructionAdapter v) {
|
public void put(Type type, InstructionAdapter v) {
|
||||||
if (getter == null) {
|
if (getter == null) {
|
||||||
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, fieldOwner, name, this.type.getDescriptor());
|
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : fieldOwner == null ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, interfaceOwner, getter.getName(), getter.getDescriptor());
|
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, getter.getName(), getter.getDescriptor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void store(InstructionAdapter v) {
|
public void store(InstructionAdapter v) {
|
||||||
if (setter == null) {
|
if (setter == null) {
|
||||||
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, fieldOwner, name, this.type.getDescriptor());
|
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : fieldOwner == null ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, interfaceOwner, setter.getName(), setter.getDescriptor());
|
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, setter.getName(), setter.getDescriptor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ public class JetArrayAccessExpression extends JetReferenceExpression {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PsiReference getReference() {
|
public PsiReference getReference() {
|
||||||
return new JetArrayAccessReference();
|
JetContainerNode indicesNode = getIndicesNode();
|
||||||
|
return indicesNode == null ? null : new JetArrayAccessReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -41,11 +42,15 @@ public class JetArrayAccessExpression extends JetReferenceExpression {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<JetExpression> getIndexExpressions() {
|
public List<JetExpression> getIndexExpressions() {
|
||||||
PsiElement container = findChildByType(JetNodeTypes.INDICES);
|
PsiElement container = getIndicesNode();
|
||||||
if (container == null) return Collections.emptyList();
|
if (container == null) return Collections.emptyList();
|
||||||
return PsiTreeUtil.getChildrenOfTypeAsList(container, JetExpression.class);
|
return PsiTreeUtil.getChildrenOfTypeAsList(container, JetExpression.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JetContainerNode getIndicesNode() {
|
||||||
|
return (JetContainerNode) findChildByType(JetNodeTypes.INDICES);
|
||||||
|
}
|
||||||
|
|
||||||
private class JetArrayAccessReference extends JetPsiReference implements MultiRangeReference {
|
private class JetArrayAccessReference extends JetPsiReference implements MultiRangeReference {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -62,7 +67,7 @@ public class JetArrayAccessExpression extends JetReferenceExpression {
|
|||||||
public List<TextRange> getRanges() {
|
public List<TextRange> getRanges() {
|
||||||
List<TextRange> list = new ArrayList<TextRange>();
|
List<TextRange> list = new ArrayList<TextRange>();
|
||||||
|
|
||||||
JetContainerNode indices = (JetContainerNode) findChildByType(JetNodeTypes.INDICES);
|
JetContainerNode indices = getIndicesNode();
|
||||||
TextRange textRange = indices.getNode().findChildByType(JetTokens.LBRACKET).getTextRange();
|
TextRange textRange = indices.getNode().findChildByType(JetTokens.LBRACKET).getTextRange();
|
||||||
TextRange lBracketRange = textRange.shiftRight(-getTextOffset());
|
TextRange lBracketRange = textRange.shiftRight(-getTextOffset());
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,13 @@ public class JetNamespace extends JetNamedDeclaration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getFQName() {
|
public String getFQName() {
|
||||||
return getName(); // TODO: Must include container namespace names, module root namespace
|
JetNamespace parent = PsiTreeUtil.getParentOfType(this, JetNamespace.class);
|
||||||
|
if (parent != null) {
|
||||||
|
String parentFQName = parent.getFQName();
|
||||||
|
if (parentFQName.length() > 0) {
|
||||||
|
return parentFQName + "." + getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getName(); // TODO: Must include module root namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,9 @@ public class JetStructureViewElement implements StructureViewTreeElement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Icon getIcon(boolean open) {
|
public Icon getIcon(boolean open) {
|
||||||
return PsiIconUtil.getProvidersIcon(myElement, open ? Iconable.ICON_FLAG_OPEN : Iconable.ICON_FLAG_CLOSED);
|
return myElement.isValid()
|
||||||
|
? PsiIconUtil.getProvidersIcon(myElement, open ? Iconable.ICON_FLAG_OPEN : Iconable.ICON_FLAG_CLOSED)
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Foo {
|
||||||
|
fun bar() = 610
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return if (Foo.bar() == 610) "OK" else "fail"
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
object A {
|
||||||
|
val x: Int = 610
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
return if (A.x != 610) "fail" else "OK"
|
||||||
|
}
|
||||||
@@ -68,6 +68,9 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
|
|||||||
String actual;
|
String actual;
|
||||||
try {
|
try {
|
||||||
actual = blackBox();
|
actual = blackBox();
|
||||||
|
} catch (NoClassDefFoundError e) {
|
||||||
|
System.out.println(generateToText());
|
||||||
|
throw e;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
throw e;
|
throw e;
|
||||||
|
|||||||
@@ -400,4 +400,8 @@ public class NamespaceGenTest extends CodegenTestCase {
|
|||||||
final StringBuilder sb = new StringBuilder("x");
|
final StringBuilder sb = new StringBuilder("x");
|
||||||
assertEquals('x', ((Character) main.invoke(null, sb)).charValue());
|
assertEquals('x', ((Character) main.invoke(null, sb)).charValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testNamespaceQualifiedMethod() throws Exception {
|
||||||
|
blackBoxFile("namespaceQualifiedMethod.jet");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author yole
|
||||||
|
*/
|
||||||
|
public class ObjectGenTest extends CodegenTestCase {
|
||||||
|
public void testSimpleObject() throws Exception {
|
||||||
|
blackBoxFile("objects/simpleObject.jet");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user