diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt index 5a96712..2d571e9 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt @@ -26,6 +26,7 @@ import net.sergeych.lyng.miniast.* import net.sergeych.lyng.obj.* import net.sergeych.lyng.pacman.ImportManager import net.sergeych.lyng.stdlib_included.rootLyng +import net.sergeych.lyng.bridge.LyngClassBridge import net.sergeych.lynon.ObjLynonClass import net.sergeych.mp_tools.globalDefer import kotlin.math.* @@ -560,9 +561,12 @@ class Script( val defaultImportManager: ImportManager by lazy { ImportManager(rootScope, SecurityManager.allowAll).apply { - addTextPackages( - rootLyng - ) + addPackage("lyng.stdlib") { module -> + module.eval(Source("lyng.stdlib", rootLyng)) + val cls = module["KotlinIterator"]?.value as? ObjClass + ?: module.raiseSymbolNotFound("KotlinIterator") + ObjKotlinIterator.bindTo(cls) + } addPackage("lyng.buffer") { it.addConstDoc( name = "Buffer", diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjKotlinIterator.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjKotlinIterator.kt index 0f606af..901c228 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjKotlinIterator.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjKotlinIterator.kt @@ -22,6 +22,7 @@ package net.sergeych.lyng.obj import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import net.sergeych.lyng.Scope +import net.sergeych.lyng.bridge.LyngClassBridge /** * Iterator wrapper to allow Kotlin collections to be returned from Lyng objects; @@ -32,9 +33,33 @@ class ObjKotlinIterator(val iterator: Iterator) : Obj() { override val objClass get() = type companion object { - val type = ObjClass("KotlinIterator", ObjIterator).apply { - addFn("next") { thisAs().iterator.next().toObj() } - addFn("hasNext") { thisAs().iterator.hasNext().toObj() } + private var boundType: ObjClass? = null + + val type: ObjClass + get() = boundType ?: error("KotlinIterator class is not bound; import lyng.stdlib first") + + internal fun bindTo(cls: ObjClass) { + if (boundType != null) { + if (boundType === cls) return + return + } + boundType = cls + LyngClassBridge.bind(cls) { + addFun("next") { scope, self, _ -> + when (self) { + is ObjKotlinIterator -> self.iterator.next().toObj() + is ObjKotlinObjIterator -> self.iterator.next() + else -> scope.raiseClassCastError("Expected KotlinIterator, got ${self.objClass.className}") + } + } + addFun("hasNext") { scope, self, _ -> + when (self) { + is ObjKotlinIterator -> self.iterator.hasNext().toObj() + is ObjKotlinObjIterator -> self.iterator.hasNext().toObj() + else -> scope.raiseClassCastError("Expected KotlinIterator, got ${self.objClass.className}") + } + } + } } } @@ -49,14 +74,8 @@ class ObjKotlinObjIterator(val iterator: Iterator) : Obj() { override val objClass get() = type companion object { - val type = ObjClass("KotlinIterator", ObjIterator).apply { - addFn("next") { - thisAs().iterator.next() - } - addFn("hasNext") { - thisAs().iterator.hasNext().toObj() - } - } + val type: ObjClass + get() = ObjKotlinIterator.type } } @@ -75,4 +94,3 @@ fun Obj.toFlow(scope: Scope): Flow = flow { emit(next.invoke(scope, iterator)) } } - diff --git a/lynglib/stdlib/lyng/root.lyng b/lynglib/stdlib/lyng/root.lyng index 13a8fe0..f44abcf 100644 --- a/lynglib/stdlib/lyng/root.lyng +++ b/lynglib/stdlib/lyng/root.lyng @@ -21,6 +21,12 @@ extern class Iterator { fun toList(): List } +// Host-provided iterator wrapper for Kotlin collections. +class KotlinIterator : Iterator { + extern override fun hasNext(): Bool + extern override fun next(): T +} + extern class Collection : Iterable { }