From 8e10536ef93b8728315aa5a0e2e4f7de69347a75 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 9 Dec 2011 18:15:05 +0400 Subject: [PATCH 01/23] Constraint priorities introduced. Not used for the time being --- .../jet/lang/resolve/calls/CallResolver.java | 9 +++-- .../calls/inference/ConstraintSystem.java | 3 +- .../calls/inference/ConstraintSystemImpl.java | 18 ++++++--- .../calls/inference/ConstraintType.java | 35 +++++++++++++++++ .../calls/inference/SubtypingConstraint.java | 39 +++++++++++++++++++ 5 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintType.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SubtypingConstraint.java diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index e611247ebe7..e8ed22f23a0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -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; @@ -465,7 +468,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(); @@ -478,12 +481,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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java index 8511fb78b37..e071e19bef5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.java @@ -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(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java index 8ea8f233b0c..931371e5f3e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java @@ -382,9 +382,9 @@ 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); } @@ -415,8 +415,16 @@ public class ConstraintSystemImpl implements ConstraintSystem { } } - // 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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintType.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintType.java new file mode 100644 index 00000000000..d66578f1d83 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintType.java @@ -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 { + // 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()); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SubtypingConstraint.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SubtypingConstraint.java new file mode 100644 index 00000000000..5f62fb11233 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/SubtypingConstraint.java @@ -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); + } +} From 92d8d2de7226c8fae4cadb22da72ac02be9ba68a Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Mon, 12 Dec 2011 10:40:42 +0200 Subject: [PATCH 02/23] functional list benchmark and part of rewrite of type info codegen for performance reasons --- .../jetbrains/jet/codegen/CodegenUtil.java | 46 +++------- .../jet/codegen/ConstructorFrameMap.java | 23 ++--- .../jet/codegen/ExpressionCodegen.java | 68 +++++++++----- .../codegen/ImplementationBodyCodegen.java | 90 ++++++------------- .../jetbrains/jet/codegen/JetTypeMapper.java | 12 +-- .../jet/codegen/NamespaceCodegen.java | 3 +- .../org/jetbrains/jet/codegen/StackValue.java | 6 +- .../jet/codegen/intrinsics/ArrayIterator.java | 4 +- .../testData/codegen/regressions/kt259.jet | 3 +- .../testData/codegen/regressions/kt785.jet | 13 +++ .../testData/codegen/typeInfo/inheritance.jet | 6 +- compiler/testData/codegen/typeInfo/inner.jet | 1 - .../jetbrains/jet/codegen/ClassGenTest.java | 2 +- .../jet/codegen/FunctionGenTest.java | 4 + .../jetbrains/jet/codegen/TypeInfoTest.java | 3 +- examples/src/benchmarks/FList.java | 86 ++++++++++++++++++ examples/src/benchmarks/FList.kt | 70 +++++++++++++++ stdlib/src/jet/DefaultJetObject.java | 5 ++ stdlib/src/jet/IntRange.java | 12 ++- stdlib/src/jet/JetObject.java | 2 + stdlib/src/jet/LongRange.java | 10 +++ stdlib/src/jet/Tuple0.java | 5 ++ stdlib/src/jet/runtime/ArrayIterator.java | 45 ++++++++++ stdlib/src/jet/typeinfo/TypeInfo.java | 10 +++ 24 files changed, 371 insertions(+), 158 deletions(-) create mode 100644 compiler/testData/codegen/regressions/kt785.jet create mode 100644 examples/src/benchmarks/FList.java create mode 100644 examples/src/benchmarks/FList.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java index 53af0cdc730..1b1bb5db25c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java @@ -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 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) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java b/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java index b27e9ab18ce..9c60a5b170e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java @@ -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 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; } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index a24e486308e..d0644e6bd5a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -979,7 +979,7 @@ public class ExpressionCodegen extends JetVisitor { } 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 { private void pushTypeArguments(ResolvedCall resolvedCall) { if(resolvedCall != null) { - Map 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 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 { 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;"); } @@ -2195,7 +2201,7 @@ public class ExpressionCodegen extends JetVisitor { } for (TypeParameterDescriptor typeParameterDescriptor : getterDescriptor.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 { } 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 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 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(1, TYPE_OBJECT); + } } else { v.getstatic(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;"); @@ -2603,11 +2623,11 @@ 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;"); while(descriptor != containingDeclaration) { descriptor = CodegenUtil.getOuterClassDescriptor(descriptor); - v.invokevirtual("jet/typeinfo/TypeInfo", "getOuterTypeInfo", "()Ljet/typeinfo/TypeInfo;"); + v.invokeinterface("jet/JetObject", "getOuterObject", "()Ljet/JetObject;"); } + v.invokeinterface("jet/JetObject", "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); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 312f297acc6..a637350f361 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -305,8 +305,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION)); } - List typeParameters = descriptor.getTypeConstructor().getParameters(); - for (int n = typeParameters.size(); n > 0; n--) { + if (CodegenUtil.requireTypeInfoConstructorArg(descriptor.getDefaultType())) { parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO); } @@ -365,12 +364,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 +398,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("", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); @@ -447,10 +446,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 +701,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 +797,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 +816,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 +853,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;"); } }); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 06b23293f82..0e62029178e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -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; @@ -575,10 +579,8 @@ public class JetTypeMapper { parameterTypes.add(mapType(CodegenUtil.getOuterClassDescriptor(classDescriptor).getDefaultType(), OwnerKind.IMPLEMENTATION)); } - List 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) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 837c1503717..9a6f2c5210a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -6,6 +6,7 @@ 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; @@ -145,7 +146,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; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index d8591fe5e4a..f9167601b55 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -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 { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java index 4c0f906e5ab..8fcd6d57500 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ArrayIterator.java @@ -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); } diff --git a/compiler/testData/codegen/regressions/kt259.jet b/compiler/testData/codegen/regressions/kt259.jet index 59a99b1bcbb..ad996781b9f 100644 --- a/compiler/testData/codegen/regressions/kt259.jet +++ b/compiler/testData/codegen/regressions/kt259.jet @@ -1,4 +1,5 @@ class A() {} + open class B() { 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" } diff --git a/compiler/testData/codegen/regressions/kt785.jet b/compiler/testData/codegen/regressions/kt785.jet new file mode 100644 index 00000000000..1b10c8c73d7 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt785.jet @@ -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" +} \ No newline at end of file diff --git a/compiler/testData/codegen/typeInfo/inheritance.jet b/compiler/testData/codegen/typeInfo/inheritance.jet index 225bda1f665..3ee02657f34 100644 --- a/compiler/testData/codegen/typeInfo/inheritance.jet +++ b/compiler/testData/codegen/typeInfo/inheritance.jet @@ -1,4 +1,4 @@ -open class A () { +open class A () { fun plus(e: T) = B (e) } @@ -6,4 +6,6 @@ class B (val e: T) : A() { fun add() = B (e) } -fun box() = if( A().plus("239").add().e == "239" ) "OK" else "fail" \ No newline at end of file +fun box() : String { + return if(A().plus("239").add().e == "239" ) "OK" else "fail" +} \ No newline at end of file diff --git a/compiler/testData/codegen/typeInfo/inner.jet b/compiler/testData/codegen/typeInfo/inner.jet index 49db9252b35..62dad284a09 100644 --- a/compiler/testData/codegen/typeInfo/inner.jet +++ b/compiler/testData/codegen/typeInfo/inner.jet @@ -4,7 +4,6 @@ class Box() { } class Inner2() : Inner() { - } fun inner() = Inner2() diff --git a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 25c697c6484..88e445a6bb1 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -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); } diff --git a/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java index 7b5a7a33e7a..431400d66bd 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/FunctionGenTest.java @@ -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"); } diff --git a/compiler/tests/org/jetbrains/jet/codegen/TypeInfoTest.java b/compiler/tests/org/jetbrains/jet/codegen/TypeInfoTest.java index 85b9dae07d8..b2396c96af6 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/TypeInfoTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/TypeInfoTest.java @@ -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()); } } - diff --git a/examples/src/benchmarks/FList.java b/examples/src/benchmarks/FList.java new file mode 100644 index 00000000000..694dd70ac96 --- /dev/null +++ b/examples/src/benchmarks/FList.java @@ -0,0 +1,86 @@ +import java.util.NoSuchElementException; + +abstract public class FList { + abstract T getHead(); + + abstract FList getTail(); + + abstract FList plus(T element); + + static class Empty extends FList { + + @Override + T getHead() { + throw new NoSuchElementException(); + } + + @Override + FList getTail() { + throw new NoSuchElementException(); + } + + @Override + FList plus(T element) { + return new OneElementList(element); + } + } + + static class OneElementList extends FList { + private T element; + + public OneElementList(T element) { + super(); + this.element = element; + } + + @Override + T getHead() { + return element; + } + + @Override + FList getTail() { + return new Empty(); + } + + @Override + FList plus(T element) { + return new StandardList(element, this); + } + } + + private static class StandardList extends FList { + private T head; + private FList tail; + + public StandardList(T head, FList tail) { + this.head = head; + this.tail = tail; + } + + @Override + T getHead() { + return head; + } + + @Override + FList getTail() { + return tail; + } + + @Override + FList plus(T element) { + return new StandardList(element, this); + } + } + + public static void main(String[] args) { + for(int k = 0; k != 10; ++k) { + long start = System.currentTimeMillis(); + FList list = new Empty(); + for(int i = 0; i != 5000000; ++i) + list = list.plus(i); + System.out.println(System.currentTimeMillis()-start); + } + } +} diff --git a/examples/src/benchmarks/FList.kt b/examples/src/benchmarks/FList.kt new file mode 100644 index 00000000000..5d806215920 --- /dev/null +++ b/examples/src/benchmarks/FList.kt @@ -0,0 +1,70 @@ +namespace flist + +abstract class FList { + abstract val head : T + abstract val tail : FList + + abstract fun plus(element: T) : FList +} + +class EmptyFList() : FList { + override val head: T + get() = throw java.util.NoSuchElementException() + + override val tail : EmptyFList + get() = EmptyFList() + + override fun plus(element: T) : FList = OneElementFList(element) +} + +class OneElementFList (override val head: T): FList { + override val tail : EmptyFList + get() = EmptyFList() + + override fun plus(element: T) : FList = StandardFList(element, this) +} + +class StandardFList (override val head: T, override val tail: FList) : FList { + override fun plus(element: T) : FList = StandardFList(element, this) +} + +fun FList.plus2(element: T): FList = + when(this) { + is EmptyFList => OneElementFList(element) + else => StandardFList(element, this) + } + +fun FList.plus3(element: T) : FList = + if(this is EmptyFList<*>) + OneElementFList(element) + else + StandardFList(element, this) + +fun main(args: Array) { + for(k in 0..3) { + val start0 = System.currentTimeMillis() + + var flist0 : FList = EmptyFList() + for(i in 0..5000000) + flist0 = flist0 + i + + System.out?.println(System.currentTimeMillis() - start0) + + val start = System.currentTimeMillis() + + var flist : FList = EmptyFList() + for(i in 0..5000000) + flist = flist.plus2(i) + + System.out?.println(System.currentTimeMillis() - start) + + val start2 = System.currentTimeMillis() + + var flist2 : FList = EmptyFList() + for(i in 0..5000000) + flist2 = flist2.plus3(i) + + System.out?.println(System.currentTimeMillis() - start2) + System.out?.println() + } +} \ No newline at end of file diff --git a/stdlib/src/jet/DefaultJetObject.java b/stdlib/src/jet/DefaultJetObject.java index 4070c14eb5d..736606a70d6 100644 --- a/stdlib/src/jet/DefaultJetObject.java +++ b/stdlib/src/jet/DefaultJetObject.java @@ -23,4 +23,9 @@ public class DefaultJetObject implements JetObject { public final TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } diff --git a/stdlib/src/jet/IntRange.java b/stdlib/src/jet/IntRange.java index 71d49ed0a73..13811dbba40 100644 --- a/stdlib/src/jet/IntRange.java +++ b/stdlib/src/jet/IntRange.java @@ -47,7 +47,12 @@ public final class IntRange implements Range, Iterable, JetObj public TypeInfo getTypeInfo() { return typeInfo; } - + + @Override + public JetObject getOuterObject() { + return null; + } + public static IntRange count(int length) { return new IntRange(0, length); } @@ -95,5 +100,10 @@ public final class IntRange implements Range, Iterable, JetObj public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } } diff --git a/stdlib/src/jet/JetObject.java b/stdlib/src/jet/JetObject.java index c06fd1f755a..96f17a323b6 100644 --- a/stdlib/src/jet/JetObject.java +++ b/stdlib/src/jet/JetObject.java @@ -4,7 +4,9 @@ import jet.typeinfo.TypeInfo; /** * @author abreslav + * @author alex.tkachman */ public interface JetObject { TypeInfo getTypeInfo(); + JetObject getOuterObject(); } diff --git a/stdlib/src/jet/LongRange.java b/stdlib/src/jet/LongRange.java index e0a358599fb..ed94c76cb31 100644 --- a/stdlib/src/jet/LongRange.java +++ b/stdlib/src/jet/LongRange.java @@ -48,6 +48,11 @@ public final class LongRange implements Range, Iterable, JetObject { return typeInfo; } + @Override + public JetObject getOuterObject() { + return null; + } + public static IntRange count(int length) { return new IntRange(0, length); } @@ -95,5 +100,10 @@ public final class LongRange implements Range, Iterable, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } } diff --git a/stdlib/src/jet/Tuple0.java b/stdlib/src/jet/Tuple0.java index 34d12022230..a4823e1dd5e 100644 --- a/stdlib/src/jet/Tuple0.java +++ b/stdlib/src/jet/Tuple0.java @@ -31,4 +31,9 @@ public class Tuple0 implements JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } \ No newline at end of file diff --git a/stdlib/src/jet/runtime/ArrayIterator.java b/stdlib/src/jet/runtime/ArrayIterator.java index 55d4e0a9cd9..7626820a6b6 100644 --- a/stdlib/src/jet/runtime/ArrayIterator.java +++ b/stdlib/src/jet/runtime/ArrayIterator.java @@ -39,6 +39,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return TypeInfo.getTypeInfo(GenericIterator.class, false, null, new TypeInfoProjection[] {(TypeInfoProjection) elementTypeInfo}); } + + @Override + public JetObject getOuterObject() { + return null; + } } public static Iterator iterator(T[] array, TypeInfo elementTypeInfo) { @@ -69,6 +74,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static ByteIterator iterator(byte[] array) { @@ -99,6 +109,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static ShortIterator iterator(short[] array) { @@ -129,6 +144,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static IntIterator iterator(int[] array) { @@ -159,6 +179,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static LongIterator iterator(long[] array) { @@ -189,6 +214,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static FloatIterator iterator(float[] array) { @@ -219,6 +249,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static DoubleIterator iterator(double[] array) { @@ -249,6 +284,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static CharIterator iterator(char[] array) { @@ -279,6 +319,11 @@ public abstract class ArrayIterator implements Iterator, JetObject { public TypeInfo getTypeInfo() { return typeInfo; } + + @Override + public JetObject getOuterObject() { + return null; + } } public static BooleanIterator iterator(boolean[] array) { diff --git a/stdlib/src/jet/typeinfo/TypeInfo.java b/stdlib/src/jet/typeinfo/TypeInfo.java index 2fb20baa47e..32db06ff044 100644 --- a/stdlib/src/jet/typeinfo/TypeInfo.java +++ b/stdlib/src/jet/typeinfo/TypeInfo.java @@ -181,6 +181,11 @@ public abstract class TypeInfo implements JetObject { throw new UnsupportedOperationException("Abstract TypeInfo"); } + @Override + public JetObject getOuterObject() { + return null; + } + @Override public String toString() { return "T:" + signature.klazz.getName() + ":" + varIndex; @@ -388,6 +393,11 @@ public abstract class TypeInfo implements JetObject { return typeInfo; } + @Override + public JetObject getOuterObject() { + return null; + } + public final boolean isSubtypeOf(TypeInfoImpl superType) { if (nullable && !superType.nullable) { return false; From 9ae40b270af5ad76e8036e4b75897d9b574e0f85 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Mon, 12 Dec 2011 15:16:16 +0400 Subject: [PATCH 03/23] KT-795: Insert brackets after applying function completion --- .../JetKeywordCompletionContributor.java | 13 +++++-- .../handlers/JetFunctionInsertHandler.java | 38 +++++++++++++++++++ .../handlers/JetKeywordInsertHandler.java | 34 +++++++++++++++++ .../references/JetSimpleNameReference.java | 22 ++++++++++- .../completion/handlers/NoParamsFunction.kt | 8 ++++ .../handlers/NoParamsFunction.kt.after | 8 ++++ .../completion/handlers/ParamsFunction.kt | 6 +++ .../handlers/ParamsFunction.kt.after | 6 +++ .../handlers/FunctionsHandlerTest.java | 28 ++++++++++++++ .../handlers/KeywordsHandlerTest.java | 31 +++++++++++++++ 10 files changed, 188 insertions(+), 6 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java create mode 100644 idea/src/org/jetbrains/jet/plugin/completion/handlers/JetKeywordInsertHandler.java create mode 100644 idea/testData/completion/handlers/NoParamsFunction.kt create mode 100644 idea/testData/completion/handlers/NoParamsFunction.kt.after create mode 100644 idea/testData/completion/handlers/ParamsFunction.kt create mode 100644 idea/testData/completion/handlers/ParamsFunction.kt.after create mode 100644 idea/tests/org/jetbrains/jet/completion/handlers/FunctionsHandlerTest.java create mode 100644 idea/tests/org/jetbrains/jet/completion/handlers/KeywordsHandlerTest.java diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java index 6f7a57c8492..eaec4204faf 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.plugin.completion; import com.intellij.codeInsight.completion.*; +import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.patterns.PlatformPatterns; import com.intellij.patterns.PsiElementPattern; @@ -11,6 +12,7 @@ import com.intellij.psi.filters.position.FilterPattern; import com.intellij.psi.filters.position.LeftNeighbour; import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.plugin.completion.handlers.JetKeywordInsertHandler; /** * A keyword contributor for Kotlin @@ -21,7 +23,9 @@ import org.jetbrains.annotations.NotNull; public class JetKeywordCompletionContributor extends CompletionContributor { private static class JetTopKeywordCompletionProvider extends CompletionProvider { - + + private final static InsertHandler KEYWORDS_INSERT_HANDLER = new JetKeywordInsertHandler(); + private final static String[] COMPLETE_KEYWORD = new String[] { "namespace", "as", "type", "class", "this", "super", "val", "var", "fun", "for", "null", "true", "false", "is", "in", "throw", "return", "break", "continue", "object", "if", "try", "else", "while", @@ -32,18 +36,19 @@ public class JetKeywordCompletionContributor extends CompletionContributor { "import", "where", "by", "get", "set", "abstract", "enum", "open", "annotation", "override", "private", "public", "internal", "protected", "catch", "out", "vararg", "inline", "finally", "final", "ref" }; - + @Override protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) { for (String keyword : COMPLETE_KEYWORD) { - result.addElement(LookupElementBuilder.create(keyword).setBold()); + + result.addElement(LookupElementBuilder.create(keyword).setInsertHandler(KEYWORDS_INSERT_HANDLER).setBold()); } for (String softKeyword : COMPLETE_SOFT_KEYWORDS) { - result.addElement(LookupElementBuilder.create(softKeyword)); + result.addElement(LookupElementBuilder.create(softKeyword).setInsertHandler(KEYWORDS_INSERT_HANDLER)); } } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java new file mode 100644 index 00000000000..68aafbc70a1 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java @@ -0,0 +1,38 @@ +package org.jetbrains.jet.plugin.completion.handlers; + +import com.intellij.codeInsight.completion.InsertHandler; +import com.intellij.codeInsight.completion.InsertionContext; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.openapi.editor.Editor; + +/** + * Inserts '()' after function proposal insert. + * + * @author Nikolay Krasko + */ +public class JetFunctionInsertHandler implements InsertHandler { + + public enum CaretPosition { IN_BRACKETS, AFTER_BRACKETS } + + private final CaretPosition caretPosition; + + public JetFunctionInsertHandler(CaretPosition caretPosition) { + this.caretPosition = caretPosition; + } + + @Override + public void handleInsert(InsertionContext context, LookupElement item) { + int startOffset = context.getStartOffset(); + int lookupStringLength = item.getLookupString().length(); + int endOffset = startOffset + lookupStringLength; + + context.getDocument().insertString(endOffset, "()"); + + Editor editor = context.getEditor(); + if (caretPosition == CaretPosition.IN_BRACKETS) { + editor.getCaretModel().moveToOffset(editor.getCaretModel().getOffset() + 1); + } else { + editor.getCaretModel().moveToOffset(editor.getCaretModel().getOffset() + 2); + } + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetKeywordInsertHandler.java b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetKeywordInsertHandler.java new file mode 100644 index 00000000000..2424d1a2c7a --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetKeywordInsertHandler.java @@ -0,0 +1,34 @@ +package org.jetbrains.jet.plugin.completion.handlers; + +import com.google.common.collect.Sets; +import com.intellij.codeInsight.completion.InsertHandler; +import com.intellij.codeInsight.completion.InsertionContext; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; + +import java.util.Set; + +/** + * @author Nikolay Krasko + */ +public class JetKeywordInsertHandler implements InsertHandler { + + private final static Set NO_SPACE_AFTER = Sets.newHashSet("this", "super", "This", "true", "false", "null"); + + @Override + public void handleInsert(InsertionContext context, LookupElement item) { + String keyword = item.getLookupString(); + + // Add space after keyword + if (!NO_SPACE_AFTER.contains(keyword)) { + Editor editor = context.getEditor(); + Document document = editor.getDocument(); + + int offset = context.getStartOffset() + keyword.length(); + context.setAddCompletionChar(false); + document.insertString(offset, " "); + editor.getCaretModel().moveToOffset(editor.getCaretModel().getOffset() + 1); + } + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java index 3239d3c47ef..54e27ce690f 100644 --- a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java +++ b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java @@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.Variance; import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade; +import org.jetbrains.jet.plugin.completion.handlers.JetFunctionInsertHandler; import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.List; @@ -37,6 +38,13 @@ import java.util.Set; * @author yole */ class JetSimpleNameReference extends JetPsiReference { + + private final static JetFunctionInsertHandler EMPTY_FUNCTION_HANDLER = new JetFunctionInsertHandler( + JetFunctionInsertHandler.CaretPosition.AFTER_BRACKETS); + + private final static JetFunctionInsertHandler PARAMS_FUNCTION_HANDLER = new JetFunctionInsertHandler( + JetFunctionInsertHandler.CaretPosition.IN_BRACKETS); + private final JetSimpleNameExpression myExpression; public JetSimpleNameReference(JetSimpleNameExpression jetSimpleNameExpression) { @@ -135,10 +143,12 @@ class JetSimpleNameReference extends JetPsiReference { String typeText = ""; String tailText = ""; boolean tailTextGrayed = false; + if (descriptor instanceof FunctionDescriptor) { FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; JetType returnType = functionDescriptor.getReturnType(); typeText = DescriptorRenderer.TEXT.renderType(returnType); + tailText = "(" + StringUtil.join(functionDescriptor.getValueParameters(), new Function() { @Override public String fun(ValueParameterDescriptor valueParameterDescriptor) { @@ -146,6 +156,14 @@ class JetSimpleNameReference extends JetPsiReference { DescriptorRenderer.TEXT.renderType(valueParameterDescriptor.getOutType()); } }, ",") + ")"; + + // TODO: A special case when it's impossible to resolve type parameters from arguments. Need '<' caret '>' + // TODO: Support omitting brackets for one argument functions + if (functionDescriptor.getValueParameters().isEmpty()) { + element = element.setInsertHandler(EMPTY_FUNCTION_HANDLER); + } else { + element = element.setInsertHandler(PARAMS_FUNCTION_HANDLER); + } } else if (descriptor instanceof VariableDescriptor) { JetType outType = ((VariableDescriptor) descriptor).getOutType(); @@ -170,8 +188,8 @@ class JetSimpleNameReference extends JetPsiReference { return result.toArray(); } - /** - * Checks that receiver declaration could be resolved to call expected receiver. + /* + * Checks if receiver declaration could be resolved to call expected receiver. */ private static boolean checkReceiverResolution ( @NotNull ReceiverDescriptor expectedReceiver, diff --git a/idea/testData/completion/handlers/NoParamsFunction.kt b/idea/testData/completion/handlers/NoParamsFunction.kt new file mode 100644 index 00000000000..120b5e55d02 --- /dev/null +++ b/idea/testData/completion/handlers/NoParamsFunction.kt @@ -0,0 +1,8 @@ +fun test() { +} + +fun other() { + te +} + +// INSERT: test \ No newline at end of file diff --git a/idea/testData/completion/handlers/NoParamsFunction.kt.after b/idea/testData/completion/handlers/NoParamsFunction.kt.after new file mode 100644 index 00000000000..920873c0b51 --- /dev/null +++ b/idea/testData/completion/handlers/NoParamsFunction.kt.after @@ -0,0 +1,8 @@ +fun test() { +} + +fun other() { + test() +} + +// INSERT: test \ No newline at end of file diff --git a/idea/testData/completion/handlers/ParamsFunction.kt b/idea/testData/completion/handlers/ParamsFunction.kt new file mode 100644 index 00000000000..c7910930150 --- /dev/null +++ b/idea/testData/completion/handlers/ParamsFunction.kt @@ -0,0 +1,6 @@ +fun test(a: Int) { +} + +fun other() { + te +} \ No newline at end of file diff --git a/idea/testData/completion/handlers/ParamsFunction.kt.after b/idea/testData/completion/handlers/ParamsFunction.kt.after new file mode 100644 index 00000000000..175892cc3a5 --- /dev/null +++ b/idea/testData/completion/handlers/ParamsFunction.kt.after @@ -0,0 +1,6 @@ +fun test(a: Int) { +} + +fun other() { + test() +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/FunctionsHandlerTest.java b/idea/tests/org/jetbrains/jet/completion/handlers/FunctionsHandlerTest.java new file mode 100644 index 00000000000..f265bde4714 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/completion/handlers/FunctionsHandlerTest.java @@ -0,0 +1,28 @@ +package org.jetbrains.jet.completion.handlers; + +import com.intellij.codeInsight.completion.LightCompletionTestCase; +import org.jetbrains.jet.plugin.PluginTestCaseBase; + +import java.io.File; + +/** + * @author Nikolay Krasko + */ +public class FunctionsHandlerTest extends LightCompletionTestCase { + + public void testNoParamsFunction() { + configureByFile("NoParamsFunction.kt"); + checkResultByFile("NoParamsFunction.kt.after"); + } + + public void testFunctionWithParams() { + configureByFile("ParamsFunction.kt"); + checkResultByFile("ParamsFunction.kt.after"); + } + + @Override + protected String getTestDataPath() { + return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() + + File.separator; + } +} diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/KeywordsHandlerTest.java b/idea/tests/org/jetbrains/jet/completion/handlers/KeywordsHandlerTest.java new file mode 100644 index 00000000000..4b6193b2549 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/completion/handlers/KeywordsHandlerTest.java @@ -0,0 +1,31 @@ +package org.jetbrains.jet.completion.handlers; + +import com.intellij.codeInsight.completion.LightCompletionTestCase; +import org.jetbrains.jet.plugin.PluginTestCaseBase; + +import java.io.File; +import java.io.IOException; + +/** + * @author Nikolay Krasko + */ +public class KeywordsHandlerTest extends LightCompletionTestCase { + + public void testSpaceAfter() throws IOException { + configureFromFileText("Test.kt", "protecte"); + complete(); + checkResultByText("protected "); + } + + public void testNoSpaceAfter() throws IOException { + configureFromFileText("Test.kt", "nul"); + complete(); + checkResultByText("null"); + } + + @Override + protected String getTestDataPath() { + return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() + + File.separator; + } +} From 6889a35fb892f314a78bec53b29bc82baff01a14 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Mon, 12 Dec 2011 13:21:47 +0200 Subject: [PATCH 04/23] no outer type info --- .../jet/codegen/ExpressionCodegen.java | 2 +- stdlib/src/jet/runtime/ArrayIterator.java | 2 +- stdlib/src/jet/typeinfo/TypeInfo.java | 66 +++++-------------- 3 files changed, 19 insertions(+), 51 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index d0644e6bd5a..9eef892f33e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -2609,7 +2609,7 @@ If finally block is present, its last expression is the value of try expression. v.getfield(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;"); } else { - v.load(1, TYPE_OBJECT); + v.load(((ConstructorFrameMap)myFrameMap).getTypeInfoIndex(), TYPE_OBJECT); } } else { diff --git a/stdlib/src/jet/runtime/ArrayIterator.java b/stdlib/src/jet/runtime/ArrayIterator.java index 7626820a6b6..0b05941e507 100644 --- a/stdlib/src/jet/runtime/ArrayIterator.java +++ b/stdlib/src/jet/runtime/ArrayIterator.java @@ -37,7 +37,7 @@ public abstract class ArrayIterator implements Iterator, JetObject { @Override public TypeInfo getTypeInfo() { - return TypeInfo.getTypeInfo(GenericIterator.class, false, null, new TypeInfoProjection[] {(TypeInfoProjection) elementTypeInfo}); + return TypeInfo.getTypeInfo(GenericIterator.class, false, new TypeInfoProjection[] {(TypeInfoProjection) elementTypeInfo}); } @Override diff --git a/stdlib/src/jet/typeinfo/TypeInfo.java b/stdlib/src/jet/typeinfo/TypeInfo.java index 32db06ff044..a5ad5850ebe 100644 --- a/stdlib/src/jet/typeinfo/TypeInfo.java +++ b/stdlib/src/jet/typeinfo/TypeInfo.java @@ -79,14 +79,6 @@ public abstract class TypeInfo implements JetObject { return new TypeInfoImpl(klazz, nullable); } - public static TypeInfo getTypeInfo(Class klazz, boolean nullable, TypeInfo outerTypeInfo) { - return new TypeInfoImpl(klazz, nullable, outerTypeInfo); - } - - public static TypeInfo getTypeInfo(Class klazz, boolean nullable, TypeInfo outerTypeInfo, TypeInfoProjection[] projections) { - return new TypeInfoImpl(klazz, nullable, outerTypeInfo, projections); - } - public static TypeInfo getTypeInfo(Class klazz, boolean nullable, TypeInfoProjection[] projections) { return new TypeInfoImpl(klazz, nullable, projections); } @@ -99,15 +91,13 @@ public abstract class TypeInfo implements JetObject { public abstract int getProjectionCount(); - public abstract TypeInfo getOuterTypeInfo(); - public abstract TypeInfoProjection getProjection(int index); public abstract TypeInfo getArgumentType(Class klass, int index); protected abstract TypeInfo substitute(List myVars); - protected abstract TypeInfo substitute(TypeInfo outer, TypeInfoProjection[] projections); + protected abstract TypeInfo substitute(TypeInfoProjection[] projections); private static class TypeInfoVar extends TypeInfo { final int varIndex; @@ -151,11 +141,6 @@ public abstract class TypeInfo implements JetObject { return 0; } - @Override - public TypeInfo getOuterTypeInfo() { - return null; - } - @Override public TypeInfoProjection getProjection(int index) { throw new UnsupportedOperationException("Abstract TypeInfo"); @@ -172,7 +157,7 @@ public abstract class TypeInfo implements JetObject { } @Override - protected TypeInfo substitute(TypeInfo outer, TypeInfoProjection[] projections) { + protected TypeInfo substitute(TypeInfoProjection[] projections) { return projections[varIndex].getType(); } @@ -197,22 +182,12 @@ public abstract class TypeInfo implements JetObject { private final Signature signature; private final boolean nullable; private final TypeInfoProjection[] projections; - private final TypeInfo outerTypeInfo; private TypeInfoImpl(Class theClass, boolean nullable) { - this(theClass, nullable, null, EMPTY); - } - - private TypeInfoImpl(Class theClass, boolean nullable, TypeInfo outerTypeInfo) { - this(theClass, nullable, outerTypeInfo, EMPTY); + this(theClass, nullable, EMPTY); } private TypeInfoImpl(Class theClass, boolean nullable, TypeInfoProjection[] projections) { - this(theClass, nullable, null, projections); - } - - private TypeInfoImpl(Class theClass, boolean nullable, TypeInfo outerTypeInfo, TypeInfoProjection[] projections) { - this.outerTypeInfo = outerTypeInfo; this.signature = Parser.parse(theClass); this.nullable = nullable; this.projections = projections; @@ -252,7 +227,7 @@ public abstract class TypeInfo implements JetObject { if(klass == this.signature.klazz) return projections[index].getType(); else { - return getSuperTypeInfo(klass).substitute(outerTypeInfo, projections).getArgumentType(klass, index); + return getSuperTypeInfo(klass).substitute(projections).getArgumentType(klass, index); } } @@ -288,14 +263,14 @@ public abstract class TypeInfo implements JetObject { } @Override - protected TypeInfo substitute(TypeInfo outer, TypeInfoProjection[] prj) { + protected TypeInfo substitute(TypeInfoProjection[] prj) { if(projections.length == 0) return new TypeInfoImpl(signature.klazz, nullable, EMPTY); else { TypeInfoProjection [] proj = new TypeInfoProjection[projections.length]; for(int i = 0; i != proj.length; ++i) { final int finalI = i; - final TypeInfo substitute = projections[finalI].getType().substitute(outer, prj); + final TypeInfo substitute = projections[finalI].getType().substitute(prj); proj[i] = new TypeInfoProjection(){ @Override @@ -364,11 +339,6 @@ public abstract class TypeInfo implements JetObject { return projections.length; } - @Override - public TypeInfo getOuterTypeInfo() { - return outerTypeInfo; - } - @Override public final String toString() { StringBuilder sb = new StringBuilder().append(signature.klazz.getName()); @@ -420,7 +390,6 @@ public abstract class TypeInfo implements JetObject { } public static class Signature { - final Signature outer; final Class klazz; List variables; @@ -429,8 +398,7 @@ public abstract class TypeInfo implements JetObject { final HashMap superSignatures = new HashMap(); - public Signature(Signature outer, Class klazz) { - this.outer = outer; + public Signature(Class klazz) { this.klazz = klazz; } @@ -512,7 +480,7 @@ public abstract class TypeInfo implements JetObject { if(value != null) { Parser parser = new Parser(value, klass.getClassLoader()); Class enclosingClass = klass.getEnclosingClass(); - Signature signature = new Signature(parse(enclosingClass), klass); + Signature signature = new Signature(klass); map.put(klass, signature); parser.parseVars(signature); parser.parseTypes(signature); @@ -527,7 +495,7 @@ public abstract class TypeInfo implements JetObject { // todo complete impl java.lang.reflect.Type genericSuperclass = klass.getGenericSuperclass(); - Signature signature = new Signature(parse(klass.getEnclosingClass()), klass); + Signature signature = new Signature(klass); TypeVariable[] typeParameters = klass.getTypeParameters(); if(typeParameters == null || typeParameters.length == 0) { @@ -692,14 +660,14 @@ public abstract class TypeInfo implements JetObject { if(klazz.equals(signature.klazz.getName())) return new TypeInfoVar(signature, nullable, signature.varNames.get(name)); else { - Signature sig = signature; - while(!klazz.equals(sig.klazz.getName())) { - sig = sig.outer; - if(sig == null) - throw new IllegalStateException(); - } +// Signature sig = signature; +// while(!klazz.equals(sig.klazz.getName())) { +// sig = sig.outer; +// if(sig == null) +// throw new IllegalStateException(); +// } - return new TypeInfoVar(sig, nullable, sig.varNames.get(name)); + throw new UnsupportedOperationException("outer type info does not supported"); } } @@ -726,7 +694,7 @@ public abstract class TypeInfo implements JetObject { private static class ArraySignature extends Signature { public ArraySignature(Class klass) { - super(null, klass); + super(klass); variables = new LinkedList(); varNames = new HashMap(); varNames.put("T", 0); From 3d918ba7e5fa121cee10bcd075ef33d57516ab83 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 12 Dec 2011 17:37:42 +0400 Subject: [PATCH 05/23] Docs --- .../org/jetbrains/jet/lang/resolve/calls/ResolvedCall.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCall.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCall.java index 521e7063eba..f5545f22ddb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCall.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolvedCall.java @@ -13,11 +13,11 @@ import java.util.Map; * @author abreslav */ public interface ResolvedCall { - /** 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(); From c45d08b7e5405e68370a16ce835595f578bb55d6 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Mon, 12 Dec 2011 16:21:02 +0200 Subject: [PATCH 06/23] fix for KT-796/797 candidate/resultingDescriptor misuse --- .../src/org/jetbrains/jet/codegen/ExpressionCodegen.java | 2 +- compiler/testData/codegen/regressions/kt796_797.jet | 8 ++++++++ compiler/tests/org/jetbrains/jet/codegen/VarArgTest.java | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/codegen/regressions/kt796_797.jet diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 9eef892f33e..c9374b6dfa7 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -2199,7 +2199,7 @@ public class ExpressionCodegen extends JetVisitor { if(getterDescriptor.getReceiverParameter().exists()) { index++; } - for (TypeParameterDescriptor typeParameterDescriptor : getterDescriptor.getTypeParameters()) { + for (TypeParameterDescriptor typeParameterDescriptor : resolvedGetCall.getCandidateDescriptor().getTypeParameters()) { if(typeParameterDescriptor.isReified()) { generateTypeInfo(resolvedGetCall.getTypeArguments().get(typeParameterDescriptor), null); index++; diff --git a/compiler/testData/codegen/regressions/kt796_797.jet b/compiler/testData/codegen/regressions/kt796_797.jet new file mode 100644 index 00000000000..03ae120b510 --- /dev/null +++ b/compiler/testData/codegen/regressions/kt796_797.jet @@ -0,0 +1,8 @@ +fun Array?.get(i : Int?) = this.sure().get(i.sure()) +fun array(vararg t : T) : Array = t + +fun box() : String { + val a : Array? = array("Str", "Str2") + val i : Int? = 1 + return if(a[i] == "Str2") "OK" else "fail" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/VarArgTest.java b/compiler/tests/org/jetbrains/jet/codegen/VarArgTest.java index e08b515771c..4a68f35e678 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/VarArgTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/VarArgTest.java @@ -74,4 +74,8 @@ public class VarArgTest extends CodegenTestCase { createEnvironmentWithFullJdk(); blackBoxFile("regressions/kt581.jet"); } + + public void testKt797() { + blackBoxFile("regressions/kt796_797.jet"); + } } From 226d1577051fd297152ad983e1f0f52291ae9618 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 12 Dec 2011 19:20:05 +0400 Subject: [PATCH 07/23] add one more condition to ErrorUtils.isError approved by Andrey Breslav --- .../frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java index 1c77b65f443..ee76f1ed2e9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java @@ -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 { From 9f87ea37a8f062cd05176468e5779a44e7ef9caf Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Mon, 12 Dec 2011 19:33:22 +0400 Subject: [PATCH 08/23] introduce jet/JetObject class name constant --- .../src/org/jetbrains/jet/codegen/ExpressionCodegen.java | 7 ++++--- .../jetbrains/jet/codegen/ImplementationBodyCodegen.java | 3 ++- .../jetbrains/jet/codegen/intrinsics/ValueTypeInfo.java | 3 ++- .../src/org/jetbrains/jet/lang/resolve/StdlibNames.java | 4 ++++ 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index c9374b6dfa7..0e81f301460 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -12,6 +12,7 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.StdlibNames; import org.jetbrains.jet.lang.resolve.calls.*; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor; @@ -2618,16 +2619,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(StdlibNames.JET_OBJECT_TYPE.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); } } else { v.load(0, TYPE_OBJECT); while(descriptor != containingDeclaration) { descriptor = CodegenUtil.getOuterClassDescriptor(descriptor); - v.invokeinterface("jet/JetObject", "getOuterObject", "()Ljet/JetObject;"); + v.invokeinterface(StdlibNames.JET_OBJECT_TYPE.getInternalName(), "getOuterObject", "()Ljet/JetObject;"); } - v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); + v.invokeinterface(StdlibNames.JET_OBJECT_TYPE.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); } v.aconst(ownerType); v.iconst(typeParameterDescriptor.getIndex()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index a637350f361..5ae78f4a284 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -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.StdlibNames; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeProjection; @@ -59,7 +60,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { getSuperClass(); List interfaces = new ArrayList(); - interfaces.add("jet/JetObject"); + interfaces.add(StdlibNames.JET_OBJECT_TYPE.getInternalName()); interfaces.addAll(getSuperInterfaces(myClass)); boolean isAbstract = false; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ValueTypeInfo.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ValueTypeInfo.java index 3c9c43d97f7..c604a291d3e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ValueTypeInfo.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ValueTypeInfo.java @@ -5,6 +5,7 @@ import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.JetTypeMapper; import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.resolve.StdlibNames; import org.objectweb.asm.Type; import org.objectweb.asm.commons.InstructionAdapter; @@ -17,7 +18,7 @@ public class ValueTypeInfo implements IntrinsicMethod { @Override public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { codegen.gen(arguments.get(0), JetTypeMapper.TYPE_JET_OBJECT); - v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); + v.invokeinterface(StdlibNames.JET_OBJECT_TYPE.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); return StackValue.onStack(JetTypeMapper.TYPE_TYPEINFO); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java index fcc779f5c99..aaad7538e0f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java @@ -29,4 +29,8 @@ public class StdlibNames { public static final String JET_METHOD_NULLABLE_RETURN_TYPE_FIELD = "nullableReturnType"; + + public static final Type JET_OBJECT_TYPE = Type.getObjectType("jet/JetObject"); + public static final String JET_OBJECT_CLASS = "jet.JetObject"; + public static final String JET_OBJECT_DESCRIPTOR = "Ljet/JetObject;"; } From 6a8e53c3c67bae8d741a897fe6868447e61d34d2 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 12 Dec 2011 20:54:55 +0400 Subject: [PATCH 09/23] Fixing errors after merge. --- .../jet/plugin/references/JetSimpleNameReference.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java index 54e27ce690f..7224322b46e 100644 --- a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java +++ b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java @@ -17,10 +17,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.calls.inference.ConstraintResolutionListener; -import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem; -import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl; -import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution; +import org.jetbrains.jet.lang.resolve.calls.inference.*; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; @@ -34,6 +31,8 @@ import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.List; import java.util.Set; +import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintType.RECEIVER; + /** * @author yole */ @@ -202,7 +201,7 @@ class JetSimpleNameReference extends JetPsiReference { ReceiverDescriptor receiverParameter = receiverArgument.getReceiverParameter(); if (expectedReceiver.exists() && receiverParameter.exists()) { - constraintSystem.addSubtypingConstraint(expectedReceiver.getType(), receiverParameter.getType()); + constraintSystem.addSubtypingConstraint(RECEIVER.assertSubtyping(expectedReceiver.getType(), receiverParameter.getType())); } else if (expectedReceiver.exists() || receiverParameter.exists()) { // Only one of receivers exist From 7f0de53cfaeb939f6f0221bdd415358a384bfec8 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 12 Dec 2011 20:55:16 +0400 Subject: [PATCH 10/23] Debug output removed --- .../org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java index 94240f21b34..8c82fd11367 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java @@ -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(); } From bb00b35e3fc304725382432000033247b55ce0ac Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Tue, 13 Dec 2011 09:46:17 +0200 Subject: [PATCH 11/23] asm Type constants moved --- .../jet/codegen/ExpressionCodegen.java | 7 +++---- .../jet/codegen/FunctionCodegen.java | 2 +- .../codegen/ImplementationBodyCodegen.java | 3 +-- .../jetbrains/jet/codegen/JetTypeMapper.java | 3 +++ .../jet/codegen/intrinsics/ValueTypeInfo.java | 3 +-- .../jet/lang/resolve/StdlibNames.java | 21 +++++++++---------- 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 0e81f301460..b8628fbc7c0 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -12,7 +12,6 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.StdlibNames; import org.jetbrains.jet.lang.resolve.calls.*; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor; @@ -2619,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(StdlibNames.JET_OBJECT_TYPE.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); + v.invokeinterface(TYPE_JET_OBJECT.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); } } else { v.load(0, TYPE_OBJECT); while(descriptor != containingDeclaration) { descriptor = CodegenUtil.getOuterClassDescriptor(descriptor); - v.invokeinterface(StdlibNames.JET_OBJECT_TYPE.getInternalName(), "getOuterObject", "()Ljet/JetObject;"); + v.invokeinterface(TYPE_JET_OBJECT.getInternalName(), "getOuterObject", "()Ljet/JetObject;"); } - v.invokeinterface(StdlibNames.JET_OBJECT_TYPE.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); + v.invokeinterface(TYPE_JET_OBJECT.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); } v.aconst(ownerType); v.iconst(typeParameterDescriptor.getIndex()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 24918f4c652..4edd7db34a4 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -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); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 5ae78f4a284..0af0a1ef2e8 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -6,7 +6,6 @@ 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.StdlibNames; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeProjection; @@ -60,7 +59,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { getSuperClass(); List interfaces = new ArrayList(); - interfaces.add(StdlibNames.JET_OBJECT_TYPE.getInternalName()); + interfaces.add(JetTypeMapper.TYPE_JET_OBJECT.getInternalName()); interfaces.addAll(getSuperInterfaces(myClass)); boolean isAbstract = false; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 0e62029178e..7fa09823a80 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -57,6 +57,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/JetParameter"); + 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; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ValueTypeInfo.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ValueTypeInfo.java index c604a291d3e..73a23e605e8 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ValueTypeInfo.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/ValueTypeInfo.java @@ -5,7 +5,6 @@ import org.jetbrains.jet.codegen.ExpressionCodegen; import org.jetbrains.jet.codegen.JetTypeMapper; import org.jetbrains.jet.codegen.StackValue; import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.resolve.StdlibNames; import org.objectweb.asm.Type; import org.objectweb.asm.commons.InstructionAdapter; @@ -18,7 +17,7 @@ public class ValueTypeInfo implements IntrinsicMethod { @Override public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments, StackValue receiver) { codegen.gen(arguments.get(0), JetTypeMapper.TYPE_JET_OBJECT); - v.invokeinterface(StdlibNames.JET_OBJECT_TYPE.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); + v.invokeinterface(JetTypeMapper.TYPE_JET_OBJECT.getInternalName(), "getTypeInfo", "()Ljet/typeinfo/TypeInfo;"); return StackValue.onStack(JetTypeMapper.TYPE_TYPEINFO); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java index aaad7538e0f..5bade930733 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java @@ -6,31 +6,30 @@ 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"; - - - public static final Type JET_OBJECT_TYPE = Type.getObjectType("jet/JetObject"); + + public static final String JET_OBJECT_CLASS = "jet.JetObject"; public static final String JET_OBJECT_DESCRIPTOR = "Ljet/JetObject;"; + + private StdlibNames() { + } } From 54336a285dd1efe769a450b1afe95bddbdb350fd Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 13 Dec 2011 12:38:37 +0400 Subject: [PATCH 12/23] Minor refactoring while working on prioritized constraints --- .../resolve/calls/ResolutionDebugInfo.java | 6 +- .../resolve/calls/inference/BoundsOwner.java | 16 + .../ConstraintResolutionListener.java | 16 +- .../calls/inference/ConstraintSystemImpl.java | 32 +- .../ConstraintSystemWithPriorities.java | 470 ++++++++++++++++++ .../DebugConstraintResolutionListener.java | 22 +- .../PrintingConstraintResolutionListener.java | 22 +- .../resolve/calls/inference/TypeValue.java | 82 +++ .../jet/lang/types/TypeSubstitutor.java | 28 +- .../lang/types/checker/JetTypeChecker.java | 4 +- .../lang/types/checker/TypingConstraints.java | 4 +- .../resolvewindow/ResolveToolwindow.java | 15 +- 12 files changed, 659 insertions(+), 58 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/BoundsOwner.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeValue.java diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java index 59968bae9a4..d254ac771e4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionDebugInfo.java @@ -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> RESULT = Slices.createSimpleSlice(); public static final WritableSlice ERRORS = Slices.createSimpleSlice(); public static final WritableSlice LOG = Slices.createSimpleSlice(); - public static final WritableSlice> BOUNDS_FOR_UNKNOWNS = Slices.createSimpleSlice(); - public static final WritableSlice> BOUNDS_FOR_KNOWNS = Slices.createSimpleSlice(); + public static final WritableSlice> BOUNDS_FOR_UNKNOWNS = Slices.createSimpleSlice(); + public static final WritableSlice> BOUNDS_FOR_KNOWNS = Slices.createSimpleSlice(); public static final WritableSlice SOLUTION = Slices.createSimpleSlice(); public static final WritableSlice> UNKNOWNS = Slices.createSimpleSlice(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/BoundsOwner.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/BoundsOwner.java new file mode 100644 index 00000000000..512b1437d77 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/BoundsOwner.java @@ -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 getUpperBounds(); + + @NotNull + Set getLowerBounds(); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintResolutionListener.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintResolutionListener.java index 6cbf129fb73..eda1db1082d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintResolutionListener.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintResolutionListener.java @@ -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 typeParameterDescriptors); - void log(Object message); - void error(Object message); + void log(Object... messageFragments); + void error(Object... messageFragments); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java index 931371e5f3e..cb68fc94d2c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java @@ -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); @@ -389,7 +389,7 @@ public class ConstraintSystemImpl implements ConstraintSystem { } 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,7 +409,7 @@ 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"); } } @@ -443,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 @@ -477,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); } } } @@ -542,7 +542,7 @@ public class ConstraintSystemImpl implements ConstraintSystem { TypeProjection typeProjection = new TypeProjection(getValue(descriptor)); - listener.log(descriptor + " |-> " + typeProjection); + listener.log(descriptor, " |-> ", typeProjection); return typeProjection; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java new file mode 100644 index 00000000000..fd408957971 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemWithPriorities.java @@ -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 SUBTYPING_CONSTRAINT_ORDER = new Comparator() { + @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 knownTypes = Maps.newLinkedHashMap(); // linked - for easier debugging + private final Map unknownTypes = Maps.newLinkedHashMap(); // linked - for easier debugging + private final Set unsolvedUnknowns = Sets.newLinkedHashSet(); // linked - for easier debugging + private final PriorityQueue constraintQueue = new PriorityQueue(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 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 <: List +// for (Map.Entry 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 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 visited) { + if (!visited.add(current)) { + return; + } + + for (TypeValue upperBound : Sets.newHashSet(current.getUpperBounds())) { + if (upperBound.isKnown()) { + continue; + } + transitiveClosure(upperBound, visited); + Set 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; + } + } + +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/DebugConstraintResolutionListener.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/DebugConstraintResolutionListener.java index b6e5731f7cf..52edf22c3f0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/DebugConstraintResolutionListener.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/DebugConstraintResolutionListener.java @@ -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 map = debugInfo.get(BOUNDS_FOR_UNKNOWNS); + Map 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 map = debugInfo.get(BOUNDS_FOR_KNOWNS); + Map 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"); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/PrintingConstraintResolutionListener.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/PrintingConstraintResolutionListener.java index 3fe1a169eeb..ac3e3528b8d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/PrintingConstraintResolutionListener.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/PrintingConstraintResolutionListener.java @@ -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); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeValue.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeValue.java new file mode 100644 index 00000000000..837036e003f --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeValue.java @@ -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 upperBounds = Sets.newLinkedHashSet(); + private final Set 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 getUpperBounds() { + return upperBounds; + } + + @Override + @NotNull + public Set 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; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java index e0e2a35b24d..55c861b18c8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java @@ -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 typeParameterDescriptors, JetType type) { + final Set 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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/JetTypeChecker.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/JetTypeChecker.java index 7147158c66c..691966d302d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/JetTypeChecker.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/JetTypeChecker.java @@ -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); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/TypingConstraints.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/TypingConstraints.java index 0276f816184..754bff7f5f8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/TypingConstraints.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/checker/TypingConstraints.java @@ -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); } diff --git a/idea/src/org/jetbrains/jet/plugin/internal/resolvewindow/ResolveToolwindow.java b/idea/src/org/jetbrains/jet/plugin/internal/resolvewindow/ResolveToolwindow.java index 94a47c390c7..4b9a6fbc102 100644 --- a/idea/src/org/jetbrains/jet/plugin/internal/resolvewindow/ResolveToolwindow.java +++ b/idea/src/org/jetbrains/jet/plugin/internal/resolvewindow/ResolveToolwindow.java @@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.ResolvedValueArgument; +import org.jetbrains.jet.lang.resolve.calls.inference.BoundsOwner; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; @@ -190,9 +191,9 @@ public class ResolveToolwindow extends JPanel { result.append("Log: \n").append(log).append(bar); } - Map knowns = debugInfo.get(BOUNDS_FOR_KNOWNS); + Map knowns = debugInfo.get(BOUNDS_FOR_KNOWNS); renderMap(knowns, result); - Map unknowns = debugInfo.get(BOUNDS_FOR_UNKNOWNS); + Map unknowns = debugInfo.get(BOUNDS_FOR_UNKNOWNS); renderMap(unknowns, result); result.append(bar); @@ -205,17 +206,17 @@ public class ResolveToolwindow extends JPanel { return result.toString(); } - private void renderMap(Map map, StringBuilder builder) { + private void renderMap(Map map, StringBuilder builder) { if (map == null) return; - for (Map.Entry entry : map.entrySet()) { + for (Map.Entry entry : map.entrySet()) { K key = entry.getKey(); - ConstraintSystemImpl.TypeValue typeValue = entry.getValue(); + BoundsOwner typeValue = entry.getValue(); builder.append("Bounds for ").append(key).append("\n"); - for (ConstraintSystemImpl.TypeValue bound : typeValue.getLowerBounds()) { + for (BoundsOwner bound : typeValue.getLowerBounds()) { builder.append(" >: ").append(bound).append("\n"); } - for (ConstraintSystemImpl.TypeValue bound : typeValue.getUpperBounds()) { + for (BoundsOwner bound : typeValue.getUpperBounds()) { builder.append(" <: ").append(bound).append("\n"); } } From 9d0a2c7243b8a8497780467610678543d608dcd3 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Tue, 13 Dec 2011 13:26:42 +0200 Subject: [PATCH 13/23] (slightly modified) contribution of Sergey Ignatov of methods for strings and arrays --- stdlib/ktSrc/Arrays.kt | 21 ++++++++++++++ stdlib/ktSrc/JavaUtil.kt | 14 ++++------ stdlib/ktSrc/String.kt | 59 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 stdlib/ktSrc/Arrays.kt create mode 100644 stdlib/ktSrc/String.kt diff --git a/stdlib/ktSrc/Arrays.kt b/stdlib/ktSrc/Arrays.kt new file mode 100644 index 00000000000..c8ddc2b5c70 --- /dev/null +++ b/stdlib/ktSrc/Arrays.kt @@ -0,0 +1,21 @@ +namespace std + +// Array "constructor" +inline fun array(vararg t : T) : Array = t + +// "constructors" for primitive types array +inline fun doubleArray(vararg content : Double) = content + +inline fun floatArray(vararg content : Float) = content + +inline fun longArray(vararg content : Long) = content + +inline fun intArray(vararg content : Int) = content + +inline fun charArray(vararg content : Char) = content + +inline fun shortArray(vararg content : Short) = content + +inline fun byteArray(vararg content : Byte) = content + +inline fun booleanArray(vararg content : Boolean) = content diff --git a/stdlib/ktSrc/JavaUtil.kt b/stdlib/ktSrc/JavaUtil.kt index ba3c74b8adb..a75df8656d9 100644 --- a/stdlib/ktSrc/JavaUtil.kt +++ b/stdlib/ktSrc/JavaUtil.kt @@ -1,11 +1,9 @@ -namespace std +namespace std.util -namespace util { - import java.util.* +import java.util.* - val Collection<*>.size : Int - get() = size() +val Collection<*>.size : Int + get() = size() - val Collection<*>.empty : Boolean - get() = isEmpty() -} \ No newline at end of file +val Collection<*>.empty : Boolean + get() = isEmpty() diff --git a/stdlib/ktSrc/String.kt b/stdlib/ktSrc/String.kt new file mode 100644 index 00000000000..22e3c9864d9 --- /dev/null +++ b/stdlib/ktSrc/String.kt @@ -0,0 +1,59 @@ +namespace std + +inline fun T?.plus(str: String?) : String { return toString() + str } + +inline fun String.lastIndexOf(s: String) = (this as java.lang.String).lastIndexOf(s) + +inline fun String.lastIndexOf(s: Char) = (this as java.lang.String).lastIndexOf(s.toString()) } + +inline fun String.indexOf(s : String) = (this as java.lang.String).indexOf(s) + +inline fun String.indexOf(p0 : String, p1 : Int) = (this as java.lang.String).indexOf(p0, p1) + +inline fun String.replaceAll(s: String, s1 : String) = (this as java.lang.String).replaceAll(s, s1).sure() + +inline fun String.trim() = (this as java.lang.String).trim().sure() + +inline fun String.toUpperCase() = (this as java.lang.String).toUpperCase().sure() + +inline fun String.toLowerCase() = (this as java.lang.String).toLowerCase().sure() + +inline fun String.length() = (this as java.lang.String).length() + +inline fun String.getBytes() = (this as java.lang.String).getBytes().sure() + +inline fun String.toCharArray() = (this as java.lang.String).toCharArray().sure() + +inline fun String.format(s : String, vararg objects : Any?) = java.lang.String.format(s, objects).sure() + +inline fun String.split(s : String) = (this as java.lang.String).split(s) + +inline fun String.substring(i : Int) = (this as java.lang.String).substring(i).sure() + +inline fun String.substring(i0 : Int, i1 : Int) = (this as java.lang.String).substring(i0, i1).sure() + +inline val String.size : Int + get() = length() + +inline val String.bytes : ByteArray + get() = getBytes() + +// "constructors" for String + +inline fun String(bytes : ByteArray, i : Int, i1 : Int, s : String) = java.lang.String(bytes, i, i1, s) as String + +inline fun String(bytes : ByteArray, i : Int, i1 : Int, charset : java.nio.charset.Charset) = java.lang.String(bytes, i, i1, charset) as String + +inline fun String(bytes : ByteArray, s : String?) = java.lang.String(bytes, s) as String + +inline fun String(bytes : ByteArray, charset : java.nio.charset.Charset) = java.lang.String(bytes, charset) as String + +inline fun String(bytes : ByteArray, i : Int, i1 : Int) = java.lang.String(bytes, i, i1) as String + +inline fun String(bytes : ByteArray) = java.lang.String(bytes) as String + +inline fun String(chars : CharArray) = java.lang.String(chars) as String + +inline fun String(stringBuffer : java.lang.StringBuffer) = java.lang.String(stringBuffer) as String + +inline fun String(stringBuilder : java.lang.StringBuilder) = java.lang.String(stringBuilder) as String From c4fd2e564fcd487af3a6bbaa86abed737b9e41d5 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Tue, 13 Dec 2011 16:15:43 +0400 Subject: [PATCH 14/23] 1. namespace class should not be accessible from Kotlin despite the fact we don't have kotlin class descriptor for it. 2. testdata is corrected due to the fact frontend has wrong qualified name in trace for root namespace --- .../org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java | 3 +++ idea/testData/completion/basic/ExtendClassName.kt | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java index 8c82fd11367..098b8ec6bdf 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java @@ -77,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()) { @@ -84,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) { diff --git a/idea/testData/completion/basic/ExtendClassName.kt b/idea/testData/completion/basic/ExtendClassName.kt index 47daf28eff9..e25d7e3528f 100644 --- a/idea/testData/completion/basic/ExtendClassName.kt +++ b/idea/testData/completion/basic/ExtendClassName.kt @@ -1,3 +1,5 @@ +namespace foo + open class MySecondClass() { } @@ -10,4 +12,4 @@ class A() : My { } } -// EXIST: MySecondClass, MyFirstClass \ No newline at end of file +// EXIST: MySecondClass, MyFirstClass From 739f3b2a36919c29cfcd40d9e1c8917e391b542d Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 13 Dec 2011 17:38:57 +0400 Subject: [PATCH 15/23] Root namespace naming problems fixed. Failing test reverted to the initial state --- .../src/org/jetbrains/jet/lang/psi/JetPsiUtil.java | 8 ++++++-- idea/testData/completion/basic/ExtendClassName.kt | 2 -- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java index 2a7c167d0fb..47cdc05dfdf 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java @@ -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(); + } } diff --git a/idea/testData/completion/basic/ExtendClassName.kt b/idea/testData/completion/basic/ExtendClassName.kt index e25d7e3528f..c4ae4f6575d 100644 --- a/idea/testData/completion/basic/ExtendClassName.kt +++ b/idea/testData/completion/basic/ExtendClassName.kt @@ -1,5 +1,3 @@ -namespace foo - open class MySecondClass() { } From ff055399a7e7009334e6d22de38bc4ad58e224e5 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Tue, 13 Dec 2011 15:45:18 +0200 Subject: [PATCH 16/23] house keeping --- .../jet/codegen/NamespaceCodegen.java | 4 +- .../testData/codegen/inputStreamIterator.jet | 1 + stdlib/ktSrc/Arrays.kt | 8 ++ .../ktSrc/{StandardLibrary.kt => JavaIo.kt} | 75 +++++++++---------- stdlib/ktSrc/String.kt | 7 +- 5 files changed, 51 insertions(+), 44 deletions(-) rename stdlib/ktSrc/{StandardLibrary.kt => JavaIo.kt} (86%) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index 9a6f2c5210a..5e8b92a7849 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -2,6 +2,7 @@ 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; @@ -43,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); diff --git a/compiler/testData/codegen/inputStreamIterator.jet b/compiler/testData/codegen/inputStreamIterator.jet index 7be02b077f2..85ff66b2ba7 100644 --- a/compiler/testData/codegen/inputStreamIterator.jet +++ b/compiler/testData/codegen/inputStreamIterator.jet @@ -1,3 +1,4 @@ +import std.* import std.io.* import java.io.* diff --git a/stdlib/ktSrc/Arrays.kt b/stdlib/ktSrc/Arrays.kt index c8ddc2b5c70..197cd1c236c 100644 --- a/stdlib/ktSrc/Arrays.kt +++ b/stdlib/ktSrc/Arrays.kt @@ -1,5 +1,7 @@ namespace std +import java.io.ByteArrayInputStream + // Array "constructor" inline fun array(vararg t : T) : Array = t @@ -19,3 +21,9 @@ inline fun shortArray(vararg content : Short) = content inline fun byteArray(vararg content : Byte) = content inline fun booleanArray(vararg content : Boolean) = content + +inline val ByteArray.inputStream : ByteArrayInputStream + get() = ByteArrayInputStream(this) + +inline fun ByteArray.inputStream(offset: Int, length: Int) = ByteArrayInputStream(this, offset, length) + diff --git a/stdlib/ktSrc/StandardLibrary.kt b/stdlib/ktSrc/JavaIo.kt similarity index 86% rename from stdlib/ktSrc/StandardLibrary.kt rename to stdlib/ktSrc/JavaIo.kt index 999cecbad2c..020809cc19b 100644 --- a/stdlib/ktSrc/StandardLibrary.kt +++ b/stdlib/ktSrc/JavaIo.kt @@ -27,47 +27,6 @@ namespace io { inline fun println(message : CharArray) { System.out?.println(message) } inline fun println() { System.out?.println() } - val ByteArray.inputStream : ByteArrayInputStream - get() = ByteArrayInputStream(this) - -// inline fun ByteArray.inputStream(offset: Int, length: Int) = ByteArrayInputStream(this, offset, length) - - fun InputStream.iterator() : ByteIterator = - object: ByteIterator() { - override val hasNext : Boolean - get() = available() > 0 - - override fun nextByte() = read().byt - } - - val InputStream.buffered : BufferedInputStream - get() = if(this is BufferedInputStream) this else BufferedInputStream(this) - -// inline fun InputStream.buffered(bufferSize: Int) = BufferedInputStream(this, bufferSize) - - val InputStream.reader : InputStreamReader - get() = InputStreamReader(this) - - val InputStream.bufferedReader : BufferedReader - get() = BufferedReader(reader) - -/* - inline fun InputStream.reader(charset: Charset) : InputStreamReader = InputStreamReader(this, charset) - - inline fun InputStream.reader(charsetName: String) = InputStreamReader(this, charsetNme) - - inline fun InputStream.reader(charset: Charset) = InputStreamReader(this, charset) - - inline fun InputStream.reader(charsetDecoder: CharsetDecoder) = InputStreamReader(this, charsetDecoder) -*/ - -// val Reader.buffered : BufferedReader -// get() = if(this instanceof BufferedReader) this else BufferedReader(this) - -// inline fun Reader.buffered(bufferSize: Int) = BufferedReader(this, bufferSize) - -// val String.reader = StringReader(this) - private val stdin : BufferedReader = BufferedReader(InputStreamReader(object : InputStream() { override fun read() : Int { return System.`in`?.read() ?: -1 @@ -107,4 +66,38 @@ namespace io { })) fun readLine() : String? = stdin.readLine() + + fun InputStream.iterator() : ByteIterator = + object: ByteIterator() { + override val hasNext : Boolean + get() = available() > 0 + + override fun nextByte() = read().byt + } + + val InputStream.buffered : BufferedInputStream + get() = if(this is BufferedInputStream) this else BufferedInputStream(this) + + // inline fun InputStream.buffered(bufferSize: Int) = BufferedInputStream(this, bufferSize) + + val InputStream.reader : InputStreamReader + get() = InputStreamReader(this) + + val InputStream.bufferedReader : BufferedReader + get() = BufferedReader(reader) + + /* + inline fun InputStream.reader(charset: Charset) : InputStreamReader = InputStreamReader(this, charset) + + inline fun InputStream.reader(charsetName: String) = InputStreamReader(this, charsetNme) + + inline fun InputStream.reader(charset: Charset) = InputStreamReader(this, charset) + + inline fun InputStream.reader(charsetDecoder: CharsetDecoder) = InputStreamReader(this, charsetDecoder) + */ + + // val Reader.buffered : BufferedReader + // get() = if(this instanceof BufferedReader) this else BufferedReader(this) + + // inline fun Reader.buffered(bufferSize: Int) = BufferedReader(this, bufferSize) } \ No newline at end of file diff --git a/stdlib/ktSrc/String.kt b/stdlib/ktSrc/String.kt index 22e3c9864d9..4df7c099d29 100644 --- a/stdlib/ktSrc/String.kt +++ b/stdlib/ktSrc/String.kt @@ -1,5 +1,7 @@ namespace std +import java.io.StringReader + inline fun T?.plus(str: String?) : String { return toString() + str } inline fun String.lastIndexOf(s: String) = (this as java.lang.String).lastIndexOf(s) @@ -35,8 +37,8 @@ inline fun String.substring(i0 : Int, i1 : Int) = (this as java.lang.String).su inline val String.size : Int get() = length() -inline val String.bytes : ByteArray - get() = getBytes() +inline val String.reader : StringReader + get() = StringReader(this) // "constructors" for String @@ -57,3 +59,4 @@ inline fun String(chars : CharArray) = java.lang.String(chars) as String inline fun String(stringBuffer : java.lang.StringBuffer) = java.lang.String(stringBuffer) as String inline fun String(stringBuilder : java.lang.StringBuilder) = java.lang.String(stringBuilder) as String + From ac29a020e26df863568bfaaef7377e830d3fe7ab Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Tue, 13 Dec 2011 17:52:38 +0400 Subject: [PATCH 17/23] do not allow mapping of error type to JVM type --- .../backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 7fa09823a80..d98c928f379 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -248,6 +248,11 @@ public class JetTypeMapper { } 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"); From 3419df7d0c67cd1642b6ec6f675d78a321a0a9e0 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Tue, 13 Dec 2011 16:00:22 +0200 Subject: [PATCH 18/23] a bit more methods (previously broke compilation) --- stdlib/ktSrc/JavaIo.kt | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/stdlib/ktSrc/JavaIo.kt b/stdlib/ktSrc/JavaIo.kt index 020809cc19b..71ab785f556 100644 --- a/stdlib/ktSrc/JavaIo.kt +++ b/stdlib/ktSrc/JavaIo.kt @@ -65,7 +65,7 @@ namespace io { } })) - fun readLine() : String? = stdin.readLine() + inline fun readLine() : String? = stdin.readLine() fun InputStream.iterator() : ByteIterator = object: ByteIterator() { @@ -75,29 +75,25 @@ namespace io { override fun nextByte() = read().byt } - val InputStream.buffered : BufferedInputStream - get() = if(this is BufferedInputStream) this else BufferedInputStream(this) + inline fun InputStream.buffered(bufferSize: Int) = BufferedInputStream(this, bufferSize) - // inline fun InputStream.buffered(bufferSize: Int) = BufferedInputStream(this, bufferSize) - - val InputStream.reader : InputStreamReader + inline val InputStream.reader : InputStreamReader get() = InputStreamReader(this) - val InputStream.bufferedReader : BufferedReader + inline val InputStream.bufferedReader : BufferedReader get() = BufferedReader(reader) - /* inline fun InputStream.reader(charset: Charset) : InputStreamReader = InputStreamReader(this, charset) - inline fun InputStream.reader(charsetName: String) = InputStreamReader(this, charsetNme) - - inline fun InputStream.reader(charset: Charset) = InputStreamReader(this, charset) + inline fun InputStream.reader(charsetName: String) = InputStreamReader(this, charsetName) inline fun InputStream.reader(charsetDecoder: CharsetDecoder) = InputStreamReader(this, charsetDecoder) - */ - // val Reader.buffered : BufferedReader - // get() = if(this instanceof BufferedReader) this else BufferedReader(this) + inline val InputStream.buffered : BufferedInputStream + get() = if(this is BufferedInputStream) this else BufferedInputStream(this) - // inline fun Reader.buffered(bufferSize: Int) = BufferedReader(this, bufferSize) +// inline val Reader.buffered : BufferedReader +// get() = if(this is BufferedReader) this else BufferedReader(this) + + inline fun Reader.buffered(bufferSize: Int) = BufferedReader(this, bufferSize) } \ No newline at end of file From b1cf0ffcee7e48738a0ae8c6e51de81db415c1ba Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Tue, 13 Dec 2011 18:28:47 +0400 Subject: [PATCH 19/23] more class and method signatures, use writer wrapper (not yet complete) own writer will be used to write both java and kotlin signatures --- .../jet/codegen/BothSignatureWriter.java | 211 ++++++++++++++++++ .../codegen/ImplementationBodyCodegen.java | 110 +++++---- .../jetbrains/jet/codegen/JetTypeMapper.java | 154 ++++++++----- .../jet/codegen/JvmClassSignature.java | 36 +++ .../jet/lang/resolve/StdlibNames.java | 1 + .../class/ExtendsAbstractListT.java | 6 + .../class/ExtendsAbstractListT.kt | 1 + .../class/ImplementsListString.java | 7 + .../class/ImplementsListString.kt | 1 + .../class/ImplementsMapPP.java | 7 + .../class/ImplementsMapPP.kt | 1 + .../method/QExtendsListString.java | 8 + .../method/QExtendsListString.kt | 3 + .../method/QExtendsString.java | 8 + .../method/QExtendsString.kt | 1 + 15 files changed, 453 insertions(+), 102 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/JvmClassSignature.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/class/ExtendsAbstractListT.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/class/ExtendsAbstractListT.kt create mode 100644 compiler/testData/compileJavaAgainstKotlin/class/ImplementsListString.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/class/ImplementsListString.kt create mode 100644 compiler/testData/compileJavaAgainstKotlin/class/ImplementsMapPP.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/class/ImplementsMapPP.kt create mode 100644 compiler/testData/compileJavaAgainstKotlin/method/QExtendsListString.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/method/QExtendsListString.kt create mode 100644 compiler/testData/compileJavaAgainstKotlin/method/QExtendsString.java create mode 100644 compiler/testData/compileJavaAgainstKotlin/method/QExtendsString.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java b/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java new file mode 100644 index 00000000000..e63487fc198 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java @@ -0,0 +1,211 @@ +package org.jetbrains.jet.codegen; + +import org.jetbrains.annotations.Nullable; +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 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 visitors = new Stack(); + + 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; + } + +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 0af0a1ef2e8..7d8298b489a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -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.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 getSuperInterfaces(JetClassOrObject aClass) { - List delegationSpecifiers = aClass.getDelegationSpecifiers(); - Set superInterfaces = new LinkedHashSet(); - - 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 interfaces = new ArrayList(); - interfaces.add(JetTypeMapper.TYPE_JET_OBJECT.getInternalName()); - 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 superInterfaces; - @Nullable - private String genericSignature() { - List 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 superInterfacesLinkedHashSet = new LinkedHashSet(); + + BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS); + + + { // type parameters + List 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(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 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; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index d98c928f379..750d036d961 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -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.*; @@ -165,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; } @@ -226,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); } @@ -237,11 +234,11 @@ 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); @@ -260,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)) { @@ -284,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; @@ -299,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); @@ -308,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)); @@ -319,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) { @@ -391,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; @@ -456,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(); @@ -489,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 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) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JvmClassSignature.java b/compiler/backend/src/org/jetbrains/jet/codegen/JvmClassSignature.java new file mode 100644 index 00000000000..e866f873f8a --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JvmClassSignature.java @@ -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 interfaces; + private final String genericSignature; + + public JvmClassSignature(String name, String superclassName, List 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 getInterfaces() { + return interfaces; + } + + public String getGenericSignature() { + return genericSignature; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java index 5bade930733..3dde936fe39 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java @@ -27,6 +27,7 @@ public class StdlibNames { 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;"; diff --git a/compiler/testData/compileJavaAgainstKotlin/class/ExtendsAbstractListT.java b/compiler/testData/compileJavaAgainstKotlin/class/ExtendsAbstractListT.java new file mode 100644 index 00000000000..2d1e5d107fc --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/class/ExtendsAbstractListT.java @@ -0,0 +1,6 @@ +class ExtendsAbstractListT { + { + Mine mine = null; + java.util.List list = mine; + } +} diff --git a/compiler/testData/compileJavaAgainstKotlin/class/ExtendsAbstractListT.kt b/compiler/testData/compileJavaAgainstKotlin/class/ExtendsAbstractListT.kt new file mode 100644 index 00000000000..472c847fd89 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/class/ExtendsAbstractListT.kt @@ -0,0 +1 @@ +abstract class Mine() : java.util.AbstractList() diff --git a/compiler/testData/compileJavaAgainstKotlin/class/ImplementsListString.java b/compiler/testData/compileJavaAgainstKotlin/class/ImplementsListString.java new file mode 100644 index 00000000000..699606e6a43 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/class/ImplementsListString.java @@ -0,0 +1,7 @@ + +class PlainExtendsListString { + { + Mine mine = null; + java.util.List list = mine; + } +} diff --git a/compiler/testData/compileJavaAgainstKotlin/class/ImplementsListString.kt b/compiler/testData/compileJavaAgainstKotlin/class/ImplementsListString.kt new file mode 100644 index 00000000000..8de577c0bcc --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/class/ImplementsListString.kt @@ -0,0 +1 @@ +abstract class Mine : java.util.List diff --git a/compiler/testData/compileJavaAgainstKotlin/class/ImplementsMapPP.java b/compiler/testData/compileJavaAgainstKotlin/class/ImplementsMapPP.java new file mode 100644 index 00000000000..5664662764e --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/class/ImplementsMapPP.java @@ -0,0 +1,7 @@ + +class ImplementsMapPP { + { + Mine mine = null; + java.util.Map map = mine; + } +} diff --git a/compiler/testData/compileJavaAgainstKotlin/class/ImplementsMapPP.kt b/compiler/testData/compileJavaAgainstKotlin/class/ImplementsMapPP.kt new file mode 100644 index 00000000000..a973a76c33e --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/class/ImplementsMapPP.kt @@ -0,0 +1 @@ +abstract class Mine : java.util.Map diff --git a/compiler/testData/compileJavaAgainstKotlin/method/QExtendsListString.java b/compiler/testData/compileJavaAgainstKotlin/method/QExtendsListString.java new file mode 100644 index 00000000000..72b7170231a --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/method/QExtendsListString.java @@ -0,0 +1,8 @@ + +class Question { + // id2 is to prevent java type parameter type inference + static T id2(T p) { return p; } + { + java.util.List s = id2(namespace.id((jet.typeinfo.TypeInfo) null, null)); + } +} diff --git a/compiler/testData/compileJavaAgainstKotlin/method/QExtendsListString.kt b/compiler/testData/compileJavaAgainstKotlin/method/QExtendsListString.kt new file mode 100644 index 00000000000..40dc99ff079 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/method/QExtendsListString.kt @@ -0,0 +1,3 @@ +import java.util.List + +fun > id(p: P1) = p diff --git a/compiler/testData/compileJavaAgainstKotlin/method/QExtendsString.java b/compiler/testData/compileJavaAgainstKotlin/method/QExtendsString.java new file mode 100644 index 00000000000..f525b5923a5 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/method/QExtendsString.java @@ -0,0 +1,8 @@ + +class Question { + // id2 is to prevent java type parameter type inference + static T id2(T p) { return p; } + { + String s = id2(namespace.id((jet.typeinfo.TypeInfo) null, null)); + } +} diff --git a/compiler/testData/compileJavaAgainstKotlin/method/QExtendsString.kt b/compiler/testData/compileJavaAgainstKotlin/method/QExtendsString.kt new file mode 100644 index 00000000000..e360425de59 --- /dev/null +++ b/compiler/testData/compileJavaAgainstKotlin/method/QExtendsString.kt @@ -0,0 +1 @@ +fun id(p: T) = p From af9c364c5c91adbd4488def989eee3211324e323 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Tue, 13 Dec 2011 18:28:49 +0400 Subject: [PATCH 20/23] JetSignatureVisitor and subclasses --- .../jet/codegen/BothSignatureWriter.java | 4 + .../codegen/signature/JetSignatureReader.java | 161 ++++++++++++++ .../signature/JetSignatureVisitor.java | 141 ++++++++++++ .../codegen/signature/JetSignatureWriter.java | 201 ++++++++++++++++++ 4 files changed, 507 insertions(+) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/signature/JetSignatureReader.java create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/signature/JetSignatureVisitor.java create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/signature/JetSignatureWriter.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java b/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java index e63487fc198..f2cb8838b1d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java @@ -1,6 +1,7 @@ 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; @@ -29,6 +30,9 @@ public class BothSignatureWriter { private final SignatureWriter signatureWriter = new SignatureWriter(); private final SignatureVisitor signatureVisitor; + + private final JetSignatureWriter jetSignatureWriter = new JetSignatureWriter(); + private final Mode mode; public BothSignatureWriter(Mode mode) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/signature/JetSignatureReader.java b/compiler/backend/src/org/jetbrains/jet/codegen/signature/JetSignatureReader.java new file mode 100644 index 00000000000..6485efde6bf --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/signature/JetSignatureReader.java @@ -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; + } + } + } + } + } + } + + +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/signature/JetSignatureVisitor.java b/compiler/backend/src/org/jetbrains/jet/codegen/signature/JetSignatureVisitor.java new file mode 100644 index 00000000000..04e1319dd03 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/signature/JetSignatureVisitor.java @@ -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 + * void. + */ + 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(); +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/signature/JetSignatureWriter.java b/compiler/backend/src/org/jetbrains/jet/codegen/signature/JetSignatureWriter.java new file mode 100644 index 00000000000..b85d48b3ecc --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/signature/JetSignatureWriter.java @@ -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; + } +} From 676595036b29f0eec7729687a60a8c07f6f06b8f Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Tue, 13 Dec 2011 18:36:06 +0400 Subject: [PATCH 21/23] move StdlibNames to frontend.java module requested by Andrey Breslav --- .../backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java | 2 +- .../org/jetbrains/jet/codegen/ImplementationBodyCodegen.java | 2 +- .../jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java | 1 - .../src/org/jetbrains/jet/lang/resolve/java}/StdlibNames.java | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) rename compiler/{frontend/src/org/jetbrains/jet/lang/resolve => frontend.java/src/org/jetbrains/jet/lang/resolve/java}/StdlibNames.java (96%) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 4edd7db34a4..1f7f2cfca14 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -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; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 7d8298b489a..421ad544fe4 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -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.OverridingUtil; -import org.jetbrains.jet.lang.resolve.StdlibNames; +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; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index cf154895c99..4bafcdc944d 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java similarity index 96% rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java rename to compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java index 3dde936fe39..bf268b52f7a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/StdlibNames.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java @@ -1,4 +1,4 @@ -package org.jetbrains.jet.lang.resolve; +package org.jetbrains.jet.lang.resolve.java; import org.objectweb.asm.Type; From 386d8b1f61430c1ee9a797760528187aff6a9f7f Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Tue, 13 Dec 2011 18:36:11 +0400 Subject: [PATCH 22/23] rename @JetParameter to @JetValueParameter requested by Andrey Breslav --- .../jetbrains/jet/codegen/FunctionCodegen.java | 18 +++++++++--------- .../jetbrains/jet/codegen/JetTypeMapper.java | 2 +- .../resolve/java/JavaDescriptorResolver.java | 6 +++--- .../jet/lang/resolve/java/StdlibNames.java | 10 +++++----- ...etParameter.java => JetValueParameter.java} | 2 +- 5 files changed, 19 insertions(+), 19 deletions(-) rename stdlib/src/jet/typeinfo/{JetParameter.java => JetValueParameter.java} (94%) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 1f7f2cfca14..ab951d0e173 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -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(); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 750d036d961..d09e0480f0b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -54,7 +54,7 @@ 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/JetParameter"); + 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"); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 4bafcdc944d..d74c6aafd28 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -369,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 { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java index bf268b52f7a..214be7c888d 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java @@ -7,12 +7,12 @@ import org.objectweb.asm.Type; */ public class StdlibNames { - 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_VALUE_PARAMETER_CLASS = "jet.typeinfo.JetValueParameter"; + public static final String JET_VALUE_PARAMETER_DESCRIPTOR = "Ljet/typeinfo/JetValueParameter;"; - 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 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"; diff --git a/stdlib/src/jet/typeinfo/JetParameter.java b/stdlib/src/jet/typeinfo/JetValueParameter.java similarity index 94% rename from stdlib/src/jet/typeinfo/JetParameter.java rename to stdlib/src/jet/typeinfo/JetValueParameter.java index bae06e264b1..c40848327db 100644 --- a/stdlib/src/jet/typeinfo/JetParameter.java +++ b/stdlib/src/jet/typeinfo/JetValueParameter.java @@ -12,7 +12,7 @@ import java.lang.annotation.Target; */ @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) -public @interface JetParameter { +public @interface JetValueParameter { /** * @return name of parameter */ From 0dcd4d682c3265a5926b945eb5b615197f83fab8 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Tue, 13 Dec 2011 18:54:13 +0400 Subject: [PATCH 23/23] more links to specification --- stdlib/src/jet/typeinfo/JetMethod.java | 2 ++ stdlib/src/jet/typeinfo/JetSignature.java | 2 ++ stdlib/src/jet/typeinfo/JetTypeDescriptor.java | 2 ++ stdlib/src/jet/typeinfo/JetTypeParameter.java | 2 ++ stdlib/src/jet/typeinfo/JetTypeProjection.java | 2 ++ stdlib/src/jet/typeinfo/JetValueParameter.java | 2 ++ 6 files changed, 12 insertions(+) diff --git a/stdlib/src/jet/typeinfo/JetMethod.java b/stdlib/src/jet/typeinfo/JetMethod.java index a999ce2f298..edc2199a870 100644 --- a/stdlib/src/jet/typeinfo/JetMethod.java +++ b/stdlib/src/jet/typeinfo/JetMethod.java @@ -11,6 +11,8 @@ import java.lang.annotation.Target; * The fact of receiver presence must be deducted from presence of 'this$receiver' parameter * * @author alex.tkachman + * + * @url http://confluence.jetbrains.net/display/JET/Jet+Signatures */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) diff --git a/stdlib/src/jet/typeinfo/JetSignature.java b/stdlib/src/jet/typeinfo/JetSignature.java index ab2455903c2..fe43b49b50d 100644 --- a/stdlib/src/jet/typeinfo/JetSignature.java +++ b/stdlib/src/jet/typeinfo/JetSignature.java @@ -7,6 +7,8 @@ import java.util.*; /** * @author alex.tkachman + * + * @url http://confluence.jetbrains.net/display/JET/Jet+Signatures */ @Retention(RetentionPolicy.RUNTIME) @interface JetSignature { diff --git a/stdlib/src/jet/typeinfo/JetTypeDescriptor.java b/stdlib/src/jet/typeinfo/JetTypeDescriptor.java index 9d289c97b41..3e2b558ff8f 100644 --- a/stdlib/src/jet/typeinfo/JetTypeDescriptor.java +++ b/stdlib/src/jet/typeinfo/JetTypeDescriptor.java @@ -2,6 +2,8 @@ package jet.typeinfo; /** * @author alex.tkachman + * + * @url http://confluence.jetbrains.net/display/JET/Jet+Signatures */ public @interface JetTypeDescriptor{ // diff --git a/stdlib/src/jet/typeinfo/JetTypeParameter.java b/stdlib/src/jet/typeinfo/JetTypeParameter.java index b57809b98e5..2a748ce97bd 100644 --- a/stdlib/src/jet/typeinfo/JetTypeParameter.java +++ b/stdlib/src/jet/typeinfo/JetTypeParameter.java @@ -9,6 +9,8 @@ import java.lang.annotation.Target; * Annotation for parameters * * @author alex.tkachman + * + * @url http://confluence.jetbrains.net/display/JET/Jet+Signatures */ @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) diff --git a/stdlib/src/jet/typeinfo/JetTypeProjection.java b/stdlib/src/jet/typeinfo/JetTypeProjection.java index 3605c0640e6..fbd90bf7739 100644 --- a/stdlib/src/jet/typeinfo/JetTypeProjection.java +++ b/stdlib/src/jet/typeinfo/JetTypeProjection.java @@ -5,6 +5,8 @@ import java.lang.annotation.RetentionPolicy; /** * @author alex.tkachman + * + * @url http://confluence.jetbrains.net/display/JET/Jet+Signatures */ @Retention(RetentionPolicy.RUNTIME) public @interface JetTypeProjection { diff --git a/stdlib/src/jet/typeinfo/JetValueParameter.java b/stdlib/src/jet/typeinfo/JetValueParameter.java index c40848327db..3a0a2992ad4 100644 --- a/stdlib/src/jet/typeinfo/JetValueParameter.java +++ b/stdlib/src/jet/typeinfo/JetValueParameter.java @@ -9,6 +9,8 @@ import java.lang.annotation.Target; * Annotation for parameters * * @author alex.tkachman + * + * @url http://confluence.jetbrains.net/display/JET/Jet+Signatures */ @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME)