associateBy and Lyng:Iterable .toFlow() for kotlin integration simplicity
This commit is contained in:
1 parent
ea2cf1f373
commit
950e8301c3
10 files changed
+86
-12
No files matched your search
@@ -158,7 +158,6 @@ class Compiler(
|
||||
isCall = true
|
||||
val lambda =
|
||||
parseLambdaExpression(cc)
|
||||
println(cc.current())
|
||||
operand = Accessor { context ->
|
||||
context.pos = next.pos
|
||||
val v = left.getter(context).value
|
||||
|
||||
@@ -87,6 +87,14 @@ open class Obj {
|
||||
// note that getInstanceMember traverses the hierarchy
|
||||
objClass.getInstanceMember(context.pos, name).value.invoke(context, this, args)
|
||||
|
||||
open suspend fun getInstanceMethod(
|
||||
context: Context,
|
||||
name: String,
|
||||
args: Arguments = Arguments.EMPTY
|
||||
): Obj =
|
||||
// note that getInstanceMember traverses the hierarchy
|
||||
objClass.getInstanceMember(context.pos, name).value
|
||||
|
||||
fun getMemberOrNull(name: String): Obj? = objClass.getInstanceMemberOrNull(name)?.value
|
||||
|
||||
// methods that to override
|
||||
@@ -210,6 +218,8 @@ open class Obj {
|
||||
context.raiseNotImplemented("indexing")
|
||||
}
|
||||
|
||||
suspend fun getAt(context: Context, index: Int): Obj = getAt(context, ObjInt(index.toLong()))
|
||||
|
||||
open suspend fun putAt(context: Context, index: Int, newValue: Obj) {
|
||||
context.raiseNotImplemented("indexing")
|
||||
}
|
||||
|
||||
@@ -48,12 +48,20 @@ val ObjIterable by lazy {
|
||||
}
|
||||
|
||||
addFn("toMap") {
|
||||
val result = mutableListOf<Obj>()
|
||||
val it = thisObj.invokeInstanceMethod(this, "iterator")
|
||||
while (it.invokeInstanceMethod(this, "hasNext").toBool()) {
|
||||
result += it.invokeInstanceMethod(this, "next")
|
||||
val result = ObjMap()
|
||||
thisObj.toFlow(this).collect { pair ->
|
||||
result.map[pair.getAt(this,0)] = pair.getAt(this, 1)
|
||||
}
|
||||
ObjMap(ObjMap.listToMap(this, result))
|
||||
result
|
||||
}
|
||||
|
||||
addFn("associateBy") {
|
||||
val association = requireOnlyArg<Statement>()
|
||||
val result = ObjMap()
|
||||
thisObj.toFlow(this).collect {
|
||||
result.map[association.call(this, it)] = it
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
addFn("forEach", isOpen = true) {
|
||||
@@ -67,12 +75,10 @@ val ObjIterable by lazy {
|
||||
}
|
||||
|
||||
addFn("map", isOpen = true) {
|
||||
val it = thisObj.invokeInstanceMethod(this, "iterator")
|
||||
val fn = requiredArg<Statement>(0)
|
||||
val result = mutableListOf<Obj>()
|
||||
while (it.invokeInstanceMethod(this, "hasNext").toBool()) {
|
||||
val x = it.invokeInstanceMethod(this, "next")
|
||||
result += fn.execute(this.copy(Arguments(listOf(x))))
|
||||
thisObj.toFlow(this).collect {
|
||||
result += fn.call(this, it)
|
||||
}
|
||||
ObjList(result)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
package net.sergeych.lyng
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
|
||||
/**
|
||||
* Iterator wrapper to allow Kotlin collections to be returned from Lyng objects;
|
||||
* each object is converted to a Lyng object.
|
||||
@@ -36,4 +39,19 @@ class ObjKotlinObjIterator(val iterator: Iterator<Obj>) : Obj() {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Lyng's Iterable to Kotlin's Flow.
|
||||
*
|
||||
* As Lyng is totally asynchronous, its iterator can't be trivially converted to Kotlin's synchronous iterator.
|
||||
* It is, though, trivially convertible to Kotlin's Flow.
|
||||
*/
|
||||
fun Obj.toFlow(context: Context): Flow<Obj> = flow {
|
||||
val iterator = invokeInstanceMethod(context, "iterator")
|
||||
val hasNext = iterator.getInstanceMethod(context, "hasNext")
|
||||
val next = iterator.getInstanceMethod(context, "next")
|
||||
while (hasNext.invoke(context, iterator).toBool()) {
|
||||
emit(next.invoke(context, iterator))
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ class ObjMapEntry(val key: Obj, val value: Obj) : Obj() {
|
||||
}
|
||||
}
|
||||
|
||||
class ObjMap(val map: MutableMap<Obj, Obj>) : Obj() {
|
||||
class ObjMap(val map: MutableMap<Obj, Obj> = mutableMapOf()) : Obj() {
|
||||
|
||||
override val objClass = type
|
||||
|
||||
|
||||
@@ -76,6 +76,9 @@ data class ObjString(val value: String) : Obj() {
|
||||
|
||||
companion object {
|
||||
val type = ObjClass("String").apply {
|
||||
addFn("toInt") {
|
||||
ObjInt(thisAs<ObjString>().value.toLong())
|
||||
}
|
||||
addFn("startsWith") {
|
||||
ObjBool(thisAs<ObjString>().value.startsWith(requiredArg<ObjString>(0).value))
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ abstract class Statement(
|
||||
val type = ObjClass("Callable")
|
||||
}
|
||||
|
||||
suspend fun call(context: Context,vararg args: Obj) = execute(context.copy(args = Arguments(*args)))
|
||||
|
||||
}
|
||||
|
||||
fun Statement.raise(text: String): Nothing {
|
||||
|
||||
Reference in new issue
Block a user