[JS IR BE] Reflection support

This commit is contained in:
Svyatoslav Kuzmich
2018-08-05 13:09:31 +03:00
parent 1471fe08d7
commit 392ad521fd
75 changed files with 563 additions and 104 deletions
@@ -4,6 +4,12 @@
*/
package kotlin
open class Error(override val message: String?, override val cause: Throwable?) : Throwable() {
constructor() : this(null, null)
constructor(_message: String?) : this(_message, null)
constructor(_cause: Throwable?) : this(null, _cause)
}
open class Exception(override val message: String?, override val cause: Throwable?) : Throwable() {
constructor() : this(null, null)
constructor(_message: String?) : this(_message, null)
+27
View File
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package kotlin
// TODO: Ignore FunctionN interfaces
public interface Function0<out R> : Function<R> {
public operator fun invoke(): R
}
public interface Function1<in P1, out R> : Function<R> {
public operator fun invoke(p1: P1): R
}
public interface Function2<in P1, in P2, out R> : Function<R> {
public operator fun invoke(p1: P1, p2: P2): R
}
public interface Function3<in P1, in P2, in P3, out R> : Function<R> {
public operator fun invoke(p1: P1, p2: P2, p3: P3): R
}
public inline fun <reified T> arrayOfNulls(size: Int): Array<T?> = js("[]") // FIXME: Implement
@@ -0,0 +1,355 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package kotlin.ranges
// FIXME: Use stdlib _Ranges.kt instead
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Int.downTo(to: Byte): IntProgression {
return IntProgression.fromClosedRange(this, to.toInt(), -1)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Long.downTo(to: Byte): LongProgression {
return LongProgression.fromClosedRange(this, to.toLong(), -1L)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Byte.downTo(to: Byte): IntProgression {
return IntProgression.fromClosedRange(this.toInt(), to.toInt(), -1)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Short.downTo(to: Byte): IntProgression {
return IntProgression.fromClosedRange(this.toInt(), to.toInt(), -1)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Char.downTo(to: Char): CharProgression {
return CharProgression.fromClosedRange(this, to, -1)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Int.downTo(to: Int): IntProgression {
return IntProgression.fromClosedRange(this, to, -1)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Long.downTo(to: Int): LongProgression {
return LongProgression.fromClosedRange(this, to.toLong(), -1L)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Byte.downTo(to: Int): IntProgression {
return IntProgression.fromClosedRange(this.toInt(), to, -1)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Short.downTo(to: Int): IntProgression {
return IntProgression.fromClosedRange(this.toInt(), to, -1)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Int.downTo(to: Long): LongProgression {
return LongProgression.fromClosedRange(this.toLong(), to, -1L)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Long.downTo(to: Long): LongProgression {
return LongProgression.fromClosedRange(this, to, -1L)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Byte.downTo(to: Long): LongProgression {
return LongProgression.fromClosedRange(this.toLong(), to, -1L)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Short.downTo(to: Long): LongProgression {
return LongProgression.fromClosedRange(this.toLong(), to, -1L)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Int.downTo(to: Short): IntProgression {
return IntProgression.fromClosedRange(this, to.toInt(), -1)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Long.downTo(to: Short): LongProgression {
return LongProgression.fromClosedRange(this, to.toLong(), -1L)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Byte.downTo(to: Short): IntProgression {
return IntProgression.fromClosedRange(this.toInt(), to.toInt(), -1)
}
/**
* Returns a progression from this value down to the specified [to] value with the step -1.
*
* The [to] value should be less than or equal to `this` value.
* If the [to] value is greater than `this` value the returned progression is empty.
*/
public infix fun Short.downTo(to: Short): IntProgression {
return IntProgression.fromClosedRange(this.toInt(), to.toInt(), -1)
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*/
public infix fun Int.until(to: Byte): IntRange {
return this .. (to.toInt() - 1).toInt()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*/
public infix fun Long.until(to: Byte): LongRange {
return this .. (to.toLong() - 1).toLong()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*/
public infix fun Byte.until(to: Byte): IntRange {
return this.toInt() .. (to.toInt() - 1).toInt()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*/
public infix fun Short.until(to: Byte): IntRange {
return this.toInt() .. (to.toInt() - 1).toInt()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*
* If the [to] value is less than or equal to `'\u0000'` the returned range is empty.
*/
public infix fun Char.until(to: Char): CharRange {
if (to <= '\u0000') return CharRange.EMPTY
return this .. (to - 1).toChar()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*
* If the [to] value is less than or equal to [Int.MIN_VALUE] the returned range is empty.
*/
public infix fun Int.until(to: Int): IntRange {
if (to <= Int.MIN_VALUE) return IntRange.EMPTY
return this .. (to - 1).toInt()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*/
public infix fun Long.until(to: Int): LongRange {
return this .. (to.toLong() - 1).toLong()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*
* If the [to] value is less than or equal to [Int.MIN_VALUE] the returned range is empty.
*/
public infix fun Byte.until(to: Int): IntRange {
if (to <= Int.MIN_VALUE) return IntRange.EMPTY
return this.toInt() .. (to - 1).toInt()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*
* If the [to] value is less than or equal to [Int.MIN_VALUE] the returned range is empty.
*/
public infix fun Short.until(to: Int): IntRange {
if (to <= Int.MIN_VALUE) return IntRange.EMPTY
return this.toInt() .. (to - 1).toInt()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*
* If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty.
*/
public infix fun Int.until(to: Long): LongRange {
if (to <= Long.MIN_VALUE) return LongRange.EMPTY
return this.toLong() .. (to - 1).toLong()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*
* If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty.
*/
public infix fun Long.until(to: Long): LongRange {
if (to <= Long.MIN_VALUE) return LongRange.EMPTY
return this .. (to - 1).toLong()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*
* If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty.
*/
public infix fun Byte.until(to: Long): LongRange {
if (to <= Long.MIN_VALUE) return LongRange.EMPTY
return this.toLong() .. (to - 1).toLong()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*
* If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty.
*/
public infix fun Short.until(to: Long): LongRange {
if (to <= Long.MIN_VALUE) return LongRange.EMPTY
return this.toLong() .. (to - 1).toLong()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*/
public infix fun Int.until(to: Short): IntRange {
return this .. (to.toInt() - 1).toInt()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*/
public infix fun Long.until(to: Short): LongRange {
return this .. (to.toLong() - 1).toLong()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*/
public infix fun Byte.until(to: Short): IntRange {
return this.toInt() .. (to.toInt() - 1).toInt()
}
/**
* Returns a range from this value up to but excluding the specified [to] value.
*
* If the [to] value is less than or equal to `this` value the returned range is empty.
*/
public infix fun Short.until(to: Short): IntRange {
return this.toInt() .. (to.toInt() - 1).toInt()
}
@@ -74,6 +74,8 @@ public fun isInterface(ctor: dynamic, IType: dynamic): Boolean {
fun typeOf(obj: dynamic) = js("typeof obj").unsafeCast<String>()
fun instanceOf(obj: dynamic, jsClass: dynamic) = js("obj instanceof jsClass").unsafeCast<Boolean>()
fun isObject(obj: dynamic): Boolean {
val objTypeOf = typeOf(obj)
@@ -96,4 +98,54 @@ public fun isArrayish(o: dynamic) =
public fun isChar(c: Any): Boolean {
return js("throw Error(\"isChar is not implemented\")").unsafeCast<Boolean>()
}
// TODO: Distinguish Boolean/Byte and Short/Char
public fun isBooleanArray(a: dynamic) = js("a instanceof Int8Array")
public fun isByteArray(a: dynamic) = js("a instanceof Int8Array")
public fun isShortArray(a: dynamic) = js("a instanceof Int16Array")
public fun isCharArray(a: dynamic) = js("a instanceof Uint16Array")
public fun isIntArray(a: dynamic) = js("a instanceof Int32Array")
public fun isFloatArray(a: dynamic) = js("a instanceof Float32Array")
public fun isDoubleArray(a: dynamic) = js("a instanceof Float64Array")
public fun isLongArray(a: dynamic) = isArray(a) // TODO: Implement
internal fun jsIn(x: String, y: dynamic): Boolean = js("x in y")
internal fun jsGetPrototypeOf(jsClass: dynamic) = js("Object.getPrototypeOf(jsClass)")
public fun jsIsType(obj: dynamic, jsClass: dynamic): Boolean {
if (jsClass === js("Object")) {
return isObject(obj)
}
if (obj == null || jsClass == null || (typeOf(obj) != "object" && typeOf(obj) != "function")) {
return false
}
if (typeOf(jsClass) == "function" && instanceOf(obj, jsClass)) {
return true
}
var proto = jsGetPrototypeOf(jsClass)
var constructor = proto?.constructor
if (constructor != null && jsIn("${'$'}metadata${'$'}", constructor)) {
var metadata = constructor.`$metadata$`
if (metadata.kind === "object") {
return obj === jsClass
}
}
var klassMetadata = jsClass.`$metadata$`
// In WebKit (JavaScriptCore) for some interfaces from DOM typeof returns "object", nevertheless they can be used in RHS of instanceof
if (klassMetadata == null) {
return instanceOf(obj, jsClass)
}
if (klassMetadata.kind === "interface" && obj.constructor != null) {
return isInterfaceImpl(obj.constructor, jsClass)
}
return false
}