Add EfficientIterables.md documentation for Kotlin interop. Optimize ObjInt operations by integrating value caching and updating number operations. Introduce high-performance enumerate method for ObjList, ObjSet, ObjRange, and custom iterables. Update compiler and loop handling for improved enumeration logic.
This commit is contained in:
1 parent
5f3a54d08f
commit
3f235878c0
12 files changed
+220
-77
No files matched your search
@@ -2040,7 +2040,7 @@ class Compiler(
|
||||
var breakCaught = false
|
||||
|
||||
if (size > 0) {
|
||||
var current = runCatching { sourceObj.getAt(forContext, ObjInt(0)) }
|
||||
var current = runCatching { sourceObj.getAt(forContext, ObjInt.of(0)) }
|
||||
.getOrElse {
|
||||
throw ScriptError(
|
||||
tOp.pos,
|
||||
@@ -2065,7 +2065,7 @@ class Compiler(
|
||||
throw lbe
|
||||
}
|
||||
if (++index >= size) break
|
||||
current = sourceObj.getAt(forContext, ObjInt(index.toLong()))
|
||||
current = sourceObj.getAt(forContext, ObjInt.of(index.toLong()))
|
||||
}
|
||||
}
|
||||
if (!breakCaught && elseStatement != null) {
|
||||
@@ -2087,7 +2087,7 @@ class Compiler(
|
||||
var result: Obj = ObjVoid
|
||||
if (catchBreak) {
|
||||
for (i in start..<end) {
|
||||
loopVar.value = ObjInt(i)
|
||||
loopVar.value = ObjInt.of(i)
|
||||
try {
|
||||
result = body.execute(forScope)
|
||||
} catch (lbe: LoopBreakContinueException) {
|
||||
@@ -2100,7 +2100,7 @@ class Compiler(
|
||||
}
|
||||
} else {
|
||||
for (i in start..<end) {
|
||||
loopVar.value = ObjInt(i)
|
||||
loopVar.value = ObjInt.of(i)
|
||||
result = body.execute(forScope)
|
||||
}
|
||||
}
|
||||
@@ -2112,38 +2112,33 @@ class Compiler(
|
||||
body: Statement, elseStatement: Statement?, label: String?,
|
||||
catchBreak: Boolean
|
||||
): Obj {
|
||||
val iterObj = sourceObj.invokeInstanceMethod(forScope, "iterator")
|
||||
var result: Obj = ObjVoid
|
||||
var completedNaturally = false
|
||||
try {
|
||||
while (iterObj.invokeInstanceMethod(forScope, "hasNext").toBool()) {
|
||||
if (catchBreak)
|
||||
try {
|
||||
loopVar.value = iterObj.invokeInstanceMethod(forScope, "next")
|
||||
result = body.execute(forScope)
|
||||
} catch (lbe: LoopBreakContinueException) {
|
||||
if (lbe.label == label || lbe.label == null) {
|
||||
if (lbe.doContinue) continue
|
||||
// premature finish, will trigger cancel in finally
|
||||
return lbe.result
|
||||
}
|
||||
throw lbe
|
||||
}
|
||||
else {
|
||||
loopVar.value = iterObj.invokeInstanceMethod(forScope, "next")
|
||||
var breakCaught = false
|
||||
sourceObj.enumerate(forScope) { item ->
|
||||
loopVar.value = item
|
||||
if (catchBreak) {
|
||||
try {
|
||||
result = body.execute(forScope)
|
||||
true
|
||||
} catch (lbe: LoopBreakContinueException) {
|
||||
if (lbe.label == label || lbe.label == null) {
|
||||
if (lbe.doContinue) true
|
||||
else {
|
||||
result = lbe.result
|
||||
breakCaught = true
|
||||
false
|
||||
}
|
||||
} else
|
||||
throw lbe
|
||||
}
|
||||
}
|
||||
completedNaturally = true
|
||||
return elseStatement?.execute(forScope) ?: result
|
||||
} finally {
|
||||
if (!completedNaturally) {
|
||||
// Best-effort cancellation on premature termination
|
||||
runCatching {
|
||||
iterObj.invokeInstanceMethod(forScope, "cancelIteration") { ObjVoid }
|
||||
}
|
||||
} else {
|
||||
result = body.execute(forScope)
|
||||
true
|
||||
}
|
||||
}
|
||||
return if (!breakCaught && elseStatement != null) {
|
||||
elseStatement.execute(forScope)
|
||||
} else result
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_VARIABLE")
|
||||
|
||||
@@ -127,6 +127,40 @@ open class Obj {
|
||||
return invokeInstanceMethod(scope, "contains", other).toBool()
|
||||
}
|
||||
|
||||
/**
|
||||
* Call [callback] for each element of this obj considering it provides [Iterator]
|
||||
* methods `hasNext` and `next`.
|
||||
*
|
||||
* IF callback returns false, iteration is stopped.
|
||||
*/
|
||||
open suspend fun enumerate(scope: Scope, callback: suspend (Obj) -> Boolean) {
|
||||
val iterator = invokeInstanceMethod(scope, "iterator")
|
||||
val hasNext = iterator.getInstanceMethod(scope, "hasNext")
|
||||
val next = iterator.getInstanceMethod(scope, "next")
|
||||
var closeIt = false
|
||||
try {
|
||||
while (hasNext.invoke(scope, iterator).toBool()) {
|
||||
val nextValue = next.invoke(scope, iterator)
|
||||
val shouldContinue = try {
|
||||
callback(nextValue)
|
||||
} catch (e: Exception) {
|
||||
// iteration aborted due to exception in callback
|
||||
closeIt = true
|
||||
throw e
|
||||
}
|
||||
if (!shouldContinue) {
|
||||
closeIt = true
|
||||
break
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (closeIt) {
|
||||
// Best-effort cancel on premature termination
|
||||
iterator.invokeInstanceMethod(scope, "cancelIteration") { ObjVoid }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default toString implementation:
|
||||
*
|
||||
@@ -444,8 +478,8 @@ open class Obj {
|
||||
is Obj -> obj
|
||||
is Double -> ObjReal(obj)
|
||||
is Float -> ObjReal(obj.toDouble())
|
||||
is Int -> ObjInt(obj.toLong())
|
||||
is Long -> ObjInt(obj)
|
||||
is Int -> ObjInt.of(obj.toLong())
|
||||
is Long -> ObjInt.of(obj)
|
||||
is String -> ObjString(obj)
|
||||
is CharSequence -> ObjString(obj.toString())
|
||||
is Boolean -> ObjBool(obj)
|
||||
|
||||
@@ -45,11 +45,11 @@ class ObjInt(val value: Long, override val isConst: Boolean = false) : Obj(), Nu
|
||||
}
|
||||
|
||||
override suspend fun incrementAndGet(scope: Scope): Obj {
|
||||
return ObjInt(value + 1)
|
||||
return of(value + 1)
|
||||
}
|
||||
|
||||
override suspend fun decrementAndGet(scope: Scope): Obj {
|
||||
return ObjInt(value - 1)
|
||||
return of(value - 1)
|
||||
}
|
||||
|
||||
override suspend fun compareTo(scope: Scope, other: Obj): Int {
|
||||
@@ -63,29 +63,29 @@ class ObjInt(val value: Long, override val isConst: Boolean = false) : Obj(), Nu
|
||||
|
||||
override suspend fun plus(scope: Scope, other: Obj): Obj =
|
||||
if (other is ObjInt)
|
||||
ObjInt(this.value + other.value)
|
||||
of(this.value + other.value)
|
||||
else
|
||||
ObjReal(this.doubleValue + other.toDouble())
|
||||
|
||||
override suspend fun minus(scope: Scope, other: Obj): Obj =
|
||||
if (other is ObjInt)
|
||||
ObjInt(this.value - other.value)
|
||||
of(this.value - other.value)
|
||||
else
|
||||
ObjReal(this.doubleValue - other.toDouble())
|
||||
|
||||
override suspend fun mul(scope: Scope, other: Obj): Obj =
|
||||
if (other is ObjInt) {
|
||||
ObjInt(this.value * other.value)
|
||||
of(this.value * other.value)
|
||||
} else ObjReal(this.value * other.toDouble())
|
||||
|
||||
override suspend fun div(scope: Scope, other: Obj): Obj =
|
||||
if (other is ObjInt)
|
||||
ObjInt(this.value / other.value)
|
||||
of(this.value / other.value)
|
||||
else ObjReal(this.value / other.toDouble())
|
||||
|
||||
override suspend fun mod(scope: Scope, other: Obj): Obj =
|
||||
if (other is ObjInt)
|
||||
ObjInt(this.value % other.value)
|
||||
of(this.value % other.value)
|
||||
else ObjReal(this.value.toDouble() % other.toDouble())
|
||||
|
||||
/**
|
||||
@@ -158,8 +158,15 @@ class ObjInt(val value: Long, override val isConst: Boolean = false) : Obj(), Nu
|
||||
}
|
||||
|
||||
companion object {
|
||||
val Zero = ObjInt(0, true)
|
||||
val One = ObjInt(1, true)
|
||||
private val cache = Array(256) { ObjInt((it - 128).toLong(), true) }
|
||||
|
||||
fun of(value: Long): ObjInt {
|
||||
return if (value in -128L..127L) cache[(value + 128).toInt()]
|
||||
else ObjInt(value)
|
||||
}
|
||||
|
||||
val Zero = of(0)
|
||||
val One = of(1)
|
||||
val type = object : ObjClass("Int") {
|
||||
override suspend fun deserialize(scope: Scope, decoder: LynonDecoder, lynonType: LynonType?): Obj =
|
||||
when (lynonType) {
|
||||
@@ -178,4 +185,5 @@ class ObjInt(val value: Long, override val isConst: Boolean = false) : Obj(), Nu
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.toObj() = ObjInt(this.toLong())
|
||||
fun Int.toObj() = ObjInt.of(this.toLong())
|
||||
fun Long.toObj() = ObjInt.of(this)
|
||||
@@ -76,36 +76,3 @@ fun Obj.toFlow(scope: Scope): Flow<Obj> = flow {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call [callback] for each element of this obj considering it provides [Iterator]
|
||||
* methods `hasNext` and `next`.
|
||||
*
|
||||
* IF callback returns false, iteration is stopped.
|
||||
*/
|
||||
suspend fun Obj.enumerate(scope: Scope, callback: suspend (Obj) -> Boolean) {
|
||||
val iterator = invokeInstanceMethod(scope, "iterator")
|
||||
val hasNext = iterator.getInstanceMethod(scope, "hasNext")
|
||||
val next = iterator.getInstanceMethod(scope, "next")
|
||||
var closeIt = false
|
||||
try {
|
||||
while (hasNext.invoke(scope, iterator).toBool()) {
|
||||
val nextValue = next.invoke(scope, iterator)
|
||||
val shouldContinue = try {
|
||||
callback(nextValue)
|
||||
} catch (e: Exception) {
|
||||
// iteration aborted due to exception in callback
|
||||
closeIt = true
|
||||
throw e
|
||||
}
|
||||
if (!shouldContinue) {
|
||||
closeIt = true
|
||||
break
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (closeIt) {
|
||||
// Best-effort cancel on premature termination
|
||||
iterator.invokeInstanceMethod(scope, "cancelIteration") { ObjVoid }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,6 +140,12 @@ class ObjList(val list: MutableList<Obj> = mutableListOf()) : Obj() {
|
||||
return list.contains(other)
|
||||
}
|
||||
|
||||
override suspend fun enumerate(scope: Scope, callback: suspend (Obj) -> Boolean) {
|
||||
for (item in list) {
|
||||
if (!callback(item)) break
|
||||
}
|
||||
}
|
||||
|
||||
override val objClass: ObjClass
|
||||
get() = type
|
||||
|
||||
|
||||
@@ -114,6 +114,36 @@ class ObjRange(val start: Obj?, val end: Obj?, val isEndInclusive: Boolean) : Ob
|
||||
start is ObjChar && end is ObjChar
|
||||
}
|
||||
|
||||
override suspend fun enumerate(scope: Scope, callback: suspend (Obj) -> Boolean) {
|
||||
if (isIntRange) {
|
||||
val s = (start as ObjInt).value
|
||||
val e = (end as ObjInt).value
|
||||
if (isEndInclusive) {
|
||||
for (i in s..e) {
|
||||
if (!callback(ObjInt.of(i))) break
|
||||
}
|
||||
} else {
|
||||
for (i in s..<e) {
|
||||
if (!callback(ObjInt.of(i))) break
|
||||
}
|
||||
}
|
||||
} else if (isCharRange) {
|
||||
val s = (start as ObjChar).value
|
||||
val e = (end as ObjChar).value
|
||||
if (isEndInclusive) {
|
||||
for (c in s..e) {
|
||||
if (!callback(ObjChar(c))) break
|
||||
}
|
||||
} else {
|
||||
for (c in s..<e) {
|
||||
if (!callback(ObjChar(c))) break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
super.enumerate(scope, callback)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun compareTo(scope: Scope, other: Obj): Int {
|
||||
return (other as? ObjRange)?.let {
|
||||
if( start == other.start && end == other.end ) 0 else -1
|
||||
|
||||
@@ -34,6 +34,12 @@ class ObjSet(val set: MutableSet<Obj> = mutableSetOf()) : Obj() {
|
||||
return set.contains(other)
|
||||
}
|
||||
|
||||
override suspend fun enumerate(scope: Scope, callback: suspend (Obj) -> Boolean) {
|
||||
for (item in set) {
|
||||
if (!callback(item)) break
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun plus(scope: Scope, other: Obj): Obj {
|
||||
return ObjSet(
|
||||
if (other is ObjSet)
|
||||
|
||||
Reference in new issue
Block a user