fixed many bugs in closures processing also in flows
This commit is contained in:
parent
9aae33d564
commit
e0ed27a01f
@ -205,6 +205,20 @@ open class Scope(
|
||||
return "S[this=$thisObj $contents]"
|
||||
}
|
||||
|
||||
fun trace(text: String="") {
|
||||
println("trace Scope: $text ------------------")
|
||||
var p = this.parent
|
||||
var level = 0
|
||||
while (p != null) {
|
||||
println(" parent#${++level}: $p")
|
||||
println(" ( ${p.args.list} )")
|
||||
p = p.parent
|
||||
}
|
||||
println("--------------------")
|
||||
ObjVoid
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun new(): Scope =
|
||||
|
@ -26,8 +26,15 @@ class Script(
|
||||
|
||||
companion object {
|
||||
|
||||
private val rootScope: Scope = Scope(null).apply {
|
||||
internal val rootScope: Scope = Scope(null).apply {
|
||||
ObjException.addExceptionsToContext(this)
|
||||
addFn("print") {
|
||||
for ((i, a) in args.withIndex()) {
|
||||
if (i > 0) print(' ' + a.asStr.value)
|
||||
else print(a.asStr.value)
|
||||
}
|
||||
ObjVoid
|
||||
}
|
||||
addFn("println") {
|
||||
for ((i, a) in args.withIndex()) {
|
||||
if (i > 0) print(' ' + a.asStr.value)
|
||||
@ -153,16 +160,26 @@ class Script(
|
||||
}
|
||||
result ?: raiseError(ObjAssertionFailedException(this,"Expected exception but nothing was thrown"))
|
||||
}
|
||||
addFn("traceScope") {
|
||||
println("trace Scope: $this")
|
||||
var p = this.parent
|
||||
var level = 0
|
||||
while (p != null) {
|
||||
println(" parent#${++level}: $p")
|
||||
p = p.parent
|
||||
addFn("require") {
|
||||
val condition = requiredArg<ObjBool>(0)
|
||||
if( !condition.value ) {
|
||||
val message = args.list.getOrNull(1)?.toString() ?: "requirement not met"
|
||||
raiseIllegalArgument(message)
|
||||
}
|
||||
ObjVoid
|
||||
}
|
||||
addFn("check") {
|
||||
val condition = requiredArg<ObjBool>(0)
|
||||
if( !condition.value ) {
|
||||
val message = args.list.getOrNull(1)?.toString() ?: "check failed"
|
||||
raiseIllegalState(message)
|
||||
}
|
||||
ObjVoid
|
||||
}
|
||||
addFn("traceScope") {
|
||||
this.trace(args.get(0)?.toString() ?: "")
|
||||
ObjVoid
|
||||
}
|
||||
|
||||
addVoidFn("delay") {
|
||||
delay((this.args.firstAndOnly().toDouble()/1000.0).roundToLong())
|
||||
@ -204,7 +221,9 @@ class Script(
|
||||
}
|
||||
|
||||
addFn("flow") {
|
||||
ObjFlow(requireOnlyArg<Statement>())
|
||||
// important is: current context contains closure often used in call;
|
||||
// we'll need it for the producer
|
||||
ObjFlow(requireOnlyArg<Statement>(), this)
|
||||
}
|
||||
|
||||
val pi = ObjReal(PI)
|
||||
|
@ -7,9 +7,7 @@ import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import kotlinx.coroutines.channels.SendChannel
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import net.sergeych.lyng.Scope
|
||||
import net.sergeych.lyng.ScriptFlowIsNoMoreCollected
|
||||
import net.sergeych.lyng.Statement
|
||||
import net.sergeych.lyng.*
|
||||
import net.sergeych.mp_tools.globalLaunch
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
@ -60,7 +58,7 @@ private fun createLyngFlowInput(scope: Scope, producer: Statement): ReceiveChann
|
||||
return channel
|
||||
}
|
||||
|
||||
class ObjFlow(val producer: Statement) : Obj() {
|
||||
class ObjFlow(val producer: Statement, val scope: Scope) : Obj() {
|
||||
|
||||
override val objClass = type
|
||||
|
||||
@ -71,7 +69,8 @@ class ObjFlow(val producer: Statement) : Obj() {
|
||||
}
|
||||
}.apply {
|
||||
addFn("iterator") {
|
||||
ObjFlowIterator(thisAs<ObjFlow>().producer)
|
||||
val objFlow = thisAs<ObjFlow>()
|
||||
ObjFlowIterator( statement { objFlow.producer.execute(ClosureScope(this,objFlow.scope)) } )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,6 +111,5 @@ val ObjIterable by lazy {
|
||||
.not()
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package net.sergeych.lyng.stdlib_included
|
||||
|
||||
internal val rootLyng = """
|
||||
|
||||
""".trimIndent()
|
16
lynglib/src/commonMain/lyng/stdlib/Iterable.lyng
Normal file
16
lynglib/src/commonMain/lyng/stdlib/Iterable.lyng
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
fun Iterable.filter( predicate ) {
|
||||
flow {
|
||||
for( item in this )
|
||||
if( predicate(item) )
|
||||
emit(item)
|
||||
}
|
||||
}
|
||||
|
||||
fun Iterable.drop(n) {
|
||||
require( n >= 0, "drop amount must be non-negative")
|
||||
var count = 0
|
||||
filter {
|
||||
count++ < N
|
||||
}
|
||||
}
|
@ -106,4 +106,67 @@ class TestCoroutines {
|
||||
assertEquals( result, f.toList())
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFlowClosures() = runTest {
|
||||
eval("""
|
||||
fun filter( a, b ) {
|
||||
println("filter: %s, %s"(a,b))
|
||||
flow {
|
||||
emit(a)
|
||||
emit(b)
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals( [5, 1], filter(5,1).toList() )
|
||||
assertEquals( [2, 3], filter(2,3).toList() )
|
||||
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun testFilterFlow() = runTest {
|
||||
eval("""
|
||||
fun filter( list, predicate ) {
|
||||
val p = predicate
|
||||
println("predicate "+predicate+" / "+p)
|
||||
flow {
|
||||
// here p is captured only once and does not change!
|
||||
for( item in list ) {
|
||||
print("filter "+p+" "+item+": ")
|
||||
if( p(item) ) {
|
||||
println("OK")
|
||||
emit(item)
|
||||
}
|
||||
else println("NO")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fun drop(i, n) {
|
||||
// require( n >= 0, "drop amount must be non-negative")
|
||||
// var count = 0
|
||||
// println("drop %d"(n))
|
||||
// filter(i) {
|
||||
// count++ >= n
|
||||
// }
|
||||
// }
|
||||
|
||||
val src = (1..1).toList()
|
||||
assertEquals( 1, filter(src) { true }.toList().size )
|
||||
println("----------------------------------------------------------")
|
||||
println("----------------------------------------------------------")
|
||||
println("----------------------------------------------------------")
|
||||
println("----------------------------------------------------------")
|
||||
assertEquals( 0, filter(src) { false }.toList().size )
|
||||
// assertEquals( 3, filter(src) { true }.size() )
|
||||
|
||||
// assertEquals( [7,8], drop((1..8).toList(),6).toList())
|
||||
// assertEquals( [1,3,5,7], filter((1..8).toList()) {
|
||||
// println("call2")
|
||||
// it % 2 == 1
|
||||
// }.toList())
|
||||
""".trimIndent())
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user