Supporting Unit.VALUE, to replace #()
#KT-2358 In Progress
This commit is contained in:
@@ -3367,7 +3367,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
throw new UnsupportedOperationException("tuple too large");
|
||||
}
|
||||
if (entries.size() == 0) {
|
||||
v.visitFieldInsn(GETSTATIC, "jet/Tuple0", "INSTANCE", "Ljet/Tuple0;");
|
||||
v.visitFieldInsn(GETSTATIC, "jet/Tuple0", "VALUE", "Ljet/Tuple0;");
|
||||
return StackValue.onStack(JET_TUPLE0_TYPE);
|
||||
}
|
||||
|
||||
|
||||
@@ -310,7 +310,7 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
public static void putTuple0Instance(InstructionAdapter v) {
|
||||
v.visitFieldInsn(GETSTATIC, "jet/Tuple0", "INSTANCE", "Ljet/Tuple0;");
|
||||
v.visitFieldInsn(GETSTATIC, "jet/Tuple0", "VALUE", "Ljet/Tuple0;");
|
||||
}
|
||||
|
||||
protected void putAsBoolean(InstructionAdapter v) {
|
||||
|
||||
@@ -148,16 +148,25 @@ public class IntrinsicMethods {
|
||||
declareIntrinsicProperty(Name.identifier("CharSequence"), Name.identifier("length"), new StringLength());
|
||||
declareIntrinsicProperty(Name.identifier("String"), Name.identifier("length"), new StringLength());
|
||||
|
||||
Name tuple0Name = JetStandardClasses.getTuple(0).getName();
|
||||
intrinsicsMap.registerIntrinsic(
|
||||
getClassObjectFqName(tuple0Name),
|
||||
Name.identifier("VALUE"), -1, new UnitValue());
|
||||
|
||||
for (PrimitiveType type : PrimitiveType.NUMBER_TYPES) {
|
||||
intrinsicsMap.registerIntrinsic(
|
||||
JetStandardClasses.STANDARD_CLASSES_FQNAME.child(type.getRangeTypeName()).toUnsafe().child(
|
||||
getClassObjectName(type.getRangeTypeName())),
|
||||
getClassObjectFqName(type.getRangeTypeName()),
|
||||
Name.identifier("EMPTY"), -1, new EmptyRange(type));
|
||||
}
|
||||
|
||||
declareArrayMethods();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static FqNameUnsafe getClassObjectFqName(@NotNull Name builtinClassName) {
|
||||
return JetStandardClasses.STANDARD_CLASSES_FQNAME.child(builtinClassName).toUnsafe().child(getClassObjectName(builtinClassName));
|
||||
}
|
||||
|
||||
private void declareArrayMethods() {
|
||||
|
||||
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2010-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JET_TUPLE0_TYPE;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class UnitValue implements IntrinsicMethod {
|
||||
|
||||
@Override
|
||||
public StackValue generate(
|
||||
ExpressionCodegen codegen,
|
||||
InstructionAdapter v,
|
||||
@NotNull Type expectedType,
|
||||
@Nullable PsiElement element,
|
||||
@Nullable List<JetExpression> arguments,
|
||||
StackValue receiver,
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
v.getstatic(JET_TUPLE0_TYPE.getInternalName(), "VALUE", JET_TUPLE0_TYPE.getDescriptor());
|
||||
return StackValue.onStack(expectedType);
|
||||
}
|
||||
}
|
||||
@@ -22,11 +22,10 @@ import java.io.PrintStream;
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TuplesAndFunctionsGenerator {
|
||||
private static int TUPLE_COUNT = 23;
|
||||
private static final int TUPLE_COUNT = 23;
|
||||
|
||||
private static void generateTuples(PrintStream out, int count) {
|
||||
generated(out);
|
||||
out.println("public class Tuple0() {}");
|
||||
for (int i = 1; i < count; i++) {
|
||||
out.print("public class Tuple" + i);
|
||||
out.print("<");
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
package jet
|
||||
|
||||
public class Tuple0() {}
|
||||
public class Tuple1<out T1>(public val _1: T1) {}
|
||||
public class Tuple2<out T1, out T2>(public val _1: T1, public val _2: T2) {}
|
||||
public class Tuple3<out T1, out T2, out T3>(public val _1: T1, public val _2: T2, public val _3: T3) {}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package jet
|
||||
|
||||
public class Tuple0 private () {
|
||||
public class object {
|
||||
public val VALUE: Tuple0
|
||||
}
|
||||
}
|
||||
@@ -25,9 +25,11 @@ import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -40,54 +42,54 @@ public class ClassDescriptorImpl extends DeclarationDescriptorNonRootImpl implem
|
||||
private ConstructorDescriptor primaryConstructor;
|
||||
private ReceiverDescriptor implicitReceiver;
|
||||
private final Modality modality;
|
||||
private ClassDescriptor classObjectDescriptor;
|
||||
private final ClassKind kind;
|
||||
|
||||
public ClassDescriptorImpl(
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@NotNull List<AnnotationDescriptor> annotations,
|
||||
@NotNull Modality modality,
|
||||
@NotNull Name name
|
||||
) {
|
||||
this(containingDeclaration, ClassKind.CLASS, annotations, modality, name);
|
||||
}
|
||||
|
||||
public ClassDescriptorImpl(
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@NotNull ClassKind kind,
|
||||
@NotNull List<AnnotationDescriptor> annotations,
|
||||
@NotNull Modality modality,
|
||||
@NotNull Name name) {
|
||||
super(containingDeclaration, annotations, name);
|
||||
this.kind = kind;
|
||||
this.modality = modality;
|
||||
}
|
||||
|
||||
public final ClassDescriptorImpl initialize(boolean sealed,
|
||||
@NotNull List<? extends TypeParameterDescriptor> typeParameters,
|
||||
@NotNull Collection<JetType> supertypes,
|
||||
@NotNull JetScope memberDeclarations,
|
||||
@NotNull Set<ConstructorDescriptor> constructors,
|
||||
@Nullable ConstructorDescriptor primaryConstructor) {
|
||||
return initialize(sealed, typeParameters, supertypes, memberDeclarations, constructors, primaryConstructor, getClassType(supertypes));
|
||||
}
|
||||
|
||||
public final ClassDescriptorImpl initialize(boolean sealed,
|
||||
@NotNull List<? extends TypeParameterDescriptor> typeParameters,
|
||||
@NotNull Collection<JetType> supertypes,
|
||||
@NotNull JetScope memberDeclarations,
|
||||
@NotNull Set<ConstructorDescriptor> constructors,
|
||||
@Nullable ConstructorDescriptor primaryConstructor,
|
||||
@Nullable JetType superclassType) {
|
||||
public final ClassDescriptorImpl initialize(
|
||||
boolean sealed,
|
||||
@NotNull List<? extends TypeParameterDescriptor> typeParameters,
|
||||
@NotNull Collection<JetType> supertypes,
|
||||
@NotNull JetScope memberDeclarations,
|
||||
@NotNull Set<ConstructorDescriptor> constructors,
|
||||
@Nullable ConstructorDescriptor primaryConstructor
|
||||
) {
|
||||
this.typeConstructor = new TypeConstructorImpl(this, getAnnotations(), sealed, getName().getName(), typeParameters, supertypes);
|
||||
this.memberDeclarations = memberDeclarations;
|
||||
this.constructors = constructors;
|
||||
this.primaryConstructor = primaryConstructor;
|
||||
this.classObjectDescriptor = classObjectDescriptor;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JetType getClassType(@NotNull Collection<JetType> types) {
|
||||
for (JetType type : types) {
|
||||
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(type);
|
||||
if (classDescriptor != null) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return JetStandardClasses.getAnyType();
|
||||
}
|
||||
|
||||
public void setPrimaryConstructor(@NotNull ConstructorDescriptor primaryConstructor) {
|
||||
this.primaryConstructor = primaryConstructor;
|
||||
}
|
||||
|
||||
public void setClassObjectDescriptor(@NotNull ClassDescriptor classObjectDescriptor) {
|
||||
this.classObjectDescriptor = classObjectDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public TypeConstructor getTypeConstructor() {
|
||||
@@ -126,18 +128,18 @@ public class ClassDescriptorImpl extends DeclarationDescriptorNonRootImpl implem
|
||||
|
||||
@Override
|
||||
public JetType getClassObjectType() {
|
||||
return null;
|
||||
return getClassObjectDescriptor().getDefaultType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassDescriptor getClassObjectDescriptor() {
|
||||
return null;
|
||||
return classObjectDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ClassKind getKind() {
|
||||
return ClassKind.CLASS;
|
||||
return kind;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
||||
@@ -91,7 +92,6 @@ public class JetStandardClasses {
|
||||
},
|
||||
JetScope.EMPTY,
|
||||
Collections.<ConstructorDescriptor>singleton(constructorDescriptor),
|
||||
null,
|
||||
null
|
||||
);
|
||||
NOTHING_TYPE = new JetTypeImpl(getNothing());
|
||||
@@ -125,7 +125,6 @@ public class JetStandardClasses {
|
||||
Collections.<JetType>emptySet(),
|
||||
JetScope.EMPTY,
|
||||
Collections.<ConstructorDescriptor>singleton(constructorDescriptor),
|
||||
null,
|
||||
null
|
||||
);
|
||||
ANY_TYPE = new JetTypeImpl(ANY.getTypeConstructor(), new JetScopeImpl() {
|
||||
@@ -201,14 +200,84 @@ public class JetStandardClasses {
|
||||
writableScope,
|
||||
Collections.<ConstructorDescriptor>singleton(constructorDescriptor),
|
||||
null);
|
||||
|
||||
if (i == 0) {
|
||||
// Unit.VALUE
|
||||
classDescriptor.setClassObjectDescriptor(createClassObjectForUnit(classDescriptor));
|
||||
}
|
||||
|
||||
TUPLE_CONSTRUCTORS.add(TUPLE[i].getTypeConstructor());
|
||||
|
||||
constructorDescriptor.initialize(classDescriptor.getTypeConstructor().getParameters(), constructorValueParameters, Visibilities.PUBLIC);
|
||||
constructorDescriptor.initialize(classDescriptor.getTypeConstructor().getParameters(), constructorValueParameters, i == 0 ? Visibilities.PRIVATE : Visibilities.PUBLIC);
|
||||
constructorDescriptor.setReturnType(classDescriptor.getDefaultType());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@NotNull
|
||||
private static ClassDescriptor createClassObjectForUnit(@NotNull ClassDescriptorImpl unitClass) {
|
||||
ClassDescriptorImpl classObjectDescriptor = new ClassDescriptorImpl(
|
||||
unitClass,
|
||||
ClassKind.CLASS_OBJECT,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
Modality.FINAL,
|
||||
DescriptorUtils.getClassObjectName(unitClass.getName())
|
||||
);
|
||||
WritableScopeImpl classObjectMemberScope = new WritableScopeImpl(
|
||||
JetScope.EMPTY,
|
||||
classObjectDescriptor,
|
||||
RedeclarationHandler.DO_NOTHING,
|
||||
"Unit class object members"
|
||||
);
|
||||
PropertyDescriptor valueProperty = createUnitValueProperty(unitClass, classObjectDescriptor);
|
||||
classObjectMemberScope.addPropertyDescriptor(valueProperty);
|
||||
classObjectMemberScope.changeLockLevel(WritableScope.LockLevel.READING);
|
||||
|
||||
ConstructorDescriptorImpl classObjectConstructorDescriptor = new ConstructorDescriptorImpl(classObjectDescriptor, Collections.<AnnotationDescriptor>emptyList(), true);
|
||||
classObjectConstructorDescriptor.initialize(
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
Collections.<ValueParameterDescriptor>emptyList(),
|
||||
Visibilities.PRIVATE
|
||||
);
|
||||
|
||||
classObjectDescriptor.initialize(
|
||||
/*sealed = */ true,
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
Collections.singleton(getAnyType()),
|
||||
classObjectMemberScope,
|
||||
Collections.<ConstructorDescriptor>singleton(classObjectConstructorDescriptor),
|
||||
classObjectConstructorDescriptor
|
||||
);
|
||||
|
||||
classObjectConstructorDescriptor.setReturnType(classObjectDescriptor.getDefaultType());
|
||||
|
||||
return classObjectDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PropertyDescriptor createUnitValueProperty(
|
||||
@NotNull ClassDescriptorImpl unitClass,
|
||||
@NotNull ClassDescriptorImpl unitClassObject
|
||||
) {
|
||||
PropertyDescriptor valueProperty = new PropertyDescriptor(
|
||||
unitClassObject,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
Modality.FINAL,
|
||||
Visibilities.PUBLIC,
|
||||
/*isVar = */ false,
|
||||
Name.identifier("VALUE"),
|
||||
CallableMemberDescriptor.Kind.DECLARATION);
|
||||
valueProperty.setType(
|
||||
unitClass.getDefaultType(),
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
unitClassObject.getImplicitReceiver(),
|
||||
ReceiverDescriptor.NO_RECEIVER);
|
||||
PropertyGetterDescriptor getter = DescriptorResolver.createDefaultGetter(valueProperty);
|
||||
getter.initialize(unitClass.getDefaultType());
|
||||
valueProperty.initialize(getter, null);
|
||||
return valueProperty;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static final int MAX_FUNCTION_ORDER = 22;
|
||||
|
||||
|
||||
@@ -1123,7 +1123,11 @@ public open class jet.Throwable : jet.Any {
|
||||
public final fun printStackTrace(): jet.Tuple0
|
||||
}
|
||||
public final class jet.Tuple0 : jet.Any {
|
||||
public final /*constructor*/ fun <init>(): jet.Tuple0
|
||||
private final /*constructor*/ fun <init>(): jet.Tuple0
|
||||
public final class object jet.Tuple0.<class-object-for-Tuple0> : jet.Any {
|
||||
private final /*constructor*/ fun <init>(): jet.Tuple0.<class-object-for-Tuple0>
|
||||
public final val VALUE: jet.Tuple0
|
||||
}
|
||||
}
|
||||
public final class jet.Tuple1</*0*/ out T1 : jet.Any?> : jet.Any {
|
||||
public final /*constructor*/ fun </*0*/ out T1 : jet.Any?><init>(/*0*/ _1: T1): jet.Tuple1<T1>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
fun foo() {}
|
||||
|
||||
fun box(): String {
|
||||
return if (foo() == Unit.VALUE) "OK" else "Fail"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fun test() {
|
||||
return Unit.VALUE : Unit
|
||||
}
|
||||
@@ -3278,6 +3278,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
||||
doTest("compiler/testData/diagnostics/tests/tuples/BasicTuples.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("UnitValue.kt")
|
||||
public void testUnitValue() throws Exception {
|
||||
doTest("compiler/testData/diagnostics/tests/tuples/UnitValue.kt");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/varargs")
|
||||
|
||||
@@ -22,6 +22,12 @@ public class TupleGenTest extends CodegenTestCase {
|
||||
public void testBasic() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("/tuples/basic.jet");
|
||||
// System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testUnitValue() {
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||
blackBoxFile("/tuples/UnitValue.kt");
|
||||
// System.out.println(generateToText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public class StringTemplate {
|
||||
@Override
|
||||
public Tuple0 invoke(Object o) {
|
||||
builder.append(o);
|
||||
return Tuple0.INSTANCE;
|
||||
return Tuple0.VALUE;
|
||||
}
|
||||
});
|
||||
return builder.toString();
|
||||
|
||||
@@ -23,19 +23,19 @@ import org.jetbrains.jet.rt.annotation.AssertInvisibleInResolver;
|
||||
*/
|
||||
@AssertInvisibleInResolver
|
||||
public class Tuple0 extends Tuple {
|
||||
public static final Tuple0 INSTANCE = new Tuple0();
|
||||
public static final Tuple0 VALUE = new Tuple0();
|
||||
|
||||
private Tuple0() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "()";
|
||||
return "Unit.VALUE";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o == INSTANCE;
|
||||
return o == VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user