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
@@ -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