Scope.copy renamed to createChild for clarity; fixed error with Exception self serializing.
This commit is contained in:
		
							parent
							
								
									c854b06683
								
							
						
					
					
						commit
						7e289382ed
					
				@ -21,7 +21,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
 | 
				
			|||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
 | 
					import org.jetbrains.kotlin.gradle.dsl.JvmTarget
 | 
				
			||||||
 | 
					
 | 
				
			||||||
group = "net.sergeych"
 | 
					group = "net.sergeych"
 | 
				
			||||||
version = "0.9.2-SNAPSHOT"
 | 
					version = "0.9.3-SNAPSHOT"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
buildscript {
 | 
					buildscript {
 | 
				
			||||||
    repositories {
 | 
					    repositories {
 | 
				
			||||||
 | 
				
			|||||||
@ -796,7 +796,7 @@ class Compiler(
 | 
				
			|||||||
            val v = left.getter(context)
 | 
					            val v = left.getter(context)
 | 
				
			||||||
            if (v.value == ObjNull && isOptional) return@Accessor v.value.asReadonly
 | 
					            if (v.value == ObjNull && isOptional) return@Accessor v.value.asReadonly
 | 
				
			||||||
            v.value.callOn(
 | 
					            v.value.callOn(
 | 
				
			||||||
                context.copy(
 | 
					                context.createChildScope(
 | 
				
			||||||
                    context.pos,
 | 
					                    context.pos,
 | 
				
			||||||
                    args.toArguments(context, detectedBlockArgument)
 | 
					                    args.toArguments(context, detectedBlockArgument)
 | 
				
			||||||
//                Arguments(
 | 
					//                Arguments(
 | 
				
			||||||
@ -902,7 +902,7 @@ class Compiler(
 | 
				
			|||||||
            val args = extras?.let { required + it } ?: required
 | 
					            val args = extras?.let { required + it } ?: required
 | 
				
			||||||
            val fn = scope.get(t.value)?.value ?: scope.raiseSymbolNotFound("annotation not found: ${t.value}")
 | 
					            val fn = scope.get(t.value)?.value ?: scope.raiseSymbolNotFound("annotation not found: ${t.value}")
 | 
				
			||||||
            if (fn !is Statement) scope.raiseIllegalArgument("annotation must be callable, got ${fn.objClass}")
 | 
					            if (fn !is Statement) scope.raiseIllegalArgument("annotation must be callable, got ${fn.objClass}")
 | 
				
			||||||
            (fn.execute(scope.copy(Arguments(args))) as? Statement)
 | 
					            (fn.execute(scope.createChildScope(Arguments(args))) as? Statement)
 | 
				
			||||||
                ?: scope.raiseClassCastError("function annotation must return callable")
 | 
					                ?: scope.raiseClassCastError("function annotation must return callable")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -1197,7 +1197,7 @@ class Compiler(
 | 
				
			|||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    if (exceptionObject != null) {
 | 
					                    if (exceptionObject != null) {
 | 
				
			||||||
                        val catchContext = this.copy(pos = cdata.catchVar.pos)
 | 
					                        val catchContext = this.createChildScope(pos = cdata.catchVar.pos)
 | 
				
			||||||
                        catchContext.addItem(cdata.catchVar.value, false, objException)
 | 
					                        catchContext.addItem(cdata.catchVar.value, false, objException)
 | 
				
			||||||
                        result = cdata.block.execute(catchContext)
 | 
					                        result = cdata.block.execute(catchContext)
 | 
				
			||||||
                        isCaught = true
 | 
					                        isCaught = true
 | 
				
			||||||
@ -1313,7 +1313,7 @@ class Compiler(
 | 
				
			|||||||
                // accessors, constructor registration, etc.
 | 
					                // accessors, constructor registration, etc.
 | 
				
			||||||
                addItem(className, false, newClass)
 | 
					                addItem(className, false, newClass)
 | 
				
			||||||
                if (initScope.isNotEmpty()) {
 | 
					                if (initScope.isNotEmpty()) {
 | 
				
			||||||
                    val classScope = copy(newThisObj = newClass)
 | 
					                    val classScope = createChildScope(newThisObj = newClass)
 | 
				
			||||||
                    newClass.classScope = classScope
 | 
					                    newClass.classScope = classScope
 | 
				
			||||||
                    for (s in initScope)
 | 
					                    for (s in initScope)
 | 
				
			||||||
                        s.execute(classScope)
 | 
					                        s.execute(classScope)
 | 
				
			||||||
@ -1367,7 +1367,7 @@ class Compiler(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return statement(body.pos) { cxt ->
 | 
					            return statement(body.pos) { cxt ->
 | 
				
			||||||
                val forContext = cxt.copy(start)
 | 
					                val forContext = cxt.createChildScope(start)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // loop var: StoredObject
 | 
					                // loop var: StoredObject
 | 
				
			||||||
                val loopSO = forContext.addItem(tVar.value, true, ObjNull)
 | 
					                val loopSO = forContext.addItem(tVar.value, true, ObjNull)
 | 
				
			||||||
@ -1536,7 +1536,7 @@ class Compiler(
 | 
				
			|||||||
            var result: Obj = ObjVoid
 | 
					            var result: Obj = ObjVoid
 | 
				
			||||||
            lateinit var doScope: Scope
 | 
					            lateinit var doScope: Scope
 | 
				
			||||||
            do {
 | 
					            do {
 | 
				
			||||||
                doScope = it.copy().apply { skipScopeCreation = true }
 | 
					                doScope = it.createChildScope().apply { skipScopeCreation = true }
 | 
				
			||||||
                try {
 | 
					                try {
 | 
				
			||||||
                    result = body.execute(doScope)
 | 
					                    result = body.execute(doScope)
 | 
				
			||||||
                } catch (e: LoopBreakContinueException) {
 | 
					                } catch (e: LoopBreakContinueException) {
 | 
				
			||||||
@ -1816,7 +1816,7 @@ class Compiler(
 | 
				
			|||||||
        val block = parseScript()
 | 
					        val block = parseScript()
 | 
				
			||||||
        return statement(startPos) {
 | 
					        return statement(startPos) {
 | 
				
			||||||
            // block run on inner context:
 | 
					            // block run on inner context:
 | 
				
			||||||
            block.execute(if (it.skipScopeCreation) it else it.copy(startPos))
 | 
					            block.execute(if (it.skipScopeCreation) it else it.createChildScope(startPos))
 | 
				
			||||||
        }.also {
 | 
					        }.also {
 | 
				
			||||||
            val t1 = cc.next()
 | 
					            val t1 = cc.next()
 | 
				
			||||||
            if (t1.type != Token.Type.RBRACE)
 | 
					            if (t1.type != Token.Type.RBRACE)
 | 
				
			||||||
 | 
				
			|||||||
@ -138,13 +138,27 @@ open class Scope(
 | 
				
			|||||||
                    )
 | 
					                    )
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun copy(pos: Pos, args: Arguments = Arguments.EMPTY, newThisObj: Obj? = null): Scope =
 | 
					    /**
 | 
				
			||||||
 | 
					     * Creates a new child scope using the provided arguments and optional `thisObj`.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fun createChildScope(pos: Pos, args: Arguments = Arguments.EMPTY, newThisObj: Obj? = null): Scope =
 | 
				
			||||||
        Scope(this, args, pos, newThisObj ?: thisObj)
 | 
					        Scope(this, args, pos, newThisObj ?: thisObj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun copy(args: Arguments = Arguments.EMPTY, newThisObj: Obj? = null): Scope =
 | 
					    /**
 | 
				
			||||||
 | 
					     * Creates a new child scope using the provided arguments and optional `thisObj`.
 | 
				
			||||||
 | 
					     * The child scope inherits the current scope's properties such as position and the existing `thisObj` if no new `thisObj` is provided.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param args The arguments to associate with the child scope. Defaults to [Arguments.EMPTY].
 | 
				
			||||||
 | 
					     * @param newThisObj The new `thisObj` to associate with the child scope. Defaults to the current scope's `thisObj` if not provided.
 | 
				
			||||||
 | 
					     * @return A new instance of [Scope] initialized with the specified arguments and `thisObj`.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fun createChildScope(args: Arguments = Arguments.EMPTY, newThisObj: Obj? = null): Scope =
 | 
				
			||||||
        Scope(this, args, pos, newThisObj ?: thisObj)
 | 
					        Scope(this, args, pos, newThisObj ?: thisObj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun copy() = Scope(this, args, pos, thisObj)
 | 
					    /**
 | 
				
			||||||
 | 
					     * @return A child scope with the same arguments, position and [thisObj]
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    fun createChildScope() = Scope(this, args, pos, thisObj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun addItem(
 | 
					    fun addItem(
 | 
				
			||||||
        name: String,
 | 
					        name: String,
 | 
				
			||||||
@ -240,8 +254,6 @@ open class Scope(
 | 
				
			|||||||
            p = p.parent
 | 
					            p = p.parent
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        println("--------------------")
 | 
					        println("--------------------")
 | 
				
			||||||
        ObjVoid
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    open fun applyClosure(closure: Scope): Scope = ClosureScope(this, closure)
 | 
					    open fun applyClosure(closure: Scope): Scope = ClosureScope(this, closure)
 | 
				
			||||||
 | 
				
			|||||||
@ -17,15 +17,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package net.sergeych.lyng.obj
 | 
					package net.sergeych.lyng.obj
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import kotlinx.coroutines.sync.Mutex
 | 
					 | 
				
			||||||
import kotlinx.coroutines.sync.withLock
 | 
					 | 
				
			||||||
import kotlinx.serialization.SerialName
 | 
					import kotlinx.serialization.SerialName
 | 
				
			||||||
import kotlinx.serialization.Serializable
 | 
					import kotlinx.serialization.Serializable
 | 
				
			||||||
import net.sergeych.lyng.*
 | 
					import net.sergeych.lyng.*
 | 
				
			||||||
import net.sergeych.lynon.LynonDecoder
 | 
					import net.sergeych.lynon.LynonDecoder
 | 
				
			||||||
import net.sergeych.lynon.LynonEncoder
 | 
					import net.sergeych.lynon.LynonEncoder
 | 
				
			||||||
import net.sergeych.lynon.LynonType
 | 
					import net.sergeych.lynon.LynonType
 | 
				
			||||||
import net.sergeych.synctools.ProtectedOp
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
open class Obj {
 | 
					open class Obj {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -39,12 +36,12 @@ open class Obj {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    var isFrozen: Boolean = false
 | 
					    var isFrozen: Boolean = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private val monitor = Mutex()
 | 
					//    private val monitor = Mutex()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //    private val memberMutex = Mutex()
 | 
					    //    private val memberMutex = Mutex()
 | 
				
			||||||
    internal var parentInstances: MutableList<Obj> = mutableListOf()
 | 
					//    internal var parentInstances: MutableList<Obj> = mutableListOf()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private val opInstances = ProtectedOp()
 | 
					//    private val opInstances = ProtectedOp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    open suspend fun inspect(scope: Scope): String = toString(scope).value
 | 
					    open suspend fun inspect(scope: Scope): String = toString(scope).value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -100,7 +97,7 @@ open class Obj {
 | 
				
			|||||||
        // note that getInstanceMember traverses the hierarchy
 | 
					        // note that getInstanceMember traverses the hierarchy
 | 
				
			||||||
        objClass.getInstanceMember(scope.pos, name).value
 | 
					        objClass.getInstanceMember(scope.pos, name).value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun getMemberOrNull(name: String): Obj? = objClass.getInstanceMemberOrNull(name)?.value
 | 
					//    fun getMemberOrNull(name: String): Obj? = objClass.getInstanceMemberOrNull(name)?.value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // methods that to override
 | 
					    // methods that to override
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -232,14 +229,14 @@ open class Obj {
 | 
				
			|||||||
        if (isFrozen) scope.raiseError("attempt to mutate frozen object")
 | 
					        if (isFrozen) scope.raiseError("attempt to mutate frozen object")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    suspend fun <T> sync(block: () -> T): T = monitor.withLock { block() }
 | 
					//    suspend fun <T> sync(block: () -> T): T = monitor.withLock { block() }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    open suspend fun readField(scope: Scope, name: String): ObjRecord {
 | 
					    open suspend fun readField(scope: Scope, name: String): ObjRecord {
 | 
				
			||||||
        // could be property or class field:
 | 
					        // could be property or class field:
 | 
				
			||||||
        val obj = objClass.getInstanceMemberOrNull(name) ?: scope.raiseError("no such field: $name")
 | 
					        val obj = objClass.getInstanceMemberOrNull(name) ?: scope.raiseError("no such field: $name")
 | 
				
			||||||
        return when (val value = obj.value) {
 | 
					        return when (val value = obj.value) {
 | 
				
			||||||
            is Statement -> {
 | 
					            is Statement -> {
 | 
				
			||||||
                ObjRecord(value.execute(scope.copy(scope.pos, newThisObj = this)), obj.isMutable)
 | 
					                ObjRecord(value.execute(scope.createChildScope(scope.pos, newThisObj = this)), obj.isMutable)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            // could be writable property naturally
 | 
					            // could be writable property naturally
 | 
				
			||||||
//            null -> ObjNull.asReadonly
 | 
					//            null -> ObjNull.asReadonly
 | 
				
			||||||
@ -268,11 +265,11 @@ open class Obj {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    suspend fun invoke(scope: Scope, thisObj: Obj, args: Arguments): Obj =
 | 
					    suspend fun invoke(scope: Scope, thisObj: Obj, args: Arguments): Obj =
 | 
				
			||||||
        callOn(scope.copy(scope.pos, args = args, newThisObj = thisObj))
 | 
					        callOn(scope.createChildScope(scope.pos, args = args, newThisObj = thisObj))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    suspend fun invoke(scope: Scope, thisObj: Obj, vararg args: Obj): Obj =
 | 
					    suspend fun invoke(scope: Scope, thisObj: Obj, vararg args: Obj): Obj =
 | 
				
			||||||
        callOn(
 | 
					        callOn(
 | 
				
			||||||
            scope.copy(
 | 
					            scope.createChildScope(
 | 
				
			||||||
                scope.pos,
 | 
					                scope.pos,
 | 
				
			||||||
                args = Arguments(args.toList()),
 | 
					                args = Arguments(args.toList()),
 | 
				
			||||||
                newThisObj = thisObj
 | 
					                newThisObj = thisObj
 | 
				
			||||||
@ -281,7 +278,7 @@ open class Obj {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    suspend fun invoke(scope: Scope, thisObj: Obj): Obj =
 | 
					    suspend fun invoke(scope: Scope, thisObj: Obj): Obj =
 | 
				
			||||||
        callOn(
 | 
					        callOn(
 | 
				
			||||||
            scope.copy(
 | 
					            scope.createChildScope(
 | 
				
			||||||
                scope.pos,
 | 
					                scope.pos,
 | 
				
			||||||
                args = Arguments.EMPTY,
 | 
					                args = Arguments.EMPTY,
 | 
				
			||||||
                newThisObj = thisObj
 | 
					                newThisObj = thisObj
 | 
				
			||||||
@ -289,7 +286,7 @@ open class Obj {
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    suspend fun invoke(scope: Scope, atPos: Pos, thisObj: Obj, args: Arguments): Obj =
 | 
					    suspend fun invoke(scope: Scope, atPos: Pos, thisObj: Obj, args: Arguments): Obj =
 | 
				
			||||||
        callOn(scope.copy(atPos, args = args, newThisObj = thisObj))
 | 
					        callOn(scope.createChildScope(atPos, args = args, newThisObj = thisObj))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    val asReadonly: ObjRecord by lazy { ObjRecord(this, false) }
 | 
					    val asReadonly: ObjRecord by lazy { ObjRecord(this, false) }
 | 
				
			||||||
@ -302,7 +299,7 @@ open class Obj {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun autoInstanceScope(parent: Scope): Scope {
 | 
					    fun autoInstanceScope(parent: Scope): Scope {
 | 
				
			||||||
        val scope = parent.copy(newThisObj = this, args = parent.args)
 | 
					        val scope = parent.createChildScope(newThisObj = this, args = parent.args)
 | 
				
			||||||
        for (m in objClass.members) {
 | 
					        for (m in objClass.members) {
 | 
				
			||||||
            scope.objects[m.key] = m.value
 | 
					            scope.objects[m.key] = m.value
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -335,7 +332,7 @@ open class Obj {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            // utilities
 | 
					            // utilities
 | 
				
			||||||
            addFn("let") {
 | 
					            addFn("let") {
 | 
				
			||||||
                args.firstAndOnly().callOn(copy(Arguments(thisObj)))
 | 
					                args.firstAndOnly().callOn(createChildScope(Arguments(thisObj)))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            addFn("apply") {
 | 
					            addFn("apply") {
 | 
				
			||||||
                val body = args.firstAndOnly()
 | 
					                val body = args.firstAndOnly()
 | 
				
			||||||
@ -347,7 +344,7 @@ open class Obj {
 | 
				
			|||||||
                thisObj
 | 
					                thisObj
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            addFn("also") {
 | 
					            addFn("also") {
 | 
				
			||||||
                args.firstAndOnly().callOn(copy(Arguments(thisObj)))
 | 
					                args.firstAndOnly().callOn(createChildScope(Arguments(thisObj)))
 | 
				
			||||||
                thisObj
 | 
					                thisObj
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            addFn("run") {
 | 
					            addFn("run") {
 | 
				
			||||||
 | 
				
			|||||||
@ -61,7 +61,7 @@ open class ObjClass(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    override suspend fun callOn(scope: Scope): Obj {
 | 
					    override suspend fun callOn(scope: Scope): Obj {
 | 
				
			||||||
        val instance = ObjInstance(this)
 | 
					        val instance = ObjInstance(this)
 | 
				
			||||||
        instance.instanceScope = scope.copy(newThisObj = instance, args = scope.args)
 | 
					        instance.instanceScope = scope.createChildScope(newThisObj = instance, args = scope.args)
 | 
				
			||||||
        if (instanceConstructor != null) {
 | 
					        if (instanceConstructor != null) {
 | 
				
			||||||
            instanceConstructor!!.execute(instance.instanceScope)
 | 
					            instanceConstructor!!.execute(instance.instanceScope)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -69,7 +69,7 @@ open class ObjClass(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    suspend fun callWithArgs(scope: Scope, vararg plainArgs: Obj): Obj {
 | 
					    suspend fun callWithArgs(scope: Scope, vararg plainArgs: Obj): Obj {
 | 
				
			||||||
        return callOn(scope.copy(Arguments(*plainArgs)))
 | 
					        return callOn(scope.createChildScope(Arguments(*plainArgs)))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -53,7 +53,7 @@ class ObjDynamic : Obj() {
 | 
				
			|||||||
    internal var writeCallback: Statement? = null
 | 
					    internal var writeCallback: Statement? = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override suspend fun readField(scope: Scope, name: String): ObjRecord {
 | 
					    override suspend fun readField(scope: Scope, name: String): ObjRecord {
 | 
				
			||||||
        return readCallback?.execute(scope.copy(Arguments(ObjString(name))))?.let {
 | 
					        return readCallback?.execute(scope.createChildScope(Arguments(ObjString(name))))?.let {
 | 
				
			||||||
            if (writeCallback != null)
 | 
					            if (writeCallback != null)
 | 
				
			||||||
                it.asMutable
 | 
					                it.asMutable
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
@ -63,17 +63,17 @@ class ObjDynamic : Obj() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override suspend fun writeField(scope: Scope, name: String, newValue: Obj) {
 | 
					    override suspend fun writeField(scope: Scope, name: String, newValue: Obj) {
 | 
				
			||||||
        writeCallback?.execute(scope.copy(Arguments(ObjString(name), newValue)))
 | 
					        writeCallback?.execute(scope.createChildScope(Arguments(ObjString(name), newValue)))
 | 
				
			||||||
            ?: super.writeField(scope, name, newValue)
 | 
					            ?: super.writeField(scope, name, newValue)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override suspend fun getAt(scope: Scope, index: Obj): Obj {
 | 
					    override suspend fun getAt(scope: Scope, index: Obj): Obj {
 | 
				
			||||||
        return readCallback?.execute( scope.copy(Arguments(index)))
 | 
					        return readCallback?.execute( scope.createChildScope(Arguments(index)))
 | 
				
			||||||
            ?: super.getAt(scope, index)
 | 
					            ?: super.getAt(scope, index)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override suspend fun putAt(scope: Scope, index: Obj, newValue: Obj) {
 | 
					    override suspend fun putAt(scope: Scope, index: Obj, newValue: Obj) {
 | 
				
			||||||
        writeCallback?.execute(scope.copy(Arguments(index, newValue)))
 | 
					        writeCallback?.execute(scope.createChildScope(Arguments(index, newValue)))
 | 
				
			||||||
            ?: super.putAt(scope, index, newValue)
 | 
					            ?: super.putAt(scope, index, newValue)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -82,7 +82,7 @@ class ObjDynamic : Obj() {
 | 
				
			|||||||
        suspend fun create(scope: Scope, builder: Statement): ObjDynamic {
 | 
					        suspend fun create(scope: Scope, builder: Statement): ObjDynamic {
 | 
				
			||||||
            val delegate = ObjDynamic()
 | 
					            val delegate = ObjDynamic()
 | 
				
			||||||
            val context = ObjDynamicContext(delegate)
 | 
					            val context = ObjDynamicContext(delegate)
 | 
				
			||||||
            builder.execute(scope.copy(newThisObj = context))
 | 
					            builder.execute(scope.createChildScope(newThisObj = context))
 | 
				
			||||||
            return delegate
 | 
					            return delegate
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -28,9 +28,9 @@ import net.sergeych.synctools.withLock
 | 
				
			|||||||
import kotlin.contracts.ExperimentalContracts
 | 
					import kotlin.contracts.ExperimentalContracts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * note on [getStackTrace]. If [useStackTrace] is not null, it is used instead. Otherwise, it is calculated
 | 
					 * Note on [getStackTrace]. If [useStackTrace] is not null, it is used instead. Otherwise, it is calculated
 | 
				
			||||||
 * from the current scope which is treated as exception scope. It is used to restore serialized
 | 
					 * from the current scope, which is treated as an exception scope. It is used to restore a serialized
 | 
				
			||||||
 * exception with stack trace; the scope of the de-serialized exception is not valid
 | 
					 * exception with stack trace; the scope of the deserialized exception is not valid
 | 
				
			||||||
 * for stack unwinding.
 | 
					 * for stack unwinding.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
open class ObjException(
 | 
					open class ObjException(
 | 
				
			||||||
@ -127,7 +127,7 @@ open class ObjException(
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val Root = ExceptionClass("Throwable").apply {
 | 
					        val Root = ExceptionClass("Exception").apply {
 | 
				
			||||||
            addConst("message", statement {
 | 
					            addConst("message", statement {
 | 
				
			||||||
                (thisObj as ObjException).message.toObj()
 | 
					                (thisObj as ObjException).message.toObj()
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
 | 
				
			|||||||
@ -58,7 +58,7 @@ class ObjFlowBuilder(val output: SendChannel<Obj>) : Obj() {
 | 
				
			|||||||
private fun createLyngFlowInput(scope: Scope, producer: Statement): ReceiveChannel<Obj> {
 | 
					private fun createLyngFlowInput(scope: Scope, producer: Statement): ReceiveChannel<Obj> {
 | 
				
			||||||
    val channel = Channel<Obj>(Channel.RENDEZVOUS)
 | 
					    val channel = Channel<Obj>(Channel.RENDEZVOUS)
 | 
				
			||||||
    val builder = ObjFlowBuilder(channel)
 | 
					    val builder = ObjFlowBuilder(channel)
 | 
				
			||||||
    val builderScope = scope.copy(newThisObj = builder)
 | 
					    val builderScope = scope.createChildScope(newThisObj = builder)
 | 
				
			||||||
    globalLaunch {
 | 
					    globalLaunch {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            producer.execute(builderScope)
 | 
					            producer.execute(builderScope)
 | 
				
			||||||
 | 
				
			|||||||
@ -32,7 +32,7 @@ class ObjInstanceClass(val name: String) : ObjClass(name) {
 | 
				
			|||||||
        val actualSize = constructorMeta?.params?.size ?: 0
 | 
					        val actualSize = constructorMeta?.params?.size ?: 0
 | 
				
			||||||
        if (args.size > actualSize)
 | 
					        if (args.size > actualSize)
 | 
				
			||||||
            scope.raiseIllegalArgument("constructor $name has only $actualSize but serialized version has ${args.size}")
 | 
					            scope.raiseIllegalArgument("constructor $name has only $actualSize but serialized version has ${args.size}")
 | 
				
			||||||
        val newScope = scope.copy(args = Arguments(args))
 | 
					        val newScope = scope.createChildScope(args = Arguments(args))
 | 
				
			||||||
        return (callOn(newScope) as ObjInstance).apply {
 | 
					        return (callOn(newScope) as ObjInstance).apply {
 | 
				
			||||||
            deserializeStateVars(scope, decoder)
 | 
					            deserializeStateVars(scope, decoder)
 | 
				
			||||||
            invokeInstanceMethod(scope, "onDeserialized") { ObjVoid }
 | 
					            invokeInstanceMethod(scope, "onDeserialized") { ObjVoid }
 | 
				
			||||||
 | 
				
			|||||||
@ -93,7 +93,7 @@ val ObjIterable by lazy {
 | 
				
			|||||||
            val fn = requiredArg<Statement>(0)
 | 
					            val fn = requiredArg<Statement>(0)
 | 
				
			||||||
            while (it.invokeInstanceMethod(this, "hasNext").toBool()) {
 | 
					            while (it.invokeInstanceMethod(this, "hasNext").toBool()) {
 | 
				
			||||||
                val x = it.invokeInstanceMethod(this, "next")
 | 
					                val x = it.invokeInstanceMethod(this, "next")
 | 
				
			||||||
                fn.execute(this.copy(Arguments(listOf(x))))
 | 
					                fn.execute(this.createChildScope(Arguments(listOf(x))))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ObjVoid
 | 
					            ObjVoid
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -71,7 +71,7 @@ abstract class ImportProvider(
 | 
				
			|||||||
            newModuleAt(pos).also {
 | 
					            newModuleAt(pos).also {
 | 
				
			||||||
                it.eval("import lyng.stdlib\n")
 | 
					                it.eval("import lyng.stdlib\n")
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }.copy()
 | 
					        }.createChildScope()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -60,7 +60,7 @@ abstract class Statement(
 | 
				
			|||||||
        val type = ObjClass("Callable")
 | 
					        val type = ObjClass("Callable")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    suspend fun call(scope: Scope, vararg args: Obj) = execute(scope.copy(args =  Arguments(*args)))
 | 
					    suspend fun call(scope: Scope, vararg args: Obj) = execute(scope.createChildScope(args =  Arguments(*args)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3170,6 +3170,34 @@ class ScriptTest {
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    fun testExceptionSerializationPlain() = runTest {
 | 
				
			||||||
 | 
					        eval(
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					                import lyng.serialization
 | 
				
			||||||
 | 
					                val x = [1,2,3]
 | 
				
			||||||
 | 
					                assertEquals( "[1,2,3]", x.toString() )
 | 
				
			||||||
 | 
					                try {    
 | 
				
			||||||
 | 
					                    throw "test"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                catch (e) {
 | 
				
			||||||
 | 
					                    println(e.stackTrace)
 | 
				
			||||||
 | 
					                    e.printStackTrace()
 | 
				
			||||||
 | 
					                    val coded = Lynon.encode(e)
 | 
				
			||||||
 | 
					                    val decoded = Lynon.decode(coded)
 | 
				
			||||||
 | 
					                    assertEquals( e::class, decoded::class )
 | 
				
			||||||
 | 
					                    assertEquals( e.stackTrace, decoded.stackTrace )
 | 
				
			||||||
 | 
					                    assertEquals( e.message, decoded.message )
 | 
				
			||||||
 | 
					                    println("-------------------- e")
 | 
				
			||||||
 | 
					                    println(e.toString())
 | 
				
			||||||
 | 
					                    println("-------------------- dee")
 | 
				
			||||||
 | 
					                    println(decoded.toString())
 | 
				
			||||||
 | 
					                    assertEquals( e.toString(), decoded.toString() )
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                """.trimIndent()
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test
 | 
					    @Test
 | 
				
			||||||
    fun testThisInClosure() = runTest {
 | 
					    fun testThisInClosure() = runTest {
 | 
				
			||||||
        eval(
 | 
					        eval(
 | 
				
			||||||
@ -3287,25 +3315,25 @@ class ScriptTest {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //    @Test
 | 
					    //    @Test
 | 
				
			||||||
    fun testMinimumOptimization() = runTest {
 | 
					//    fun testMinimumOptimization() = runTest {
 | 
				
			||||||
        val x = Scope().eval(
 | 
					//        val x = Scope().eval(
 | 
				
			||||||
            """
 | 
					//            """
 | 
				
			||||||
                fun naiveCountHappyNumbers() {
 | 
					//                fun naiveCountHappyNumbers() {
 | 
				
			||||||
                    var count = 0
 | 
					//                    var count = 0
 | 
				
			||||||
                    for( n1 in 0..9 )
 | 
					//                    for( n1 in 0..9 )
 | 
				
			||||||
                        for( n2 in 0..9 )
 | 
					//                        for( n2 in 0..9 )
 | 
				
			||||||
                            for( n3 in 0..9 )
 | 
					//                            for( n3 in 0..9 )
 | 
				
			||||||
                                for( n4 in 0..9 )
 | 
					//                                for( n4 in 0..9 )
 | 
				
			||||||
                                    for( n5 in 0..9 )
 | 
					//                                    for( n5 in 0..9 )
 | 
				
			||||||
                                        for( n6 in 0..9 )
 | 
					//                                        for( n6 in 0..9 )
 | 
				
			||||||
                                            if( n1 + n2 + n3 == n4 + n5 + n6 ) count++
 | 
					//                                            if( n1 + n2 + n3 == n4 + n5 + n6 ) count++
 | 
				
			||||||
                    count
 | 
					//                    count
 | 
				
			||||||
                }
 | 
					//                }
 | 
				
			||||||
                naiveCountHappyNumbers()
 | 
					//                naiveCountHappyNumbers()
 | 
				
			||||||
            """.trimIndent()
 | 
					//            """.trimIndent()
 | 
				
			||||||
        ).toInt()
 | 
					//        ).toInt()
 | 
				
			||||||
        assertEquals(55252, x)
 | 
					//        assertEquals(55252, x)
 | 
				
			||||||
    }
 | 
					//    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test
 | 
					    @Test
 | 
				
			||||||
    fun testRegex1() = runTest {
 | 
					    fun testRegex1() = runTest {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user