Step 27C: report lambda bytecode fallbacks

This commit is contained in:
Sergey Chernov 2026-02-12 00:02:09 +03:00
parent 18278794d6
commit 86ac7eee54
2 changed files with 23 additions and 7 deletions

View File

@ -129,6 +129,7 @@ Goal: migrate the compiler so all values live in frames/bytecode, keeping JVM te
- [ ] Delete `BytecodeConst.ValueFn`, `CmdMakeValueFn`, and `MAKE_VALUE_FN` (blocked: some lambdas still fall back to non-bytecode bodies).
- [x] Delete `BytecodeConst.StatementVal`, `CmdEvalStmt`, and `EVAL_STMT`.
- [x] Add bytecode-backed `::class` via `ClassOperatorRef` + `GET_OBJ_CLASS` to avoid ValueFn for class operator.
- [x] Add a bytecode fallback reporter hook for lambdas to locate remaining non-bytecode cases.
- [ ] Remove `emitStatementCall`/`emitStatementEval` once unused.
- [ ] Step 28: Scope as facade only.
- [ ] Audit bytecode execution paths for `Statement.execute` usage and remove remaining calls.

View File

@ -1040,6 +1040,7 @@ class Compiler(
class Settings(
val miniAstSink: MiniAstSink? = null,
val resolutionSink: ResolutionSink? = null,
val bytecodeFallbackReporter: ((Pos, String) -> Unit)? = null,
val useBytecodeStatements: Boolean = true,
val strictSlotRefs: Boolean = true,
val allowUnresolvedRefs: Boolean = false,
@ -1050,6 +1051,7 @@ class Compiler(
// Optional sink for mini-AST streaming (null by default, zero overhead when not used)
private val miniSink: MiniAstSink? = settings.miniAstSink
private val resolutionSink: ResolutionSink? = settings.resolutionSink
private val bytecodeFallbackReporter: ((Pos, String) -> Unit)? = settings.bytecodeFallbackReporter
private val seedScope: Scope? = settings.seedScope
private val useFastLocalRefs: Boolean = settings.useFastLocalRefs
private var resolutionScriptDepth = 0
@ -2907,15 +2909,28 @@ class Compiler(
paramKnownClasses[param.name] = cls
}
val returnLabels = label?.let { setOf(it) } ?: emptySet()
val fnStatements = if (useBytecodeStatements && !containsUnsupportedForBytecode(body)) {
val fnStatements = if (useBytecodeStatements) {
if (containsUnsupportedForBytecode(body)) {
bytecodeFallbackReporter?.invoke(
body.pos,
"lambda contains unsupported bytecode statements"
)
body
} else {
returnLabelStack.addLast(returnLabels)
try {
wrapFunctionBytecode(body, "<lambda>", paramKnownClasses)
} catch (e: net.sergeych.lyng.bytecode.BytecodeCompileException) {
val pos = e.pos ?: body.pos
bytecodeFallbackReporter?.invoke(
pos,
"lambda bytecode compile failed: ${e.message}"
)
body
} finally {
returnLabelStack.removeLast()
}
}
} else {
body
}