Intrinsic default objects implementation

This commit is contained in:
Nikolay Krasko
2015-03-03 19:24:20 +03:00
parent 05de376fc3
commit 1f79e0905f
16 changed files with 319 additions and 16 deletions
+1
View File
@@ -4,6 +4,7 @@
<w>accessors</w>
<w>goto</w>
<w>gradle</w>
<w>intrinsics</w>
<w>kdoc</w>
<w>kompiler</w>
<w>memoize</w>
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2015 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.kotlin.backend.common.builtins
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.resolve.DescriptorUtils
public abstract class DefaultObjectMapping {
public fun hasMappingToObject(classDescriptor: ClassDescriptor): Boolean {
if (!DescriptorUtils.isDefaultObject(classDescriptor)) return false
val containingDeclaration = classDescriptor.getContainingDeclaration()
if (containingDeclaration !is ClassDescriptor) return false
return KotlinBuiltIns.isPrimitiveType(containingDeclaration.getDefaultType()) ||
KotlinBuiltIns.getInstance().getString() == containingDeclaration ||
KotlinBuiltIns.getInstance().getEnum() == containingDeclaration
}
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicObjects;
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.ClassKind;
@@ -33,7 +34,7 @@ public class FieldInfo {
throw new UnsupportedOperationException("Can't create singleton field for class: " + classDescriptor);
}
if (kind == ClassKind.OBJECT) {
if (kind == ClassKind.OBJECT || IntrinsicObjects.INSTANCE$.hasMappingToObject(classDescriptor)) {
Type type = typeMapper.mapType(classDescriptor);
return new FieldInfo(type, type, JvmAbi.INSTANCE_FIELD, true);
}
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2015 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.kotlin.codegen.intrinsics
import org.jetbrains.kotlin.backend.common.builtins.DefaultObjectMapping
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
public object IntrinsicObjects : DefaultObjectMapping() {
public fun mapType(classDescriptor: ClassDescriptor): FqName? {
if (!hasMappingToObject(classDescriptor)) return null
val containingDeclaration = classDescriptor.getContainingDeclaration()
val name = Name.identifier(containingDeclaration.getName().asString() + "DefaultObject")
return FqName("kotlin.jvm.internal").child(name)
}
}
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicObjects;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.codegen.*;
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
@@ -293,6 +294,18 @@ public class JetTypeMapper {
return Type.getType("[" + boxType(mapType(memberType, kind)).getDescriptor());
}
if (descriptor instanceof ClassDescriptor) {
FqName defaultObjectMappedFqName = IntrinsicObjects.INSTANCE$.mapType((ClassDescriptor) descriptor);
if (defaultObjectMappedFqName != null) {
Type asmType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(defaultObjectMappedFqName);
if (signatureVisitor != null) {
signatureVisitor.writeAsmType(asmType);
}
return asmType;
}
}
if (descriptor instanceof ClassDescriptor) {
Type asmType = computeAsmType((ClassDescriptor) descriptor.getOriginal());
writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, projectionsAllowed);
@@ -399,10 +412,10 @@ public class JetTypeMapper {
else {
Variance projectionKind = projectionsAllowed
? getEffectiveVariance(
parameter.getVariance(),
argument.getProjectionKind(),
howThisTypeIsUsed
)
parameter.getVariance(),
argument.getProjectionKind(),
howThisTypeIsUsed
)
: Variance.INVARIANT;
signatureVisitor.writeTypeArgument(projectionKind);
+2
View File
@@ -22,6 +22,8 @@ package kotlin
* information on enum classes.
*/
public abstract class Enum<E : Enum<E>>(name: String, ordinal: Int): Comparable<E> {
class object {}
/**
* Returns the name of this enum constant, exactly as declared in its enum declaration.
*/
+12
View File
@@ -61,6 +61,8 @@ public abstract class Number {
* values of this type are represented as values of the primitive type `double`.
*/
public class Double private () : Number, Comparable<Double> {
class object : FloatingPointConstants<Double> {}
public override fun compareTo(other: Double): Int
public fun compareTo(other: Float): Int
public fun compareTo(other: Long) : Int
@@ -135,6 +137,8 @@ public class Double private () : Number, Comparable<Double> {
* values of this type are represented as values of the primitive type `float`.
*/
public class Float private () : Number, Comparable<Float> {
class object : FloatingPointConstants<Float> {}
public fun compareTo(other: Double): Int
public override fun compareTo(other: Float): Int
public fun compareTo(other: Long) : Int
@@ -210,6 +214,8 @@ public class Float private () : Number, Comparable<Float> {
* as values of the primitive type `long`.
*/
public class Long private () : Number, Comparable<Long> {
class object {}
public fun compareTo(other: Double): Int
public fun compareTo(other: Float) : Int
public override fun compareTo(other: Long): Int
@@ -293,6 +299,8 @@ public class Long private () : Number, Comparable<Long> {
* as values of the primitive type `int`.
*/
public class Int private () : Number, Comparable<Int> {
class object {}
public fun compareTo(other: Double): Int
public fun compareTo(other: Float) : Int
public fun compareTo(other: Long) : Int
@@ -376,6 +384,8 @@ public class Int private () : Number, Comparable<Int> {
* as values of the primitive type `short`.
*/
public class Short private () : Number, Comparable<Short> {
class object {}
public fun compareTo(other: Double): Int
public fun compareTo(other: Float) : Int
public fun compareTo(other: Long) : Int
@@ -451,6 +461,8 @@ public class Short private () : Number, Comparable<Short> {
* as values of the primitive type `byte`.
*/
public class Byte private () : Number, Comparable<Byte> {
class object {}
public fun compareTo(other: Double): Int
public fun compareTo(other: Float) : Int
public fun compareTo(other: Long) : Int
+2
View File
@@ -21,6 +21,8 @@ package kotlin
* implemented as instances of this class.
*/
public class String : Comparable<String>, CharSequence {
class object {}
/**
* Returns a string obtained by concatenating this string with the string representation of the given [other] object.
*/
@@ -0,0 +1,23 @@
/*
* Copyright 2010-2015 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 kotlin
public trait FloatingPointConstants<T> {
public val POSITIVE_INFINITY: T
public val NEGATIVE_INFINITY: T
public val NaN: T
}
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2015 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 kotlin.jvm.internal
private object DoubleDefaultObject : FloatingPointConstants<Double> {
override val POSITIVE_INFINITY : Double = java.lang.Double.POSITIVE_INFINITY
override val NEGATIVE_INFINITY : Double = java.lang.Double.NEGATIVE_INFINITY
override val NaN : Double = java.lang.Double.NaN
}
private object FloatDefaultObject : FloatingPointConstants<Float> {
override val POSITIVE_INFINITY : Float = java.lang.Float.POSITIVE_INFINITY
override val NEGATIVE_INFINITY : Float = java.lang.Float.NEGATIVE_INFINITY
override val NaN : Float = java.lang.Float.NaN
}
private object IntDefaultObject {}
private object LongDefaultObject {}
private object ShortDefaultObject {}
private object ByteDefaultObject {}
private object StringDefaultObject {}
private object EnumDefaultObject {}
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2015 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 kotlin.js.internal
private object DoubleDefaultObject : FloatingPointConstants<Double> {
override val POSITIVE_INFINITY: Double = js("Number.POSITIVE_INFINITY")
override val NEGATIVE_INFINITY: Double = js("Number.NEGATIVE_INFINITY")
override val NaN: Double = js("Number.NaN")
}
private object FloatDefaultObject : FloatingPointConstants<Float> {
override val POSITIVE_INFINITY : Float = js("Number.POSITIVE_INFINITY")
override val NEGATIVE_INFINITY : Float = js("Number.NEGATIVE_INFINITY")
override val NaN : Float = js("Number.NaN")
}
private object IntDefaultObject {}
private object LongDefaultObject {}
private object ShortDefaultObject {}
private object ByteDefaultObject {}
private object StringDefaultObject {}
private object EnumDefaultObject {}
@@ -18,26 +18,29 @@ package org.jetbrains.kotlin.js.translate.intrinsic;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.js.translate.intrinsic.functions.FunctionIntrinsics;
import org.jetbrains.kotlin.js.translate.intrinsic.objects.ObjectIntrinsics;
import org.jetbrains.kotlin.js.translate.intrinsic.operation.BinaryOperationIntrinsics;
/**
* Provides mechanism to substitute method calls /w native constructs directly.
*/
public final class Intrinsics {
@NotNull
private final FunctionIntrinsics functionIntrinsics = new FunctionIntrinsics();
private final BinaryOperationIntrinsics binaryOperationIntrinsics = new BinaryOperationIntrinsics();
private final ObjectIntrinsics objectIntrinsics = new ObjectIntrinsics();
@NotNull
public BinaryOperationIntrinsics getBinaryOperationIntrinsics() {
return binaryOperationIntrinsics;
}
@NotNull
private final BinaryOperationIntrinsics binaryOperationIntrinsics = new BinaryOperationIntrinsics();
@NotNull
public FunctionIntrinsics getFunctionIntrinsics() {
return functionIntrinsics;
}
}
@NotNull
public ObjectIntrinsics getObjectIntrinsics() {
return objectIntrinsics;
}
}
@@ -0,0 +1,59 @@
/*
* Copyright 2010-2015 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.kotlin.js.translate.intrinsic.objects
import com.google.dart.compiler.backend.js.ast.JsArrayAccess
import com.google.dart.compiler.backend.js.ast.JsExpression
import org.jetbrains.kotlin.backend.common.builtins.DefaultObjectMapping
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.js.config.LibrarySourcesConfig
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
class DefaultClassObjectIntrinsic(val fqName: FqName, val moduleName: String): ObjectIntrinsic {
override fun apply(context: TranslationContext): JsExpression {
val nameRef = context.getQualifiedReference(fqName)
return JsAstUtils.replaceRootReference(
nameRef,
JsArrayAccess(context.namer().kotlin("modules"), context.program().getStringLiteral(moduleName)))
}
}
public class ObjectIntrinsics : DefaultObjectMapping() {
public fun getIntrinsic(classDescriptor: ClassDescriptor): ObjectIntrinsic {
if (!hasMappingToObject(classDescriptor)) return NO_OBJECT_INTRINSIC
val containingDeclaration = classDescriptor.getContainingDeclaration()
val name = Name.identifier(containingDeclaration.getName().asString() + "DefaultObject")
return DefaultClassObjectIntrinsic(FqName("kotlin.js.internal").child(name), LibrarySourcesConfig.STDLIB_JS_MODULE_NAME)
}
}
public trait ObjectIntrinsic {
fun apply(context: TranslationContext): JsExpression
fun exists(): Boolean = true
}
object NO_OBJECT_INTRINSIC : ObjectIntrinsic {
override fun apply(context: TranslationContext): JsExpression =
throw UnsupportedOperationException("ObjectIntrinsic#NO_OBJECT_INTRINSIC_#apply")
override fun exists(): Boolean = false
}
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.js.translate.context.Namer;
import org.jetbrains.kotlin.js.translate.context.TemporaryVariable;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
import org.jetbrains.kotlin.js.translate.intrinsic.objects.ObjectIntrinsic;
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
import org.jetbrains.kotlin.psi.JetReferenceExpression;
import org.jetbrains.kotlin.psi.JetSimpleNameExpression;
@@ -60,13 +61,24 @@ public class DefaultObjectAccessTranslator extends AbstractTranslator implements
private DefaultObjectAccessTranslator(@NotNull DeclarationDescriptor descriptor, @NotNull TranslationContext context) {
super(context);
JsExpression fqReference = translateAsFQReference(descriptor, context());
this.referenceToDefaultObject = generateReferenceToDefaultObject(descriptor, context);
}
@NotNull
private static JsExpression generateReferenceToDefaultObject(@NotNull DeclarationDescriptor descriptor, @NotNull TranslationContext context) {
if (descriptor instanceof ClassDescriptor) {
ObjectIntrinsic objectIntrinsic = context.intrinsics().getObjectIntrinsics().getIntrinsic((ClassDescriptor) descriptor);
if (objectIntrinsic.exists()) {
return objectIntrinsic.apply(context);
}
}
JsExpression fqReference = translateAsFQReference(descriptor, context);
if (isObject(descriptor) || isEnumEntry(descriptor)) {
this.referenceToDefaultObject = fqReference;
}
else {
this.referenceToDefaultObject = Namer.getDefaultObjectAccessor(fqReference);
return fqReference;
}
return Namer.getDefaultObjectAccessor(fqReference);
}
@Override
+1
View File
@@ -6,6 +6,7 @@
<include name="src/kotlin/Functions.kt"/>
<include name="src/kotlin/Iterators.kt"/>
<include name="src/kotlin/Range.kt"/>
<include name="src/kotlin/FloatingPointConstants.kt"/>
</fileset>
<union id="js.lib.files">
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2015 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 kotlin.jvm
public val Int.Default.MIN_VALUE: Int get() = java.lang.Integer.MIN_VALUE
public val Int.Default.MAX_VALUE: Int get() = java.lang.Integer.MAX_VALUE
public val Double.Default.MIN_VALUE: Double get() = java.lang.Double.MIN_VALUE
public val Double.Default.MAX_VALUE: Double get() = java.lang.Double.MAX_VALUE
public val Float.Default.MIN_VALUE: Float get() = java.lang.Float.MIN_VALUE
public val Float.Default.MAX_VALUE: Float get() = java.lang.Float.MAX_VALUE
public val Long.Default.MIN_VALUE: Long get() = java.lang.Long.MIN_VALUE
public val Long.Default.MAX_VALUE: Long get() = java.lang.Long.MAX_VALUE
public val Short.Default.MIN_VALUE: Short get() = java.lang.Short.MIN_VALUE
public val Short.Default.MAX_VALUE: Short get() = java.lang.Short.MAX_VALUE
public val Byte.Default.MIN_VALUE: Byte get() = java.lang.Byte.MIN_VALUE
public val Byte.Default.MAX_VALUE: Byte get() = java.lang.Byte.MAX_VALUE