Step 24D: bytecode-only closure path for lambdas
This commit is contained in:
parent
c066dc7150
commit
abbebec153
@ -2877,7 +2877,12 @@ class Compiler(
|
||||
override val pos: Pos = body.pos
|
||||
override suspend fun execute(scope: Scope): Obj {
|
||||
// and the source closure of the lambda which might have other thisObj.
|
||||
val context = scope.applyClosure(closureScope, preferredThisType = expectedReceiverType)
|
||||
val useBytecodeClosure = closureScope.captureRecords != null
|
||||
val context = if (useBytecodeClosure) {
|
||||
scope.applyClosureForBytecode(closureScope, preferredThisType = expectedReceiverType)
|
||||
} else {
|
||||
scope.applyClosure(closureScope, preferredThisType = expectedReceiverType)
|
||||
}
|
||||
if (paramSlotPlanSnapshot.isNotEmpty()) context.applySlotPlan(paramSlotPlanSnapshot)
|
||||
if (captureSlots.isNotEmpty()) {
|
||||
val captureRecords = closureScope.captureRecords
|
||||
|
||||
@ -832,6 +832,20 @@ open class Scope(
|
||||
open fun applyClosure(closure: Scope, preferredThisType: String? = null): Scope =
|
||||
ClosureScope(this, closure, preferredThisType)
|
||||
|
||||
internal fun applyClosureForBytecode(closure: Scope, preferredThisType: String? = null): Scope {
|
||||
val context = createChildScope(newThisObj = closure.thisObj)
|
||||
val desired = preferredThisType?.let { typeName ->
|
||||
thisVariants.firstOrNull { it.objClass.className == typeName }
|
||||
}
|
||||
val merged = ArrayList<Obj>(thisVariants.size + closure.thisVariants.size + 1)
|
||||
desired?.let { merged.add(it) }
|
||||
merged.addAll(thisVariants)
|
||||
merged.addAll(closure.thisVariants)
|
||||
context.setThisVariants(closure.thisObj, merged)
|
||||
context.currentClassCtx = closure.currentClassCtx ?: currentClassCtx
|
||||
return context
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve and evaluate a qualified identifier exactly as compiled code would.
|
||||
* For input like `A.B.C`, it builds the same ObjRef chain the compiler emits:
|
||||
|
||||
@ -18,7 +18,6 @@
|
||||
package net.sergeych.lyng.obj
|
||||
|
||||
import net.sergeych.lyng.Arguments
|
||||
import net.sergeych.lyng.ClosureScope
|
||||
import net.sergeych.lyng.Scope
|
||||
import net.sergeych.lyng.Statement
|
||||
|
||||
@ -63,7 +62,7 @@ open class ObjDynamic(var readCallback: Statement? = null, var writeCallback: St
|
||||
* with method invocation which is implemented separately in [invokeInstanceMethod] below.
|
||||
*/
|
||||
override suspend fun readField(scope: Scope, name: String): ObjRecord {
|
||||
val execBase = builderScope?.let { ClosureScope(scope, it) } ?: scope
|
||||
val execBase = builderScope?.let { scope.applyClosure(it) } ?: scope
|
||||
return readCallback?.execute(execBase.createChildScope(Arguments(ObjString(name))))?.let {
|
||||
if (writeCallback != null)
|
||||
it.asMutable
|
||||
@ -83,26 +82,26 @@ open class ObjDynamic(var readCallback: Statement? = null, var writeCallback: St
|
||||
args: Arguments,
|
||||
onNotFoundResult: (suspend () -> Obj?)?
|
||||
): Obj {
|
||||
val execBase = builderScope?.let { ClosureScope(scope, it) } ?: scope
|
||||
val execBase = builderScope?.let { scope.applyClosure(it) } ?: scope
|
||||
val over = readCallback?.execute(execBase.createChildScope(Arguments(ObjString(name))))
|
||||
return over?.invoke(scope, scope.thisObj, args)
|
||||
?: super.invokeInstanceMethod(scope, name, args, onNotFoundResult)
|
||||
}
|
||||
|
||||
override suspend fun writeField(scope: Scope, name: String, newValue: Obj) {
|
||||
val execBase = builderScope?.let { ClosureScope(scope, it) } ?: scope
|
||||
val execBase = builderScope?.let { scope.applyClosure(it) } ?: scope
|
||||
writeCallback?.execute(execBase.createChildScope(Arguments(ObjString(name), newValue)))
|
||||
?: super.writeField(scope, name, newValue)
|
||||
}
|
||||
|
||||
override suspend fun getAt(scope: Scope, index: Obj): Obj {
|
||||
val execBase = builderScope?.let { ClosureScope(scope, it) } ?: scope
|
||||
val execBase = builderScope?.let { scope.applyClosure(it) } ?: scope
|
||||
return readCallback?.execute(execBase.createChildScope(Arguments(index)))
|
||||
?: super.getAt(scope, index)
|
||||
}
|
||||
|
||||
override suspend fun putAt(scope: Scope, index: Obj, newValue: Obj) {
|
||||
val execBase = builderScope?.let { ClosureScope(scope, it) } ?: scope
|
||||
val execBase = builderScope?.let { scope.applyClosure(it) } ?: scope
|
||||
writeCallback?.execute(execBase.createChildScope(Arguments(index, newValue)))
|
||||
?: super.putAt(scope, index, newValue)
|
||||
}
|
||||
|
||||
@ -18,7 +18,6 @@
|
||||
package net.sergeych.lyng.obj
|
||||
|
||||
import net.sergeych.lyng.Arguments
|
||||
import net.sergeych.lyng.ClosureScope
|
||||
import net.sergeych.lyng.Scope
|
||||
import net.sergeych.lyng.Statement
|
||||
|
||||
@ -35,9 +34,9 @@ class ObjProperty(
|
||||
suspend fun callGetter(scope: Scope, instance: Obj, declaringClass: ObjClass? = null): Obj {
|
||||
val g = getter ?: scope.raiseError("property $name has no getter")
|
||||
// Execute getter in a child scope of the instance with 'this' properly set
|
||||
// Use ClosureScope to match extension function behavior (access to instance scope + call scope)
|
||||
// Match extension function behavior (access to instance scope + call scope).
|
||||
val instanceScope = (instance as? ObjInstance)?.instanceScope ?: instance.autoInstanceScope(scope)
|
||||
val execScope = ClosureScope(scope, instanceScope).createChildScope(newThisObj = instance)
|
||||
val execScope = scope.applyClosure(instanceScope).createChildScope(newThisObj = instance)
|
||||
execScope.currentClassCtx = declaringClass
|
||||
return g.execute(execScope)
|
||||
}
|
||||
@ -45,9 +44,9 @@ class ObjProperty(
|
||||
suspend fun callSetter(scope: Scope, instance: Obj, value: Obj, declaringClass: ObjClass? = null) {
|
||||
val s = setter ?: scope.raiseError("property $name has no setter")
|
||||
// Execute setter in a child scope of the instance with 'this' properly set and the value as an argument
|
||||
// Use ClosureScope to match extension function behavior
|
||||
// Match extension function behavior (access to instance scope + call scope).
|
||||
val instanceScope = (instance as? ObjInstance)?.instanceScope ?: instance.autoInstanceScope(scope)
|
||||
val execScope = ClosureScope(scope, instanceScope).createChildScope(args = Arguments(value), newThisObj = instance)
|
||||
val execScope = scope.applyClosure(instanceScope).createChildScope(args = Arguments(value), newThisObj = instance)
|
||||
execScope.currentClassCtx = declaringClass
|
||||
s.execute(execScope)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user