Merge branch 'master' of ssh://git.labs.intellij.net/jet
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
@@ -12,14 +11,13 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yole
|
* @author yole
|
||||||
|
* @author alex.tkacman
|
||||||
*/
|
*/
|
||||||
public class CallableMethod implements Callable {
|
public class CallableMethod implements Callable {
|
||||||
private String owner;
|
private String owner;
|
||||||
private final Method signature;
|
private final Method signature;
|
||||||
private final int invokeOpcode;
|
private int invokeOpcode;
|
||||||
private final List<Type> valueParameterTypes;
|
private final List<Type> valueParameterTypes;
|
||||||
private boolean acceptsTypeArguments = false;
|
|
||||||
private boolean ownerFromCall = false;
|
|
||||||
private DeclarationDescriptor thisClass = null;
|
private DeclarationDescriptor thisClass = null;
|
||||||
private DeclarationDescriptor receiverClass = null;
|
private DeclarationDescriptor receiverClass = null;
|
||||||
private Type generateCalleeType = null;
|
private Type generateCalleeType = null;
|
||||||
@@ -35,10 +33,6 @@ public class CallableMethod implements Callable {
|
|||||||
return owner;
|
return owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOwner(String owner) {
|
|
||||||
this.owner = owner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Method getSignature() {
|
public Method getSignature() {
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
@@ -51,14 +45,6 @@ public class CallableMethod implements Callable {
|
|||||||
return valueParameterTypes;
|
return valueParameterTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean acceptsTypeArguments() {
|
|
||||||
return acceptsTypeArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAcceptsTypeArguments(boolean acceptsTypeArguments) {
|
|
||||||
this.acceptsTypeArguments = acceptsTypeArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNeedsReceiver(@Nullable DeclarationDescriptor receiverClass) {
|
public void setNeedsReceiver(@Nullable DeclarationDescriptor receiverClass) {
|
||||||
this.receiverClass = receiverClass;
|
this.receiverClass = receiverClass;
|
||||||
}
|
}
|
||||||
@@ -67,14 +53,6 @@ public class CallableMethod implements Callable {
|
|||||||
this.thisClass = receiverClass;
|
this.thisClass = receiverClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOwnerFromCall() {
|
|
||||||
return ownerFromCall;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwnerFromCall(boolean ownerFromCall) {
|
|
||||||
this.ownerFromCall = ownerFromCall;
|
|
||||||
}
|
|
||||||
|
|
||||||
void invoke(InstructionAdapter v) {
|
void invoke(InstructionAdapter v) {
|
||||||
v.visitMethodInsn(getInvokeOpcode(), getOwner(), getSignature().getName(), getSignature().getDescriptor());
|
v.visitMethodInsn(getInvokeOpcode(), getOwner(), getSignature().getName(), getSignature().getDescriptor());
|
||||||
}
|
}
|
||||||
@@ -106,5 +84,4 @@ public class CallableMethod implements Callable {
|
|||||||
public DeclarationDescriptor getThisClass() {
|
public DeclarationDescriptor getThisClass() {
|
||||||
return thisClass;
|
return thisClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
@@ -11,6 +14,7 @@ import org.objectweb.asm.commons.InstructionAdapter;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,12 +41,12 @@ public abstract class ClassBodyCodegen {
|
|||||||
this.v = v;
|
this.v = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generate() {
|
public final void generate(@Nullable HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||||
generateDeclaration();
|
generateDeclaration();
|
||||||
|
|
||||||
generateClassBody();
|
generateClassBody();
|
||||||
|
|
||||||
generateSyntheticParts();
|
generateSyntheticParts(accessors);
|
||||||
|
|
||||||
generateStaticInitializer();
|
generateStaticInitializer();
|
||||||
|
|
||||||
@@ -51,7 +55,7 @@ public abstract class ClassBodyCodegen {
|
|||||||
|
|
||||||
protected abstract void generateDeclaration();
|
protected abstract void generateDeclaration();
|
||||||
|
|
||||||
protected void generateSyntheticParts() {
|
protected void generateSyntheticParts(HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateClassBody() {
|
private void generateClassBody() {
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ public class ClassBuilder {
|
|||||||
int access,
|
int access,
|
||||||
String name,
|
String name,
|
||||||
String desc,
|
String desc,
|
||||||
String signature,
|
@Nullable String signature,
|
||||||
Object value) {
|
@Nullable Object value) {
|
||||||
return v.visitField(access, name, desc, signature, value);
|
return v.visitField(access, name, desc, signature, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,11 +49,11 @@ public class ClassBuilder {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void defineClass(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
public void defineClass(int version, int access, String name, @Nullable String signature, String superName, String[] interfaces) {
|
||||||
v.visit(version, access, name, signature, superName, interfaces);
|
v.visit(version, access, name, signature, superName, interfaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitSource(String name, String debug) {
|
public void visitSource(String name, @Nullable String debug) {
|
||||||
v.visitSource(name, debug);
|
v.visitSource(name, debug);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author max
|
* @author max
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
@@ -15,29 +19,30 @@ public class ClassCodegen {
|
|||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generate(ClassContext parentContext, JetClassOrObject aClass) {
|
public void generate(ClassContext context, JetClassOrObject aClass) {
|
||||||
GenerationState.prepareAnonymousClasses((JetElement) aClass, state.getTypeMapper());
|
GenerationState.prepareAnonymousClasses((JetElement) aClass, state.getTypeMapper());
|
||||||
|
|
||||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||||
|
|
||||||
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
|
final ClassContext contextForInners = context.intoClass(null, descriptor, OwnerKind.IMPLEMENTATION);
|
||||||
|
|
||||||
final ClassContext contextForInners = parentContext.intoClass(null, descriptor, OwnerKind.IMPLEMENTATION);
|
|
||||||
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
||||||
if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) {
|
if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) {
|
||||||
generate(contextForInners, (JetClass) declaration);
|
generate(contextForInners, (JetClass) declaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.accessors);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateImplementation(ClassContext parentContext, JetClassOrObject aClass, OwnerKind kind) {
|
private void generateImplementation(ClassContext context, JetClassOrObject aClass, OwnerKind kind, HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||||
ClassBuilder v = state.forClassImplementation(descriptor);
|
ClassBuilder v = state.forClassImplementation(descriptor);
|
||||||
new ImplementationBodyCodegen(aClass, parentContext.intoClass(null, descriptor, kind), v, state).generate();
|
ClassContext classContext = context.intoClass(null, descriptor, kind);
|
||||||
|
new ImplementationBodyCodegen(aClass, classContext, v, state).generate(accessors);
|
||||||
|
|
||||||
if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) {
|
if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) {
|
||||||
v = state.forTraitImplementation(descriptor);
|
v = state.forTraitImplementation(descriptor);
|
||||||
new TraitImplBodyCodegen(aClass, parentContext.intoClass(null, descriptor, OwnerKind.TRAIT_IMPL), v, state).generate();
|
new TraitImplBodyCodegen(aClass, context.intoClass(null, descriptor, OwnerKind.TRAIT_IMPL), v, state).generate(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
import org.jetbrains.jet.lang.psi.JetTypeReference;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
import org.objectweb.asm.commons.InstructionAdapter;
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.diagnostics.Errors.WRONG_GETTER_RETURN_TYPE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @author max
|
* @author max
|
||||||
@@ -20,11 +26,12 @@ public class ClassContext {
|
|||||||
private final DeclarationDescriptor contextType;
|
private final DeclarationDescriptor contextType;
|
||||||
private final OwnerKind contextKind;
|
private final OwnerKind contextKind;
|
||||||
private final StackValue thisExpression;
|
private final StackValue thisExpression;
|
||||||
private final ClassContext parentContext;
|
final ClassContext parentContext;
|
||||||
public final FunctionOrClosureCodegen closure;
|
public final FunctionOrClosureCodegen closure;
|
||||||
private boolean thisWasUsed = false;
|
private boolean thisWasUsed = false;
|
||||||
|
|
||||||
HashMap<JetType,Integer> typeInfoConstants;
|
HashMap<JetType,Integer> typeInfoConstants;
|
||||||
|
HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors;
|
||||||
|
|
||||||
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, FunctionOrClosureCodegen closureCodegen) {
|
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, FunctionOrClosureCodegen closureCodegen) {
|
||||||
this.contextType = contextType;
|
this.contextType = contextType;
|
||||||
@@ -61,7 +68,7 @@ public class ClassContext {
|
|||||||
return new ClassContext(descriptor, OwnerKind.NAMESPACE, null, this, null);
|
return new ClassContext(descriptor, OwnerKind.NAMESPACE, null, this, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassContext intoClass(FunctionOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) {
|
public ClassContext intoClass(@Nullable FunctionOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) {
|
||||||
final StackValue thisValue;
|
final StackValue thisValue;
|
||||||
thisValue = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
thisValue = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
|
||||||
@@ -193,4 +200,59 @@ public class ClassContext {
|
|||||||
}
|
}
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeclarationDescriptor getAccessor(DeclarationDescriptor descriptor) {
|
||||||
|
if(accessors == null) {
|
||||||
|
accessors = new HashMap<DeclarationDescriptor,DeclarationDescriptor>();
|
||||||
|
}
|
||||||
|
descriptor = descriptor.getOriginal();
|
||||||
|
DeclarationDescriptor accessor = accessors.get(descriptor);
|
||||||
|
if(accessor != null)
|
||||||
|
return accessor;
|
||||||
|
|
||||||
|
if(descriptor instanceof FunctionDescriptor) {
|
||||||
|
FunctionDescriptorImpl myAccessor = new FunctionDescriptorImpl(contextType,
|
||||||
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
|
descriptor.getName() + "$bridge$" + accessors.size());
|
||||||
|
FunctionDescriptor fd = (FunctionDescriptor) descriptor;
|
||||||
|
myAccessor.initialize(fd.getReceiverParameter().exists() ? fd.getReceiverParameter().getType() : null,
|
||||||
|
fd.getExpectedThisObject(),
|
||||||
|
fd.getTypeParameters(),
|
||||||
|
fd.getValueParameters(),
|
||||||
|
fd.getReturnType(),
|
||||||
|
fd.getModality(),
|
||||||
|
fd.getVisibility());
|
||||||
|
accessor = myAccessor;
|
||||||
|
}
|
||||||
|
else if(descriptor instanceof PropertyDescriptor) {
|
||||||
|
PropertyDescriptor pd = (PropertyDescriptor) descriptor;
|
||||||
|
PropertyDescriptor myAccessor = new PropertyDescriptor(contextType,
|
||||||
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
|
pd.getModality(),
|
||||||
|
pd.getVisibility(),
|
||||||
|
pd.isVar(),
|
||||||
|
pd.getReceiverParameter().exists() ? pd.getReceiverParameter().getType() : null,
|
||||||
|
pd.getExpectedThisObject(),
|
||||||
|
pd.getName() + "$bridge$" + accessors.size(),
|
||||||
|
pd.getInType(),
|
||||||
|
pd.getOutType());
|
||||||
|
PropertyGetterDescriptor pgd = new PropertyGetterDescriptor(
|
||||||
|
myAccessor, Collections.<AnnotationDescriptor>emptyList(), myAccessor.getModality(),
|
||||||
|
myAccessor.getVisibility(),
|
||||||
|
myAccessor.getOutType(), false, false);
|
||||||
|
PropertySetterDescriptor psd = new PropertySetterDescriptor(
|
||||||
|
myAccessor.getModality(),
|
||||||
|
myAccessor.getVisibility(),
|
||||||
|
myAccessor,
|
||||||
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
|
false, false);
|
||||||
|
myAccessor.initialize(Collections.<TypeParameterDescriptor>emptyList(), pgd, psd);
|
||||||
|
accessor = myAccessor;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
accessors.put(descriptor, accessor);
|
||||||
|
return accessor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ package org.jetbrains.jet.codegen;
|
|||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassKind;
|
import org.jetbrains.jet.lang.descriptors.ClassKind;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.objectweb.asm.Type;
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
@@ -62,4 +64,38 @@ public class CodegenUtil {
|
|||||||
|
|
||||||
return hasOuterTypeInfo(outerClassDescriptor);
|
return hasOuterTypeInfo(outerClassDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean hasDerivedTypeInfoField(JetType type, boolean exceptOwn) {
|
||||||
|
if(!exceptOwn) {
|
||||||
|
if(!isInterface(type))
|
||||||
|
if(hasTypeInfoField(type))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
||||||
|
if(hasDerivedTypeInfoField(jetType, false))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasTypeInfoField(JetType type) {
|
||||||
|
List<TypeParameterDescriptor> parameters = type.getConstructor().getParameters();
|
||||||
|
for (TypeParameterDescriptor parameter : parameters) {
|
||||||
|
if(parameter.isReified())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
||||||
|
if(hasTypeInfoField(jetType))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassDescriptor outerClassDescriptor = getOuterClassDescriptor(type.getConstructor().getDeclarationDescriptor());
|
||||||
|
if(outerClassDescriptor == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return hasTypeInfoField(outerClassDescriptor.getDefaultType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
// if(hND != null)
|
// if(hND != null)
|
||||||
// invokeFunctionNoParams(hND, Type.BOOLEAN_TYPE, v);
|
// invokeFunctionNoParams(hND, Type.BOOLEAN_TYPE, v);
|
||||||
// else
|
// else
|
||||||
intermediateValueForProperty((PropertyDescriptor) hasNextDescriptor, false, false, false).put(Type.BOOLEAN_TYPE, v);
|
intermediateValueForProperty((PropertyDescriptor) hasNextDescriptor, false, null).put(Type.BOOLEAN_TYPE, v);
|
||||||
}
|
}
|
||||||
v.ifeq(end);
|
v.ifeq(end);
|
||||||
|
|
||||||
@@ -760,9 +760,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor);
|
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor);
|
||||||
if (declaration instanceof PsiField) {
|
if (declaration instanceof PsiField) {
|
||||||
|
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||||
PsiField psiField = (PsiField) declaration;
|
PsiField psiField = (PsiField) declaration;
|
||||||
final String owner = JetTypeMapper.jvmName(psiField.getContainingClass());
|
final String owner = typeMapper.getOwner(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
||||||
final Type fieldType = JetTypeMapper.psiTypeToAsm(psiField.getType());
|
final Type fieldType = typeMapper.mapType(propertyDescriptor.getReturnType());
|
||||||
final boolean isStatic = psiField.hasModifierProperty(PsiModifier.STATIC);
|
final boolean isStatic = psiField.hasModifierProperty(PsiModifier.STATIC);
|
||||||
if (!isStatic) {
|
if (!isStatic) {
|
||||||
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||||
@@ -812,9 +813,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
boolean isStatic = container instanceof NamespaceDescriptorImpl;
|
boolean isStatic = container instanceof NamespaceDescriptorImpl;
|
||||||
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL ;
|
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL ;
|
||||||
JetExpression r = getReceiverForSelector(expression);
|
JetExpression r = getReceiverForSelector(expression);
|
||||||
final boolean forceInterface = r != null && !(r instanceof JetThisExpression);
|
|
||||||
final boolean isSuper = r instanceof JetSuperExpression;
|
final boolean isSuper = r instanceof JetSuperExpression;
|
||||||
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField, forceInterface, isSuper);
|
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression)r : null);
|
||||||
if (!isStatic) {
|
if (!isStatic) {
|
||||||
if (receiver == StackValue.none()) {
|
if (receiver == StackValue.none()) {
|
||||||
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
|
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
|
||||||
@@ -825,6 +825,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
ClassDescriptor propReceiverDescriptor = (ClassDescriptor) propertyDescriptor.getContainingDeclaration();
|
ClassDescriptor propReceiverDescriptor = (ClassDescriptor) propertyDescriptor.getContainingDeclaration();
|
||||||
if(!CodegenUtil.isInterface(propReceiverDescriptor) && CodegenUtil.isInterface(receiverType.getConstructor().getDeclarationDescriptor())) {
|
if(!CodegenUtil.isInterface(propReceiverDescriptor) && CodegenUtil.isInterface(receiverType.getConstructor().getDeclarationDescriptor())) {
|
||||||
// I hope it happens only in case of required super class for traits
|
// I hope it happens only in case of required super class for traits
|
||||||
|
assert propReceiverDescriptor != null;
|
||||||
v.checkcast(typeMapper.mapType(propReceiverDescriptor.getDefaultType()));
|
v.checkcast(typeMapper.mapType(propReceiverDescriptor.getDefaultType()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -895,9 +896,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
else {
|
else {
|
||||||
owner = typeMapper.getOwner(functionDescriptor, OwnerKind.IMPLEMENTATION);
|
owner = typeMapper.getOwner(functionDescriptor, OwnerKind.IMPLEMENTATION);
|
||||||
if(containingDeclaration instanceof JavaClassDescriptor) {
|
if(containingDeclaration instanceof JavaClassDescriptor) {
|
||||||
PsiClass psiElement = (PsiClass) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, containingDeclaration);
|
isInterface = CodegenUtil.isInterface(containingDeclaration);
|
||||||
assert psiElement != null;
|
|
||||||
isInterface = psiElement.isInterface();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.OBJECT)
|
if(containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.OBJECT)
|
||||||
@@ -913,11 +912,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
StackValue.onStack(typeMapper.mapType(functionDescriptor.getReturnType())).coerce(type, v);
|
StackValue.onStack(typeMapper.mapType(functionDescriptor.getReturnType())).coerce(type, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, boolean forceInterface, boolean isSuper) {
|
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, @Nullable JetSuperExpression superExpression) {
|
||||||
|
boolean isSuper = superExpression != null;
|
||||||
|
|
||||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||||
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
|
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
|
||||||
propertyDescriptor = propertyDescriptor.getOriginal();
|
propertyDescriptor = propertyDescriptor.getOriginal();
|
||||||
boolean isInsideClass = !forceInterface && containingDeclaration == context.getContextClass() && contextKind() != OwnerKind.TRAIT_IMPL;
|
boolean isInsideClass = containingDeclaration == context.getContextClass() && contextKind() != OwnerKind.TRAIT_IMPL;
|
||||||
Method getter;
|
Method getter;
|
||||||
Method setter;
|
Method setter;
|
||||||
if (forceField) {
|
if (forceField) {
|
||||||
@@ -926,11 +927,33 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
getter = isInsideClass && (propertyDescriptor.getGetter() == null || propertyDescriptor.getGetter().isDefault())
|
if (isInsideClass && (propertyDescriptor.getGetter() == null || propertyDescriptor.getGetter().isDefault())) {
|
||||||
? null : typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
getter = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(isSuper) {
|
||||||
|
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
|
||||||
|
ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement);
|
||||||
|
if(!CodegenUtil.isInterface(propertyDescriptor.getContainingDeclaration())) {
|
||||||
|
if(enclosed != null && enclosed != context.getContextClass()) {
|
||||||
|
ClassContext c = context;
|
||||||
|
while(c.getContextDescriptor() != enclosed) {
|
||||||
|
c = c.getParentContext();
|
||||||
|
}
|
||||||
|
propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor);
|
||||||
|
isSuper = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
||||||
|
}
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
setter = isInsideClass && (propertyDescriptor.getSetter() == null || propertyDescriptor.getSetter().isDefault())
|
if (isInsideClass && (propertyDescriptor.getSetter() == null || propertyDescriptor.getSetter().isDefault())) {
|
||||||
? null : typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
setter = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setter = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String owner;
|
String owner;
|
||||||
@@ -970,7 +993,28 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private StackValue invokeFunction(JetCallExpression expression, DeclarationDescriptor fd, StackValue receiver) {
|
private StackValue invokeFunction(JetCallExpression expression, DeclarationDescriptor fd, StackValue receiver) {
|
||||||
Callable callableMethod = resolveToCallable(fd);
|
boolean superCall = false;
|
||||||
|
if (expression.getParent() instanceof JetQualifiedExpression) {
|
||||||
|
final JetExpression receiverExpression = ((JetQualifiedExpression) expression.getParent()).getReceiverExpression();
|
||||||
|
if (receiverExpression instanceof JetSuperExpression) {
|
||||||
|
superCall = true;
|
||||||
|
JetSuperExpression superExpression = (JetSuperExpression) receiverExpression;
|
||||||
|
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
|
||||||
|
ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement);
|
||||||
|
if(!CodegenUtil.isInterface(fd.getContainingDeclaration())) {
|
||||||
|
if(enclosed != null && enclosed != context.getContextClass()) {
|
||||||
|
ClassContext c = context;
|
||||||
|
while(c.getContextDescriptor() != enclosed) {
|
||||||
|
c = c.getParentContext();
|
||||||
|
}
|
||||||
|
fd = c.getAccessor((FunctionDescriptor) fd);
|
||||||
|
superCall = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Callable callableMethod = resolveToCallable(fd, superCall);
|
||||||
return invokeCallable(fd, callableMethod, expression, receiver);
|
return invokeCallable(fd, callableMethod, expression, receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1002,22 +1046,19 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
return StackValue.none();
|
return StackValue.none();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Callable resolveToCallable(DeclarationDescriptor fd) {
|
private Callable resolveToCallable(DeclarationDescriptor fd, boolean superCall) {
|
||||||
final IntrinsicMethod intrinsic = intrinsics.getIntrinsic(fd);
|
final IntrinsicMethod intrinsic = intrinsics.getIntrinsic(fd);
|
||||||
if (intrinsic != null) {
|
if (intrinsic != null) {
|
||||||
return intrinsic;
|
return intrinsic;
|
||||||
}
|
}
|
||||||
PsiElement declarationPsiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, fd);
|
|
||||||
|
|
||||||
CallableMethod callableMethod;
|
CallableMethod callableMethod;
|
||||||
if (declarationPsiElement instanceof PsiMethod || declarationPsiElement instanceof JetNamedFunction) {
|
if (fd instanceof VariableAsFunctionDescriptor) {
|
||||||
callableMethod = typeMapper.mapToCallableMethod((PsiNamedElement) declarationPsiElement, null);
|
assert !superCall;
|
||||||
}
|
|
||||||
else if (fd instanceof VariableAsFunctionDescriptor) {
|
|
||||||
callableMethod = asCallableMethod((FunctionDescriptor) fd);
|
callableMethod = asCallableMethod((FunctionDescriptor) fd);
|
||||||
}
|
}
|
||||||
else if (fd instanceof FunctionDescriptor) {
|
else if (fd instanceof FunctionDescriptor) {
|
||||||
callableMethod = typeMapper.mapToCallableMethod((FunctionDescriptor) fd, null);
|
callableMethod = typeMapper.mapToCallableMethod((FunctionDescriptor) fd, superCall, OwnerKind.IMPLEMENTATION);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("can't resolve declaration to callable: " + fd);
|
throw new UnsupportedOperationException("can't resolve declaration to callable: " + fd);
|
||||||
@@ -1042,10 +1083,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
if (calleeType != null && expression instanceof JetCallExpression) {
|
if (calleeType != null && expression instanceof JetCallExpression) {
|
||||||
gen(expression.getCalleeExpression(), calleeType);
|
gen(expression.getCalleeExpression(), calleeType);
|
||||||
}
|
}
|
||||||
if (callableMethod.isOwnerFromCall()) {
|
|
||||||
setOwnerFromCall(callableMethod, expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callableMethod.isNeedsThis()) {
|
if (callableMethod.isNeedsThis()) {
|
||||||
if(callableMethod.isNeedsReceiver()) {
|
if(callableMethod.isNeedsReceiver()) {
|
||||||
generateThisOrOuter((ClassDescriptor) callableMethod.getThisClass()).put(JetTypeMapper.TYPE_OBJECT, v);
|
generateThisOrOuter((ClassDescriptor) callableMethod.getThisClass()).put(JetTypeMapper.TYPE_OBJECT, v);
|
||||||
@@ -1053,7 +1091,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (receiver == StackValue.none()) {
|
if (receiver == StackValue.none()) {
|
||||||
generateThisOrOuter((ClassDescriptor) callableMethod.getThisClass()).put(JetTypeMapper.TYPE_OBJECT, v);;
|
generateThisOrOuter((ClassDescriptor) callableMethod.getThisClass()).put(JetTypeMapper.TYPE_OBJECT, v);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||||
@@ -1071,28 +1109,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mask = pushMethodArguments(expression, callableMethod.getValueParameterTypes());
|
int mask = pushMethodArguments(expression, callableMethod.getValueParameterTypes());
|
||||||
if (callableMethod.acceptsTypeArguments()) {
|
pushTypeArguments(expression);
|
||||||
pushTypeArguments(expression);
|
|
||||||
}
|
|
||||||
if(mask == 0)
|
if(mask == 0)
|
||||||
callableMethod.invoke(v);
|
callableMethod.invoke(v);
|
||||||
else
|
else
|
||||||
callableMethod.invokeWithDefault(v, mask);
|
callableMethod.invokeWithDefault(v, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setOwnerFromCall(CallableMethod callableMethod, JetCallElement expression) {
|
|
||||||
if (expression.getParent() instanceof JetQualifiedExpression) {
|
|
||||||
final JetExpression receiver = ((JetQualifiedExpression) expression.getParent()).getReceiverExpression();
|
|
||||||
JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, receiver);
|
|
||||||
assert expressionType != null;
|
|
||||||
DeclarationDescriptor declarationDescriptor = expressionType.getConstructor().getDeclarationDescriptor();
|
|
||||||
PsiElement ownerDeclaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, declarationDescriptor);
|
|
||||||
if (ownerDeclaration instanceof PsiClass) {
|
|
||||||
callableMethod.setOwner(typeMapper.mapType(expressionType).getInternalName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JetExpression getReceiverForSelector(PsiElement expression) {
|
private static JetExpression getReceiverForSelector(PsiElement expression) {
|
||||||
if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) {
|
if (expression.getParent() instanceof JetDotQualifiedExpression && !isReceiver(expression)) {
|
||||||
final JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent();
|
final JetDotQualifiedExpression parent = (JetDotQualifiedExpression) expression.getParent();
|
||||||
@@ -1362,7 +1385,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
|
DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
|
||||||
final Callable callable = resolveToCallable(op);
|
final Callable callable = resolveToCallable(op, false);
|
||||||
if (callable instanceof IntrinsicMethod) {
|
if (callable instanceof IntrinsicMethod) {
|
||||||
IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
|
IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
|
||||||
return intrinsic.generate(this, v, expressionType(expression), expression,
|
return intrinsic.generate(this, v, expressionType(expression), expression,
|
||||||
@@ -1388,6 +1411,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
FunctionDescriptor op = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
|
FunctionDescriptor op = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
|
||||||
|
assert op != null;
|
||||||
leftValue.put(typeMapper.mapType(op.getValueParameters().get(0).getOutType()), v);
|
leftValue.put(typeMapper.mapType(op.getValueParameters().get(0).getOutType()), v);
|
||||||
genToJVMStack(expression.getRight());
|
genToJVMStack(expression.getRight());
|
||||||
v.swap();
|
v.swap();
|
||||||
@@ -1647,7 +1671,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
|
|
||||||
private StackValue generateAugmentedAssignment(JetBinaryExpression expression) {
|
private StackValue generateAugmentedAssignment(JetBinaryExpression expression) {
|
||||||
DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
|
DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
|
||||||
final Callable callable = resolveToCallable(op);
|
final Callable callable = resolveToCallable(op, false);
|
||||||
final JetExpression lhs = expression.getLeft();
|
final JetExpression lhs = expression.getLeft();
|
||||||
|
|
||||||
// if(lhs instanceof JetArrayAccessExpression) {
|
// if(lhs instanceof JetArrayAccessExpression) {
|
||||||
@@ -1726,7 +1750,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
@Override
|
@Override
|
||||||
public StackValue visitPrefixExpression(JetPrefixExpression expression, StackValue receiver) {
|
public StackValue visitPrefixExpression(JetPrefixExpression expression, StackValue receiver) {
|
||||||
DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationSign());
|
DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationSign());
|
||||||
final Callable callable = resolveToCallable(op);
|
final Callable callable = resolveToCallable(op, false);
|
||||||
if (callable instanceof IntrinsicMethod) {
|
if (callable instanceof IntrinsicMethod) {
|
||||||
IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
|
IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
|
||||||
return intrinsic.generate(this, v, expressionType(expression), expression,
|
return intrinsic.generate(this, v, expressionType(expression), expression,
|
||||||
@@ -1831,11 +1855,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
final PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, constructorDescriptor);
|
final PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, constructorDescriptor);
|
||||||
Type type;
|
Type type;
|
||||||
if (declaration instanceof PsiMethod) {
|
if (declaration instanceof PsiMethod) {
|
||||||
type = generateJavaConstructorCall(expression, (PsiMethod) declaration);
|
type = generateJavaConstructorCall(expression);
|
||||||
}
|
}
|
||||||
else if (constructorDescriptor instanceof ConstructorDescriptor) {
|
else if (constructorDescriptor instanceof ConstructorDescriptor) {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
|
JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
|
||||||
|
assert expressionType != null;
|
||||||
type = typeMapper.mapType(expressionType, OwnerKind.IMPLEMENTATION);
|
type = typeMapper.mapType(expressionType, OwnerKind.IMPLEMENTATION);
|
||||||
if (type.getSort() == Type.ARRAY) {
|
if (type.getSort() == Type.ARRAY) {
|
||||||
generateNewArray(expression, expressionType);
|
generateNewArray(expression, expressionType);
|
||||||
@@ -1856,7 +1881,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
else {
|
else {
|
||||||
// this$0 need to be put on stack
|
// this$0 need to be put on stack
|
||||||
v.dup();
|
v.dup();
|
||||||
v.load(0, JetTypeMapper.jetImplementationType(classDecl));
|
v.load(0, typeMapper.jetImplementationType(classDecl));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1875,19 +1900,23 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void pushTypeArguments(JetCallElement expression) {
|
private void pushTypeArguments(JetCallElement expression) {
|
||||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
|
JetExpression calleeExpression = expression.getCalleeExpression();
|
||||||
|
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, calleeExpression);
|
||||||
if(resolvedCall != null) {
|
if(resolvedCall != null) {
|
||||||
Map<TypeParameterDescriptor, JetType> typeArguments = resolvedCall.getTypeArguments();
|
Map<TypeParameterDescriptor, JetType> typeArguments = resolvedCall.getTypeArguments();
|
||||||
CallableDescriptor resultingDescriptor = resolvedCall.getCandidateDescriptor();
|
CallableDescriptor resultingDescriptor = resolvedCall.getCandidateDescriptor();
|
||||||
for (TypeParameterDescriptor typeParameterDescriptor : resultingDescriptor.getTypeParameters()) {
|
for (TypeParameterDescriptor typeParameterDescriptor : resultingDescriptor.getTypeParameters()) {
|
||||||
JetType jetType = typeArguments.get(typeParameterDescriptor);
|
if(typeParameterDescriptor.isReified()) {
|
||||||
generateTypeInfo(jetType);
|
JetType jetType = typeArguments.get(typeParameterDescriptor);
|
||||||
|
generateTypeInfo(jetType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (JetTypeProjection jetTypeArgument : expression.getTypeArguments()) {
|
throw new UnsupportedOperationException();
|
||||||
pushTypeArgument(jetTypeArgument);
|
// for (JetTypeProjection jetTypeArgument : expression.getTypeArguments()) {
|
||||||
}
|
// pushTypeArgument(jetTypeArgument);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1896,12 +1925,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
generateTypeInfo(typeArgument);
|
generateTypeInfo(typeArgument);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type generateJavaConstructorCall(JetCallExpression expression, PsiMethod constructor) {
|
private Type generateJavaConstructorCall(JetCallExpression expression) {
|
||||||
PsiClass javaClass = constructor.getContainingClass();
|
FunctionDescriptor descriptor = (FunctionDescriptor) resolveCalleeDescriptor(expression);
|
||||||
Type type = JetTypeMapper.psiClassType(javaClass);
|
ClassDescriptor javaClass = (ClassDescriptor) descriptor.getContainingDeclaration();
|
||||||
|
Type type = typeMapper.mapType(javaClass.getDefaultType());
|
||||||
v.anew(type);
|
v.anew(type);
|
||||||
v.dup();
|
v.dup();
|
||||||
final CallableMethod callableMethod = JetTypeMapper.mapToCallableMethod(constructor);
|
final CallableMethod callableMethod = typeMapper.mapToCallableMethod(descriptor, false, OwnerKind.IMPLEMENTATION);
|
||||||
invokeMethodWithArguments(callableMethod, expression, StackValue.none());
|
invokeMethodWithArguments(callableMethod, expression, StackValue.none());
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@@ -1984,14 +2014,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
gen(array, arrayType);
|
gen(array, arrayType);
|
||||||
final List<JetExpression> indices = expression.getIndexExpressions();
|
final List<JetExpression> indices = expression.getIndexExpressions();
|
||||||
FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
|
FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
|
||||||
|
assert operationDescriptor != null;
|
||||||
if (arrayType.getSort() == Type.ARRAY && indices.size() == 1 && operationDescriptor.getValueParameters().get(0).getOutType().equals(state.getStandardLibrary().getIntType())) {
|
if (arrayType.getSort() == Type.ARRAY && indices.size() == 1 && operationDescriptor.getValueParameters().get(0).getOutType().equals(state.getStandardLibrary().getIntType())) {
|
||||||
for (JetExpression index : indices) {
|
for (JetExpression index : indices) {
|
||||||
gen(index, Type.INT_TYPE);
|
gen(index, Type.INT_TYPE);
|
||||||
}
|
}
|
||||||
|
assert type != null;
|
||||||
if(state.getStandardLibrary().getArray().equals(type.getConstructor().getDeclarationDescriptor())) {
|
if(state.getStandardLibrary().getArray().equals(type.getConstructor().getDeclarationDescriptor())) {
|
||||||
JetType elementType = type.getArguments().get(0).getType();
|
JetType elementType = type.getArguments().get(0).getType();
|
||||||
Type notBoxed = typeMapper.mapType(elementType);
|
Type notBoxed = typeMapper.mapType(elementType);
|
||||||
Type boxed = JetTypeMapper.boxType(notBoxed);
|
|
||||||
return StackValue.arrayElement(notBoxed, true);
|
return StackValue.arrayElement(notBoxed, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1999,28 +2030,30 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CallableMethod accessor = typeMapper.mapToCallableMethod(operationDescriptor, OwnerKind.IMPLEMENTATION);
|
CallableMethod accessor = typeMapper.mapToCallableMethod(operationDescriptor, false, OwnerKind.IMPLEMENTATION);
|
||||||
|
|
||||||
boolean isGetter = accessor.getSignature().getName().equals("get");
|
boolean isGetter = accessor.getSignature().getName().equals("get");
|
||||||
|
|
||||||
ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression);
|
ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression);
|
||||||
FunctionDescriptor setterDescriptor = resolvedSetCall == null ? null : resolvedSetCall.getResultingDescriptor();
|
FunctionDescriptor setterDescriptor = resolvedSetCall == null ? null : resolvedSetCall.getResultingDescriptor();
|
||||||
CallableMethod setter = resolvedSetCall == null ? null : typeMapper.mapToCallableMethod(setterDescriptor, OwnerKind.IMPLEMENTATION);
|
CallableMethod setter = resolvedSetCall == null ? null : typeMapper.mapToCallableMethod(setterDescriptor, false, OwnerKind.IMPLEMENTATION);
|
||||||
|
|
||||||
ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression);
|
ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression);
|
||||||
FunctionDescriptor getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor();
|
FunctionDescriptor getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor();
|
||||||
CallableMethod getter = resolvedGetCall == null ? null : typeMapper.mapToCallableMethod(getterDescriptor, OwnerKind.IMPLEMENTATION);
|
CallableMethod getter = resolvedGetCall == null ? null : typeMapper.mapToCallableMethod(getterDescriptor, false, OwnerKind.IMPLEMENTATION);
|
||||||
|
|
||||||
Type asmType;
|
Type asmType;
|
||||||
Type[] argumentTypes = accessor.getSignature().getArgumentTypes();
|
Type[] argumentTypes = accessor.getSignature().getArgumentTypes();
|
||||||
int index = 0;
|
int index = 0;
|
||||||
if(isGetter) {
|
if(isGetter) {
|
||||||
|
assert getterDescriptor != null;
|
||||||
if(getterDescriptor.getReceiverParameter().exists()) {
|
if(getterDescriptor.getReceiverParameter().exists()) {
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
asmType = accessor.getSignature().getReturnType();
|
asmType = accessor.getSignature().getReturnType();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
assert setterDescriptor != null;
|
||||||
if(setterDescriptor.getReceiverParameter().exists()) {
|
if(setterDescriptor.getReceiverParameter().exists()) {
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
@@ -2035,46 +2068,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void _derefArray(JetType type) {
|
|
||||||
if (state.getStandardLibrary().getArray().equals(type.getConstructor().getDeclarationDescriptor())) {
|
|
||||||
JetType elementType = type.getArguments().get(0).getType();
|
|
||||||
JetStandardLibrary standardLibrary = state.getStandardLibrary();
|
|
||||||
if (elementType.equals(standardLibrary.getIntType())) {
|
|
||||||
v.getfield("jet/arrays/JetIntArray", "array", "[I");
|
|
||||||
}
|
|
||||||
else if (elementType.equals(standardLibrary.getLongType())) {
|
|
||||||
v.getfield("jet/arrays/JetLongArray", "array", "[J");
|
|
||||||
}
|
|
||||||
else if (elementType.equals(standardLibrary.getShortType())) {
|
|
||||||
v.getfield("jet/arrays/JetShortArray", "array", "[S");
|
|
||||||
}
|
|
||||||
else if (elementType.equals(standardLibrary.getByteType())) {
|
|
||||||
v.getfield("jet/arrays/JetByteArray", "array", "[B");
|
|
||||||
}
|
|
||||||
else if (elementType.equals(standardLibrary.getCharType())) {
|
|
||||||
v.getfield("jet/arrays/JetCharArray", "array", "[C");
|
|
||||||
}
|
|
||||||
else if (elementType.equals(standardLibrary.getFloatType())) {
|
|
||||||
v.getfield("jet/arrays/JetFloatArray", "array", "[F");
|
|
||||||
}
|
|
||||||
else if (elementType.equals(standardLibrary.getDoubleType())) {
|
|
||||||
v.getfield("jet/arrays/JetDoubleArray", "array", "[D");
|
|
||||||
}
|
|
||||||
else if (elementType.equals(standardLibrary.getBooleanType())) {
|
|
||||||
v.getfield("jet/arrays/JetBooleanArray", "array", "[Z");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(typeMapper.isGenericsArray(type)) {
|
|
||||||
v.visitTypeInsn(Opcodes.CHECKCAST, "jet/arrays/JetArray");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
v.getfield("jet/arrays/JetGenericArray", "array", "[Ljava/lang/Object;");
|
|
||||||
v.visitTypeInsn(Opcodes.CHECKCAST, "[" + typeMapper.mapType(elementType).getDescriptor());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue visitThrowExpression(JetThrowExpression expression, StackValue receiver) {
|
public StackValue visitThrowExpression(JetThrowExpression expression, StackValue receiver) {
|
||||||
gen(expression.getThrownExpression(), JetTypeMapper.TYPE_OBJECT);
|
gen(expression.getThrownExpression(), JetTypeMapper.TYPE_OBJECT);
|
||||||
@@ -2326,7 +2319,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!typeMapper.hasTypeInfoField(jetType) && !(bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, jetType.getConstructor().getDeclarationDescriptor()) instanceof PsiClass)) {
|
if(!CodegenUtil.hasTypeInfoField(jetType) && !(bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, jetType.getConstructor().getDeclarationDescriptor()) instanceof PsiClass)) {
|
||||||
// TODO: we need some better checks here
|
// TODO: we need some better checks here
|
||||||
v.getstatic(typeMapper.mapType(jetType, OwnerKind.IMPLEMENTATION).getInternalName(), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
|
v.getstatic(typeMapper.mapType(jetType, OwnerKind.IMPLEMENTATION).getInternalName(), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||||
return;
|
return;
|
||||||
@@ -2383,12 +2376,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
|
||||||
if (context.getContextClass() instanceof ClassDescriptor) {
|
if (context.getContextClass() instanceof ClassDescriptor) {
|
||||||
ClassDescriptor descriptor = (ClassDescriptor) context.getContextClass();
|
ClassDescriptor descriptor = (ClassDescriptor) context.getContextClass();
|
||||||
|
assert containingDeclaration != null;
|
||||||
JetType defaultType = ((ClassDescriptor)containingDeclaration).getDefaultType();
|
JetType defaultType = ((ClassDescriptor)containingDeclaration).getDefaultType();
|
||||||
Type ownerType = typeMapper.mapType(defaultType);
|
Type ownerType = typeMapper.mapType(defaultType);
|
||||||
ownerType = JetTypeMapper.boxType(ownerType);
|
ownerType = JetTypeMapper.boxType(ownerType);
|
||||||
if (containingDeclaration == context.getContextClass()) {
|
if (containingDeclaration == context.getContextClass()) {
|
||||||
if(!CodegenUtil.isInterface(descriptor)) {
|
if(!CodegenUtil.isInterface(descriptor)) {
|
||||||
if (typeMapper.hasTypeInfoField(defaultType)) {
|
if (CodegenUtil.hasTypeInfoField(defaultType)) {
|
||||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
v.getfield(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
v.getfield(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||||
}
|
}
|
||||||
@@ -2501,7 +2495,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) call);
|
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) call);
|
||||||
if (descriptor instanceof PropertyDescriptor) {
|
if (descriptor instanceof PropertyDescriptor) {
|
||||||
v.load(subjectLocal, subjectType);
|
v.load(subjectLocal, subjectType);
|
||||||
conditionValue = intermediateValueForProperty((PropertyDescriptor) descriptor, false, false, false);
|
conditionValue = intermediateValueForProperty((PropertyDescriptor) descriptor, false, null);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("unknown simple name resolve result: " + descriptor);
|
throw new UnsupportedOperationException("unknown simple name resolve result: " + descriptor);
|
||||||
|
|||||||
@@ -33,8 +33,9 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void gen(JetNamedFunction f) {
|
public void gen(JetNamedFunction f) {
|
||||||
Method method = state.getTypeMapper().mapToCallableMethod(f, owner.getContextKind()).getSignature();
|
|
||||||
final FunctionDescriptor functionDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, f);
|
final FunctionDescriptor functionDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, f);
|
||||||
|
assert functionDescriptor != null;
|
||||||
|
Method method = state.getTypeMapper().mapToCallableMethod(functionDescriptor, false, owner.getContextKind()).getSignature();
|
||||||
generateMethod(f, method, functionDescriptor);
|
generateMethod(f, method, functionDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,9 +106,7 @@ public class FunctionCodegen {
|
|||||||
iv.areturn(jvmSignature.getReturnType());
|
iv.areturn(jvmSignature.getReturnType());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (int i = 0; i < paramDescrs.size(); i++) {
|
for (ValueParameterDescriptor parameter : paramDescrs) {
|
||||||
ValueParameterDescriptor parameter = paramDescrs.get(i);
|
|
||||||
|
|
||||||
Type sharedVarType = codegen.getSharedVarType(parameter);
|
Type sharedVarType = codegen.getSharedVarType(parameter);
|
||||||
Type localVarType = state.getTypeMapper().mapType(parameter.getOutType());
|
Type localVarType = state.getTypeMapper().mapType(parameter.getOutType());
|
||||||
if (sharedVarType != null) {
|
if (sharedVarType != null) {
|
||||||
@@ -253,6 +252,7 @@ public class FunctionCodegen {
|
|||||||
iv.ifeq(loadArg);
|
iv.ifeq(loadArg);
|
||||||
|
|
||||||
JetParameter jetParameter = (JetParameter) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, parameterDescriptor);
|
JetParameter jetParameter = (JetParameter) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, parameterDescriptor);
|
||||||
|
assert jetParameter != null;
|
||||||
codegen.gen(jetParameter.getDefaultValue(), t);
|
codegen.gen(jetParameter.getDefaultValue(), t);
|
||||||
|
|
||||||
endArg = new Label();
|
endArg = new Label();
|
||||||
@@ -270,7 +270,8 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||||
iv.load(var++, JetTypeMapper.TYPE_OBJECT);
|
if(typeParameterDescriptor.isReified())
|
||||||
|
iv.load(var++, JetTypeMapper.TYPE_OBJECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isStatic) {
|
if(!isStatic) {
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ public class GenerationState {
|
|||||||
closure.name = nameAndVisitor.getFirst();
|
closure.name = nameAndVisitor.getFirst();
|
||||||
final ClassContext objectContext = closure.context.intoClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION);
|
final ClassContext objectContext = closure.context.intoClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION);
|
||||||
|
|
||||||
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate();
|
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(null);
|
||||||
|
|
||||||
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
|
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
|
||||||
CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
||||||
|
|||||||
@@ -40,12 +40,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
||||||
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
|
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
|
||||||
|
assert superType != null;
|
||||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||||
PsiElement superPsi = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
PsiElement superPsi = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
||||||
|
|
||||||
if (superPsi instanceof PsiClass) {
|
if (superPsi instanceof PsiClass) {
|
||||||
PsiClass psiClass = (PsiClass) superPsi;
|
PsiClass psiClass = (PsiClass) superPsi;
|
||||||
String fqn = psiClass.getQualifiedName();
|
String fqn = psiClass.getQualifiedName();
|
||||||
|
assert fqn != null;
|
||||||
if (psiClass.isInterface()) {
|
if (psiClass.isInterface()) {
|
||||||
superInterfaces.add(fqn.replace('.', '/'));
|
superInterfaces.add(fqn.replace('.', '/'));
|
||||||
}
|
}
|
||||||
@@ -55,7 +57,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
while (psiClass != null) {
|
while (psiClass != null) {
|
||||||
for (PsiClass ifs : psiClass.getInterfaces()) {
|
for (PsiClass ifs : psiClass.getInterfaces()) {
|
||||||
superInterfaces.add(ifs.getQualifiedName().replace('.', '/'));
|
String qualifiedName = ifs.getQualifiedName();
|
||||||
|
assert qualifiedName != null;
|
||||||
|
superInterfaces.add(qualifiedName.replace('.', '/'));
|
||||||
}
|
}
|
||||||
psiClass = psiClass.getSuperClass();
|
psiClass = psiClass.getSuperClass();
|
||||||
}
|
}
|
||||||
@@ -67,7 +71,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(superPsi == null || ((JetClass)superPsi).isTrait())
|
if(superPsi == null || ((JetClass)superPsi).isTrait())
|
||||||
superInterfaces.add(JetTypeMapper.jvmNameForInterface(superClassDescriptor));
|
superInterfaces.add(state.getTypeMapper().jvmNameForImplementation(superClassDescriptor, OwnerKind.IMPLEMENTATION));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return superInterfaces;
|
return superInterfaces;
|
||||||
@@ -127,6 +131,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
||||||
if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) {
|
if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) {
|
||||||
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
|
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
|
||||||
|
assert superType != null;
|
||||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||||
final PsiElement declaration = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
final PsiElement declaration = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
||||||
if (declaration != null) {
|
if (declaration != null) {
|
||||||
@@ -149,9 +154,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generateSyntheticParts() {
|
protected void generateSyntheticParts(HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||||
generateFieldForObjectInstance();
|
generateFieldForObjectInstance();
|
||||||
generateFieldForClassObject();
|
generateFieldForClassObject();
|
||||||
|
generateAccessors(accessors);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
generatePrimaryConstructor();
|
generatePrimaryConstructor();
|
||||||
@@ -161,12 +167,86 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
generateGetTypeInfo();
|
generateGetTypeInfo();
|
||||||
//genGetSuperTypesTypeInfo();
|
}
|
||||||
|
|
||||||
|
private void generateAccessors(HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||||
|
if(accessors != null) {
|
||||||
|
for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : accessors.entrySet()) {
|
||||||
|
if(entry.getValue() instanceof FunctionDescriptor) {
|
||||||
|
FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
|
||||||
|
FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
|
||||||
|
|
||||||
|
Method method = state.getTypeMapper().mapSignature(bridge.getName(), bridge);
|
||||||
|
Method originalMethod = state.getTypeMapper().mapSignature(original.getName(), original);
|
||||||
|
Type[] argTypes = method.getArgumentTypes();
|
||||||
|
|
||||||
|
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null);
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
|
|
||||||
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||||
|
Type argType = argTypes[i];
|
||||||
|
iv.load(reg, argType);
|
||||||
|
//noinspection AssignmentToForLoopParameter
|
||||||
|
reg += argType.getSize();
|
||||||
|
}
|
||||||
|
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
|
||||||
|
|
||||||
|
iv.areturn(method.getReturnType());
|
||||||
|
mv.visitMaxs(0,0);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
else if(entry.getValue() instanceof PropertyDescriptor) {
|
||||||
|
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
|
||||||
|
PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
|
||||||
|
|
||||||
|
Method method = state.getTypeMapper().mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION);
|
||||||
|
Method originalMethod = state.getTypeMapper().mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
|
||||||
|
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
|
|
||||||
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
|
||||||
|
|
||||||
|
iv.areturn(method.getReturnType());
|
||||||
|
mv.visitMaxs(0,0);
|
||||||
|
mv.visitEnd();
|
||||||
|
|
||||||
|
method = state.getTypeMapper().mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION);
|
||||||
|
originalMethod = state.getTypeMapper().mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
|
||||||
|
mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
|
iv = new InstructionAdapter(mv);
|
||||||
|
|
||||||
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
Type[] argTypes = method.getArgumentTypes();
|
||||||
|
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||||
|
Type argType = argTypes[i];
|
||||||
|
iv.load(reg, argType);
|
||||||
|
//noinspection AssignmentToForLoopParameter
|
||||||
|
reg += argType.getSize();
|
||||||
|
}
|
||||||
|
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
|
||||||
|
|
||||||
|
iv.areturn(method.getReturnType());
|
||||||
|
mv.visitMaxs(0,0);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateFieldForObjectInstance() {
|
private void generateFieldForObjectInstance() {
|
||||||
if (isNonLiteralObject()) {
|
if (isNonLiteralObject()) {
|
||||||
Type type = JetTypeMapper.jetImplementationType(descriptor);
|
Type type = state.getTypeMapper().jetImplementationType(descriptor);
|
||||||
v.newField(myClass, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$instance", type.getDescriptor(), null, null);
|
v.newField(myClass, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$instance", type.getDescriptor(), null, null);
|
||||||
|
|
||||||
staticInitializerChunks.add(new CodeChunk() {
|
staticInitializerChunks.add(new CodeChunk() {
|
||||||
@@ -176,7 +256,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
v.anew(Type.getObjectType(name));
|
v.anew(Type.getObjectType(name));
|
||||||
v.dup();
|
v.dup();
|
||||||
v.invokespecial(name, "<init>", "()V");
|
v.invokespecial(name, "<init>", "()V");
|
||||||
v.putstatic(name, "$instance", JetTypeMapper.jetImplementationType(descriptor).getDescriptor());
|
v.putstatic(name, "$instance", state.getTypeMapper().jetImplementationType(descriptor).getDescriptor());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -272,7 +352,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
HashSet<FunctionDescriptor> overridden = new HashSet<FunctionDescriptor>();
|
HashSet<FunctionDescriptor> overridden = new HashSet<FunctionDescriptor>();
|
||||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||||
if (declaration instanceof JetFunction) {
|
if (declaration instanceof JetFunction) {
|
||||||
overridden.addAll(state.getBindingContext().get(BindingContext.FUNCTION, declaration).getOverriddenDescriptors());
|
FunctionDescriptor functionDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, declaration);
|
||||||
|
assert functionDescriptor != null;
|
||||||
|
overridden.addAll(functionDescriptor.getOverriddenDescriptors());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,6 +366,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
else {
|
else {
|
||||||
JetType superType = state.getBindingContext().get(BindingContext.TYPE, superCall.getTypeReference());
|
JetType superType = state.getBindingContext().get(BindingContext.TYPE, superCall.getTypeReference());
|
||||||
List<Type> parameterTypes = new ArrayList<Type>();
|
List<Type> parameterTypes = new ArrayList<Type>();
|
||||||
|
assert superType != null;
|
||||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||||
if (CodegenUtil.hasThis0(superClassDescriptor)) {
|
if (CodegenUtil.hasThis0(superClassDescriptor)) {
|
||||||
iv.load(1, JetTypeMapper.TYPE_OBJECT);
|
iv.load(1, JetTypeMapper.TYPE_OBJECT);
|
||||||
@@ -313,9 +396,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
codegen.genToJVMStack(((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression());
|
codegen.genToJVMStack(((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression());
|
||||||
|
|
||||||
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
|
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
|
||||||
|
assert superType != null;
|
||||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||||
String delegateField = "$delegate_" + n;
|
String delegateField = "$delegate_" + n;
|
||||||
Type fieldType = JetTypeMapper.jetInterfaceType(superClassDescriptor);
|
Type fieldType = state.getTypeMapper().jetImplementationType(superClassDescriptor);
|
||||||
String fieldDesc = fieldType.getDescriptor();
|
String fieldDesc = fieldType.getDescriptor();
|
||||||
v.newField(specifier, Opcodes.ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null);
|
v.newField(specifier, Opcodes.ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null);
|
||||||
iv.putfield(classname, delegateField, fieldDesc);
|
iv.putfield(classname, delegateField, fieldDesc);
|
||||||
@@ -323,14 +407,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
JetClass superClass = (JetClass) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
JetClass superClass = (JetClass) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
||||||
final ClassContext delegateContext = context.intoClass(null, superClassDescriptor,
|
final ClassContext delegateContext = context.intoClass(null, superClassDescriptor,
|
||||||
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false),
|
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false),
|
||||||
JetTypeMapper.jvmNameForInterface(superClassDescriptor)));
|
state.getTypeMapper().jvmNameForImplementation(superClassDescriptor, OwnerKind.IMPLEMENTATION)));
|
||||||
generateDelegates(superClass, delegateContext, overridden);
|
generateDelegates(superClass, delegateContext, overridden);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final ClassDescriptor outerDescriptor = getOuterClassDescriptor();
|
final ClassDescriptor outerDescriptor = getOuterClassDescriptor();
|
||||||
if (outerDescriptor != null && outerDescriptor.getKind() != ClassKind.OBJECT) {
|
if (outerDescriptor != null && outerDescriptor.getKind() != ClassKind.OBJECT) {
|
||||||
final Type type = JetTypeMapper.jetImplementationType(outerDescriptor);
|
final Type type = state.getTypeMapper().jetImplementationType(outerDescriptor);
|
||||||
String interfaceDesc = type.getDescriptor();
|
String interfaceDesc = type.getDescriptor();
|
||||||
final String fieldName = "this$0";
|
final String fieldName = "this$0";
|
||||||
v.newField(myClass, Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null);
|
v.newField(myClass, Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null);
|
||||||
@@ -339,7 +423,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
iv.putfield(classname, fieldName, interfaceDesc);
|
iv.putfield(classname, fieldName, interfaceDesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.getTypeMapper().hasTypeInfoField(descriptor.getDefaultType()) && kind == OwnerKind.IMPLEMENTATION) {
|
if (CodegenUtil.hasTypeInfoField(descriptor.getDefaultType()) && kind == OwnerKind.IMPLEMENTATION) {
|
||||||
generateTypeInfoInitializer(frameMap.getFirstTypeParameter(), frameMap.getTypeParameterCount(), iv);
|
generateTypeInfoInitializer(frameMap.getFirstTypeParameter(), frameMap.getTypeParameterCount(), iv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,14 +534,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
ConstructorDescriptor constructorDescriptor,
|
ConstructorDescriptor constructorDescriptor,
|
||||||
ConstructorFrameMap frameMap) {
|
ConstructorFrameMap frameMap) {
|
||||||
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
|
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
|
||||||
PsiElement declaration = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDecl);
|
|
||||||
Type type;
|
Type type;
|
||||||
if (declaration instanceof PsiClass) {
|
type = state.getTypeMapper().jetImplementationType(classDecl);
|
||||||
type = JetTypeMapper.psiClassType((PsiClass) declaration);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
type = JetTypeMapper.jetImplementationType(classDecl);
|
|
||||||
}
|
|
||||||
|
|
||||||
iv.load(0, type);
|
iv.load(0, type);
|
||||||
|
|
||||||
@@ -652,7 +730,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
if(propertyDescriptor.getOutType().isNullable())
|
if(propertyDescriptor.getOutType().isNullable())
|
||||||
type = JetTypeMapper.boxType(type);
|
type = JetTypeMapper.boxType(type);
|
||||||
codegen.gen(initializer, type);
|
codegen.gen(initializer, type);
|
||||||
codegen.intermediateValueForProperty(propertyDescriptor, false, false, false).store(iv);
|
codegen.intermediateValueForProperty(propertyDescriptor, false, null).store(iv);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -671,7 +749,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
if (declaration instanceof JetProperty) {
|
if (declaration instanceof JetProperty) {
|
||||||
propertyCodegen.gen((JetProperty) declaration);
|
propertyCodegen.gen((JetProperty) declaration);
|
||||||
}
|
}
|
||||||
else if (declaration instanceof JetFunction) {
|
else if (declaration instanceof JetNamedFunction) {
|
||||||
if (!overriden.contains(state.getBindingContext().get(BindingContext.FUNCTION, declaration))) {
|
if (!overriden.contains(state.getBindingContext().get(BindingContext.FUNCTION, declaration))) {
|
||||||
functionCodegen.gen((JetNamedFunction) declaration);
|
functionCodegen.gen((JetNamedFunction) declaration);
|
||||||
}
|
}
|
||||||
@@ -706,8 +784,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
JetType defaultType = descriptor.getDefaultType();
|
JetType defaultType = descriptor.getDefaultType();
|
||||||
if(state.getTypeMapper().hasTypeInfoField(defaultType)) {
|
if(CodegenUtil.hasTypeInfoField(defaultType)) {
|
||||||
if(!state.getTypeMapper().hasDerivedTypeInfoField(defaultType, true)) {
|
if(!CodegenUtil.hasDerivedTypeInfoField(defaultType, true)) {
|
||||||
v.newField(myClass, Opcodes.ACC_PRIVATE, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
v.newField(myClass, Opcodes.ACC_PRIVATE, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
||||||
|
|
||||||
MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
|
MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
|
||||||
@@ -773,51 +851,4 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
private void generateClassObject(JetClassObject declaration) {
|
private void generateClassObject(JetClassObject declaration) {
|
||||||
state.forClass().generate(context, declaration.getObjectDeclaration());
|
state.forClass().generate(context, declaration.getObjectDeclaration());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void genGetSuperTypesTypeInfo() {
|
|
||||||
if(!(myClass instanceof JetClass) || ((JetClass)myClass).isTrait()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String sig = getGetSuperTypesTypeInfoSignature(descriptor.getDefaultType());
|
|
||||||
|
|
||||||
final MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
|
|
||||||
"$$getSuperTypesTypeInfo",
|
|
||||||
sig,
|
|
||||||
null /* TODO */,
|
|
||||||
null);
|
|
||||||
mv.visitCode();
|
|
||||||
InstructionAdapter v = new InstructionAdapter(mv);
|
|
||||||
|
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(v, new FrameMap(), Type.VOID_TYPE, context, state);
|
|
||||||
|
|
||||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
|
||||||
|
|
||||||
int k = 1;
|
|
||||||
for (TypeParameterDescriptor parameterDescriptor : descriptor.getTypeConstructor().getParameters()) {
|
|
||||||
codegen.addTypeParameter(parameterDescriptor, StackValue.local(k++, JetTypeMapper.TYPE_TYPEINFO));
|
|
||||||
}
|
|
||||||
|
|
||||||
for(JetType superType : descriptor.getTypeConstructor().getSupertypes()) {
|
|
||||||
for (TypeProjection typeProjection : superType.getArguments()) {
|
|
||||||
codegen.generateTypeInfo(typeProjection.getType());
|
|
||||||
}
|
|
||||||
v.invokestatic(state.getTypeMapper().mapType(superType).getInternalName(), "$$getSuperTypesTypeInfo", getGetSuperTypesTypeInfoSignature(superType));
|
|
||||||
}
|
|
||||||
|
|
||||||
v.areturn(Type.VOID_TYPE);
|
|
||||||
mv.visitMaxs(0, 0);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getGetSuperTypesTypeInfoSignature(JetType type) {
|
|
||||||
List<TypeParameterDescriptor> typeParameters = type.getConstructor().getParameters();
|
|
||||||
StringBuilder sb = new StringBuilder("(Ljava/util/Set;");
|
|
||||||
for(TypeParameterDescriptor tp : typeParameters)
|
|
||||||
sb.append("Ljet/typeinfo/TypeInfo;");
|
|
||||||
sb.append(")V");
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import jet.JetObject;
|
|||||||
import jet.typeinfo.TypeInfo;
|
import jet.typeinfo.TypeInfo;
|
||||||
import jet.typeinfo.TypeInfoProjection;
|
import jet.typeinfo.TypeInfoProjection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
@@ -15,11 +16,12 @@ import org.jetbrains.jet.lexer.JetTokens;
|
|||||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
import org.objectweb.asm.commons.InstructionAdapter;
|
|
||||||
import org.objectweb.asm.commons.Method;
|
import org.objectweb.asm.commons.Method;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yole
|
* @author yole
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
@@ -57,7 +59,9 @@ public class JetTypeMapper {
|
|||||||
private final Map<JetExpression, String> classNamesForAnonymousClasses = new HashMap<JetExpression, String>();
|
private final Map<JetExpression, String> classNamesForAnonymousClasses = new HashMap<JetExpression, String>();
|
||||||
private final Map<String, Integer> anonymousSubclassesCount = new HashMap<String, Integer>();
|
private final Map<String, Integer> anonymousSubclassesCount = new HashMap<String, Integer>();
|
||||||
|
|
||||||
private final HashMap<JetType,String> knowTypes = new HashMap<JetType, String>();
|
private final HashMap<JetType,String> knowTypeNames = new HashMap<JetType, String>();
|
||||||
|
private final HashMap<JetType,Type> knowTypes = new HashMap<JetType, Type>();
|
||||||
|
|
||||||
public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
|
public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
|
||||||
public static final Type TYPE_ITERATOR = Type.getObjectType("jet/Iterator");
|
public static final Type TYPE_ITERATOR = Type.getObjectType("jet/Iterator");
|
||||||
public static final Type TYPE_INT_RANGE = Type.getObjectType("jet/IntRange");
|
public static final Type TYPE_INT_RANGE = Type.getObjectType("jet/IntRange");
|
||||||
@@ -75,14 +79,7 @@ public class JetTypeMapper {
|
|||||||
this.standardLibrary = standardLibrary;
|
this.standardLibrary = standardLibrary;
|
||||||
this.bindingContext = bindingContext;
|
this.bindingContext = bindingContext;
|
||||||
initKnownTypes();
|
initKnownTypes();
|
||||||
}
|
initKnownTypeNames();
|
||||||
|
|
||||||
static String jvmName(PsiClass psiClass) {
|
|
||||||
final String qName = psiClass.getQualifiedName();
|
|
||||||
if (qName == null) {
|
|
||||||
throw new UnsupportedOperationException("can't evaluate JVM name for anonymous class " + psiClass);
|
|
||||||
}
|
|
||||||
return qName.replace(".", "/");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isIntPrimitive(Type type) {
|
public static boolean isIntPrimitive(Type type) {
|
||||||
@@ -102,68 +99,6 @@ public class JetTypeMapper {
|
|||||||
|| type == Type.VOID_TYPE;
|
|| type == Type.VOID_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Type psiTypeToAsm(PsiType type) {
|
|
||||||
if(type instanceof PsiArrayType) {
|
|
||||||
PsiArrayType psiArrayType = (PsiArrayType) type;
|
|
||||||
return Type.getType("[" + psiTypeToAsm(psiArrayType.getComponentType()).getDescriptor());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type instanceof PsiPrimitiveType) {
|
|
||||||
if (type == PsiType.VOID) {
|
|
||||||
return Type.VOID_TYPE;
|
|
||||||
}
|
|
||||||
if (type == PsiType.INT) {
|
|
||||||
return Type.INT_TYPE;
|
|
||||||
}
|
|
||||||
if (type == PsiType.LONG) {
|
|
||||||
return Type.LONG_TYPE;
|
|
||||||
}
|
|
||||||
if (type == PsiType.BOOLEAN) {
|
|
||||||
return Type.BOOLEAN_TYPE;
|
|
||||||
}
|
|
||||||
if (type == PsiType.BYTE) {
|
|
||||||
return Type.BYTE_TYPE;
|
|
||||||
}
|
|
||||||
if (type == PsiType.SHORT) {
|
|
||||||
return Type.SHORT_TYPE;
|
|
||||||
}
|
|
||||||
if (type == PsiType.CHAR) {
|
|
||||||
return Type.CHAR_TYPE;
|
|
||||||
}
|
|
||||||
if (type == PsiType.FLOAT) {
|
|
||||||
return Type.FLOAT_TYPE;
|
|
||||||
}
|
|
||||||
if (type == PsiType.DOUBLE) {
|
|
||||||
return Type.DOUBLE_TYPE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type instanceof PsiClassType) {
|
|
||||||
PsiClass psiClass = ((PsiClassType) type).resolve();
|
|
||||||
if (psiClass instanceof PsiTypeParameter) {
|
|
||||||
final PsiClassType[] extendsListTypes = psiClass.getExtendsListTypes();
|
|
||||||
if (extendsListTypes.length > 0) {
|
|
||||||
throw new UnsupportedOperationException("should return common supertype");
|
|
||||||
}
|
|
||||||
return TYPE_OBJECT;
|
|
||||||
}
|
|
||||||
if (psiClass == null) {
|
|
||||||
throw new UnsupportedOperationException("unresolved PsiClassType: " + type);
|
|
||||||
}
|
|
||||||
return psiClassType(psiClass);
|
|
||||||
}
|
|
||||||
throw new UnsupportedOperationException("don't know how to map type " + type + " to ASM");
|
|
||||||
}
|
|
||||||
|
|
||||||
static Method getMethodDescriptor(PsiMethod method) {
|
|
||||||
Type returnType = method.isConstructor() ? Type.VOID_TYPE : psiTypeToAsm(method.getReturnType());
|
|
||||||
PsiParameter[] parameters = method.getParameterList().getParameters();
|
|
||||||
Type[] parameterTypes = new Type[parameters.length];
|
|
||||||
for (int i = 0; i < parameters.length; i++) {
|
|
||||||
parameterTypes[i] = psiTypeToAsm(parameters[i].getType());
|
|
||||||
}
|
|
||||||
return new Method(method.isConstructor() ? "<init>" : method.getName(), Type.getMethodDescriptor(returnType, parameterTypes));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Type getBoxedType(final Type type) {
|
public static Type getBoxedType(final Type type) {
|
||||||
switch (type.getSort()) {
|
switch (type.getSort()) {
|
||||||
case Type.BYTE:
|
case Type.BYTE:
|
||||||
@@ -186,44 +121,8 @@ public class JetTypeMapper {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasTypeInfoField(JetType type) {
|
|
||||||
if(type.getConstructor().getParameters().size() > 0) {
|
|
||||||
if(!(bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, type.getConstructor().getDeclarationDescriptor()) instanceof PsiClass))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
|
||||||
if(hasTypeInfoField(jetType))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClassDescriptor outerClassDescriptor = CodegenUtil.getOuterClassDescriptor(type.getConstructor().getDeclarationDescriptor());
|
|
||||||
if(outerClassDescriptor == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return hasTypeInfoField(outerClassDescriptor.getDefaultType());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasDerivedTypeInfoField(JetType type, boolean exceptOwn) {
|
|
||||||
if(!exceptOwn) {
|
|
||||||
if(!CodegenUtil.isInterface(type))
|
|
||||||
if(hasTypeInfoField(type))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
|
||||||
if(hasDerivedTypeInfoField(jetType, false))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String jvmName(ClassDescriptor jetClass, OwnerKind kind) {
|
public String jvmName(ClassDescriptor jetClass, OwnerKind kind) {
|
||||||
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, jetClass);
|
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, jetClass);
|
||||||
if (declaration instanceof PsiClass) {
|
|
||||||
return jvmName((PsiClass) declaration);
|
|
||||||
}
|
|
||||||
if (declaration instanceof JetObjectDeclaration && ((JetObjectDeclaration) declaration).isObjectLiteral()) {
|
if (declaration instanceof JetObjectDeclaration && ((JetObjectDeclaration) declaration).isObjectLiteral()) {
|
||||||
final PsiElement parent = declaration.getParent();
|
final PsiElement parent = declaration.getParent();
|
||||||
if (parent instanceof JetClassObject) {
|
if (parent instanceof JetClassObject) {
|
||||||
@@ -245,15 +144,15 @@ public class JetTypeMapper {
|
|||||||
return jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
return jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) {
|
private String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) {
|
||||||
if (jetClass.getKind() == ClassKind.OBJECT) {
|
if (jetClass.getKind() == ClassKind.OBJECT) {
|
||||||
return jvmNameForImplementation(jetClass);
|
return jvmNameForImplementation(jetClass, OwnerKind.IMPLEMENTATION);
|
||||||
}
|
}
|
||||||
else if (kind == OwnerKind.IMPLEMENTATION) {
|
else if (kind == OwnerKind.IMPLEMENTATION) {
|
||||||
return jvmNameForImplementation(jetClass);
|
return jvmNameForImplementation(jetClass, OwnerKind.IMPLEMENTATION);
|
||||||
}
|
}
|
||||||
else if (kind == OwnerKind.TRAIT_IMPL) {
|
else if (kind == OwnerKind.TRAIT_IMPL) {
|
||||||
return jvmNameForTraitImpl(jetClass);
|
return jvmNameForImplementation(jetClass, OwnerKind.IMPLEMENTATION) + "$$TImpl";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert false : "Unsuitable kind";
|
assert false : "Unsuitable kind";
|
||||||
@@ -268,16 +167,8 @@ public class JetTypeMapper {
|
|||||||
return Type.getType("L" + jvmName(jetClass, kind) + ";");
|
return Type.getType("L" + jvmName(jetClass, kind) + ";");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Type psiClassType(PsiClass psiClass) {
|
Type jetImplementationType(ClassDescriptor classDescriptor) {
|
||||||
return Type.getType("L" + jvmName(psiClass) + ";");
|
return Type.getType("L" + jvmNameForImplementation(classDescriptor, OwnerKind.IMPLEMENTATION) + ";");
|
||||||
}
|
|
||||||
|
|
||||||
static Type jetInterfaceType(ClassDescriptor classDescriptor) {
|
|
||||||
return Type.getType("L" + jvmNameForInterface(classDescriptor) + ";");
|
|
||||||
}
|
|
||||||
|
|
||||||
static Type jetImplementationType(ClassDescriptor classDescriptor) {
|
|
||||||
return Type.getType("L" + jvmNameForImplementation(classDescriptor) + ";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String jvmName(JetNamespace namespace) {
|
public static String jvmName(JetNamespace namespace) {
|
||||||
@@ -288,30 +179,22 @@ public class JetTypeMapper {
|
|||||||
return NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(namespace));
|
return NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(namespace));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String jvmNameForInterface(ClassDescriptor descriptor) {
|
public String jvmNameForImplementation(ClassDescriptor descriptor, OwnerKind kind) {
|
||||||
return DescriptorRenderer.getFQName(descriptor).replace('.', '/');
|
return mapType(descriptor.getDefaultType(), kind).getInternalName();
|
||||||
}
|
|
||||||
|
|
||||||
public static String jvmNameForImplementation(ClassDescriptor descriptor) {
|
|
||||||
return jvmNameForInterface(descriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String jvmNameForTraitImpl(ClassDescriptor descriptor) {
|
|
||||||
return jvmNameForInterface(descriptor) + "$$TImpl";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOwner(DeclarationDescriptor descriptor, OwnerKind kind) {
|
public String getOwner(DeclarationDescriptor descriptor, OwnerKind kind) {
|
||||||
String owner;
|
String owner;
|
||||||
if (descriptor.getContainingDeclaration() instanceof NamespaceDescriptorImpl) {
|
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||||
owner = jvmName((NamespaceDescriptor) descriptor.getContainingDeclaration());
|
if (containingDeclaration instanceof NamespaceDescriptor) {
|
||||||
|
owner = jvmName((NamespaceDescriptor) containingDeclaration);
|
||||||
}
|
}
|
||||||
else if (descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
|
else if (containingDeclaration instanceof ClassDescriptor) {
|
||||||
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration();
|
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
|
||||||
if (kind instanceof OwnerKind.DelegateKind) {
|
if (kind instanceof OwnerKind.DelegateKind) {
|
||||||
kind = OwnerKind.IMPLEMENTATION;
|
kind = OwnerKind.IMPLEMENTATION;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert classDescriptor != null;
|
|
||||||
if (classDescriptor.getKind() == ClassKind.OBJECT) {
|
if (classDescriptor.getKind() == ClassKind.OBJECT) {
|
||||||
kind = OwnerKind.IMPLEMENTATION;
|
kind = OwnerKind.IMPLEMENTATION;
|
||||||
}
|
}
|
||||||
@@ -319,23 +202,19 @@ public class JetTypeMapper {
|
|||||||
owner = jvmName(classDescriptor, kind);
|
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 " + containingDeclaration);
|
||||||
}
|
}
|
||||||
return owner;
|
return owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull public Type mapReturnType(@NotNull final JetType jetType, OwnerKind kind) {
|
@NotNull public Type mapReturnType(final JetType jetType) {
|
||||||
if (jetType.equals(JetStandardClasses.getUnitType()) || jetType.equals(JetStandardClasses.getNothingType())) {
|
if (jetType.equals(JetStandardClasses.getUnitType()) || jetType.equals(JetStandardClasses.getNothingType())) {
|
||||||
return Type.VOID_TYPE;
|
return Type.VOID_TYPE;
|
||||||
}
|
}
|
||||||
if (jetType.equals(JetStandardClasses.getNullableNothingType())) {
|
if (jetType.equals(JetStandardClasses.getNullableNothingType())) {
|
||||||
return TYPE_OBJECT;
|
return TYPE_OBJECT;
|
||||||
}
|
}
|
||||||
return mapType(jetType, kind);
|
return mapType(jetType, OwnerKind.IMPLEMENTATION);
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull public Type mapReturnType(final JetType jetType) {
|
|
||||||
return mapReturnType(jetType, OwnerKind.IMPLEMENTATION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull public Type mapType(final JetType jetType) {
|
@NotNull public Type mapType(final JetType jetType) {
|
||||||
@@ -343,85 +222,9 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull public Type mapType(@NotNull final JetType jetType, OwnerKind kind) {
|
@NotNull public Type mapType(@NotNull final JetType jetType, OwnerKind kind) {
|
||||||
if (jetType.equals(JetStandardClasses.getNothingType()) || jetType.equals(JetStandardClasses.getNullableNothingType())) {
|
Type known = knowTypes.get(jetType);
|
||||||
return TYPE_NOTHING;
|
if(known != null)
|
||||||
}
|
return known;
|
||||||
if (jetType.equals(standardLibrary.getIntType())) {
|
|
||||||
return Type.INT_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getNullableIntType())) {
|
|
||||||
return JL_INTEGER_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getLongType())) {
|
|
||||||
return Type.LONG_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getNullableLongType())) {
|
|
||||||
return JL_LONG_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getShortType())) {
|
|
||||||
return Type.SHORT_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getNullableShortType())) {
|
|
||||||
return JL_SHORT_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getByteType())) {
|
|
||||||
return Type.BYTE_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getNullableByteType())) {
|
|
||||||
return JL_BYTE_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getCharType())) {
|
|
||||||
return Type.CHAR_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getNullableCharType())) {
|
|
||||||
return JL_CHAR_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getFloatType())) {
|
|
||||||
return Type.FLOAT_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getNullableFloatType())) {
|
|
||||||
return JL_FLOAT_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getDoubleType())) {
|
|
||||||
return Type.DOUBLE_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getNullableDoubleType())) {
|
|
||||||
return JL_DOUBLE_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getBooleanType())) {
|
|
||||||
return Type.BOOLEAN_TYPE;
|
|
||||||
}
|
|
||||||
if (jetType.equals(standardLibrary.getNullableBooleanType())) {
|
|
||||||
return JL_BOOLEAN_TYPE;
|
|
||||||
}
|
|
||||||
if(jetType.equals(standardLibrary.getByteArrayType())){
|
|
||||||
return ARRAY_BYTE_TYPE;
|
|
||||||
}
|
|
||||||
if(jetType.equals(standardLibrary.getShortArrayType())){
|
|
||||||
return ARRAY_SHORT_TYPE;
|
|
||||||
}
|
|
||||||
if(jetType.equals(standardLibrary.getIntArrayType())){
|
|
||||||
return ARRAY_INT_TYPE;
|
|
||||||
}
|
|
||||||
if(jetType.equals(standardLibrary.getLongArrayType())){
|
|
||||||
return ARRAY_LONG_TYPE;
|
|
||||||
}
|
|
||||||
if(jetType.equals(standardLibrary.getFloatArrayType())){
|
|
||||||
return ARRAY_FLOAT_TYPE;
|
|
||||||
}
|
|
||||||
if(jetType.equals(standardLibrary.getDoubleArrayType())){
|
|
||||||
return ARRAY_DOUBLE_TYPE;
|
|
||||||
}
|
|
||||||
if(jetType.equals(standardLibrary.getCharArrayType())){
|
|
||||||
return ARRAY_CHAR_TYPE;
|
|
||||||
}
|
|
||||||
if(jetType.equals(standardLibrary.getBooleanArrayType())){
|
|
||||||
return ARRAY_BOOL_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jetType.equals(standardLibrary.getStringType()) || jetType.equals(standardLibrary.getNullableStringType())) {
|
|
||||||
return Type.getType(String.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||||
if (standardLibrary.getArray().equals(descriptor)) {
|
if (standardLibrary.getArray().equals(descriptor)) {
|
||||||
@@ -439,7 +242,10 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor instanceof ClassDescriptor) {
|
if (descriptor instanceof ClassDescriptor) {
|
||||||
return Type.getObjectType(jvmName((ClassDescriptor) descriptor, kind));
|
String name = DescriptorRenderer.getFQName(descriptor).replace('.', '/');
|
||||||
|
if(name.startsWith("<java_root>"))
|
||||||
|
name = name.substring("<java_root>".length()+1);
|
||||||
|
return Type.getObjectType(name + (kind == OwnerKind.TRAIT_IMPL ? "$$TImpl" : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descriptor instanceof TypeParameterDescriptor) {
|
if (descriptor instanceof TypeParameterDescriptor) {
|
||||||
@@ -503,6 +309,54 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, boolean superCall, OwnerKind kind) {
|
||||||
|
if(functionDescriptor == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration();
|
||||||
|
final List<Type> valueParameterTypes = new ArrayList<Type>();
|
||||||
|
Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind);
|
||||||
|
String owner;
|
||||||
|
int invokeOpcode;
|
||||||
|
ClassDescriptor thisClass;
|
||||||
|
if (functionParent instanceof NamespaceDescriptor) {
|
||||||
|
assert !superCall;
|
||||||
|
owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent));
|
||||||
|
invokeOpcode = INVOKESTATIC;
|
||||||
|
thisClass = null;
|
||||||
|
}
|
||||||
|
else if (functionDescriptor instanceof ConstructorDescriptor) {
|
||||||
|
assert !superCall;
|
||||||
|
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
|
||||||
|
owner = jvmName(containingClass, OwnerKind.IMPLEMENTATION);
|
||||||
|
invokeOpcode = INVOKESPECIAL;
|
||||||
|
thisClass = null;
|
||||||
|
}
|
||||||
|
else if (functionParent instanceof ClassDescriptor) {
|
||||||
|
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
|
||||||
|
boolean isInterface = CodegenUtil.isInterface(containingClass);
|
||||||
|
owner = jvmName(containingClass, isInterface && superCall ? OwnerKind.TRAIT_IMPL : OwnerKind.IMPLEMENTATION);
|
||||||
|
invokeOpcode = isInterface
|
||||||
|
? (superCall ? Opcodes.INVOKESTATIC : Opcodes.INVOKEINTERFACE)
|
||||||
|
: (superCall ? Opcodes.INVOKESPECIAL : Opcodes.INVOKEVIRTUAL);
|
||||||
|
if(isInterface && superCall) {
|
||||||
|
descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, OwnerKind.TRAIT_IMPL);
|
||||||
|
}
|
||||||
|
thisClass = containingClass;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException("unknown function parent");
|
||||||
|
}
|
||||||
|
|
||||||
|
final CallableMethod result = new CallableMethod(owner, descriptor, invokeOpcode, valueParameterTypes);
|
||||||
|
result.setNeedsThis(thisClass);
|
||||||
|
if(functionDescriptor.getReceiverParameter().exists()) {
|
||||||
|
result.setNeedsReceiver(functionDescriptor.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private Method mapSignature(FunctionDescriptor f, List<Type> valueParameterTypes, OwnerKind kind) {
|
private Method mapSignature(FunctionDescriptor f, List<Type> valueParameterTypes, OwnerKind kind) {
|
||||||
final ReceiverDescriptor receiverTypeRef = f.getReceiverParameter();
|
final ReceiverDescriptor receiverTypeRef = f.getReceiverParameter();
|
||||||
final JetType receiverType = !receiverTypeRef.exists() ? null : receiverTypeRef.getType();
|
final JetType receiverType = !receiverTypeRef.exists() ? null : receiverTypeRef.getType();
|
||||||
@@ -527,95 +381,15 @@ public class JetTypeMapper {
|
|||||||
valueParameterTypes.add(type);
|
valueParameterTypes.add(type);
|
||||||
parameterTypes.add(type);
|
parameterTypes.add(type);
|
||||||
}
|
}
|
||||||
for (int n = f.getTypeParameters().size(); n > 0; n--) {
|
for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) {
|
||||||
parameterTypes.add(TYPE_TYPEINFO);
|
if(parameterDescriptor.isReified()) {
|
||||||
|
parameterTypes.add(TYPE_TYPEINFO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Type returnType = mapReturnType(f.getReturnType());
|
Type returnType = f instanceof ConstructorDescriptor ? Type.VOID_TYPE : mapReturnType(f.getReturnType());
|
||||||
return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CallableMethod mapToCallableMethod(PsiNamedElement declaration, OwnerKind kind) {
|
|
||||||
if (declaration instanceof PsiMethod) {
|
|
||||||
return mapToCallableMethod((PsiMethod) declaration);
|
|
||||||
}
|
|
||||||
if (!(declaration instanceof JetNamedFunction)) {
|
|
||||||
throw new UnsupportedOperationException("unknown declaration type " + declaration);
|
|
||||||
}
|
|
||||||
JetNamedFunction f = (JetNamedFunction) declaration;
|
|
||||||
final FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f);
|
|
||||||
assert functionDescriptor != null;
|
|
||||||
return mapToCallableMethod(functionDescriptor, kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
static CallableMethod mapToCallableMethod(PsiMethod method) {
|
|
||||||
final PsiClass containingClass = method.getContainingClass();
|
|
||||||
String owner = jvmName(containingClass);
|
|
||||||
Method signature = getMethodDescriptor(method);
|
|
||||||
List<Type> valueParameterTypes = new ArrayList<Type>();
|
|
||||||
Collections.addAll(valueParameterTypes, signature.getArgumentTypes());
|
|
||||||
int opcode;
|
|
||||||
boolean ownerFromCall = false;
|
|
||||||
DeclarationDescriptor thisClass = null;
|
|
||||||
if (method.isConstructor()) {
|
|
||||||
opcode = Opcodes.INVOKESPECIAL;
|
|
||||||
}
|
|
||||||
else if (method.hasModifierProperty(PsiModifier.STATIC)) {
|
|
||||||
opcode = Opcodes.INVOKESTATIC;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert containingClass != null;
|
|
||||||
if (containingClass.isInterface()) {
|
|
||||||
opcode = Opcodes.INVOKEINTERFACE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
opcode = Opcodes.INVOKEVIRTUAL;
|
|
||||||
}
|
|
||||||
ownerFromCall = true;
|
|
||||||
thisClass = JetStandardClasses.getAny(); // todo - this is hack, correct descriptor needed
|
|
||||||
}
|
|
||||||
final CallableMethod result = new CallableMethod(owner, signature, opcode, valueParameterTypes);
|
|
||||||
result.setNeedsThis(thisClass);
|
|
||||||
result.setOwnerFromCall(ownerFromCall);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
|
||||||
if(functionDescriptor == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration();
|
|
||||||
final List<Type> valueParameterTypes = new ArrayList<Type>();
|
|
||||||
Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind);
|
|
||||||
String owner;
|
|
||||||
int invokeOpcode;
|
|
||||||
ClassDescriptor thisClass;
|
|
||||||
if (functionParent instanceof NamespaceDescriptor) {
|
|
||||||
owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent));
|
|
||||||
invokeOpcode = Opcodes.INVOKESTATIC;
|
|
||||||
thisClass = null;
|
|
||||||
}
|
|
||||||
else if (functionParent instanceof ClassDescriptor) {
|
|
||||||
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
|
|
||||||
owner = jvmName(containingClass, OwnerKind.IMPLEMENTATION);
|
|
||||||
invokeOpcode = CodegenUtil.isInterface(containingClass)
|
|
||||||
? Opcodes.INVOKEINTERFACE
|
|
||||||
: Opcodes.INVOKEVIRTUAL;
|
|
||||||
thisClass = containingClass;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new UnsupportedOperationException("unknown function parent");
|
|
||||||
}
|
|
||||||
|
|
||||||
final CallableMethod result = new CallableMethod(owner, descriptor, invokeOpcode, valueParameterTypes);
|
|
||||||
result.setAcceptsTypeArguments(true);
|
|
||||||
result.setNeedsThis(thisClass);
|
|
||||||
if(functionDescriptor.getReceiverParameter().exists()) {
|
|
||||||
result.setNeedsReceiver(functionDescriptor.getReceiverParameter().getType().getConstructor().getDeclarationDescriptor());
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Method mapSignature(String name, FunctionDescriptor f) {
|
public Method mapSignature(String name, FunctionDescriptor f) {
|
||||||
final ReceiverDescriptor receiver = f.getReceiverParameter();
|
final ReceiverDescriptor receiver = f.getReceiverParameter();
|
||||||
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
|
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
|
||||||
@@ -666,6 +440,7 @@ public class JetTypeMapper {
|
|||||||
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[0]);
|
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[0]);
|
||||||
else {
|
else {
|
||||||
ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
|
ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
|
||||||
|
assert containingDeclaration != null;
|
||||||
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[] { mapType(containingDeclaration.getDefaultType()) });
|
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[] { mapType(containingDeclaration.getDefaultType()) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -681,6 +456,7 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
|
ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
|
||||||
|
assert containingDeclaration != null;
|
||||||
return new Method(PropertyCodegen.setterName(descriptor.getName()), Type.VOID_TYPE, new Type[] { mapType(containingDeclaration.getDefaultType()), paramType });
|
return new Method(PropertyCodegen.setterName(descriptor.getName()), Type.VOID_TYPE, new Type[] { mapType(containingDeclaration.getDefaultType()), paramType });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -713,18 +489,16 @@ public class JetTypeMapper {
|
|||||||
List<Type> valueParameterTypes = new ArrayList<Type>();
|
List<Type> valueParameterTypes = new ArrayList<Type>();
|
||||||
final Method method = mapConstructorSignature(descriptor, valueParameterTypes);
|
final Method method = mapConstructorSignature(descriptor, valueParameterTypes);
|
||||||
String owner = jvmName(descriptor.getContainingDeclaration(), kind);
|
String owner = jvmName(descriptor.getContainingDeclaration(), kind);
|
||||||
final CallableMethod result = new CallableMethod(owner, method, Opcodes.INVOKESPECIAL, valueParameterTypes);
|
return new CallableMethod(owner, method, INVOKESPECIAL, valueParameterTypes);
|
||||||
result.setAcceptsTypeArguments(!(bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor.getContainingDeclaration()) instanceof PsiClass));
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getAccessModifiers(JetDeclaration p, int defaultFlags) {
|
static int getAccessModifiers(JetDeclaration p, int defaultFlags) {
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if (p.hasModifier(JetTokens.PUBLIC_KEYWORD)) {
|
if (p.hasModifier(JetTokens.PUBLIC_KEYWORD)) {
|
||||||
flags |= Opcodes.ACC_PUBLIC;
|
flags |= ACC_PUBLIC;
|
||||||
}
|
}
|
||||||
else if (p.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
|
else if (p.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
|
||||||
flags |= Opcodes.ACC_PRIVATE;
|
flags |= ACC_PRIVATE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
flags |= defaultFlags;
|
flags |= defaultFlags;
|
||||||
@@ -746,7 +520,7 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ClassDescriptor aClass = bindingContext.get(BindingContext.CLASS, container);
|
ClassDescriptor aClass = bindingContext.get(BindingContext.CLASS, container);
|
||||||
baseName = jvmNameForInterface(aClass);
|
baseName = jvmNameForImplementation(aClass, OwnerKind.IMPLEMENTATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
Integer count = anonymousSubclassesCount.get(baseName);
|
Integer count = anonymousSubclassesCount.get(baseName);
|
||||||
@@ -768,40 +542,90 @@ public class JetTypeMapper {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initKnownTypes() {
|
private void initKnownTypeNames() {
|
||||||
knowTypes.put(standardLibrary.getIntType(), "INT_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getIntType(), "INT_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getNullableIntType(), "NULLABLE_INT_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getNullableIntType(), "NULLABLE_INT_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getLongType(), "LONG_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getLongType(), "LONG_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getNullableLongType(), "NULLABLE_LONG_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getNullableLongType(), "NULLABLE_LONG_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getShortType(),"SHORT_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getShortType(),"SHORT_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getNullableShortType(),"NULLABLE_SHORT_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getNullableShortType(),"NULLABLE_SHORT_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getByteType(),"BYTE_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getByteType(),"BYTE_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getNullableByteType(),"NULLABLE_BYTE_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getNullableByteType(),"NULLABLE_BYTE_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getCharType(),"CHAR_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getCharType(),"CHAR_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getNullableCharType(),"NULLABLE_CHAR_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getNullableCharType(),"NULLABLE_CHAR_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getFloatType(),"FLOAT_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getFloatType(),"FLOAT_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getNullableFloatType(),"NULLABLE_FLOAT_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getNullableFloatType(),"NULLABLE_FLOAT_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getDoubleType(),"DOUBLE_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getDoubleType(),"DOUBLE_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getNullableDoubleType(),"NULLABLE_DOUBLE_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getNullableDoubleType(),"NULLABLE_DOUBLE_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getBooleanType(),"BOOLEAN_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getBooleanType(),"BOOLEAN_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getNullableBooleanType(),"NULLABLE_BOOLEAN_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getNullableBooleanType(),"NULLABLE_BOOLEAN_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getStringType(),"STRING_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getStringType(),"STRING_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getNullableStringType(),"NULLABLE_STRING_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getNullableStringType(),"NULLABLE_STRING_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getTuple0Type(),"TUPLE0_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getTuple0Type(),"TUPLE0_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getNullableTuple0Type(),"NULLABLE_TUPLE0_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getNullableTuple0Type(),"NULLABLE_TUPLE0_TYPE_INFO");
|
||||||
|
|
||||||
knowTypes.put(standardLibrary.getIntArrayType(), "INT_ARRAY_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getIntArrayType(), "INT_ARRAY_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getLongArrayType(), "LONG_ARRAY_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getLongArrayType(), "LONG_ARRAY_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getShortArrayType(),"SHORT_ARRAY_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getShortArrayType(),"SHORT_ARRAY_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getByteArrayType(),"BYTE_ARRAY_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getByteArrayType(),"BYTE_ARRAY_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getCharArrayType(),"CHAR_ARRAY_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getCharArrayType(),"CHAR_ARRAY_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getFloatArrayType(),"FLOAT_ARRAY_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getFloatArrayType(),"FLOAT_ARRAY_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getDoubleArrayType(),"DOUBLE_ARRAY_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getDoubleArrayType(),"DOUBLE_ARRAY_TYPE_INFO");
|
||||||
knowTypes.put(standardLibrary.getBooleanArrayType(),"BOOLEAN_ARRAY_TYPE_INFO");
|
knowTypeNames.put(standardLibrary.getBooleanArrayType(),"BOOLEAN_ARRAY_TYPE_INFO");
|
||||||
|
knowTypeNames.put(standardLibrary.getNullableIntArrayType(), "INT_ARRAY_TYPE_INFO");
|
||||||
|
knowTypeNames.put(standardLibrary.getNullableLongArrayType(), "LONG_ARRAY_TYPE_INFO");
|
||||||
|
knowTypeNames.put(standardLibrary.getNullableShortArrayType(),"SHORT_ARRAY_TYPE_INFO");
|
||||||
|
knowTypeNames.put(standardLibrary.getNullableByteArrayType(),"BYTE_ARRAY_TYPE_INFO");
|
||||||
|
knowTypeNames.put(standardLibrary.getNullableCharArrayType(),"CHAR_ARRAY_TYPE_INFO");
|
||||||
|
knowTypeNames.put(standardLibrary.getNullableFloatArrayType(),"FLOAT_ARRAY_TYPE_INFO");
|
||||||
|
knowTypeNames.put(standardLibrary.getNullableDoubleArrayType(),"DOUBLE_ARRAY_TYPE_INFO");
|
||||||
|
knowTypeNames.put(standardLibrary.getNullableBooleanArrayType(),"BOOLEAN_ARRAY_TYPE_INFO");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initKnownTypes() {
|
||||||
|
knowTypes.put(JetStandardClasses.getNothingType(), TYPE_NOTHING);
|
||||||
|
knowTypes.put(JetStandardClasses.getNullableNothingType(), TYPE_NOTHING);
|
||||||
|
|
||||||
|
knowTypes.put(standardLibrary.getIntType(), Type.INT_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableIntType(), JL_INTEGER_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getLongType(), Type.LONG_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableLongType(), JL_LONG_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getShortType(),Type.SHORT_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableShortType(),JL_SHORT_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getByteType(),Type.BYTE_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableByteType(),JL_BYTE_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getCharType(),Type.CHAR_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableCharType(),JL_CHAR_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getFloatType(),Type.FLOAT_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableFloatType(),JL_FLOAT_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getDoubleType(),Type.DOUBLE_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableDoubleType(),JL_DOUBLE_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getBooleanType(),Type.BOOLEAN_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableBooleanType(),JL_BOOLEAN_TYPE);
|
||||||
|
|
||||||
|
knowTypes.put(standardLibrary.getStringType(),JL_STRING_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableStringType(),JL_STRING_TYPE);
|
||||||
|
|
||||||
|
knowTypes.put(standardLibrary.getIntArrayType(), ARRAY_INT_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getLongArrayType(), ARRAY_LONG_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getShortArrayType(),ARRAY_SHORT_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getByteArrayType(),ARRAY_BYTE_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getCharArrayType(),ARRAY_CHAR_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getFloatArrayType(),ARRAY_FLOAT_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getDoubleArrayType(),ARRAY_DOUBLE_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getBooleanArrayType(),ARRAY_BOOL_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableIntArrayType(), ARRAY_INT_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableLongArrayType(), ARRAY_LONG_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableShortArrayType(),ARRAY_SHORT_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableByteArrayType(),ARRAY_BYTE_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableCharArrayType(),ARRAY_CHAR_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableFloatArrayType(),ARRAY_FLOAT_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableDoubleArrayType(),ARRAY_DOUBLE_TYPE);
|
||||||
|
knowTypes.put(standardLibrary.getNullableBooleanArrayType(),ARRAY_BOOL_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String isKnownTypeInfo(JetType jetType) {
|
public String isKnownTypeInfo(JetType jetType) {
|
||||||
return knowTypes.get(jetType);
|
return knowTypeNames.get(jetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGenericsArray(JetType type) {
|
public boolean isGenericsArray(JetType type) {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public class NamespaceCodegen {
|
|||||||
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
|
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
|
||||||
final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
|
final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
|
||||||
codegen.genToJVMStack(initializer);
|
codegen.genToJVMStack(initializer);
|
||||||
codegen.intermediateValueForProperty(descriptor, true, false, false).store(new InstructionAdapter(mv));
|
codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,6 +196,11 @@ public class NamespaceCodegen {
|
|||||||
if (fqName.length() == 0) {
|
if (fqName.length() == 0) {
|
||||||
return "namespace";
|
return "namespace";
|
||||||
}
|
}
|
||||||
return fqName.replace('.', '/') + "/namespace";
|
|
||||||
|
String name = fqName.replace('.', '/') + "/namespace";
|
||||||
|
if(name.startsWith("<java_root>")) {
|
||||||
|
name = name.substring("<java_root>".length() + 1, name.length() - ".namespace".length());
|
||||||
|
}
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -642,12 +642,12 @@ public abstract class StackValue {
|
|||||||
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + "$$TImpl", getter.getName(), getter.getDescriptor().replace("(","(L" + owner + ";"));
|
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + "$$TImpl", getter.getName(), getter.getDescriptor().replace("(","(L" + owner + ";"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (getter == null) {
|
if (getter == null) {
|
||||||
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor());
|
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, getter.getName(), getter.getDescriptor());
|
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, getter.getName(), getter.getDescriptor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
coerce(type, v);
|
coerce(type, v);
|
||||||
}
|
}
|
||||||
@@ -658,10 +658,10 @@ public abstract class StackValue {
|
|||||||
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + "$$TImpl", setter.getName(), setter.getDescriptor().replace("(","(L" + owner + ";"));
|
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + "$$TImpl", setter.getName(), setter.getDescriptor().replace("(","(L" + owner + ";"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (setter == null) {
|
if (setter == null) {
|
||||||
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
|
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, setter.getName(), setter.getDescriptor());
|
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, setter.getName(), setter.getDescriptor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ public class IntrinsicMethods {
|
|||||||
final PsiMethod[] methods = stringPsiClass.findMethodsByName(stringMember.getName(), false);
|
final PsiMethod[] methods = stringPsiClass.findMethodsByName(stringMember.getName(), false);
|
||||||
for (PsiMethod method : methods) {
|
for (PsiMethod method : methods) {
|
||||||
if (method.getParameterList().getParametersCount() == stringMethod.getValueParameters().size()) {
|
if (method.getParameterList().getParametersCount() == stringMethod.getValueParameters().size()) {
|
||||||
myMethods.put(stringMethod, new PsiMethodCall(method));
|
myMethods.put(stringMethod, new PsiMethodCall(stringMethod));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package org.jetbrains.jet.codegen.intrinsics;
|
package org.jetbrains.jet.codegen.intrinsics;
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.PsiMethod;
|
|
||||||
import org.jetbrains.jet.codegen.CallableMethod;
|
import org.jetbrains.jet.codegen.CallableMethod;
|
||||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||||
|
import org.jetbrains.jet.codegen.OwnerKind;
|
||||||
import org.jetbrains.jet.codegen.StackValue;
|
import org.jetbrains.jet.codegen.StackValue;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetCallExpression;
|
import org.jetbrains.jet.lang.psi.JetCallExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
@@ -14,18 +15,19 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yole
|
* @author yole
|
||||||
|
* @author alex.tkachman
|
||||||
*/
|
*/
|
||||||
public class PsiMethodCall implements IntrinsicMethod {
|
public class PsiMethodCall implements IntrinsicMethod {
|
||||||
private final PsiMethod myMethod;
|
private final FunctionDescriptor myMethod;
|
||||||
|
|
||||||
public PsiMethodCall(PsiMethod method) {
|
public PsiMethodCall(FunctionDescriptor method) {
|
||||||
myMethod = method;
|
myMethod = method;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element,
|
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element,
|
||||||
List<JetExpression> arguments, StackValue receiver) {
|
List<JetExpression> arguments, StackValue receiver) {
|
||||||
final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod, null);
|
final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod, false, OwnerKind.IMPLEMENTATION);
|
||||||
codegen.invokeMethodWithArguments(callableMethod, (JetCallExpression) element, receiver);
|
codegen.invokeMethodWithArguments(callableMethod, (JetCallExpression) element, receiver);
|
||||||
return StackValue.onStack(callableMethod.getSignature().getReturnType());
|
return StackValue.onStack(callableMethod.getSignature().getReturnType());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -243,16 +243,8 @@ public class CallResolver {
|
|||||||
// }
|
// }
|
||||||
// else {
|
// else {
|
||||||
// }
|
// }
|
||||||
if (reference instanceof JetFakeReference) {
|
trace.record(RESOLVED_CALL, call.getCalleeExpression(), resolvedCall);
|
||||||
// This means that the callable being invoked was represented by an expression
|
trace.record(REFERENCE_TARGET, reference, descriptor);
|
||||||
// rather than a reference expression
|
|
||||||
JetFakeReference fakeReference = (JetFakeReference) reference;
|
|
||||||
trace.record(RESOLVED_CALL, fakeReference.getActualElement(), resolvedCall);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
trace.record(RESOLVED_CALL, reference, resolvedCall);
|
|
||||||
trace.record(REFERENCE_TARGET, reference, descriptor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -102,6 +102,15 @@ public class JetStandardLibrary {
|
|||||||
private JetType doubleArrayType;
|
private JetType doubleArrayType;
|
||||||
private JetType booleanArrayType;
|
private JetType booleanArrayType;
|
||||||
|
|
||||||
|
private JetType nullableByteArrayType;
|
||||||
|
private JetType nullableCharArrayType;
|
||||||
|
private JetType nullableShortArrayType;
|
||||||
|
private JetType nullableIntArrayType;
|
||||||
|
private JetType nullableLongArrayType;
|
||||||
|
private JetType nullableFloatArrayType;
|
||||||
|
private JetType nullableDoubleArrayType;
|
||||||
|
private JetType nullableBooleanArrayType;
|
||||||
|
|
||||||
public JetType getTuple0Type() {
|
public JetType getTuple0Type() {
|
||||||
return tuple0Type;
|
return tuple0Type;
|
||||||
}
|
}
|
||||||
@@ -167,8 +176,21 @@ public class JetStandardLibrary {
|
|||||||
this.floatType = new JetTypeImpl(getFloat());
|
this.floatType = new JetTypeImpl(getFloat());
|
||||||
this.doubleType = new JetTypeImpl(getDouble());
|
this.doubleType = new JetTypeImpl(getDouble());
|
||||||
this.booleanType = new JetTypeImpl(getBoolean());
|
this.booleanType = new JetTypeImpl(getBoolean());
|
||||||
|
|
||||||
this.stringType = new JetTypeImpl(getString());
|
this.stringType = new JetTypeImpl(getString());
|
||||||
|
this.nullableStringType = TypeUtils.makeNullable(stringType);
|
||||||
|
|
||||||
this.tuple0Type = new JetTypeImpl(JetStandardClasses.getTuple(0));
|
this.tuple0Type = new JetTypeImpl(JetStandardClasses.getTuple(0));
|
||||||
|
this.nullableTuple0Type = TypeUtils.makeNullable(tuple0Type);
|
||||||
|
|
||||||
|
this.nullableByteType = TypeUtils.makeNullable(byteType);
|
||||||
|
this.nullableCharType = TypeUtils.makeNullable(charType);
|
||||||
|
this.nullableShortType = TypeUtils.makeNullable(shortType);
|
||||||
|
this.nullableIntType = TypeUtils.makeNullable(intType);
|
||||||
|
this.nullableLongType = TypeUtils.makeNullable(longType);
|
||||||
|
this.nullableFloatType = TypeUtils.makeNullable(floatType);
|
||||||
|
this.nullableDoubleType = TypeUtils.makeNullable(doubleType);
|
||||||
|
this.nullableBooleanType = TypeUtils.makeNullable(booleanType);
|
||||||
|
|
||||||
this.byteArrayClass = (ClassDescriptor) libraryScope.getClassifier("ByteArray");
|
this.byteArrayClass = (ClassDescriptor) libraryScope.getClassifier("ByteArray");
|
||||||
this.charArrayClass = (ClassDescriptor) libraryScope.getClassifier("CharArray");
|
this.charArrayClass = (ClassDescriptor) libraryScope.getClassifier("CharArray");
|
||||||
@@ -188,16 +210,14 @@ public class JetStandardLibrary {
|
|||||||
this.doubleArrayType = new JetTypeImpl(doubleArrayClass);
|
this.doubleArrayType = new JetTypeImpl(doubleArrayClass);
|
||||||
this.booleanArrayType = new JetTypeImpl(booleanArrayClass);
|
this.booleanArrayType = new JetTypeImpl(booleanArrayClass);
|
||||||
|
|
||||||
this.nullableByteType = TypeUtils.makeNullable(byteType);
|
this.nullableByteArrayType = TypeUtils.makeNullable(byteArrayType);
|
||||||
this.nullableCharType = TypeUtils.makeNullable(charType);
|
this.nullableCharArrayType = TypeUtils.makeNullable(charArrayType);
|
||||||
this.nullableShortType = TypeUtils.makeNullable(shortType);
|
this.nullableShortArrayType = TypeUtils.makeNullable(shortArrayType);
|
||||||
this.nullableIntType = TypeUtils.makeNullable(intType);
|
this.nullableIntArrayType = TypeUtils.makeNullable(intArrayType);
|
||||||
this.nullableLongType = TypeUtils.makeNullable(longType);
|
this.nullableLongArrayType = TypeUtils.makeNullable(longArrayType);
|
||||||
this.nullableFloatType = TypeUtils.makeNullable(floatType);
|
this.nullableFloatArrayType = TypeUtils.makeNullable(floatArrayType);
|
||||||
this.nullableDoubleType = TypeUtils.makeNullable(doubleType);
|
this.nullableDoubleArrayType = TypeUtils.makeNullable(doubleArrayType);
|
||||||
this.nullableBooleanType = TypeUtils.makeNullable(booleanType);
|
this.nullableBooleanArrayType = TypeUtils.makeNullable(booleanArrayType);
|
||||||
this.nullableStringType = TypeUtils.makeNullable(stringType);
|
|
||||||
this.nullableTuple0Type = TypeUtils.makeNullable(tuple0Type);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,4 +521,36 @@ public class JetStandardLibrary {
|
|||||||
initStdClasses();
|
initStdClasses();
|
||||||
return booleanArrayClass;
|
return booleanArrayClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JetType getNullableByteArrayType() {
|
||||||
|
return nullableByteArrayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetType getNullableCharArrayType() {
|
||||||
|
return nullableCharArrayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetType getNullableShortArrayType() {
|
||||||
|
return nullableShortArrayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetType getNullableIntArrayType() {
|
||||||
|
return nullableIntArrayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetType getNullableLongArrayType() {
|
||||||
|
return nullableLongArrayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetType getNullableFloatArrayType() {
|
||||||
|
return nullableFloatArrayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetType getNullableDoubleArrayType() {
|
||||||
|
return nullableDoubleArrayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JetType getNullableBooleanArrayType() {
|
||||||
|
return nullableBooleanArrayType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class C() : B() {
|
|||||||
<!VARIABLE_EXPECTED!>getInt()<!> = 12
|
<!VARIABLE_EXPECTED!>getInt()<!> = 12
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foo(c: C) {
|
fun bar(c: C) {
|
||||||
<!VARIABLE_EXPECTED!>this<!> = c //should be an error
|
<!VARIABLE_EXPECTED!>this<!> = c //should be an error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,4 +126,4 @@ fun Array<Int>.checkThis() {
|
|||||||
|
|
||||||
abstract class Ab {
|
abstract class Ab {
|
||||||
abstract fun getArray() : Array<Int>
|
abstract fun getArray() : Array<Int>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
class N() : java.util.ArrayList<String>() {
|
import java.util.ArrayList
|
||||||
override fun add(el: String) : Boolean {
|
trait Tr {
|
||||||
super.add(el)
|
fun extra() : String = "_"
|
||||||
return super.add(el + el)
|
}
|
||||||
|
|
||||||
|
class N() : ArrayList<Any>(), Tr {
|
||||||
|
override fun add(el: Any) : Boolean {
|
||||||
|
super<ArrayList>.add(el)
|
||||||
|
return super<ArrayList>.add(el.toString() + super<Tr>.extra() + el + extra())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun extra() : String = super<Tr>.extra() + super<Tr>.extra()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val n = N()
|
val n = N()
|
||||||
n.add("239")
|
n.add("239")
|
||||||
if (n.get(0) == "239" && n.get(1) == "239239") return "OK";
|
if (n.get(0) == "239" && n.get(1) == "239_239__") return "OK";
|
||||||
return "fail";
|
return "fail";
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
trait BK {
|
||||||
|
fun x() : Int = 50
|
||||||
|
}
|
||||||
|
|
||||||
|
trait K : BK {
|
||||||
|
override fun x() : Int = super.x() * 2
|
||||||
|
}
|
||||||
|
|
||||||
|
open class M() {
|
||||||
|
open fun x() : Int = 10
|
||||||
|
|
||||||
|
open var y = 500
|
||||||
|
}
|
||||||
|
|
||||||
|
open class N() : M(), K {
|
||||||
|
|
||||||
|
override fun x() : Int = 20
|
||||||
|
|
||||||
|
override var y = 200
|
||||||
|
|
||||||
|
open class C() : K {
|
||||||
|
fun test1() = x()
|
||||||
|
fun test2() = super<M>@N.x()
|
||||||
|
fun test3() = super<K>@N.x()
|
||||||
|
fun test4() = super<K>.x()
|
||||||
|
fun test5() = y
|
||||||
|
fun test6() : Int {
|
||||||
|
super<M>@N.y += 200
|
||||||
|
return super<M>@N.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
if (N().C().test1() != 100) return "test1 fail";
|
||||||
|
if (N().C().test2() != 10) return "test2 fail";
|
||||||
|
if (N().C().test3() != 100) return "test3 fail";
|
||||||
|
if (N().C().test4() != 100) return "test4 fail";
|
||||||
|
if (N().C().test5() != 200) return "test5 fail";
|
||||||
|
if (N().C().test6() != 700) return "test6 fail";
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
@@ -15,4 +15,9 @@ public class SuperGenTest extends CodegenTestCase {
|
|||||||
blackBoxFile("/super/basicmethod.jet");
|
blackBoxFile("/super/basicmethod.jet");
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testEnclosedMethod () {
|
||||||
|
blackBoxFile("/super/enclosed.jet");
|
||||||
|
System.out.println(generateToText());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user