diff --git a/bytecode_migration_plan.md b/bytecode_migration_plan.md index 2e02408..7d31a9c 100644 --- a/bytecode_migration_plan.md +++ b/bytecode_migration_plan.md @@ -122,7 +122,8 @@ Goal: migrate the compiler so all values live in frames/bytecode, keeping JVM te - [x] Add JVM disasm coverage to ensure module init has no `CALL_SLOT` to `Callable@...` for declarations. - [ ] Step 26: Bytecode-backed lambdas (remove `ValueFnRef` runtime execution). - [x] Compile lambda bodies to bytecode and emit an opcode to create a callable from bytecode + capture plan. - - [ ] Remove `containsValueFnRef`/`forceScopeSlots` workaround once lambdas are bytecode. + - [x] Remove `containsValueFnRef` helper now that lambdas are bytecode-backed. + - [ ] Remove `forceScopeSlots` branches once no bytecode paths depend on scope slots. - [x] Add JVM tests for captured locals and delegated locals inside lambdas on the bytecode path. - [ ] Step 27: Remove interpreter opcodes and constants from bytecode runtime. - [ ] Delete `BytecodeConst.ValueFn`, `CmdMakeValueFn`, and `MAKE_VALUE_FN`. diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/BytecodeCompiler.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/BytecodeCompiler.kt index a45d795..3376709 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/BytecodeCompiler.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/bytecode/BytecodeCompiler.kt @@ -6860,91 +6860,6 @@ class BytecodeCompiler( } } - private fun containsValueFnRef(stmt: Statement): Boolean { - if (stmt is BytecodeStatement) return containsValueFnRef(stmt.original) - return when (stmt) { - is ExpressionStatement -> containsValueFnRef(stmt.ref) - is BlockStatement -> stmt.statements().any { containsValueFnRef(it) } - is VarDeclStatement -> stmt.initializer?.let { containsValueFnRef(it) } ?: false - is DestructuringVarDeclStatement -> { - containsValueFnRef(stmt.initializer) || containsValueFnRef(stmt.pattern) - } - is net.sergeych.lyng.ForInStatement -> { - containsValueFnRef(stmt.source) || - containsValueFnRef(stmt.body) || - (stmt.elseStatement?.let { containsValueFnRef(it) } ?: false) - } - is net.sergeych.lyng.WhileStatement -> { - containsValueFnRef(stmt.condition) || - containsValueFnRef(stmt.body) || - (stmt.elseStatement?.let { containsValueFnRef(it) } ?: false) - } - is net.sergeych.lyng.DoWhileStatement -> { - containsValueFnRef(stmt.body) || - containsValueFnRef(stmt.condition) || - (stmt.elseStatement?.let { containsValueFnRef(it) } ?: false) - } - is IfStatement -> { - containsValueFnRef(stmt.condition) || - containsValueFnRef(stmt.ifBody) || - (stmt.elseBody?.let { containsValueFnRef(it) } ?: false) - } - is net.sergeych.lyng.ReturnStatement -> { - stmt.resultExpr?.let { containsValueFnRef(it) } ?: false - } - is net.sergeych.lyng.ThrowStatement -> containsValueFnRef(stmt.throwExpr) - else -> false - } - } - - private fun containsValueFnRef(ref: ObjRef): Boolean { - return when (ref) { - is ValueFnRef -> true - is BinaryOpRef -> containsValueFnRef(binaryLeft(ref)) || containsValueFnRef(binaryRight(ref)) - is UnaryOpRef -> containsValueFnRef(unaryOperand(ref)) - is CastRef -> containsValueFnRef(ref.castValueRef()) || containsValueFnRef(ref.castTypeRef()) - is AssignRef -> { - val target = assignTarget(ref) - if (target != null) { - containsValueFnRef(target) || containsValueFnRef(assignValue(ref)) - } else { - containsValueFnRef(ref.target) || containsValueFnRef(assignValue(ref)) - } - } - is AssignOpRef -> containsValueFnRef(ref.target) || containsValueFnRef(ref.value) - is AssignIfNullRef -> containsValueFnRef(ref.target) || containsValueFnRef(ref.value) - is IncDecRef -> containsValueFnRef(ref.target) - is ConditionalRef -> { - containsValueFnRef(ref.condition) || - containsValueFnRef(ref.ifTrue) || - containsValueFnRef(ref.ifFalse) - } - is ElvisRef -> containsValueFnRef(ref.left) || containsValueFnRef(ref.right) - is FieldRef -> containsValueFnRef(ref.target) - is IndexRef -> containsValueFnRef(ref.targetRef) || containsValueFnRef(ref.indexRef) - is CallRef -> ref.tailBlock || containsValueFnRef(ref.target) || ref.args.any { arg -> - val stmt = arg.value - stmt is ExpressionStatement && containsValueFnRef(stmt.ref) - } - is MethodCallRef -> ref.tailBlock || containsValueFnRef(ref.receiver) || ref.args.any { arg -> - val stmt = arg.value - stmt is ExpressionStatement && containsValueFnRef(stmt.ref) - } - is ThisMethodSlotCallRef -> ref.hasTailBlock() || ref.arguments().any { arg -> - val stmt = arg.value - stmt is ExpressionStatement && containsValueFnRef(stmt.ref) - } - is ListLiteralRef -> ref.entries().any { entry -> - when (entry) { - is net.sergeych.lyng.ListEntry.Element -> containsValueFnRef(entry.ref) - is net.sergeych.lyng.ListEntry.Spread -> containsValueFnRef(entry.ref) - } - } - is StatementRef -> containsValueFnRef(ref.statement) - else -> false - } - } - private fun extractRangeRef(source: Statement): RangeRef? { val target = if (source is BytecodeStatement) source.original else source val expr = target as? ExpressionStatement ?: return null