Step 9: module-level bytecode execution
This commit is contained in:
parent
e2f503744d
commit
58581d6bf0
@ -29,9 +29,9 @@ Goal: migrate the compiler so all values live in frames/bytecode, keeping JVM te
|
|||||||
- [x] Support `ClassScopeMemberRef` without scope-map fallback.
|
- [x] Support `ClassScopeMemberRef` without scope-map fallback.
|
||||||
- [x] Step 8: ObjDynamic member access in bytecode.
|
- [x] Step 8: ObjDynamic member access in bytecode.
|
||||||
- [x] Allow dynamic receiver field/method lookup without falling back to interpreter.
|
- [x] Allow dynamic receiver field/method lookup without falling back to interpreter.
|
||||||
- [ ] Step 9: Module-level bytecode execution.
|
- [x] Step 9: Module-level bytecode execution.
|
||||||
- [ ] Compile `Script` bodies to bytecode instead of interpreting at module scope.
|
- [x] Compile `Script` bodies to bytecode instead of interpreting at module scope.
|
||||||
- [ ] Keep import/module slot seeding in frame-only flow.
|
- [x] Keep import/module slot seeding in frame-only flow.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
|
|||||||
@ -1526,11 +1526,10 @@ class Compiler(
|
|||||||
resolutionScriptDepth == 1 &&
|
resolutionScriptDepth == 1 &&
|
||||||
statements.none { containsUnsupportedForBytecode(it) } &&
|
statements.none { containsUnsupportedForBytecode(it) } &&
|
||||||
statements.none { containsDelegatedRefs(it) }
|
statements.none { containsDelegatedRefs(it) }
|
||||||
val finalStatements = if (wrapScriptBytecode) {
|
val (finalStatements, moduleBytecode) = if (wrapScriptBytecode) {
|
||||||
val unwrapped = statements.map { unwrapBytecodeDeep(it) }
|
val unwrapped = statements.map { unwrapBytecodeDeep(it) }
|
||||||
val block = InlineBlockStatement(unwrapped, start)
|
val block = InlineBlockStatement(unwrapped, start)
|
||||||
listOf(
|
val bytecodeStmt = BytecodeStatement.wrap(
|
||||||
BytecodeStatement.wrap(
|
|
||||||
block,
|
block,
|
||||||
"<script>",
|
"<script>",
|
||||||
allowLocalSlots = true,
|
allowLocalSlots = true,
|
||||||
@ -1538,13 +1537,13 @@ class Compiler(
|
|||||||
moduleScopeId = moduleSlotPlan()?.id,
|
moduleScopeId = moduleSlotPlan()?.id,
|
||||||
slotTypeByScopeId = slotTypeByScopeId,
|
slotTypeByScopeId = slotTypeByScopeId,
|
||||||
knownNameObjClass = knownClassMapForBytecode()
|
knownNameObjClass = knownClassMapForBytecode()
|
||||||
)
|
) as BytecodeStatement
|
||||||
)
|
unwrapped to bytecodeStmt.bytecodeFunction()
|
||||||
} else {
|
} else {
|
||||||
statements
|
statements to null
|
||||||
}
|
}
|
||||||
val moduleRefs = importedModules.map { ImportBindingSource.Module(it.scope.packageName, it.pos) }
|
val moduleRefs = importedModules.map { ImportBindingSource.Module(it.scope.packageName, it.pos) }
|
||||||
Script(start, finalStatements, modulePlan, importBindings.toMap(), moduleRefs)
|
Script(start, finalStatements, modulePlan, importBindings.toMap(), moduleRefs, moduleBytecode)
|
||||||
}.also {
|
}.also {
|
||||||
// Best-effort script end notification (use current position)
|
// Best-effort script end notification (use current position)
|
||||||
miniSink?.onScriptEnd(
|
miniSink?.onScriptEnd(
|
||||||
|
|||||||
@ -20,6 +20,8 @@ package net.sergeych.lyng
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.yield
|
import kotlinx.coroutines.yield
|
||||||
import net.sergeych.lyng.Script.Companion.defaultImportManager
|
import net.sergeych.lyng.Script.Companion.defaultImportManager
|
||||||
|
import net.sergeych.lyng.bytecode.CmdFunction
|
||||||
|
import net.sergeych.lyng.bytecode.CmdVm
|
||||||
import net.sergeych.lyng.miniast.*
|
import net.sergeych.lyng.miniast.*
|
||||||
import net.sergeych.lyng.obj.*
|
import net.sergeych.lyng.obj.*
|
||||||
import net.sergeych.lyng.pacman.ImportManager
|
import net.sergeych.lyng.pacman.ImportManager
|
||||||
@ -35,10 +37,12 @@ class Script(
|
|||||||
private val moduleSlotPlan: Map<String, Int> = emptyMap(),
|
private val moduleSlotPlan: Map<String, Int> = emptyMap(),
|
||||||
private val importBindings: Map<String, ImportBinding> = emptyMap(),
|
private val importBindings: Map<String, ImportBinding> = emptyMap(),
|
||||||
private val importedModules: List<ImportBindingSource.Module> = emptyList(),
|
private val importedModules: List<ImportBindingSource.Module> = emptyList(),
|
||||||
|
private val moduleBytecode: CmdFunction? = null,
|
||||||
// private val catchReturn: Boolean = false,
|
// private val catchReturn: Boolean = false,
|
||||||
) : Statement() {
|
) : Statement() {
|
||||||
|
|
||||||
override suspend fun execute(scope: Scope): Obj {
|
override suspend fun execute(scope: Scope): Obj {
|
||||||
|
scope.pos = pos
|
||||||
val isModuleScope = scope is ModuleScope
|
val isModuleScope = scope is ModuleScope
|
||||||
val shouldSeedModule = isModuleScope || scope.thisObj === ObjVoid
|
val shouldSeedModule = isModuleScope || scope.thisObj === ObjVoid
|
||||||
val moduleTarget = scope
|
val moduleTarget = scope
|
||||||
@ -79,6 +83,9 @@ class Script(
|
|||||||
if (shouldSeedModule) {
|
if (shouldSeedModule) {
|
||||||
seedModuleSlots(moduleTarget)
|
seedModuleSlots(moduleTarget)
|
||||||
}
|
}
|
||||||
|
moduleBytecode?.let { fn ->
|
||||||
|
return CmdVm().execute(fn, scope, scope.args.list)
|
||||||
|
}
|
||||||
var lastResult: Obj = ObjVoid
|
var lastResult: Obj = ObjVoid
|
||||||
for (s in statements) {
|
for (s in statements) {
|
||||||
lastResult = s.execute(scope)
|
lastResult = s.execute(scope)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user