Merge remote-tracking branch 'origin/master'

This commit is contained in:
svtk
2011-12-13 19:43:31 +04:00
88 changed files with 2524 additions and 498 deletions
@@ -0,0 +1,215 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.signature.JetSignatureWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter;
import org.objectweb.asm.util.CheckSignatureAdapter;
import java.util.Stack;
/**
* @author Stepan Koltsov
*/
public class BothSignatureWriter {
private static final boolean DEBUG_SIGNATURE_WRITER = true;
enum Mode {
METHOD(CheckSignatureAdapter.METHOD_SIGNATURE),
CLASS(CheckSignatureAdapter.CLASS_SIGNATURE),
;
private final int asmType;
Mode(int asmType) {
this.asmType = asmType;
}
}
private final SignatureWriter signatureWriter = new SignatureWriter();
private final SignatureVisitor signatureVisitor;
private final JetSignatureWriter jetSignatureWriter = new JetSignatureWriter();
private final Mode mode;
public BothSignatureWriter(Mode mode) {
this.mode = mode;
if (DEBUG_SIGNATURE_WRITER) {
signatureVisitor = new CheckSignatureAdapter(mode.asmType, signatureWriter);
} else {
signatureVisitor = signatureWriter;
}
}
// TODO: ignore when debugging is disabled
private Stack<SignatureVisitor> visitors = new Stack<SignatureVisitor>();
private void push(SignatureVisitor visitor) {
visitors.push(visitor);
}
private void pop() {
visitors.pop();
}
private SignatureVisitor signatureVisitor() {
return !visitors.isEmpty() ? visitors.peek() : signatureVisitor;
}
private void checkTopLevel() {
if (DEBUG_SIGNATURE_WRITER) {
if (!visitors.isEmpty()) {
throw new IllegalStateException();
}
}
}
private void checkMode(Mode mode) {
if (DEBUG_SIGNATURE_WRITER) {
if (mode != this.mode) {
throw new IllegalStateException();
}
}
}
/**
* Shortcut
*/
public void writeAsmType(Type asmType) {
switch (asmType.getSort()) {
case Type.OBJECT:
writeClassBegin(asmType.getInternalName());
writeClassEnd();
return;
case Type.ARRAY:
writeArrayType();
writeAsmType(asmType.getElementType());
writeArrayEnd();
return;
default:
String descriptor = asmType.getDescriptor();
if (descriptor.length() != 1) {
throw new IllegalStateException();
}
signatureVisitor().visitBaseType(descriptor.charAt(0));
}
}
public void writeClassBegin(String internalName) {
signatureVisitor().visitClassType(internalName);
}
public void writeClassEnd() {
signatureVisitor().visitEnd();
}
public void writeArrayType() {
push(signatureVisitor().visitArrayType());
}
public void writeArrayEnd() {
pop();
}
public void writeTypeArgument(char c) {
push(signatureVisitor().visitTypeArgument(c));
}
public void writeTypeArgumentEnd() {
pop();
}
public void writeTypeVariable(final String name) {
signatureVisitor().visitTypeVariable(name);
}
public void writeFormalTypeParameter(final String name) {
checkTopLevel();
signatureVisitor().visitFormalTypeParameter(name);
}
public void writeClassBound() {
push(signatureVisitor().visitClassBound());
}
public void writeClassBoundEnd() {
pop();
}
public void writeInterfaceBound() {
push(signatureVisitor().visitInterfaceBound());
}
public void writeInterfaceBoundEnd() {
pop();
}
public void writeParameterType() {
push(signatureVisitor().visitParameterType());
}
public void writeParameterTypeEnd() {
pop();
}
public void writeReturnType() {
push(signatureVisitor().visitReturnType());
}
public void writeReturnTypeEnd() {
pop();
}
public void writeSuperclass() {
checkTopLevel();
checkMode(Mode.CLASS);
push(signatureVisitor().visitSuperclass());
}
public void writeSuperclassEnd() {
pop();
if (!visitors.isEmpty()) {
throw new IllegalStateException();
}
}
public void writeInterface() {
checkTopLevel();
checkMode(Mode.CLASS);
push(signatureVisitor().visitInterface());
}
public void writeInterfaceEnd() {
pop();
if (!visitors.isEmpty()) {
throw new IllegalStateException();
}
}
@Nullable
public String makeJavaString() {
if (!visitors.isEmpty()) {
throw new IllegalStateException();
}
return signatureWriter.toString();
}
@Nullable
public String makeKotlinString() {
// TODO: not implemented yet
return null;
}
}
@@ -57,26 +57,18 @@ public class CodegenUtil {
return (ClassDescriptor) outerDescriptor;
}
public static boolean hasOuterTypeInfo(ClassDescriptor descriptor) {
ClassDescriptor outerClassDescriptor = getOuterClassDescriptor(descriptor);
if(outerClassDescriptor == null)
return false;
if(outerClassDescriptor.getTypeConstructor().getParameters().size() > 0)
return true;
return hasOuterTypeInfo(outerClassDescriptor);
}
public static boolean hasDerivedTypeInfoField(JetType type, boolean exceptOwn) {
if(!exceptOwn) {
if(!isInterface(type))
if(hasTypeInfoField(type))
return true;
public static boolean hasDerivedTypeInfoField(JetType type) {
for (JetType jetType : type.getConstructor().getSupertypes()) {
if(hasTypeInfoField(jetType))
return true;
}
for (JetType jetType : type.getConstructor().getSupertypes()) {
if(hasDerivedTypeInfoField(jetType, false))
return false;
}
public static boolean requireTypeInfoConstructorArg(JetType type) {
for (TypeParameterDescriptor parameter : type.getConstructor().getParameters()) {
if(parameter.isReified())
return true;
}
@@ -87,22 +79,10 @@ public class CodegenUtil {
if(isInterface(type))
return false;
List<TypeParameterDescriptor> parameters = type.getConstructor().getParameters();
for (TypeParameterDescriptor parameter : parameters) {
if(parameter.isReified())
return true;
}
if(requireTypeInfoConstructorArg(type))
return true;
for (JetType jetType : type.getConstructor().getSupertypes()) {
if(hasTypeInfoField(jetType))
return true;
}
ClassDescriptor outerClassDescriptor = getOuterClassDescriptor(type.getConstructor().getDeclarationDescriptor());
if(outerClassDescriptor == null || isClassObject(type.getConstructor().getDeclarationDescriptor()))
return false;
return hasTypeInfoField(outerClassDescriptor.getDefaultType());
return hasDerivedTypeInfoField(type);
}
public static FunctionDescriptor createInvoke(ExpressionAsFunctionDescriptor fd) {
@@ -12,11 +12,11 @@ import java.util.List;
/**
* @author yole
* @author alex.tkachman
*/
public class ConstructorFrameMap extends FrameMap {
private int myOuterThisIndex = -1;
private int myFirstTypeParameter = -1;
private int myTypeParameterCount = 0;
private int myTypeInfoIndex = -1;
public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor, ClassDescriptor classDescriptor, OwnerKind kind) {
enterTemp(); // this
@@ -27,15 +27,8 @@ public class ConstructorFrameMap extends FrameMap {
}
if (classDescriptor != null) {
List<TypeParameterDescriptor> parameters = classDescriptor.getTypeConstructor().getParameters();
for (TypeParameterDescriptor parameter : parameters) {
if(parameter.isReified()) {
int index = enterTemp();
myTypeParameterCount++;
if(myFirstTypeParameter == -1) {
myFirstTypeParameter = index;
}
}
if (CodegenUtil.requireTypeInfoConstructorArg(classDescriptor.getDefaultType())) {
myTypeInfoIndex = enterTemp();
}
}
@@ -54,11 +47,7 @@ public class ConstructorFrameMap extends FrameMap {
return myOuterThisIndex;
}
public int getFirstTypeParameter() {
return myFirstTypeParameter;
}
public int getTypeParameterCount() {
return myTypeParameterCount;
public int getTypeInfoIndex() {
return myTypeInfoIndex;
}
}
@@ -979,7 +979,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
else if (descriptor instanceof TypeParameterDescriptor) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
loadTypeParameterTypeInfo(typeParameterDescriptor);
loadTypeParameterTypeInfo(typeParameterDescriptor, null);
v.invokevirtual("jet/typeinfo/TypeInfo", "getClassObject", "()Ljava/lang/Object;");
v.checkcast(asmType(typeParameterDescriptor.getClassObjectType()));
@@ -2033,26 +2033,32 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private void pushTypeArguments(ResolvedCall<? extends CallableDescriptor> resolvedCall) {
if(resolvedCall != null) {
Map<TypeParameterDescriptor, JetType> typeArguments = resolvedCall.getTypeArguments();
CallableDescriptor resultingDescriptor = resolvedCall.getCandidateDescriptor();
for (TypeParameterDescriptor typeParameterDescriptor : resultingDescriptor.getTypeParameters()) {
if(typeParameterDescriptor.isReified()) {
JetType jetType = typeArguments.get(typeParameterDescriptor);
generateTypeInfo(jetType);
if(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor) {
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
ClassDescriptor containingDeclaration = constructorDescriptor.getContainingDeclaration();
if(CodegenUtil.requireTypeInfoConstructorArg(containingDeclaration.getDefaultType())) {
generateTypeInfo(containingDeclaration.getDefaultType(), resolvedCall.getTypeArguments());
}
}
else {
Map<TypeParameterDescriptor, JetType> typeArguments = resolvedCall.getTypeArguments();
CallableDescriptor resultingDescriptor = resolvedCall.getCandidateDescriptor();
for (TypeParameterDescriptor typeParameterDescriptor : resultingDescriptor.getTypeParameters()) {
if(typeParameterDescriptor.isReified()) {
JetType jetType = typeArguments.get(typeParameterDescriptor);
generateTypeInfo(jetType, typeArguments);
}
}
}
}
else {
throw new UnsupportedOperationException();
// for (JetTypeProjection jetTypeArgument : expression.getTypeArguments()) {
// pushTypeArgument(jetTypeArgument);
// }
}
}
public void pushTypeArgument(JetTypeProjection jetTypeArgument) {
JetType typeArgument = bindingContext.get(BindingContext.TYPE, jetTypeArgument.getTypeReference());
generateTypeInfo(typeArgument);
generateTypeInfo(typeArgument, null);
}
private Type generateJavaConstructorCall(JetCallExpression expression) {
@@ -2091,7 +2097,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if(isArray) {
JetType elementType = typeMapper.getGenericsElementType(arrayType);
if(elementType != null) {
generateTypeInfo(elementType);
generateTypeInfo(elementType, null);
gen(args.get(0).getArgumentExpression(), Type.INT_TYPE);
v.invokevirtual("jet/typeinfo/TypeInfo", "newArray", "(I)[Ljava/lang/Object;");
}
@@ -2193,9 +2199,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if(getterDescriptor.getReceiverParameter().exists()) {
index++;
}
for (TypeParameterDescriptor typeParameterDescriptor : getterDescriptor.getTypeParameters()) {
for (TypeParameterDescriptor typeParameterDescriptor : resolvedGetCall.getCandidateDescriptor().getTypeParameters()) {
if(typeParameterDescriptor.isReified()) {
generateTypeInfo(resolvedGetCall.getTypeArguments().get(typeParameterDescriptor));
generateTypeInfo(resolvedGetCall.getTypeArguments().get(typeParameterDescriptor), null);
index++;
}
}
@@ -2215,7 +2221,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
for (TypeParameterDescriptor typeParameterDescriptor : setterDescriptor.getOriginal().getTypeParameters()) {
if(typeParameterDescriptor.isReified()) {
generateTypeInfo(resolvedSetCall.getTypeArguments().get(typeParameterDescriptor));
generateTypeInfo(resolvedSetCall.getTypeArguments().get(typeParameterDescriptor), null);
index++;
}
}
@@ -2503,7 +2509,7 @@ If finally block is present, its last expression is the value of try expression.
}
}
else {
generateTypeInfo(jetType);
generateTypeInfo(jetType, null);
expressionToGen.put(TYPE_OBJECT, v);
if (leaveExpressionOnStack) {
v.dupX1();
@@ -2512,7 +2518,7 @@ If finally block is present, its last expression is the value of try expression.
}
}
public void generateTypeInfo(JetType jetType) {
public void generateTypeInfo(JetType jetType, Map<TypeParameterDescriptor, JetType> typeArguments) {
String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType);
if(knownTypeInfo != null) {
v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;");
@@ -2521,7 +2527,7 @@ If finally block is present, its last expression is the value of try expression.
DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor instanceof TypeParameterDescriptor) {
loadTypeParameterTypeInfo((TypeParameterDescriptor) declarationDescriptor);
loadTypeParameterTypeInfo((TypeParameterDescriptor) declarationDescriptor, typeArguments);
return;
}
@@ -2551,7 +2557,7 @@ If finally block is present, its last expression is the value of try expression.
TypeProjection argument = arguments.get(i);
v.dup();
v.iconst(i);
generateTypeInfo(argument.getType());
generateTypeInfo(argument.getType(), typeArguments);
genTypeInfoToProjection(v, argument.getProjectionKind());
v.astore(TYPE_OBJECT);
}
@@ -2573,12 +2579,21 @@ If finally block is present, its last expression is the value of try expression.
throw new UnsupportedOperationException(variance.toString());
}
private void loadTypeParameterTypeInfo(TypeParameterDescriptor typeParameterDescriptor) {
private void loadTypeParameterTypeInfo(TypeParameterDescriptor typeParameterDescriptor, @Nullable Map<TypeParameterDescriptor, JetType> typeArguments) {
final StackValue value = typeParameterExpressions.get(typeParameterDescriptor);
if (value != null) {
value.put(TYPE_TYPEINFO, v);
return;
}
if(typeArguments != null) {
JetType jetType = typeArguments.get(typeParameterDescriptor);
if(jetType != null && !jetType.equals(typeParameterDescriptor.getDefaultType())) {
generateTypeInfo(jetType, typeArguments);
return;
}
}
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
if (context.getThisDescriptor() != null) {
ClassDescriptor descriptor = context.getThisDescriptor();
@@ -2589,8 +2604,13 @@ If finally block is present, its last expression is the value of try expression.
if (containingDeclaration == context.getThisDescriptor()) {
if(!CodegenUtil.isInterface(descriptor)) {
if (CodegenUtil.hasTypeInfoField(defaultType)) {
v.load(0, TYPE_OBJECT);
v.getfield(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
if(!(context instanceof CodegenContext.ConstructorContext)) {
v.load(0, TYPE_OBJECT);
v.getfield(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
}
else {
v.load(((ConstructorFrameMap)myFrameMap).getTypeInfoIndex(), TYPE_OBJECT);
}
}
else {
v.getstatic(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
@@ -2598,16 +2618,16 @@ If finally block is present, its last expression is the value of try expression.
}
else {
v.load(0, TYPE_OBJECT);
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
v.invokeinterface(TYPE_JET_OBJECT.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
}
}
else {
v.load(0, TYPE_OBJECT);
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
while(descriptor != containingDeclaration) {
descriptor = CodegenUtil.getOuterClassDescriptor(descriptor);
v.invokevirtual("jet/typeinfo/TypeInfo", "getOuterTypeInfo", "()Ljet/typeinfo/TypeInfo;");
v.invokeinterface(TYPE_JET_OBJECT.getInternalName(), "getOuterObject", "()Ljet/JetObject;");
}
v.invokeinterface(TYPE_JET_OBJECT.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
}
v.aconst(ownerType);
v.iconst(typeParameterDescriptor.getIndex());
@@ -2737,7 +2757,7 @@ If finally block is present, its last expression is the value of try expression.
v.anew(tupleType);
v.dup();
generateTypeInfo(new ProjectionErasingJetType(bindingContext.get(BindingContext.EXPRESSION_TYPE, expression)));
generateTypeInfo(new ProjectionErasingJetType(bindingContext.get(BindingContext.EXPRESSION_TYPE, expression)), null);
for (JetExpression entry : entries) {
gen(entry, TYPE_OBJECT);
}
@@ -6,7 +6,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.StdlibNames;
import org.jetbrains.jet.lang.resolve.java.StdlibNames;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Label;
@@ -86,7 +86,7 @@ public class FunctionCodegen {
if(v.generateCode()) {
int start = 0;
if(kind != OwnerKind.TRAIT_IMPL) {
AnnotationVisitor av = mv.visitAnnotation(StdlibNames.JET_METHOD_TYPE.getDescriptor(), true);
AnnotationVisitor av = mv.visitAnnotation(JetTypeMapper.JET_METHOD_TYPE.getDescriptor(), true);
if(functionDescriptor.getReturnType().isNullable()) {
av.visit(StdlibNames.JET_METHOD_NULLABLE_RETURN_TYPE_FIELD, true);
}
@@ -94,15 +94,15 @@ public class FunctionCodegen {
}
if(kind == OwnerKind.TRAIT_IMPL) {
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_PARAMETER_DESCRIPTOR, true);
av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, "this$self");
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_VALUE_PARAMETER_DESCRIPTOR, true);
av.visit(StdlibNames.JET_VALUE_PARAMETER_NAME_FIELD, "this$self");
av.visitEnd();
}
if(receiverParameter.exists()) {
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_PARAMETER_DESCRIPTOR, true);
av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, "this$receiver");
AnnotationVisitor av = mv.visitParameterAnnotation(start++, StdlibNames.JET_VALUE_PARAMETER_DESCRIPTOR, true);
av.visit(StdlibNames.JET_VALUE_PARAMETER_NAME_FIELD, "this$receiver");
if(receiverParameter.getType().isNullable()) {
av.visit(StdlibNames.JET_PARAMETER_NULLABLE_FIELD, true);
av.visit(StdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true);
}
av.visitEnd();
}
@@ -112,14 +112,14 @@ public class FunctionCodegen {
av.visitEnd();
}
for(int i = 0; i != paramDescrs.size(); ++i) {
AnnotationVisitor av = mv.visitParameterAnnotation(i + start, StdlibNames.JET_PARAMETER_DESCRIPTOR, true);
AnnotationVisitor av = mv.visitParameterAnnotation(i + start, StdlibNames.JET_VALUE_PARAMETER_DESCRIPTOR, true);
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i);
av.visit(StdlibNames.JET_PARAMETER_NAME_FIELD, parameterDescriptor.getName());
av.visit(StdlibNames.JET_VALUE_PARAMETER_NAME_FIELD, parameterDescriptor.getName());
if(parameterDescriptor.hasDefaultValue()) {
av.visit(StdlibNames.JET_PARAMETER_HAS_DEFAULT_VALUE_FIELD, true);
av.visit(StdlibNames.JET_VALUE_PARAMETER_HAS_DEFAULT_VALUE_FIELD, true);
}
if(parameterDescriptor.getOutType().isNullable()) {
av.visit(StdlibNames.JET_PARAMETER_NULLABLE_FIELD, true);
av.visit(StdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true);
}
av.visitEnd();
}
@@ -6,6 +6,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.OverridingUtil;
import org.jetbrains.jet.lang.resolve.java.StdlibNames;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
@@ -16,9 +17,6 @@ import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method;
import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter;
import org.objectweb.asm.util.CheckSignatureAdapter;
import java.util.*;
@@ -29,7 +27,9 @@ import java.util.*;
*/
public class ImplementationBodyCodegen extends ClassBodyCodegen {
private JetDelegationSpecifier superCall;
private String superClass = "java/lang/Object";
private String superClass;
@Nullable // null means java/lang/Object
private JetType superClassType;
private final JetTypeMapper typeMapper;
private final BindingContext bindingContext;
@@ -39,28 +39,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
bindingContext = state.getBindingContext();
}
private Set<String> getSuperInterfaces(JetClassOrObject aClass) {
List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers();
Set<String> superInterfaces = new LinkedHashSet<String>();
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
if(CodegenUtil.isInterface(superClassDescriptor)) {
superInterfaces.add(typeMapper.getFQName(superClassDescriptor));
}
}
return superInterfaces;
}
@Override
protected void generateDeclaration() {
getSuperClass();
List<String> interfaces = new ArrayList<String>();
interfaces.add("jet/JetObject");
interfaces.addAll(getSuperInterfaces(myClass));
JvmClassSignature signature = signature();
boolean isAbstract = false;
boolean isInterface = false;
@@ -77,10 +60,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface
? Opcodes.ACC_INTERFACE
: 0/*Opcodes.ACC_SUPER*/),
jvmName(),
genericSignature(),
superClass,
interfaces.toArray(new String[interfaces.size()])
signature.getName(),
signature.getGenericSignature(),
signature.getSuperclassName(),
signature.getInterfaces().toArray(new String[0])
);
v.visitSource(myClass.getContainingFile().getName(), null);
@@ -94,30 +77,57 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
annotationVisitor.visitEnd();
}
}
private JvmClassSignature signature() {
String genericSignature;
List<String> superInterfaces;
@Nullable
private String genericSignature() {
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters();
SignatureWriter signatureWriter = new SignatureWriter();
SignatureVisitor signatureVisitor = JetTypeMapper.DEBUG_SIGNATURE_WRITER
? new CheckSignatureAdapter(CheckSignatureAdapter.CLASS_SIGNATURE, signatureWriter)
: signatureWriter;
for (TypeParameterDescriptor typeParameter : typeParameters) {
signatureVisitor.visitFormalTypeParameter(typeParameter.getName());
SignatureVisitor classBoundVisitor = signatureVisitor.visitClassBound();
// TODO: wrong
JetTypeMapper.visitAsmType(classBoundVisitor, JetTypeMapper.TYPE_OBJECT);
{
LinkedHashSet<String> superInterfacesLinkedHashSet = new LinkedHashSet<String>();
BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
{ // type parameters
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters();
typeMapper.writeFormalTypeParameters(typeParameters, signatureVisitor);
}
{ // superclass
signatureVisitor.writeSuperclass();
if (superClassType == null) {
signatureVisitor.writeClassBegin(superClass);
signatureVisitor.writeClassEnd();
} else {
typeMapper.mapType(superClassType, OwnerKind.IMPLEMENTATION, signatureVisitor, true);
}
signatureVisitor.writeSuperclassEnd();
}
{ // superinterfaces
superInterfacesLinkedHashSet.add(StdlibNames.JET_OBJECT_INTERNAL);
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
if (CodegenUtil.isInterface(superClassDescriptor)) {
signatureVisitor.writeInterface();
Type jvmName = typeMapper.mapType(superType, OwnerKind.IMPLEMENTATION, signatureVisitor, true);
signatureVisitor.writeInterfaceEnd();
superInterfacesLinkedHashSet.add(jvmName.getInternalName());
}
}
superInterfaces = new ArrayList<String>(superInterfacesLinkedHashSet);
}
// TODO: null if class is not generic and does not have generic superclasses
genericSignature = signatureVisitor.makeJavaString();
}
SignatureVisitor superclassSignatureVisitor = signatureVisitor.visitSuperclass();
// TODO: wrong
superclassSignatureVisitor.visitClassType("java/lang/Object");
// TODO: add interfaces
superclassSignatureVisitor.visitEnd();
// TODO: return null if class is not generic and does not have generic superclasses
return signatureWriter.toString();
return new JvmClassSignature(jvmName(), superClass, superInterfaces, genericSignature);
}
private String jvmName() {
@@ -125,6 +135,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
protected void getSuperClass() {
superClass = "java/lang/Object";
superClassType = null;
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
if(myClass instanceof JetClass && ((JetClass) myClass).isTrait())
@@ -136,6 +149,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
assert superType != null;
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
if(!CodegenUtil.isInterface(superClassDescriptor)) {
superClassType = superType;
superClass = typeMapper.mapType(superClassDescriptor.getDefaultType(), kind).getInternalName();
superCall = specifier;
}
@@ -305,8 +319,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
}
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters();
for (int n = typeParameters.size(); n > 0; n--) {
if (CodegenUtil.requireTypeInfoConstructorArg(descriptor.getDefaultType())) {
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
}
@@ -365,12 +378,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final InstructionAdapter iv = new InstructionAdapter(mv);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, constructorContext, state);
for(int slot = 0; slot != frameMap.getTypeParameterCount(); ++slot) {
if(constructorDescriptor != null)
codegen.addTypeParameter(constructorDescriptor.getTypeParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
else
codegen.addTypeParameter(descriptor.getTypeConstructor().getParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
}
// for(int slot = 0; slot != frameMap.getTypeParameterCount(); ++slot) {
// if(constructorDescriptor != null)
// codegen.addTypeParameter(constructorDescriptor.getTypeParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
// else
// codegen.addTypeParameter(descriptor.getTypeConstructor().getParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
// }
String classname = typeMapper.mapType(descriptor.getDefaultType(), kind).getInternalName();
final Type classType = Type.getType("L" + classname + ";");
@@ -399,7 +412,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
}
for(TypeProjection typeParameterDescriptor : superType.getArguments()) {
codegen.generateTypeInfo(typeParameterDescriptor.getType());
codegen.generateTypeInfo(typeParameterDescriptor.getType(), null);
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
}
Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
@@ -447,10 +460,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.load(0, classType);
iv.load(frameMap.getOuterThisIndex(), type);
iv.putfield(classname, fieldName, interfaceDesc);
Type outerType = typeMapper.mapType(outerDescriptor.getDefaultType());
MethodVisitor outer = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getOuterObject", "()Ljet/JetObject;", null, null);
outer.visitCode();
outer.visitVarInsn(Opcodes.ALOAD, 0);
outer.visitFieldInsn(Opcodes.GETFIELD, classname, "this$0", outerType.getDescriptor());
outer.visitInsn(Opcodes.ARETURN);
outer.visitMaxs(0, 0);
outer.visitEnd();
}
if (CodegenUtil.hasTypeInfoField(descriptor.getDefaultType()) && kind == OwnerKind.IMPLEMENTATION) {
generateTypeInfoInitializer(frameMap.getFirstTypeParameter(), frameMap.getTypeParameterCount(), iv);
if (CodegenUtil.requireTypeInfoConstructorArg(descriptor.getDefaultType()) && kind == OwnerKind.IMPLEMENTATION) {
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(frameMap.getTypeInfoIndex(), JetTypeMapper.TYPE_OBJECT);
iv.invokevirtual(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V");
}
if(closure != null) {
@@ -691,46 +715,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.aconst(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION));
iv.iconst(0);
if(CodegenUtil.hasOuterTypeInfo(descriptor)) {
iv.load(1, JetTypeMapper.TYPE_OBJECT);
iv.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
}
if(typeParamCount != 0) {
iv.iconst(typeParamCount);
iv.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
for (int i = 0; i < typeParamCount; i++) {
iv.dup();
iv.iconst(i);
iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT);
iv.checkcast(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
iv.astore(JetTypeMapper.TYPE_OBJECT);
}
if(CodegenUtil.hasOuterTypeInfo(descriptor)) {
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
}
else
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
}
else {
if(CodegenUtil.hasOuterTypeInfo(descriptor)) {
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfo;");
}
else
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
}
iv.invokevirtual(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V");
}
protected void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) {
for (JetDeclaration declaration : myClass.getDeclarations()) {
if (declaration instanceof JetProperty) {
@@ -827,15 +811,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
return;
JetType defaultType = descriptor.getDefaultType();
if(CodegenUtil.hasTypeInfoField(defaultType)) {
if(!CodegenUtil.hasDerivedTypeInfoField(defaultType, true)) {
if(CodegenUtil.requireTypeInfoConstructorArg(defaultType)) {
if(!CodegenUtil.hasDerivedTypeInfoField(defaultType)) {
v.newField(myClass, Opcodes.ACC_PROTECTED, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
InstructionAdapter iv = null;
if (v.generateCode()) {
mv.visitCode();
iv = new InstructionAdapter(mv);
InstructionAdapter iv = new InstructionAdapter(mv);
String owner = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
@@ -847,7 +830,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv = v.newMethod(myClass, Opcodes.ACC_PROTECTED | Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V", null, null);
if (v.generateCode()) {
mv.visitCode();
iv = new InstructionAdapter(mv);
InstructionAdapter iv = new InstructionAdapter(mv);
String owner = typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName();
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(1, JetTypeMapper.TYPE_OBJECT);
@@ -884,14 +867,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
public void generate(InstructionAdapter v) {
v.aconst(typeMapper.mapType(descriptor.getDefaultType(), OwnerKind.IMPLEMENTATION));
v.iconst(0);
ClassDescriptor outerClassDescriptor = CodegenUtil.getOuterClassDescriptor(descriptor);
if(outerClassDescriptor == null || CodegenUtil.isClassObject(descriptor)) {
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
}
else {
v.getstatic(typeMapper.mapType(outerClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfo;");
}
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
v.putstatic(typeMapper.mapType(descriptor.getDefaultType(), kind).getInternalName(), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
}
});
@@ -18,9 +18,6 @@ import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;
import org.objectweb.asm.signature.SignatureVisitor;
import org.objectweb.asm.signature.SignatureWriter;
import org.objectweb.asm.util.CheckSignatureAdapter;
import java.util.*;
@@ -57,6 +54,9 @@ public class JetTypeMapper {
public static final Type ARRAY_DOUBLE_TYPE = Type.getType(double[].class);
public static final Type ARRAY_BOOL_TYPE = Type.getType(boolean[].class);
public static final Type ARRAY_GENERIC_TYPE = Type.getType(Object[].class);
public static final Type JET_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetValueParameter");
public static final Type JET_TYPE_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetTypeParameter");
public static final Type JET_METHOD_TYPE = Type.getObjectType("jet/typeinfo/JetMethod");
private final JetStandardLibrary standardLibrary;
private final BindingContext bindingContext;
@@ -86,7 +86,11 @@ public class JetTypeMapper {
public static final Type TYPE_LONG_ITERATOR = Type.getObjectType("jet/LongIterator");
public static final Type TYPE_FLOAT_ITERATOR = Type.getObjectType("jet/FloatIterator");
public static final Type TYPE_DOUBLE_ITERATOR = Type.getObjectType("jet/DoubleIterator");
public JetStandardLibrary getStandardLibrary() {
return standardLibrary;
}
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
this.standardLibrary = standardLibrary;
this.bindingContext = bindingContext;
@@ -158,10 +162,10 @@ public class JetTypeMapper {
return mapReturnType(jetType, null);
}
@NotNull private Type mapReturnType(final JetType jetType, @Nullable SignatureVisitor signatureVisitor) {
@NotNull private Type mapReturnType(final JetType jetType, @Nullable BothSignatureWriter signatureVisitor) {
if (jetType.equals(JetStandardClasses.getUnitType()) || jetType.equals(JetStandardClasses.getNothingType())) {
if (signatureVisitor != null) {
signatureVisitor.visitBaseType('V');
signatureVisitor.writeAsmType(Type.VOID_TYPE);
}
return Type.VOID_TYPE;
}
@@ -219,10 +223,10 @@ public class JetTypeMapper {
}
@NotNull public Type mapType(final JetType jetType) {
return mapType(jetType, (SignatureVisitor) null);
return mapType(jetType, (BothSignatureWriter) null);
}
@NotNull private Type mapType(JetType jetType, @Nullable SignatureVisitor signatureVisitor) {
@NotNull private Type mapType(JetType jetType, @Nullable BothSignatureWriter signatureVisitor) {
return mapType(jetType, OwnerKind.IMPLEMENTATION, signatureVisitor);
}
@@ -230,17 +234,22 @@ public class JetTypeMapper {
return mapType(jetType, kind, null);
}
@NotNull private Type mapType(JetType jetType, OwnerKind kind, @Nullable SignatureVisitor signatureVisitor) {
@NotNull private Type mapType(JetType jetType, OwnerKind kind, @Nullable BothSignatureWriter signatureVisitor) {
return mapType(jetType, kind, signatureVisitor, false);
}
@NotNull private Type mapType(JetType jetType, OwnerKind kind, @Nullable SignatureVisitor signatureVisitor, boolean boxPrimitive) {
@NotNull public Type mapType(JetType jetType, OwnerKind kind, @Nullable BothSignatureWriter signatureVisitor, boolean boxPrimitive) {
Type known = knowTypes.get(jetType);
if (known != null) {
return mapKnownAsmType(jetType, known, signatureVisitor, boxPrimitive);
}
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
if (ErrorUtils.isError(descriptor)) {
throw new IllegalStateException("should not compile an error type");
}
if (standardLibrary.getArray().equals(descriptor)) {
if (jetType.getArguments().size() != 1) {
throw new UnsupportedOperationException("arrays must have one type argument");
@@ -248,8 +257,9 @@ public class JetTypeMapper {
JetType memberType = jetType.getArguments().get(0).getType();
if (signatureVisitor != null) {
SignatureVisitor arraySignatureVisitor = signatureVisitor.visitArrayType();
mapType(memberType, kind, arraySignatureVisitor, true);
signatureVisitor.writeArrayType();
mapType(memberType, kind, signatureVisitor, true);
signatureVisitor.writeArrayEnd();
}
if (!isGenericsArray(jetType)) {
@@ -272,13 +282,14 @@ public class JetTypeMapper {
Type asmType = Type.getObjectType(name + (kind == OwnerKind.TRAIT_IMPL ? "$$TImpl" : ""));
if (signatureVisitor != null) {
signatureVisitor.visitClassType(asmType.getInternalName());
signatureVisitor.writeClassBegin(asmType.getInternalName());
for (TypeProjection proj : jetType.getArguments()) {
// TODO: +-
SignatureVisitor argumentSignatureVisitor = signatureVisitor.visitTypeArgument('=');
mapType(proj.getType(), kind, argumentSignatureVisitor, true);
signatureVisitor.writeTypeArgument('=');
mapType(proj.getType(), kind, signatureVisitor, true);
signatureVisitor.writeTypeArgumentEnd();
}
signatureVisitor.visitEnd();
signatureVisitor.writeClassEnd();
}
return asmType;
@@ -287,7 +298,7 @@ public class JetTypeMapper {
if (descriptor instanceof TypeParameterDescriptor) {
if (signatureVisitor != null) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) jetType.getConstructor().getDeclarationDescriptor();
signatureVisitor.visitTypeVariable(typeParameterDescriptor.getName());
signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName());
}
return mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind);
@@ -296,7 +307,7 @@ public class JetTypeMapper {
throw new UnsupportedOperationException("Unknown type " + jetType);
}
private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable SignatureVisitor signatureVisitor, boolean genericTypeParameter) {
private Type mapKnownAsmType(JetType jetType, Type asmType, @Nullable BothSignatureWriter signatureVisitor, boolean genericTypeParameter) {
if (signatureVisitor != null) {
if (genericTypeParameter) {
visitAsmType(signatureVisitor, boxType(asmType));
@@ -307,23 +318,8 @@ public class JetTypeMapper {
return asmType;
}
public static void visitAsmType(SignatureVisitor visitor, Type asmType) {
switch (asmType.getSort()) {
case Type.OBJECT:
visitor.visitClassType(asmType.getInternalName());
visitor.visitEnd();
return;
case Type.ARRAY:
SignatureVisitor elementSignatureVisitor = visitor.visitArrayType();
visitAsmType(elementSignatureVisitor, asmType.getElementType());
return;
default:
String descriptor = asmType.getDescriptor();
if (descriptor.length() != 1) {
throw new IllegalStateException();
}
visitor.visitBaseType(descriptor.charAt(0));
}
public static void visitAsmType(BothSignatureWriter visitor, Type asmType) {
visitor.writeAsmType(asmType);
}
public static Type unboxType(final Type type) {
@@ -379,8 +375,6 @@ public class JetTypeMapper {
return asmType;
}
public static final boolean DEBUG_SIGNATURE_WRITER = true;
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, boolean superCall, OwnerKind kind) {
if(functionDescriptor == null)
return null;
@@ -444,22 +438,12 @@ public class JetTypeMapper {
needGenericSignature = false;
}
SignatureWriter signatureWriter = null;
SignatureVisitor signatureVisitor = null;
BothSignatureWriter signatureVisitor = null;
if (needGenericSignature) {
signatureWriter = new SignatureWriter();
signatureVisitor = DEBUG_SIGNATURE_WRITER ? new CheckSignatureAdapter(CheckSignatureAdapter.METHOD_SIGNATURE, signatureWriter) : signatureWriter;
signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD);
}
for (TypeParameterDescriptor typeParameterDescriptor : f.getTypeParameters()) {
if (signatureVisitor != null) {
signatureVisitor.visitFormalTypeParameter(typeParameterDescriptor.getName());
SignatureVisitor classBoundVisitor = signatureVisitor.visitClassBound();
// TODO: wrong base
visitAsmType(classBoundVisitor, TYPE_OBJECT);
// TODO: interfaces
}
}
writeFormalTypeParameters(f.getTypeParameters(), signatureVisitor);
final ReceiverDescriptor receiverTypeRef = f.getReceiverParameter();
final JetType receiverType = !receiverTypeRef.exists() ? null : receiverTypeRef.getType();
@@ -477,24 +461,98 @@ public class JetTypeMapper {
parameterTypes.add(type);
}
if (receiverType != null) {
parameterTypes.add(mapType(receiverType, signatureVisitor != null ? signatureVisitor.visitParameterType() : null));
if (signatureVisitor != null) {
signatureVisitor.writeParameterType();
}
parameterTypes.add(mapType(receiverType, signatureVisitor));
if (signatureVisitor != null) {
signatureVisitor.writeParameterTypeEnd();
}
}
for (TypeParameterDescriptor parameterDescriptor : f.getTypeParameters()) {
if(parameterDescriptor.isReified()) {
parameterTypes.add(TYPE_TYPEINFO);
if (signatureVisitor != null) {
visitAsmType(signatureVisitor.visitParameterType(), TYPE_TYPEINFO);
signatureVisitor.writeParameterType();
visitAsmType(signatureVisitor, TYPE_TYPEINFO);
signatureVisitor.writeParameterTypeEnd();
}
}
}
for (ValueParameterDescriptor parameter : parameters) {
Type type = mapType(parameter.getOutType(), signatureVisitor != null ? signatureVisitor.visitParameterType() : null);
if (signatureVisitor != null) {
signatureVisitor.writeParameterType();
}
Type type = mapType(parameter.getOutType(), signatureVisitor);
if (signatureVisitor != null) {
signatureVisitor.writeParameterTypeEnd();
}
valueParameterTypes.add(type);
parameterTypes.add(type);
}
Type returnType = f instanceof ConstructorDescriptor ? Type.VOID_TYPE : mapReturnType(f.getReturnType(), signatureVisitor != null ? signatureVisitor.visitReturnType() : null);
Type returnType;
if (f instanceof ConstructorDescriptor) {
returnType = Type.VOID_TYPE;
if (signatureVisitor != null) {
signatureVisitor.writeReturnType();
visitAsmType(signatureVisitor, Type.VOID_TYPE);
signatureVisitor.writeReturnTypeEnd();
}
} else {
if (signatureVisitor != null) {
signatureVisitor.writeReturnType();
returnType = mapReturnType(f.getReturnType(), signatureVisitor);
signatureVisitor.writeReturnTypeEnd();
}
else {
returnType = mapReturnType(f.getReturnType(), null);
}
}
Method method = new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
return new JvmMethodSignature(method, signatureWriter != null ? signatureWriter.toString() : null);
return new JvmMethodSignature(method, signatureVisitor != null ? signatureVisitor.makeJavaString() : null);
}
public void writeFormalTypeParameters(List<TypeParameterDescriptor> typeParameters, BothSignatureWriter signatureVisitor) {
if (signatureVisitor == null) {
return;
}
for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
writeFormalTypeParameter(typeParameterDescriptor, signatureVisitor);
}
}
private void writeFormalTypeParameter(TypeParameterDescriptor typeParameterDescriptor, BothSignatureWriter signatureVisitor) {
signatureVisitor.writeFormalTypeParameter(typeParameterDescriptor.getName());
classBound:
{
signatureVisitor.writeClassBound();
for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
if (!CodegenUtil.isInterface(jetType)) {
mapType(jetType, signatureVisitor);
break classBound;
}
}
}
// "extends Object" seems to be not optional according to ClassFileFormat-Java5.pdf
}
signatureVisitor.writeClassBoundEnd();
for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
if (CodegenUtil.isInterface(jetType)) {
signatureVisitor.writeInterfaceBound();
mapType(jetType, signatureVisitor);
signatureVisitor.writeInterfaceBoundEnd();
}
}
}
}
public JvmMethodSignature mapSignature(String name, FunctionDescriptor f) {
@@ -575,10 +633,8 @@ public class JetTypeMapper {
parameterTypes.add(mapType(CodegenUtil.getOuterClassDescriptor(classDescriptor).getDefaultType(), OwnerKind.IMPLEMENTATION));
}
List<TypeParameterDescriptor> typeParameters = classDescriptor.getTypeConstructor().getParameters();
for (TypeParameterDescriptor typeParameter : typeParameters) {
if(typeParameter.isReified())
parameterTypes.add(TYPE_TYPEINFO);
if (CodegenUtil.requireTypeInfoConstructorArg(classDescriptor.getDefaultType())) {
parameterTypes.add(TYPE_TYPEINFO);
}
for (ValueParameterDescriptor parameter : parameters) {
@@ -0,0 +1,36 @@
package org.jetbrains.jet.codegen;
import java.util.List;
/**
* @author Stepan Koltsov
*/
public class JvmClassSignature {
private final String name;
private final String superclassName;
private final List<String> interfaces;
private final String genericSignature;
public JvmClassSignature(String name, String superclassName, List<String> interfaces, String genericSignature) {
this.name = name;
this.superclassName = superclassName;
this.interfaces = interfaces;
this.genericSignature = genericSignature;
}
public String getName() {
return name;
}
public String getSuperclassName() {
return superclassName;
}
public List<String> getInterfaces() {
return interfaces;
}
public String getGenericSignature() {
return genericSignature;
}
}
@@ -2,10 +2,12 @@ package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiFile;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.TypeUtils;
@@ -42,7 +44,8 @@ public class NamespaceCodegen {
}
public void generate(JetNamespace namespace) {
final CodegenContext context = CodegenContext.STATIC.intoNamespace(state.getBindingContext().get(BindingContext.NAMESPACE, namespace));
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.NAMESPACE, namespace);
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
@@ -145,7 +148,7 @@ public class NamespaceCodegen {
}
DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor();
if(!jetType.equals(root) && jetType.getArguments().size() == 0 && !(declarationDescriptor instanceof JavaClassDescriptor)) {
if(!jetType.equals(root) && jetType.getArguments().size() == 0 && !(declarationDescriptor instanceof JavaClassDescriptor) && !JetStandardClasses.getAny().equals(declarationDescriptor)) {
// TODO: we need some better checks here
v.getstatic(typeMapper.mapType(jetType, OwnerKind.IMPLEMENTATION).getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
return;
@@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
@@ -629,7 +630,7 @@ public abstract class StackValue {
for (TypeParameterDescriptor typeParameterDescriptor : setterDescriptor.getOriginal().getTypeParameters()) {
if(typeParameterDescriptor.isReified()) {
codegen.generateTypeInfo(resolvedSetCall.getTypeArguments().get(typeParameterDescriptor));
codegen.generateTypeInfo(resolvedSetCall.getTypeArguments().get(typeParameterDescriptor), null);
}
}
@@ -1010,7 +1011,8 @@ public abstract class StackValue {
return codegen.typeMapper.mapType(callableMethod.getReceiverClass());
}
else {
return codegen.typeMapper.mapType(callableMethod.getThisType());
JetType thisType = callableMethod.getThisType();
return codegen.typeMapper.mapType(thisType);
}
}
else {
@@ -5,14 +5,12 @@ import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.StackValue;
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.JetCallExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
@@ -30,7 +28,7 @@ public class ArrayIterator implements IntrinsicMethod {
ClassDescriptor containingDeclaration = (ClassDescriptor) funDescriptor.getContainingDeclaration().getOriginal();
JetStandardLibrary standardLibrary = codegen.getState().getStandardLibrary();
if(containingDeclaration.equals(standardLibrary.getArray())) {
codegen.generateTypeInfo(funDescriptor.getReturnType().getArguments().get(0).getType());
codegen.generateTypeInfo(funDescriptor.getReturnType().getArguments().get(0).getType(), null);
v.invokestatic("jet/runtime/ArrayIterator", "iterator", "([Ljava/lang/Object;Ljet/typeinfo/TypeInfo;)Ljet/Iterator;");
return StackValue.onStack(JetTypeMapper.TYPE_ITERATOR);
}
@@ -17,7 +17,7 @@ public class ValueTypeInfo implements IntrinsicMethod {
@Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
codegen.gen(arguments.get(0), JetTypeMapper.TYPE_JET_OBJECT);
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
v.invokeinterface(JetTypeMapper.TYPE_JET_OBJECT.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
return StackValue.onStack(JetTypeMapper.TYPE_TYPEINFO);
}
}
@@ -0,0 +1,161 @@
package org.jetbrains.jet.codegen.signature;
import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureVisitor;
/**
* @author Stepan Koltsov
*
* @see SignatureReader
*/
public class JetSignatureReader {
private final String signature;
public JetSignatureReader(String signature) {
this.signature = signature;
}
public void accept(final JetSignatureVisitor v) {
String signature = this.signature;
int len = signature.length();
int pos;
char c;
if (signature.charAt(0) == '<') {
pos = 2;
do {
int end = signature.indexOf(':', pos);
v.visitFormalTypeParameter(signature.substring(pos - 1, end));
pos = end + 1;
c = signature.charAt(pos);
if (c == 'L' || c == '[' || c == 'T') {
pos = parseType(signature, pos, v.visitClassBound());
}
while ((c = signature.charAt(pos++)) == ':') {
pos = parseType(signature, pos, v.visitInterfaceBound());
}
} while (c != '>');
} else {
pos = 0;
}
if (signature.charAt(pos) == '(') {
pos++;
while (signature.charAt(pos) != ')') {
pos = parseType(signature, pos, v.visitParameterType());
}
pos = parseType(signature, pos + 1, v.visitReturnType());
while (pos < len) {
pos = parseType(signature, pos + 1, v.visitExceptionType());
}
} else {
pos = parseType(signature, pos, v.visitSuperclass());
while (pos < len) {
pos = parseType(signature, pos, v.visitInterface());
}
}
}
private static int parseType(
final String signature,
int pos,
final JetSignatureVisitor v)
{
char c;
int start, end;
boolean visited, inner;
String name;
boolean nullable = false;
if (signature.charAt(pos) == '?') {
nullable = true;
pos++;
}
switch (c = signature.charAt(pos++)) {
case 'Z':
case 'C':
case 'B':
case 'S':
case 'I':
case 'F':
case 'J':
case 'D':
case 'V':
v.visitBaseType(c, nullable);
return pos;
case '[':
return parseType(signature, pos, v.visitArrayType(nullable));
case 'T':
end = signature.indexOf(';', pos);
v.visitTypeVariable(signature.substring(pos, end), nullable);
return end + 1;
default: // case 'L':
start = pos;
visited = false;
inner = false;
for (;;) {
switch (c = signature.charAt(pos++)) {
case '.':
case ';':
if (!visited) {
name = signature.substring(start, pos - 1);
if (inner) {
v.visitInnerClassType(name, nullable);
} else {
v.visitClassType(name, nullable);
}
}
if (c == ';') {
v.visitEnd();
return pos;
}
start = pos;
visited = false;
inner = true;
break;
case '<':
name = signature.substring(start, pos - 1);
if (inner) {
v.visitInnerClassType(name, nullable);
} else {
v.visitClassType(name, nullable);
}
visited = true;
top: for (;;) {
switch (c = signature.charAt(pos)) {
case '>':
break top;
case '*':
++pos;
v.visitTypeArgument();
break;
case '+':
case '-':
pos = parseType(signature,
pos + 1,
v.visitTypeArgument(c));
break;
default:
pos = parseType(signature,
pos,
v.visitTypeArgument('='));
break;
}
}
}
}
}
}
}
@@ -0,0 +1,141 @@
package org.jetbrains.jet.codegen.signature;
import org.objectweb.asm.signature.SignatureVisitor;
/**
* @author Stepan Koltsov
*
* @see SignatureVisitor
* @url http://confluence.jetbrains.net/display/JET/Jet+Signatures
*/
public interface JetSignatureVisitor {
/**
* Wildcard for an "extends" type argument.
*/
char EXTENDS = '+';
/**
* Wildcard for a "super" type argument.
*/
char SUPER = '-';
/**
* Wildcard for a normal type argument.
*/
char INSTANCEOF = '=';
/**
* Visits a formal type parameter.
*
* @param name the name of the formal parameter.
*/
void visitFormalTypeParameter(String name);
/**
* Visits the class bound of the last visited formal type parameter.
*
* @return a non null visitor to visit the signature of the class bound.
*/
JetSignatureVisitor visitClassBound();
/**
* Visits an interface bound of the last visited formal type parameter.
*
* @return a non null visitor to visit the signature of the interface bound.
*/
JetSignatureVisitor visitInterfaceBound();
/**
* Visits the type of the super class.
*
* @return a non null visitor to visit the signature of the super class
* type.
*/
JetSignatureVisitor visitSuperclass();
/**
* Visits the type of an interface implemented by the class.
*
* @return a non null visitor to visit the signature of the interface type.
*/
JetSignatureVisitor visitInterface();
/**
* Visits the type of a method parameter.
*
* @return a non null visitor to visit the signature of the parameter type.
*/
JetSignatureVisitor visitParameterType();
/**
* Visits the return type of the method.
*
* @return a non null visitor to visit the signature of the return type.
*/
JetSignatureVisitor visitReturnType();
/**
* Visits the type of a method exception.
*
* @return a non null visitor to visit the signature of the exception type.
*/
JetSignatureVisitor visitExceptionType();
/**
* Visits a signature corresponding to a primitive type.
*
* @param descriptor the descriptor of the primitive type, or 'V' for
* <tt>void</tt>.
*/
void visitBaseType(char descriptor, boolean nullable);
/**
* Visits a signature corresponding to a type variable.
*
* @param name the name of the type variable.
*/
void visitTypeVariable(String name, boolean nullable);
/**
* Visits a signature corresponding to an array type.
*
* @return a non null visitor to visit the signature of the array element
* type.
*/
JetSignatureVisitor visitArrayType(boolean nullable);
/**
* Starts the visit of a signature corresponding to a class or interface
* type.
*
* @param name the internal name of the class or interface.
*/
void visitClassType(String name, boolean nullable);
/**
* Visits an inner class.
*
* @param name the local name of the inner class in its enclosing class.
*/
void visitInnerClassType(String name, boolean nullable);
/**
* Visits an unbounded type argument of the last visited class or inner
* class type.
*/
void visitTypeArgument();
/**
* Visits a type argument of the last visited class or inner class type.
*
* @param wildcard '+', '-' or '='.
* @return a non null visitor to visit the signature of the type argument.
*/
JetSignatureVisitor visitTypeArgument(char wildcard);
/**
* Ends the visit of a signature corresponding to a class or interface type.
*/
void visitEnd();
}
@@ -0,0 +1,201 @@
package org.jetbrains.jet.codegen.signature;
import org.objectweb.asm.signature.SignatureWriter;
/**
* @author Stepan Koltsov
*
* @see SignatureWriter
*/
public class JetSignatureWriter implements JetSignatureVisitor {
/**
* Buffer used to construct the signature.
*/
private final StringBuffer buf = new StringBuffer();
/**
* Indicates if the signature contains formal type parameters.
*/
private boolean hasFormals;
/**
* Indicates if the signature contains method parameter types.
*/
private boolean hasParameters;
/**
* Stack used to keep track of class types that have arguments. Each element
* of this stack is a boolean encoded in one bit. The top of the stack is
* the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
* /2.
*/
private int argumentStack;
/**
* Constructs a new {@link SignatureWriter} object.
*/
public JetSignatureWriter() {
}
// ------------------------------------------------------------------------
// Implementation of the SignatureVisitor interface
// ------------------------------------------------------------------------
@Override
public void visitFormalTypeParameter(final String name) {
if (!hasFormals) {
hasFormals = true;
buf.append('<');
}
buf.append(name);
buf.append(':');
}
@Override
public JetSignatureWriter visitClassBound() {
return this;
}
@Override
public JetSignatureWriter visitInterfaceBound() {
buf.append(':');
return this;
}
@Override
public JetSignatureWriter visitSuperclass() {
endFormals();
return this;
}
@Override
public JetSignatureWriter visitInterface() {
return this;
}
@Override
public JetSignatureWriter visitParameterType() {
endFormals();
if (!hasParameters) {
hasParameters = true;
buf.append('(');
}
return this;
}
@Override
public JetSignatureWriter visitReturnType() {
endFormals();
if (!hasParameters) {
buf.append('(');
}
buf.append(')');
return this;
}
@Override
public JetSignatureWriter visitExceptionType() {
buf.append('^');
return this;
}
private void visitNullabe(boolean nullable) {
if (nullable) {
buf.append('?');
}
}
@Override
public void visitBaseType(final char descriptor, boolean nullable) {
visitNullabe(nullable);
buf.append(descriptor);
}
@Override
public void visitTypeVariable(final String name, boolean nullable) {
visitNullabe(nullable);
buf.append('T');
buf.append(name);
buf.append(';');
}
@Override
public JetSignatureWriter visitArrayType(boolean nullable) {
visitNullabe(nullable);
buf.append('[');
return this;
}
@Override
public void visitClassType(final String name, boolean nullable) {
visitNullabe(nullable);
buf.append('L');
buf.append(name);
argumentStack *= 2;
}
@Override
public void visitInnerClassType(final String name, boolean nullable) {
endArguments();
visitNullabe(nullable);
buf.append('.');
buf.append(name);
argumentStack *= 2;
}
@Override
public void visitTypeArgument() {
if (argumentStack % 2 == 0) {
++argumentStack;
buf.append('<');
}
buf.append('*');
}
@Override
public JetSignatureWriter visitTypeArgument(final char wildcard) {
if (argumentStack % 2 == 0) {
++argumentStack;
buf.append('<');
}
if (wildcard != '=') {
buf.append(wildcard);
}
return this;
}
@Override
public void visitEnd() {
endArguments();
buf.append(';');
}
public String toString() {
return buf.toString();
}
// ------------------------------------------------------------------------
// Utility methods
// ------------------------------------------------------------------------
/**
* Ends the formal type parameters section of the signature.
*/
private void endFormals() {
if (hasFormals) {
hasFormals = false;
buf.append('>');
}
}
/**
* Ends the type arguments of a class or inner class type.
*/
private void endArguments() {
if (argumentStack % 2 != 0) {
buf.append('>');
}
argumentStack /= 2;
}
}
@@ -14,7 +14,6 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.StdlibNames;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.plugin.JetFileType;
@@ -370,13 +369,13 @@ public class JavaDescriptorResolver {
PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
attributes.toString();
if (annotation.getQualifiedName().equals(StdlibNames.JET_PARAMETER_CLASS)) {
PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_PARAMETER_NAME_FIELD);
if (annotation.getQualifiedName().equals(StdlibNames.JET_VALUE_PARAMETER_CLASS)) {
PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_VALUE_PARAMETER_NAME_FIELD);
if (nameExpression != null) {
name = (String) nameExpression.getValue();
}
PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_PARAMETER_NULLABLE_FIELD);
PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD);
if (nullableExpression != null) {
nullable = (Boolean) nullableExpression.getValue();
} else {
@@ -58,7 +58,6 @@ public class JavaPackageScope extends JetScopeImpl {
return Collections.emptySet();
}
System.out.println(psiClass.getQualifiedName());
return semanticServices.getDescriptorResolver().resolveFunctionGroup(containingDescriptor, psiClass, null, name, true);
// return Collections.emptySet();
}
@@ -78,6 +77,7 @@ public class JavaPackageScope extends JetScopeImpl {
final PsiPackage javaPackage = semanticServices.getDescriptorResolver().findPackage(packageFQN);
if (javaPackage != null) {
boolean isKotlinNamespace = semanticServices.getKotlinNamespaceDescriptor(javaPackage.getQualifiedName()) != null;
final JavaDescriptorResolver descriptorResolver = semanticServices.getDescriptorResolver();
for (PsiPackage psiSubPackage : javaPackage.getSubPackages()) {
@@ -85,6 +85,8 @@ public class JavaPackageScope extends JetScopeImpl {
}
for (PsiClass psiClass : javaPackage.getClasses()) {
if (isKotlinNamespace && "namespace".equals(psiClass.getName())) continue;
// If this is a Kotlin class, we have already taken it through a containing namespace descriptor
ClassDescriptor kotlinClassDescriptor = semanticServices.getKotlinClassDescriptor(psiClass.getQualifiedName());
if (kotlinClassDescriptor != null) {
@@ -0,0 +1,36 @@
package org.jetbrains.jet.lang.resolve.java;
import org.objectweb.asm.Type;
/**
* @author Stepan Koltsov
*/
public class StdlibNames {
public static final String JET_VALUE_PARAMETER_CLASS = "jet.typeinfo.JetValueParameter";
public static final String JET_VALUE_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetValueParameter;";
public static final String JET_VALUE_PARAMETER_NAME_FIELD = "name";
public static final String JET_VALUE_PARAMETER_HAS_DEFAULT_VALUE_FIELD = "hasDefaultValue";
public static final String JET_VALUE_PARAMETER_NULLABLE_FIELD = "nullable";
public static final String JET_TYPE_PARAMETER_CLASS = "jet.typeinfo.JetTypeParameter";
public static final String JET_TYPE_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetTypeParameter;";
public static final String JET_TYPE_PARAMETER_NAME_FIELD = "name";
public static final String JET_METHOD_CLASS = "jet.typeinfo.JetMethod";
public static final String JET_METHOD_DESCRIPTOR = "Ljet/typeinfo/JetMethod;";
public static final String JET_METHOD_NULLABLE_RETURN_TYPE_FIELD = "nullableReturnType";
public static final String JET_OBJECT_INTERNAL = "jet/JetObject";
public static final String JET_OBJECT_CLASS = "jet.JetObject";
public static final String JET_OBJECT_DESCRIPTOR = "Ljet/JetObject;";
private StdlibNames() {
}
}
@@ -131,11 +131,15 @@ public class JetPsiUtil {
public static String getFQName(JetClass jetClass) {
JetNamedDeclaration parent = PsiTreeUtil.getParentOfType(jetClass, JetNamespace.class, JetClass.class);
if (parent instanceof JetNamespace) {
return getFQName(((JetNamespace) parent)) + "." + jetClass.getName();
return makeFQName(getFQName(((JetNamespace) parent)), jetClass);
}
if (parent instanceof JetClass) {
return getFQName(((JetClass) parent)) + "." + jetClass.getName();
return makeFQName(getFQName(((JetClass) parent)), jetClass);
}
return jetClass.getName();
}
private static String makeFQName(String prefix, JetClass jetClass) {
return (prefix.length() == 0 ? "" : prefix + ".") + jetClass.getName();
}
}
@@ -1,32 +0,0 @@
package org.jetbrains.jet.lang.resolve;
import org.objectweb.asm.Type;
/**
* @author Stepan Koltsov
*/
public class StdlibNames {
public static final Type JET_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetParameter");
public static final String JET_PARAMETER_CLASS = "jet.typeinfo.JetParameter";
public static final String JET_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetParameter;";
public static final String JET_PARAMETER_NAME_FIELD = "name";
public static final String JET_PARAMETER_HAS_DEFAULT_VALUE_FIELD = "hasDefaultValue";
public static final String JET_PARAMETER_NULLABLE_FIELD = "nullable";
public static final Type JET_TYPE_PARAMETER_TYPE = Type.getObjectType("jet/typeinfo/JetTypeParameter");
public static final String JET_TYPE_PARAMETER_CLASS = "jet.typeinfo.JetTypeParameter";
public static final String JET_TYPE_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetTypeParameter;";
public static final String JET_TYPE_PARAMETER_NAME_FIELD = "name";
public static final Type JET_METHOD_TYPE = Type.getObjectType("jet/typeinfo/JetMethod");
public static final String JET_METHOD_CLASS = "jet.typeinfo.JetMethod";
public static final String JET_METHOD_DESCRIPTOR = "Ljet/typeinfo/JetMethod;";
public static final String JET_METHOD_NULLABLE_RETURN_TYPE_FIELD = "nullableReturnType";
}
@@ -29,6 +29,9 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.calls.ResolutionStatus.*;
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl.MAP_TO_CANDIDATE;
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl.MAP_TO_RESULT;
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.EXPECTED_TYPE;
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.RECEIVER;
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.VALUE_ARGUMENT;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
@@ -470,7 +473,7 @@ public class CallResolver {
ExpressionTypingServices temporaryServices = new ExpressionTypingServices(semanticServices, traceForUnknown);
JetType type = temporaryServices.getType(scope, expression, substituteDontCare.substitute(valueParameterDescriptor.getOutType(), Variance.INVARIANT));
if (type != null) {
constraintSystem.addSubtypingConstraint(type, effectiveExpectedType);
constraintSystem.addSubtypingConstraint(VALUE_ARGUMENT.assertSubtyping(type, effectiveExpectedType));
}
else {
candidateCall.argumentHasNoType();
@@ -483,12 +486,12 @@ public class CallResolver {
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
ReceiverDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter();
if (receiverArgument.exists() && receiverParameter.exists()) {
constraintSystem.addSubtypingConstraint(receiverArgument.getType(), receiverParameter.getType());
constraintSystem.addSubtypingConstraint(RECEIVER.assertSubtyping(receiverArgument.getType(), receiverParameter.getType()));
}
// Return type
if (expectedType != NO_EXPECTED_TYPE) {
constraintSystem.addSubtypingConstraint(candidateWithFreshVariables.getReturnType(), expectedType);
constraintSystem.addSubtypingConstraint(EXPECTED_TYPE.assertSubtyping(candidateWithFreshVariables.getReturnType(), expectedType));
}
// Solution
@@ -5,7 +5,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
import org.jetbrains.jet.lang.resolve.calls.inference.BoundsOwner;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.util.slicedmap.*;
@@ -22,8 +22,8 @@ public class ResolutionDebugInfo {
public static final WritableSlice<One, ResolvedCall<? extends CallableDescriptor>> RESULT = Slices.createSimpleSlice();
public static final WritableSlice<One, StringBuilder> ERRORS = Slices.createSimpleSlice();
public static final WritableSlice<One, StringBuilder> LOG = Slices.createSimpleSlice();
public static final WritableSlice<One, Map<TypeParameterDescriptor, ConstraintSystemImpl.TypeValue>> BOUNDS_FOR_UNKNOWNS = Slices.createSimpleSlice();
public static final WritableSlice<One, Map<JetType, ConstraintSystemImpl.TypeValue>> BOUNDS_FOR_KNOWNS = Slices.createSimpleSlice();
public static final WritableSlice<One, Map<TypeParameterDescriptor, BoundsOwner>> BOUNDS_FOR_UNKNOWNS = Slices.createSimpleSlice();
public static final WritableSlice<One, Map<JetType, BoundsOwner>> BOUNDS_FOR_KNOWNS = Slices.createSimpleSlice();
public static final WritableSlice<One, ConstraintSystemSolution> SOLUTION = Slices.createSimpleSlice();
public static final WritableSlice<One, Collection<TypeParameterDescriptor>> UNKNOWNS = Slices.createSimpleSlice();
@@ -13,11 +13,11 @@ import java.util.Map;
* @author abreslav
*/
public interface ResolvedCall<D extends CallableDescriptor> {
/** A target callable descriptor as it was accessible in the corresponding scope, i.e. with type parameters not substituted */
/** A target callable descriptor as it was accessible in the corresponding scope, i.e. with type arguments not substituted */
@NotNull
D getCandidateDescriptor();
/** Type parameters are substituted */
/** Type arguments are substituted. This descriptor is guaranteed to have NO declared type parameters */
@NotNull
D getResultingDescriptor();
@@ -0,0 +1,16 @@
package org.jetbrains.jet.lang.resolve.calls.inference;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
/**
* @author abreslav
*/
public interface BoundsOwner {
@NotNull
Set<TypeValue> getUpperBounds();
@NotNull
Set<TypeValue> getLowerBounds();
}
@@ -12,11 +12,11 @@ public interface ConstraintResolutionListener {
public static final ConstraintResolutionListener DO_NOTHING = new ConstraintResolutionListener() {
@Override
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue) {
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, BoundsOwner typeValue) {
}
@Override
public void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue) {
public void constraintsForKnownType(JetType type, BoundsOwner typeValue) {
}
@Override
@@ -24,18 +24,18 @@ public interface ConstraintResolutionListener {
}
@Override
public void log(Object message) {
public void log(Object... messageFragments) {
}
@Override
public void error(Object message) {
public void error(Object... messageFragments) {
}
};
void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue);
void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue);
void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, BoundsOwner typeValue);
void constraintsForKnownType(JetType type, BoundsOwner typeValue);
void done(ConstraintSystemSolution solution, Set<TypeParameterDescriptor> typeParameterDescriptors);
void log(Object message);
void error(Object message);
void log(Object... messageFragments);
void error(Object... messageFragments);
}
@@ -2,7 +2,6 @@ package org.jetbrains.jet.lang.resolve.calls.inference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.Variance;
/**
@@ -11,7 +10,7 @@ import org.jetbrains.jet.lang.types.Variance;
public interface ConstraintSystem {
void registerTypeVariable(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull Variance positionVariance);
void addSubtypingConstraint(@NotNull JetType lower, @NotNull JetType upper);
void addSubtypingConstraint(@NotNull SubtypingConstraint constraint);
@NotNull
ConstraintSystemSolution solve();
@@ -143,7 +143,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
}
listener.log("minimal solution from lowerbounds for " + this + " is " + commonSupertype);
listener.log("minimal solution from lowerbounds for ", this, " is ", commonSupertype);
value = new KnownType(commonSupertype);
}
else {
@@ -247,10 +247,10 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
@Override
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
boolean result = delegate.assertEqualTypes(a, b, typeCheckingProcedure);
if (!result) {
listener.error("-- Failed to equate " + a + " and " + b);
listener.error("-- Failed to equate ", a, " and ", b);
}
return result;
}
@@ -259,16 +259,16 @@ public class ConstraintSystemImpl implements ConstraintSystem {
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
boolean result = delegate.assertEqualTypeConstructors(a, b);
if (!result) {
listener.error("-- Type constructors are not equal: " + a + " and " + b);
listener.error("-- Type constructors are not equal: ", a, " and ", b);
}
return result;
}
@Override
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
boolean result = delegate.assertSubtype(subtype, supertype, typeCheckingProcedure);
if (!result) {
listener.error("-- " + subtype + " can't be a subtype of " + supertype);
listener.error("-- ", subtype, " can't be a subtype of ", supertype);
}
return result;
}
@@ -277,7 +277,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
boolean result = delegate.noCorrespondingSupertype(subtype, supertype);
if (!result) {
listener.error("-- " + subtype + " has no supertype corresponding to " + supertype);
listener.error("-- ", subtype, " has no supertype corresponding to ", supertype);
}
return result;
}
@@ -294,7 +294,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
private TypeCheckingProcedure createConstraintExpander() {
return new TypeCheckingProcedure(new TypeConstraintBuilderAdapter(new TypingConstraints() {
@Override
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
TypeValue aValue = getTypeValueFor(a);
TypeValue bValue = getTypeValueFor(b);
@@ -309,7 +309,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
@Override
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
TypeValue subtypeValue = getTypeValueFor(subtype);
TypeValue supertypeValue = getTypeValueFor(supertype);
@@ -382,14 +382,14 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
@Override
public void addSubtypingConstraint(@NotNull JetType lower, @NotNull JetType upper) {
TypeValue typeValueForLower = getTypeValueFor(lower);
TypeValue typeValueForUpper = getTypeValueFor(upper);
public void addSubtypingConstraint(@NotNull SubtypingConstraint constraint) {
TypeValue typeValueForLower = getTypeValueFor(constraint.getSubtype());
TypeValue typeValueForUpper = getTypeValueFor(constraint.getSupertype());
addSubtypingConstraintOnTypeValues(typeValueForLower, typeValueForUpper);
}
private void addSubtypingConstraintOnTypeValues(TypeValue typeValueForLower, TypeValue typeValueForUpper) {
listener.log("Constraint added: " + typeValueForLower + " :< " + typeValueForUpper);
listener.log("Constraint added: ", typeValueForLower, " :< ", typeValueForUpper);
if (typeValueForLower != typeValueForUpper) {
typeValueForLower.addUpperBound(typeValueForUpper);
typeValueForUpper.addLowerBound(typeValueForLower);
@@ -409,14 +409,22 @@ public class ConstraintSystemImpl implements ConstraintSystem {
KnownType knownBoundType = (KnownType) upperBound;
boolean ok = constraintExpander.isSubtypeOf(jetType, knownBoundType.getType());
if (!ok) {
listener.error("Error while expanding '" + jetType + " :< " + knownBoundType.getType() + "'");
listener.error("Error while expanding '", jetType, " :< ", knownBoundType.getType(), "'");
return new Solution().registerError("Mismatch while expanding constraints");
}
}
}
// Lower bounds?
for (TypeValue lowerBound : typeValue.getLowerBounds()) {
if (lowerBound instanceof KnownType) {
KnownType knownBoundType = (KnownType) lowerBound;
boolean ok = constraintExpander.isSubtypeOf(knownBoundType.getType(), jetType);
if (!ok) {
listener.error("Error while expanding '" + knownBoundType.getType() + " :< " + jetType + "'");
return new Solution().registerError("Mismatch while expanding constraints");
}
}
}
}
// Fill in upper bounds from type parameter bounds
@@ -435,11 +443,11 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
for (UnknownType unknownType : unknownTypes.values()) {
listener.constraintsForUnknown(unknownType.getTypeParameterDescriptor(), unknownType);
// listener.constraintsForUnknown(unknownType.getTypeParameterDescriptor(), unknownType);
}
for (KnownType knownType : knownTypes.values()) {
listener.constraintsForKnownType(knownType.getType(), knownType);
// listener.constraintsForKnownType(knownType.getType(), knownType);
}
// Find inconsistencies
@@ -469,14 +477,14 @@ public class ConstraintSystemImpl implements ConstraintSystem {
JetType boundingType = solution.getSubstitutor().substitute(upperBound.getValue().getType(), Variance.INVARIANT);
if (!typeChecker.isSubtypeOf(type, boundingType)) { // TODO
solution.registerError("Constraint violation: " + type + " is not a subtype of " + boundingType);
listener.error("Constraint violation: " + type + " :< " + boundingType);
listener.error("Constraint violation: ", type, " :< ", boundingType);
}
}
for (TypeValue lowerBound : typeValue.getLowerBounds()) {
JetType boundingType = solution.getSubstitutor().substitute(lowerBound.getValue().getType(), Variance.INVARIANT);
if (!typeChecker.isSubtypeOf(boundingType, type)) {
solution.registerError("Constraint violation: " + boundingType + " is not a subtype of " + type);
listener.error("Constraint violation: " + boundingType + " :< " + type);
listener.error("Constraint violation: ", boundingType, " :< ", type);
}
}
}
@@ -534,7 +542,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
TypeProjection typeProjection = new TypeProjection(getValue(descriptor));
listener.log(descriptor + " |-> " + typeProjection);
listener.log(descriptor, " |-> ", typeProjection);
return typeProjection;
}
@@ -0,0 +1,470 @@
package org.jetbrains.jet.lang.resolve.calls.inference;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure;
import org.jetbrains.jet.lang.types.checker.TypingConstraints;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.PARAMETER_BOUND;
/**
* @author abreslav
*/
public class ConstraintSystemWithPriorities implements ConstraintSystem {
public static final Comparator<SubtypingConstraint> SUBTYPING_CONSTRAINT_ORDER = new Comparator<SubtypingConstraint>() {
@Override
public int compare(SubtypingConstraint o1, SubtypingConstraint o2) {
return o1.getType().compareTo(o2.getType());
}
};
private static class LoopInTypeVariableConstraintsException extends RuntimeException {
public LoopInTypeVariableConstraintsException() {}
}
//==========================================================================================================================================================
private final Map<JetType, TypeValue> knownTypes = Maps.newLinkedHashMap(); // linked - for easier debugging
private final Map<TypeParameterDescriptor, TypeValue> unknownTypes = Maps.newLinkedHashMap(); // linked - for easier debugging
private final Set<TypeValue> unsolvedUnknowns = Sets.newLinkedHashSet(); // linked - for easier debugging
private final PriorityQueue<SubtypingConstraint> constraintQueue = new PriorityQueue<SubtypingConstraint>(10, SUBTYPING_CONSTRAINT_ORDER);
private final JetTypeChecker typeChecker = JetTypeChecker.INSTANCE;
private final TypeCheckingProcedure constraintExpander;
private final ConstraintResolutionListener listener;
public ConstraintSystemWithPriorities(ConstraintResolutionListener listener) {
this.listener = listener;
this.constraintExpander = createConstraintExpander();
}
@NotNull
private TypeValue getTypeValueFor(@NotNull JetType type) {
DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor instanceof TypeParameterDescriptor) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor;
// Checking that this is not a T?, but exactly T
if (typeParameterDescriptor.getDefaultType().isNullable() == type.isNullable()) {
TypeValue unknownType = unknownTypes.get(typeParameterDescriptor);
if (unknownType != null) {
return unknownType;
}
}
}
TypeValue typeValue = knownTypes.get(type);
if (typeValue == null) {
typeValue = new TypeValue(type);
knownTypes.put(type, typeValue);
}
return typeValue;
}
@Override
public void registerTypeVariable(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull Variance positionVariance) {
assert !unknownTypes.containsKey(typeParameterDescriptor);
TypeValue typeValue = new TypeValue(typeParameterDescriptor, positionVariance);
unknownTypes.put(typeParameterDescriptor, typeValue);
unsolvedUnknowns.add(typeValue);
}
@NotNull
private TypeValue getTypeVariable(TypeParameterDescriptor typeParameterDescriptor) {
TypeValue unknownType = unknownTypes.get(typeParameterDescriptor);
if (unknownType == null) {
throw new IllegalArgumentException("This type parameter is not an unknown in this constraint system: " + typeParameterDescriptor);
}
return unknownType;
}
@Override
public void addSubtypingConstraint(@NotNull SubtypingConstraint constraint) {
constraintQueue.add(constraint);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Constraint expansion
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private TypeCheckingProcedure createConstraintExpander() {
return new TypeCheckingProcedure(new TypeConstraintBuilderAdapter(new TypingConstraints() {
@Override
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
TypeValue aValue = getTypeValueFor(a);
TypeValue bValue = getTypeValueFor(b);
return expandEqualityConstraint(aValue, bValue);
}
@Override
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
return a.equals(b)
|| unknownTypes.containsKey(a.getDeclarationDescriptor())
|| unknownTypes.containsKey(b.getDeclarationDescriptor());
}
@Override
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
TypeValue subtypeValue = getTypeValueFor(subtype);
TypeValue supertypeValue = getTypeValueFor(supertype);
if (someUnknown(subtypeValue, supertypeValue)) {
expandSubtypingConstraint(subtypeValue, supertypeValue);
}
return true; // For known types further expansion happens automatically
}
@Override
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
// If some of the types is an unknown, the constraint must be generated, and we should carry on
// otherwise there can be no solution, and we should fail
TypeValue subTypeValue = getTypeValueFor(subtype);
TypeValue superTypeValue = getTypeValueFor(supertype);
boolean someUnknown = someUnknown(subTypeValue, superTypeValue);
if (someUnknown) {
expandSubtypingConstraint(subTypeValue, superTypeValue);
}
return someUnknown;
}
private boolean someUnknown(TypeValue subtypeValue, TypeValue supertypeValue) {
return !subtypeValue.isKnown() || !supertypeValue.isKnown();
}
}, listener));
}
private boolean assignValueTo(TypeValue unknown, JetType value) {
if (unknown.hasValue()) {
// If we have already assigned a value to this unknown,
// it is a conflict to assign another one, unless this new one is equal to the previous
return TypeUtils.equalTypes(unknown.getType(), value);
}
unsolvedUnknowns.remove(unknown);
unknown.setValue(value);
return true;
}
private boolean mergeUnknowns(@NotNull TypeValue a, @NotNull TypeValue b) {
assert !a.isKnown() && !b.isKnown();
listener.error("!!!mergeUnknowns() is not implemented!!!");
return false;
}
public boolean expandEqualityConstraint(TypeValue a, TypeValue b) {
if (a.isKnown() && b.isKnown()) {
return constraintExpander.equalTypes(a.getType(), b.getType());
}
// At least one of them is unknown
if (a.isKnown()) {
TypeValue tmp = a;
a = b;
b = tmp;
}
// Now a is definitely unknown
if (b.isKnown()) {
return assignValueTo(a, b.getType());
}
// They are both unknown
return mergeUnknowns(a, b);
}
private boolean expandSubtypingConstraint(TypeValue lower, TypeValue upper) {
listener.log("Constraint added: ", lower, " :< ", upper);
if (lower == upper) return true;
// Remember for a later check
lower.addUpperBound(upper);
upper.addLowerBound(lower);
if (lower.isKnown() && upper.isKnown()) {
// Two known types: expand constraints
return constraintExpander.isSubtypeOf(lower.getType(), upper.getType());
}
else if (!lower.isKnown() && !upper.isKnown()) {
// Two unknown types: merge them into one variable
return mergeUnknowns(lower, upper);
}
else {
// One unknown and one known
if (upper.isKnown()) {
if (TypeUtils.canHaveSubtypes(typeChecker, upper.getType())) {
// Upper bound is final -> we have to equate the lower bounds to it
return expandEqualityConstraint(lower, upper);
}
if (lower.getLowerBounds().contains(upper)) {
// upper :< lower :< upper
return expandEqualityConstraint(lower, upper);
}
}
else {
if (upper.getUpperBounds().contains(lower)) {
// lower :< upper :< lower
return expandEqualityConstraint(lower, upper);
}
}
}
return true;
}
@Override
@NotNull
public ConstraintSystemSolution solve() {
Solution solution = new Solution();
// At this point we only have type values, no bounds added for them, no values computed for unknown types
// Generate low-priority constraints from bounds
for (Map.Entry<TypeParameterDescriptor, TypeValue> entry : Sets.newHashSet(unknownTypes.entrySet())) {
TypeParameterDescriptor typeParameterDescriptor = entry.getKey();
TypeValue typeValue = entry.getValue();
for (JetType upperBound : typeParameterDescriptor.getUpperBounds()) {
addSubtypingConstraint(PARAMETER_BOUND.assertSubtyping(typeValue.getOriginalType(), getTypeValueFor(upperBound).getOriginalType()));
}
for (JetType lowerBound : typeParameterDescriptor.getLowerBounds()) {
addSubtypingConstraint(PARAMETER_BOUND.assertSubtyping(getTypeValueFor(lowerBound).getOriginalType(), typeValue.getOriginalType()));
}
}
// Expand and solve constraints
while (!constraintQueue.isEmpty()) {
SubtypingConstraint constraint = constraintQueue.poll();
// Apply constraint
TypeValue lower = getTypeValueFor(constraint.getSubtype());
TypeValue upper = getTypeValueFor(constraint.getSupertype());
boolean success = expandSubtypingConstraint(lower, upper);
if (!success) {
solution.registerError(constraint.getErrorMessage());
break;
}
// (???) Propagate info
// Any unknowns left?
if (unsolvedUnknowns.isEmpty()) break;
}
// Now, let's check the rest of the constraints
// Expand custom bounds, e.g. List<T> <: List<Int>
// for (Map.Entry<JetType, TypeValue> entry : Sets.newHashSet(knownTypes.entrySet())) {
// JetType jetType = entry.getKey();
// TypeValue typeValue = entry.getValue();
//
// for (TypeValue upperBound : typeValue.getUpperBounds()) {
// if (upperBound.isKnown()) {
// boolean ok = constraintExpander.isSubtypeOf(jetType, upperBound.getType());
// if (!ok) {
// listener.error("Error while expanding '" + jetType + " :< " + upperBound.getType() + "'");
// return new Solution().registerError("Mismatch while expanding constraints");
// }
// }
// }
//
// // Lower bounds. Probably not needed for known types, as everything is symmetrical anyway
// }
// effective bounds for each node
// Set<TypeValue> visited = Sets.newHashSet();
// for (TypeValue unknownType : unknownTypes.values()) {
// transitiveClosure(unknownType, visited);
// }
for (TypeValue unknownType : unknownTypes.values()) {
listener.constraintsForUnknown(unknownType.getTypeParameterDescriptor(), unknownType);
}
for (TypeValue knownType : knownTypes.values()) {
listener.constraintsForKnownType(knownType.getType(), knownType);
}
// Find inconsistencies
// Compute values and check that all bounds are respected by solutions:
// we have set some of them from equality constraints with known types
// and thus the bounds may be violated if some of the constraints conflict
for (TypeValue unknownType : unknownTypes.values()) {
check(unknownType, solution);
}
for (TypeValue knownType : knownTypes.values()) {
check(knownType, solution);
}
listener.done(solution, unknownTypes.keySet());
return solution;
}
private void transitiveClosure(TypeValue current, Set<TypeValue> visited) {
if (!visited.add(current)) {
return;
}
for (TypeValue upperBound : Sets.newHashSet(current.getUpperBounds())) {
if (upperBound.isKnown()) {
continue;
}
transitiveClosure(upperBound, visited);
Set<TypeValue> upperBounds = upperBound.getUpperBounds();
for (TypeValue transitiveBound : upperBounds) {
expandSubtypingConstraint(current, transitiveBound);
}
}
}
private void check(TypeValue typeValue, Solution solution) {
try {
JetType resultingType = typeValue.getType();
JetType type = solution.getSubstitutor().substitute(resultingType, Variance.INVARIANT); // TODO
for (TypeValue upperBound : typeValue.getUpperBounds()) {
JetType boundingType = solution.getSubstitutor().substitute(upperBound.getType(), Variance.INVARIANT);
if (!typeChecker.isSubtypeOf(type, boundingType)) { // TODO
solution.registerError("Constraint violation: " + type + " is not a subtype of " + boundingType);
listener.error("Constraint violation: ", type, " :< ", boundingType);
}
}
for (TypeValue lowerBound : typeValue.getLowerBounds()) {
JetType boundingType = solution.getSubstitutor().substitute(lowerBound.getType(), Variance.INVARIANT);
if (!typeChecker.isSubtypeOf(boundingType, type)) {
solution.registerError("Constraint violation: " + boundingType + " is not a subtype of " + type);
listener.error("Constraint violation: ", boundingType, " :< ", type);
}
}
}
catch (LoopInTypeVariableConstraintsException e) {
listener.error("Loop detected");
solution.registerError("[TODO] Loop in constraints");
}
}
private static class Error implements SolutionStatus {
private final String message;
private Error(String message) {
this.message = message;
}
@Override
public boolean isSuccessful() {
return false;
}
@Override
public String toString() {
return message;
}
}
public class Solution implements ConstraintSystemSolution {
private final TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(new TypeSubstitutor.TypeSubstitution() {
@Override
public TypeProjection get(TypeConstructor key) {
DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor();
if (declarationDescriptor instanceof TypeParameterDescriptor) {
TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor;
if (!unknownTypes.containsKey(descriptor)) return null;
TypeProjection typeProjection = new TypeProjection(getValue(descriptor));
listener.log(descriptor, " |-> ", typeProjection);
return typeProjection;
}
return null;
}
@Override
public boolean isEmpty() {
return false;
}
});
private SolutionStatus status;
public Solution() {
this.status = SolutionStatus.SUCCESS;
}
private Solution registerError(String message) {
status = new Error(message);
return this;
}
@NotNull
@Override
public SolutionStatus getStatus() {
return status;
}
@Override
public JetType getValue(TypeParameterDescriptor typeParameterDescriptor) {
return getTypeVariable(typeParameterDescriptor).getType();
}
@NotNull
@Override
public TypeSubstitutor getSubstitutor() {
return typeSubstitutor;
}
}
private static final class TypeConstraintBuilderAdapter implements TypingConstraints {
private final TypingConstraints delegate;
private final ConstraintResolutionListener listener;
private TypeConstraintBuilderAdapter(TypingConstraints delegate, ConstraintResolutionListener listener) {
this.delegate = delegate;
this.listener = listener;
}
@Override
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
boolean result = delegate.assertEqualTypes(a, b, typeCheckingProcedure);
if (!result) {
listener.error("-- Failed to equate ", a, " and ", b);
}
return result;
}
@Override
public boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b) {
boolean result = delegate.assertEqualTypeConstructors(a, b);
if (!result) {
listener.error("-- Type constructors are not equal: ", a, " and ", b);
}
return result;
}
@Override
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
boolean result = delegate.assertSubtype(subtype, supertype, typeCheckingProcedure);
if (!result) {
listener.error("-- " + subtype + " can't be a subtype of " + supertype);
}
return result;
}
@Override
public boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype) {
boolean result = delegate.noCorrespondingSupertype(subtype, supertype);
if (!result) {
listener.error("-- " + subtype + " has no supertype corresponding to " + supertype);
}
return result;
}
}
}
@@ -0,0 +1,35 @@
package org.jetbrains.jet.lang.resolve.calls.inference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.JetType;
import java.text.MessageFormat;
/**
* @author abreslav
*/
public enum ConstraintType implements Comparable<ConstraintType> {
// The order of these constants DOES matter
// they are compared according to ordinal() values
// First element has the highest priority
RECEIVER("{0} is not a subtype of the expected receiver type {1}"),
VALUE_ARGUMENT("Type mismatch: argument type is {0}, but {1} was expected"),
EXPECTED_TYPE("Resulting type is {0} but {1} was expected"),
PARAMETER_BOUND("Type parameter bound is not satisfied: {0} is not a subtype of {1}");
private final String errorMessageTemplate; // {0} is subtype, {1} is supertye
private ConstraintType(@NotNull String errorMessageTemplate) {
this.errorMessageTemplate = errorMessageTemplate;
}
@NotNull
public SubtypingConstraint assertSubtyping(@NotNull JetType subtype, @NotNull JetType supertype) {
return new SubtypingConstraint(this, subtype, supertype);
}
@NotNull
public String makeErrorMessage(@NotNull SubtypingConstraint constraint) {
return MessageFormat.format(errorMessageTemplate, constraint.getSubtype(), constraint.getSupertype());
}
}
@@ -23,9 +23,9 @@ public class DebugConstraintResolutionListener implements ConstraintResolutionLi
}
@Override
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue) {
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, BoundsOwner typeValue) {
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
Map<TypeParameterDescriptor, ConstraintSystemImpl.TypeValue> map = debugInfo.get(BOUNDS_FOR_UNKNOWNS);
Map<TypeParameterDescriptor, BoundsOwner> map = debugInfo.get(BOUNDS_FOR_UNKNOWNS);
if (map == null) {
map = Maps.newLinkedHashMap();
debugInfo.set(BOUNDS_FOR_UNKNOWNS, map);
@@ -34,9 +34,9 @@ public class DebugConstraintResolutionListener implements ConstraintResolutionLi
}
@Override
public void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue) {
public void constraintsForKnownType(JetType type, BoundsOwner typeValue) {
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
Map<JetType,ConstraintSystemImpl.TypeValue> map = debugInfo.get(BOUNDS_FOR_KNOWNS);
Map<JetType,BoundsOwner> map = debugInfo.get(BOUNDS_FOR_KNOWNS);
if (map == null) {
map = Maps.newLinkedHashMap();
debugInfo.set(BOUNDS_FOR_KNOWNS, map);
@@ -52,24 +52,30 @@ public class DebugConstraintResolutionListener implements ConstraintResolutionLi
}
@Override
public void log(Object message) {
public void log(Object... messageFragments) {
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
StringBuilder stringBuilder = debugInfo.get(LOG);
if (stringBuilder == null) {
stringBuilder = new StringBuilder();
debugInfo.set(LOG, stringBuilder);
}
stringBuilder.append(message).append("\n");
for (Object m : messageFragments) {
stringBuilder.append(m);
}
stringBuilder.append("\n");
}
@Override
public void error(Object message) {
public void error(Object... messageFragments) {
if (!ResolutionDebugInfo.isResolutionDebugEnabled()) return;
StringBuilder stringBuilder = debugInfo.get(ERRORS);
if (stringBuilder == null) {
stringBuilder = new StringBuilder();
debugInfo.set(ERRORS, stringBuilder);
}
stringBuilder.append(message).append("\n");
for (Object m : messageFragments) {
stringBuilder.append(m);
}
stringBuilder.append("\n");
}
}
@@ -12,13 +12,13 @@ import java.util.Set;
public class PrintingConstraintResolutionListener implements ConstraintResolutionListener {
@Override
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, ConstraintSystemImpl.TypeValue typeValue) {
public void constraintsForUnknown(TypeParameterDescriptor typeParameterDescriptor, BoundsOwner typeValue) {
println("Constraints for " + typeParameterDescriptor);
printTypeValue(typeValue);
}
@Override
public void constraintsForKnownType(JetType type, ConstraintSystemImpl.TypeValue typeValue) {
public void constraintsForKnownType(JetType type, BoundsOwner typeValue) {
println("Constraints for " + type);
printTypeValue(typeValue);
}
@@ -31,20 +31,24 @@ public class PrintingConstraintResolutionListener implements ConstraintResolutio
}
@Override
public void log(Object message) {
println(message);
public void log(Object... messageFragments) {
for (Object fragment : messageFragments) {
println(fragment);
}
}
@Override
public void error(Object message) {
println(message);
public void error(Object... messageFragments) {
for (Object fragment : messageFragments) {
println(fragment);
}
}
private void printTypeValue(ConstraintSystemImpl.TypeValue typeValue) {
for (ConstraintSystemImpl.TypeValue bound : typeValue.getUpperBounds()) {
private void printTypeValue(BoundsOwner typeValue) {
for (BoundsOwner bound : typeValue.getUpperBounds()) {
println(" :< " + bound);
}
for (ConstraintSystemImpl.TypeValue bound : typeValue.getLowerBounds()) {
for (BoundsOwner bound : typeValue.getLowerBounds()) {
println(" :> " + bound);
}
}
@@ -0,0 +1,39 @@
package org.jetbrains.jet.lang.resolve.calls.inference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.JetType;
/**
* @author abreslav
*/
public class SubtypingConstraint {
private final ConstraintType type;
private final JetType subtype;
private final JetType supertype;
public SubtypingConstraint(@NotNull ConstraintType type, @NotNull JetType subtype, @NotNull JetType supertype) {
this.type = type;
this.subtype = subtype;
this.supertype = supertype;
}
@NotNull
public JetType getSubtype() {
return subtype;
}
@NotNull
public JetType getSupertype() {
return supertype;
}
@NotNull
public ConstraintType getType() {
return type;
}
@NotNull
public String getErrorMessage() {
return type.makeErrorMessage(this);
}
}
@@ -0,0 +1,82 @@
package org.jetbrains.jet.lang.resolve.calls.inference;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.Variance;
import java.util.Set;
/**
* @author abreslav
*/
public class TypeValue implements BoundsOwner {
private final Set<TypeValue> upperBounds = Sets.newLinkedHashSet();
private final Set<TypeValue> lowerBounds = Sets.newLinkedHashSet();
private final Variance positionVariance;
private final TypeParameterDescriptor typeParameterDescriptor; // Null for known types
private final JetType originalType;
private JetType value; // For an unknown the value found by constraint resolution, for a known just it's value
// Unknown type
public TypeValue(@NotNull TypeParameterDescriptor typeParameterDescriptor, @NotNull Variance positionVariance) {
this.positionVariance = positionVariance;
this.typeParameterDescriptor = typeParameterDescriptor;
this.originalType = typeParameterDescriptor.getDefaultType();
}
// Known type
public TypeValue(@NotNull JetType knownType) {
this.positionVariance = null;
this.typeParameterDescriptor = null;
this.originalType = knownType;
}
public boolean isKnown() {
return typeParameterDescriptor == null;
}
public TypeParameterDescriptor getTypeParameterDescriptor() {
return typeParameterDescriptor;
}
@Override
@NotNull
public Set<TypeValue> getUpperBounds() {
return upperBounds;
}
@Override
@NotNull
public Set<TypeValue> getLowerBounds() {
return lowerBounds;
}
@NotNull
public JetType getType() {
return value;
}
@NotNull
public JetType getOriginalType() {
return originalType;
}
public void addUpperBound(@NotNull TypeValue bound) {
upperBounds.add(bound);
}
public void addLowerBound(@NotNull TypeValue bound) {
lowerBounds.add(bound);
}
public void setValue(@NotNull JetType value) {
this.value = value;
}
public boolean hasValue() {
return value != null;
}
}
@@ -203,7 +203,7 @@ public class ErrorUtils {
}
public static boolean isError(@NotNull DeclarationDescriptor candidate) {
return candidate.getContainingDeclaration() == getErrorClass() || candidate == ERROR_MODULE;
return candidate == getErrorClass() || candidate.getContainingDeclaration() == getErrorClass() || candidate == ERROR_MODULE;
}
private static class ErrorTypeImpl implements JetType {
@@ -1,19 +1,41 @@
package org.jetbrains.jet.lang.types;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author abreslav
*/
public class TypeSubstitutor {
public static TypeSubstitutor makeConstantSubstitutor(Collection<TypeParameterDescriptor> typeParameterDescriptors, JetType type) {
final Set<TypeConstructor> constructors = Sets.newHashSet();
for (TypeParameterDescriptor typeParameterDescriptor : typeParameterDescriptors) {
constructors.add(typeParameterDescriptor.getTypeConstructor());
}
final TypeProjection projection = new TypeProjection(type);
return create(new TypeSubstitution() {
@Override
public TypeProjection get(TypeConstructor key) {
if (constructors.contains(key)) {
return projection;
}
return null;
}
@Override
public boolean isEmpty() {
return false;
}
});
}
public interface TypeSubstitution {
TypeSubstitution EMPTY = new TypeSubstitution() {
@Override
@@ -46,7 +46,7 @@ public class JetTypeChecker {
private static class TypeCheckerTypingConstraints implements TypingConstraints {
@Override
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure) {
public boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
return typeCheckingProcedure.equalTypes(a, b);
// return TypeUtils.equalTypes(a, b);
}
@@ -57,7 +57,7 @@ public class JetTypeChecker {
}
@Override
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure) {
public boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure) {
return typeCheckingProcedure.isSubtypeOf(subtype, supertype);
}
@@ -8,11 +8,11 @@ import org.jetbrains.jet.lang.types.TypeConstructor;
* Methods of this class return true to continue type checking and false to fail
*/
public interface TypingConstraints {
boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, TypeCheckingProcedure typeCheckingProcedure);
boolean assertEqualTypes(@NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure);
boolean assertEqualTypeConstructors(@NotNull TypeConstructor a, @NotNull TypeConstructor b);
boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, TypeCheckingProcedure typeCheckingProcedure);
boolean assertSubtype(@NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure);
boolean noCorrespondingSupertype(@NotNull JetType subtype, @NotNull JetType supertype);
}
@@ -1,3 +1,4 @@
import std.*
import std.io.*
import java.io.*
@@ -1,4 +1,5 @@
class A() {}
open class B<T>() {
fun isT (a : Any?) : Boolean {
return a is T
@@ -167,7 +168,6 @@ fun t26 () : Boolean {
}
fun box() : String {
/*
if(!t1()) {
return "t1 failed"
}
@@ -243,7 +243,6 @@ fun box() : String {
if(!t25()) {
return "t25 failed"
}
*/
if(!t26()) {
return "t26 failed"
}
@@ -0,0 +1,13 @@
class A() {
var x : Int = 0
var z = { () =>
x++
}
}
fun box() : String {
val a = A()
a.z() //problem is here
return if (a.x == 1) "OK" else "fail"
}
@@ -0,0 +1,8 @@
fun <T> Array<T>?.get(i : Int?) = this.sure().get(i.sure())
fun <T> array(vararg t : T) : Array<T> = t
fun box() : String {
val a : Array<String>? = array<String>("Str", "Str2")
val i : Int? = 1
return if(a[i] == "Str2") "OK" else "fail"
}
@@ -1,4 +1,4 @@
open class A<T> () {
open class A<out T> () {
fun plus(e: T) = B<T> (e)
}
@@ -6,4 +6,6 @@ class B<T> (val e: T) : A<T>() {
fun add() = B<T> (e)
}
fun box() = if( A<String>().plus("239").add().e == "239" ) "OK" else "fail"
fun box() : String {
return if(A<String>().plus("239").add().e == "239" ) "OK" else "fail"
}
@@ -4,7 +4,6 @@ class Box<T>() {
}
class Inner2() : Inner() {
}
fun inner() = Inner2()
@@ -0,0 +1,6 @@
class ExtendsAbstractListT {
{
Mine<String> mine = null;
java.util.List<String> list = mine;
}
}
@@ -0,0 +1 @@
abstract class Mine<T>() : java.util.AbstractList<T>()
@@ -0,0 +1,7 @@
class PlainExtendsListString {
{
Mine mine = null;
java.util.List<String> list = mine;
}
}
@@ -0,0 +1 @@
abstract class Mine : java.util.List<String>
@@ -0,0 +1,7 @@
class ImplementsMapPP {
{
Mine<String, Integer> mine = null;
java.util.Map<Integer, String> map = mine;
}
}
@@ -0,0 +1 @@
abstract class Mine<P1, P2> : java.util.Map<P2, P1>
@@ -0,0 +1,8 @@
class Question {
// id2 is to prevent java type parameter type inference
static <T> T id2(T p) { return p; }
{
java.util.List<String> s = id2(namespace.id((jet.typeinfo.TypeInfo) null, null));
}
}
@@ -0,0 +1,3 @@
import java.util.List
fun <P1 : List<String>> id(p: P1) = p
@@ -0,0 +1,8 @@
class Question {
// id2 is to prevent java type parameter type inference
static <T> T id2(T p) { return p; }
{
String s = id2(namespace.id((jet.typeinfo.TypeInfo) null, null));
}
}
@@ -0,0 +1 @@
fun <T : String> id(p: T) = p
@@ -24,7 +24,7 @@ public class ClassGenTest extends CodegenTestCase {
public void testArrayListInheritance() throws Exception {
loadFile("classes/inheritingFromArrayList.jet");
System.out.println(generateToText());
final Class aClass = loadClass("Foo", generateClassesInFile());
assertInstanceOf(aClass.newInstance(), List.class);
}
@@ -81,6 +81,10 @@ public class FunctionGenTest extends CodegenTestCase {
blackBoxFile("regressions/kt395.jet");
}
public void testKt785 () {
// blackBoxFile("regressions/kt785.jet");
}
public void testFunction () throws InvocationTargetException, IllegalAccessException {
blackBoxFile("functions/functionExpression.jet");
}
@@ -140,7 +140,7 @@ public class TypeInfoTest extends CodegenTestCase {
public void testInner() throws Exception {
blackBoxFile("typeInfo/inner.jet");
// System.out.println(generateToText());
System.out.println(generateToText());
}
public void testInheritance() throws Exception {
@@ -148,4 +148,3 @@ public class TypeInfoTest extends CodegenTestCase {
System.out.println(generateToText());
}
}
@@ -74,4 +74,8 @@ public class VarArgTest extends CodegenTestCase {
createEnvironmentWithFullJdk();
blackBoxFile("regressions/kt581.jet");
}
public void testKt797() {
blackBoxFile("regressions/kt796_797.jet");
}
}