KT-2583 Support *Range.EMPTY

#KT-2583 fixed
This commit is contained in:
Evgeny Gerashchenko
2012-08-08 22:50:29 +04:00
parent d9f30f6763
commit 0124c7bb5a
8 changed files with 171 additions and 4 deletions
@@ -30,6 +30,8 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
import javax.inject.Inject;
import java.util.*;
@@ -65,6 +67,20 @@ public class ClosureAnnotator {
public void init() {
mapFilesToNamespaces(files);
prepareAnonymousClasses();
prepareClassObjectsForBuiltinRanges();
}
private void prepareClassObjectsForBuiltinRanges() {
// this is needed for range classes because they have class objects with
// intrinsic members
JetScope stdLibraryScope = JetStandardLibrary.getInstance().getLibraryScope();
for (PrimitiveType type : PrimitiveType.NUMBER_TYPES) {
ClassDescriptor klass = (ClassDescriptor) stdLibraryScope.getClassifier(type.getRangeTypeName());
String rangeInternalName = JvmClassName.byFqNameWithoutInnerClasses(
JetStandardClasses.STANDARD_CLASSES_FQNAME.child(type.getRangeTypeName())).getInternalName();
JvmClassName classObjectInternalName = JvmClassName.byInternalName(rangeInternalName + JvmAbi.CLASS_OBJECT_SUFFIX);
classNamesForClassDescriptor.put(klass.getClassObjectDescriptor(), classObjectInternalName);
}
}
@@ -0,0 +1,56 @@
/*
* 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.GenerationState;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
import java.util.List;
/**
* @author Evgeny Gerashchenko
* @since 08.08.12
*/
public class EmptyRange implements IntrinsicMethod {
private final PrimitiveType elementType;
public EmptyRange(PrimitiveType elementType) {
this.elementType = elementType;
}
@Override
public StackValue generate(ExpressionCodegen codegen,
InstructionAdapter v,
@NotNull Type expectedType,
@Nullable PsiElement element,
@Nullable List<JetExpression> arguments,
StackValue receiver,
@NotNull GenerationState state) {
JvmClassName name = JvmClassName.byFqNameWithoutInnerClasses(elementType.getRangeClassName().getFqName());
v.getstatic(name.toString(), "empty", "L" + name + ";");
return StackValue.onStack(expectedType);
}
}
@@ -17,7 +17,6 @@
package org.jetbrains.jet.codegen.intrinsics;
import com.google.common.collect.ImmutableList;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Opcodes;
@@ -25,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
@@ -34,7 +34,6 @@ import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.lang.PrimitiveType;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -141,6 +140,12 @@ public class IntrinsicMethods {
declareIntrinsicProperty(Name.identifier("CharSequence"), Name.identifier("length"), new StringLength());
declareIntrinsicProperty(Name.identifier("String"), Name.identifier("length"), new StringLength());
for (PrimitiveType type : PrimitiveType.NUMBER_TYPES) {
intrinsicsMap.registerIntrinsic(
JetStandardClasses.STANDARD_CLASSES_FQNAME.child(type.getRangeTypeName()).toUnsafe().child(JetPsiUtil.NO_NAME_PROVIDED),
Name.identifier("EMPTY"), -1, new EmptyRange(type));
}
declareArrayMethods();
}
@@ -228,5 +233,4 @@ public class IntrinsicMethods {
}
return intrinsicMethod;
}
}
@@ -82,11 +82,18 @@ class IntrinsicsMap {
private Map<Key, IntrinsicMethod> intrinsicsMap = Maps.newHashMap();
/**
* @param valueParameterCount -1 for property
*/
public void registerIntrinsic(@NotNull FqNameUnsafe owner, @NotNull Name name, int valueParameterCount, @NotNull IntrinsicMethod impl) {
intrinsicsMap.put(new Key(owner, name, valueParameterCount), impl);
}
/**
* @param valueParameterCount -1 for property
*/
public void registerIntrinsic(@NotNull FqName owner, @NotNull Name name, int valueParameterCount, @NotNull IntrinsicMethod impl) {
intrinsicsMap.put(new Key(owner.toUnsafe(), name, valueParameterCount), impl);
registerIntrinsic(owner.toUnsafe(), name, valueParameterCount, impl);
}
+28
View File
@@ -18,6 +18,10 @@ public class IntRange(public val start : Int, public val size : Int) : Range<Int
public fun step(step: Int) : IntIterator
public val isReversed : Boolean
public class object {
public val EMPTY: IntRange
}
}
public class LongRange(public val start : Long, public val size : Long) : Range<Long>, LongIterable {
@@ -34,6 +38,10 @@ public class LongRange(public val start : Long, public val size : Long) : Range<
public fun step(step: Long) : LongIterator
public val isReversed : Boolean
public class object {
public val EMPTY: LongRange
}
}
public class ByteRange(public val start : Byte, public val size : Int) : Range<Byte>, ByteIterable {
@@ -50,6 +58,10 @@ public class ByteRange(public val start : Byte, public val size : Int) : Range<B
public fun step(step: Int) : ByteIterator
public val isReversed : Boolean
public class object {
public val EMPTY: ByteRange
}
}
public class ShortRange(public val start : Short, public val size : Int) : Range<Short>, ShortIterable {
@@ -66,6 +78,10 @@ public class ShortRange(public val start : Short, public val size : Int) : Range
public fun step(step: Int) : ShortIterator
public val isReversed : Boolean
public class object {
public val EMPTY: ShortRange
}
}
public class CharRange(public val start : Char, public val size : Int) : Range<Char>, CharIterable {
@@ -82,6 +98,10 @@ public class CharRange(public val start : Char, public val size : Int) : Range<C
public fun step(step: Int) : CharIterator
public val isReversed : Boolean
public class object {
public val EMPTY: CharRange
}
}
public class FloatRange(public val start : Float, public val size : Float) : Range<Float> {
@@ -94,6 +114,10 @@ public class FloatRange(public val start : Float, public val size : Float) : Ran
public fun step(step: Float) : FloatIterator
public val isReversed : Boolean
public class object {
public val EMPTY: FloatRange
}
}
public class DoubleRange(public val start : Double, public val size : Double) : Range<Double> {
@@ -106,4 +130,8 @@ public class DoubleRange(public val start : Double, public val size : Double) :
public fun step(step: Double) : DoubleIterator
public val isReversed : Boolean
public class object {
public val EMPTY: DoubleRange
}
}
+28
View File
@@ -130,6 +130,10 @@ public final class jet.ByteRange : jet.Range<jet.Byte>, jet.ByteIterable {
public final val size: jet.Int
public final val start: jet.Byte
public final fun step(/*0*/ step: jet.Int): jet.ByteIterator
public final class object jet.ByteRange.<no name provided> : jet.Any {
internal final /*constructor*/ fun <init>(): jet.ByteRange.<no name provided>
public final val EMPTY: jet.ByteRange
}
}
public final class jet.Char : jet.Number, jet.Comparable<jet.Char> {
public final /*constructor*/ fun <init>(): jet.Char
@@ -220,6 +224,10 @@ public final class jet.CharRange : jet.Range<jet.Char>, jet.CharIterable {
public final val size: jet.Int
public final val start: jet.Char
public final fun step(/*0*/ step: jet.Int): jet.CharIterator
public final class object jet.CharRange.<no name provided> : jet.Any {
internal final /*constructor*/ fun <init>(): jet.CharRange.<no name provided>
public final val EMPTY: jet.CharRange
}
}
public abstract trait jet.CharSequence : jet.Any {
public abstract fun get(/*0*/ index: jet.Int): jet.Char
@@ -319,6 +327,10 @@ public final class jet.DoubleRange : jet.Range<jet.Double> {
public final val size: jet.Double
public final val start: jet.Double
public final fun step(/*0*/ step: jet.Double): jet.DoubleIterator
public final class object jet.DoubleRange.<no name provided> : jet.Any {
internal final /*constructor*/ fun <init>(): jet.DoubleRange.<no name provided>
public final val EMPTY: jet.DoubleRange
}
}
public abstract class jet.ExtensionFunction0</*0*/ in T : jet.Any?, /*1*/ out R : jet.Any?> : jet.Any {
public final /*constructor*/ fun </*0*/ in T : jet.Any?, /*1*/ out R : jet.Any?><init>(): jet.ExtensionFunction0<T, R>
@@ -503,6 +515,10 @@ public final class jet.FloatRange : jet.Range<jet.Float> {
public final val size: jet.Float
public final val start: jet.Float
public final fun step(/*0*/ step: jet.Float): jet.FloatIterator
public final class object jet.FloatRange.<no name provided> : jet.Any {
internal final /*constructor*/ fun <init>(): jet.FloatRange.<no name provided>
public final val EMPTY: jet.FloatRange
}
}
public abstract class jet.Function0</*0*/ out R : jet.Any?> : jet.Any {
public final /*constructor*/ fun </*0*/ out R : jet.Any?><init>(): jet.Function0<R>
@@ -700,6 +716,10 @@ public final class jet.IntRange : jet.Range<jet.Int>, jet.IntIterable {
public final val size: jet.Int
public final val start: jet.Int
public final fun step(/*0*/ step: jet.Int): jet.IntIterator
public final class object jet.IntRange.<no name provided> : jet.Any {
internal final /*constructor*/ fun <init>(): jet.IntRange.<no name provided>
public final val EMPTY: jet.IntRange
}
}
public abstract trait jet.Iterable</*0*/ out T : jet.Any?> : jet.Any {
public abstract fun iterator(): jet.Iterator<T>
@@ -808,6 +828,10 @@ public final class jet.LongRange : jet.Range<jet.Long>, jet.LongIterable {
public final val size: jet.Long
public final val start: jet.Long
public final fun step(/*0*/ step: jet.Long): jet.LongIterator
public final class object jet.LongRange.<no name provided> : jet.Any {
internal final /*constructor*/ fun <init>(): jet.LongRange.<no name provided>
public final val EMPTY: jet.LongRange
}
}
public final class jet.Nothing {
private final /*constructor*/ fun <init>(): jet.Nothing
@@ -920,6 +944,10 @@ public final class jet.ShortRange : jet.Range<jet.Short>, jet.ShortIterable {
public final val size: jet.Int
public final val start: jet.Short
public final fun step(/*0*/ step: jet.Int): jet.ShortIterator
public final class object jet.ShortRange.<no name provided> : jet.Any {
internal final /*constructor*/ fun <init>(): jet.ShortRange.<no name provided>
public final val EMPTY: jet.ShortRange
}
}
public final class jet.String : jet.Comparable<jet.String>, jet.CharSequence {
public final /*constructor*/ fun <init>(): jet.String
+24
View File
@@ -0,0 +1,24 @@
fun box(): String {
if (IntRange(0, 0) != IntRange.EMPTY) {
return IntRange.EMPTY.toString()
}
if (CharRange(0.toChar(), 0) != CharRange.EMPTY) {
return CharRange.EMPTY.toString()
}
if (ByteRange(0, 0) != ByteRange.EMPTY) {
return ByteRange.EMPTY.toString()
}
if (ShortRange(0, 0) != ShortRange.EMPTY) {
return ShortRange.EMPTY.toString()
}
if (FloatRange(0.toFloat(), 0.toFloat()) != FloatRange.EMPTY) {
return FloatRange.EMPTY.toString()
}
if (LongRange(0, 0) != LongRange.EMPTY) {
return LongRange.EMPTY.toString()
}
if (DoubleRange(0.0, 0.0) != DoubleRange.EMPTY) {
return DoubleRange.EMPTY.toString()
}
return "OK"
}
@@ -444,4 +444,8 @@ public class PrimitiveTypesTest extends CodegenTestCase {
public void testKt2275() {
blackBoxFile("regressions/kt2275.kt");
}
public void testEmptyRanges() throws Exception {
blackBoxFile("emptyRanges.kt");
}
}