- fixed CLI -x mode

- fixed a wrong error message when global symbol is not found
This commit is contained in:
sergeych committed 2026-03-31 20:52:31 +03:00
1 parent 6e9333844e
commit c097464750
13 files changed
+426 -77

No files matched your search

@@ -187,6 +187,8 @@ class Compiler(
private val externCallableNames: MutableSet<String> = mutableSetOf()
private val externBindingNames: MutableSet<String> = mutableSetOf()
private val moduleDeclaredNames: MutableSet<String> = mutableSetOf()
private val predeclaredTopLevelValueNames: MutableSet<String> = mutableSetOf()
private val moduleReferencePosByName: MutableMap<String, Pos> = mutableMapOf()
private var seedingSlotPlan: Boolean = false
private fun moduleForcedLocalSlotInfo(): Map<String, ForcedLocalSlotInfo> {
@@ -393,6 +395,7 @@ class Compiler(
}
declareSlotNameIn(plan, nameToken.value, isMutable = t.value == "var", isDelegated = false)
moduleDeclaredNames.add(nameToken.value)
predeclaredTopLevelValueNames.add(nameToken.value)
}
"class", "object" -> {
val nameToken = nextNonWs()
@@ -933,6 +936,7 @@ class Compiler(
}
}
captureLocalRef(name, slotLoc, pos)?.let { ref ->
moduleReferencePosByName.putIfAbsent(name, pos)
resolutionSink?.reference(name, pos)
return ref
}
@@ -978,8 +982,11 @@ class Compiler(
if (moduleLoc != null) {
val moduleDeclaredNames = localNamesStack.firstOrNull()
if (moduleDeclaredNames == null || !moduleDeclaredNames.contains(name)) {
resolveImportBinding(name, pos)?.let { resolved ->
registerImportBinding(name, resolved.binding, pos)
val resolvedImport = resolveImportBinding(name, pos)
if (resolvedImport != null) {
registerImportBinding(name, resolvedImport.binding, pos)
} else if (predeclaredTopLevelValueNames.contains(name)) {
throw ScriptError(pos, "symbol '$name' is not defined")
}
}
val ref = LocalSlotRef(
@@ -1008,8 +1015,11 @@ class Compiler(
if (moduleEntry != null) {
val moduleDeclaredNames = localNamesStack.firstOrNull()
if (moduleDeclaredNames == null || !moduleDeclaredNames.contains(name)) {
resolveImportBinding(name, pos)?.let { resolved ->
registerImportBinding(name, resolved.binding, pos)
val resolvedImport = resolveImportBinding(name, pos)
if (resolvedImport != null) {
registerImportBinding(name, resolvedImport.binding, pos)
} else if (predeclaredTopLevelValueNames.contains(name)) {
throw ScriptError(pos, "symbol '$name' is not defined")
}
}
val moduleLoc = SlotLocation(
@@ -1020,6 +1030,7 @@ class Compiler(
moduleEntry.isDelegated
)
captureLocalRef(name, moduleLoc, pos)?.let { ref ->
moduleReferencePosByName.putIfAbsent(name, pos)
resolutionSink?.reference(name, pos)
return ref
}
@@ -1046,6 +1057,7 @@ class Compiler(
strictSlotRefs
)
}
moduleReferencePosByName.putIfAbsent(name, pos)
resolutionSink?.reference(name, pos)
return ref
}
@@ -1080,6 +1092,7 @@ class Compiler(
val slot = lookupSlotLocation(name)
if (slot != null) {
captureLocalRef(name, slot, pos)?.let { ref ->
moduleReferencePosByName.putIfAbsent(name, pos)
resolutionSink?.reference(name, pos)
return ref
}
@@ -1106,6 +1119,7 @@ class Compiler(
strictSlotRefs
)
}
moduleReferencePosByName.putIfAbsent(name, pos)
resolutionSink?.reference(name, pos)
return ref
}
@@ -1757,6 +1771,8 @@ class Compiler(
callableReturnTypeByScopeId = callableReturnTypeByScopeId,
callableReturnTypeByName = callableReturnTypeByName,
externBindingNames = externBindingNames,
preparedModuleBindingNames = importBindings.keys,
scopeRefPosByName = moduleReferencePosByName,
lambdaCaptureEntriesByRef = lambdaCaptureEntriesByRef
) as BytecodeStatement
unwrapped to bytecodeStmt.bytecodeFunction()
@@ -2085,6 +2101,8 @@ class Compiler(
callableReturnTypeByName = callableReturnTypeByName,
externCallableNames = externCallableNames,
externBindingNames = externBindingNames,
preparedModuleBindingNames = importBindings.keys,
scopeRefPosByName = moduleReferencePosByName,
lambdaCaptureEntriesByRef = lambdaCaptureEntriesByRef
)
}
@@ -2116,6 +2134,8 @@ class Compiler(
callableReturnTypeByName = callableReturnTypeByName,
externCallableNames = externCallableNames,
externBindingNames = externBindingNames,
preparedModuleBindingNames = importBindings.keys,
scopeRefPosByName = moduleReferencePosByName,
lambdaCaptureEntriesByRef = lambdaCaptureEntriesByRef
)
}
@@ -2172,6 +2192,8 @@ class Compiler(
callableReturnTypeByName = callableReturnTypeByName,
externCallableNames = externCallableNames,
externBindingNames = externBindingNames,
preparedModuleBindingNames = importBindings.keys,
scopeRefPosByName = moduleReferencePosByName,
lambdaCaptureEntriesByRef = lambdaCaptureEntriesByRef
)
}
@@ -43,6 +43,8 @@ class BytecodeCompiler(
private val callableReturnTypeByName: Map<String, ObjClass> = emptyMap(),
private val externCallableNames: Set<String> = emptySet(),
private val externBindingNames: Set<String> = emptySet(),
private val preparedModuleBindingNames: Set<String> = emptySet(),
private val scopeRefPosByName: Map<String, Pos> = emptyMap(),
private val lambdaCaptureEntriesByRef: Map<ValueFnRef, List<LambdaCaptureEntry>> = emptyMap(),
) {
private val useScopeSlots: Boolean = allowedScopeNames != null || scopeSlotNameSet != null
@@ -53,12 +55,15 @@ class BytecodeCompiler(
private var scopeSlotIndices = IntArray(0)
private var scopeSlotNames = emptyArray<String?>()
private var scopeSlotIsModule = BooleanArray(0)
private var scopeSlotRequiresPreparedBinding = BooleanArray(0)
private var scopeSlotRefPos = emptyArray<Pos?>()
private var scopeSlotMutables = BooleanArray(0)
private var scopeKeyByIndex = emptyArray<ScopeSlotKey?>()
private val scopeSlotMap = LinkedHashMap<ScopeSlotKey, Int>()
private val scopeSlotNameMap = LinkedHashMap<ScopeSlotKey, String>()
private val scopeSlotMutableMap = LinkedHashMap<ScopeSlotKey, Boolean>()
private val scopeSlotIndexByName = LinkedHashMap<String, Int>()
private val scopeSlotRefPosByKey = LinkedHashMap<ScopeSlotKey, Pos>()
private val pendingScopeNameRefs = LinkedHashSet<String>()
private val addrSlotByScopeSlot = LinkedHashMap<Int, Int>()
private data class LocalSlotInfo(val name: String, val isMutable: Boolean, val isDelegated: Boolean)
@@ -119,6 +124,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -140,6 +147,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -158,6 +167,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -176,6 +187,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -194,6 +207,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -212,6 +227,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -230,6 +247,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -248,6 +267,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -266,6 +287,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -284,6 +307,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -302,6 +327,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -322,6 +349,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -340,6 +369,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -358,6 +389,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -376,6 +409,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -395,6 +430,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -416,6 +453,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -439,6 +478,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -459,6 +500,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -534,6 +577,7 @@ class BytecodeCompiler(
resolved = SlotType.INT
}
if (mapped < scopeSlotCount && resolved != SlotType.UNKNOWN) {
noteScopeSlotRef(mapped, ref.pos())
val addrSlot = ensureScopeAddr(mapped)
val local = allocSlot()
emitLoadFromAddr(addrSlot, local, resolved)
@@ -544,6 +588,7 @@ class BytecodeCompiler(
return CompiledValue(local, resolved)
}
if (mapped < scopeSlotCount && resolved == SlotType.UNKNOWN) {
noteScopeSlotRef(mapped, ref.pos())
val addrSlot = ensureScopeAddr(mapped)
val local = allocSlot()
emitLoadFromAddr(addrSlot, local, SlotType.OBJ)
@@ -563,6 +608,7 @@ class BytecodeCompiler(
}
if (allowLocalSlots) {
scopeSlotIndexByName[ref.name]?.let { slot ->
noteScopeSlotRef(slot, callSitePos())
val resolved = slotTypes[slot] ?: SlotType.UNKNOWN
return CompiledValue(slot, resolved)
}
@@ -585,6 +631,7 @@ class BytecodeCompiler(
return CompiledValue(slot, resolved)
}
scopeSlotIndexByName[ref.name]?.let { slot ->
noteScopeSlotRef(slot, callSitePos())
val resolved = slotTypes[slot] ?: SlotType.UNKNOWN
return CompiledValue(slot, resolved)
}
@@ -596,6 +643,7 @@ class BytecodeCompiler(
val slot = ref.slotIndex()
val resolved = slotTypes[slot] ?: SlotType.UNKNOWN
if (slot < scopeSlotCount && resolved != SlotType.UNKNOWN) {
noteScopeSlotRef(slot, callSitePos())
val addrSlot = ensureScopeAddr(slot)
val local = allocSlot()
emitLoadFromAddr(addrSlot, local, resolved)
@@ -5002,6 +5050,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -5021,6 +5071,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -5041,6 +5093,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -5061,6 +5115,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -5084,6 +5140,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -5103,6 +5161,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -5727,6 +5787,8 @@ class BytecodeCompiler(
scopeSlotIndices,
scopeSlotNames,
scopeSlotIsModule,
scopeSlotRequiresPreparedBinding,
scopeSlotRefPos,
localSlotNames,
localSlotMutables,
localSlotDelegated,
@@ -7599,6 +7661,12 @@ class BytecodeCompiler(
private fun assignValue(ref: AssignRef): ObjRef = ref.value
private fun refPos(ref: BinaryOpRef): Pos = Pos.builtIn
private fun noteScopeSlotRef(slot: Int, pos: Pos) {
if (slot >= scopeSlotCount) return
val key = scopeKeyByIndex.getOrNull(slot) ?: return
scopeSlotRefPosByKey.putIfAbsent(key, pos)
}
private fun resolveSlot(ref: LocalSlotRef): Int? {
loopSlotOverrides[ref.name]?.let { return it }
val scopeId = refScopeId(ref)
@@ -7606,8 +7674,14 @@ class BytecodeCompiler(
val key = ScopeSlotKey(scopeId, refSlot(ref))
val localIndex = localSlotIndexByKey[key]
if (localIndex != null) return scopeSlotCount + localIndex
scopeSlotMap[key]?.let { return it }
scopeSlotIndexByName[ref.name]?.let { return it }
scopeSlotMap[key]?.let {
scopeSlotRefPosByKey.putIfAbsent(key, ref.pos())
return it
}
scopeSlotIndexByName[ref.name]?.let {
scopeSlotRefPosByKey.putIfAbsent(key, ref.pos())
return it
}
}
if (ref.captureOwnerScopeId != null) {
val scopeKey = ScopeSlotKey(refScopeId(ref), refSlot(ref))
@@ -7617,7 +7691,11 @@ class BytecodeCompiler(
return scopeSlotCount + localIndex
}
}
return scopeSlotMap[scopeKey]
val resolved = scopeSlotMap[scopeKey]
if (resolved != null) {
scopeSlotRefPosByKey.putIfAbsent(scopeKey, ref.pos())
}
return resolved
}
if (ref.isDelegated) {
val localKey = ScopeSlotKey(refScopeId(ref), refSlot(ref))
@@ -7628,7 +7706,11 @@ class BytecodeCompiler(
val localIndex = localSlotIndexByKey[localKey]
if (localIndex != null) return scopeSlotCount + localIndex
val scopeKey = ScopeSlotKey(refScopeId(ref), refSlot(ref))
return scopeSlotMap[scopeKey]
val resolved = scopeSlotMap[scopeKey]
if (resolved != null) {
scopeSlotRefPosByKey.putIfAbsent(scopeKey, ref.pos())
}
return resolved
}
private fun resolveCapturedOwnerScopeSlot(ref: LocalSlotRef): Int? {
@@ -7858,6 +7940,8 @@ class BytecodeCompiler(
scopeSlotIndices = IntArray(scopeSlotCount)
scopeSlotNames = arrayOfNulls(scopeSlotCount)
scopeSlotIsModule = BooleanArray(scopeSlotCount)
scopeSlotRequiresPreparedBinding = BooleanArray(scopeSlotCount)
scopeSlotRefPos = arrayOfNulls(scopeSlotCount)
scopeSlotMutables = BooleanArray(scopeSlotCount) { true }
scopeKeyByIndex = arrayOfNulls(scopeSlotCount)
for ((key, index) in scopeSlotMap) {
@@ -7865,6 +7949,8 @@ class BytecodeCompiler(
scopeSlotIndices[index] = key.slot
scopeSlotNames[index] = name
scopeSlotIsModule[index] = moduleScopeId != null && key.scopeId == moduleScopeId
scopeSlotRequiresPreparedBinding[index] = name != null && preparedModuleBindingNames.contains(name)
scopeSlotRefPos[index] = name?.let { scopeRefPosByName[it] } ?: scopeSlotRefPosByKey[key]
scopeSlotMutableMap[key]?.let { scopeSlotMutables[index] = it }
scopeKeyByIndex[index] = key
}
@@ -88,6 +88,8 @@ class BytecodeStatement private constructor(
callableReturnTypeByName: Map<String, ObjClass> = emptyMap(),
externCallableNames: Set<String> = emptySet(),
externBindingNames: Set<String> = emptySet(),
preparedModuleBindingNames: Set<String> = emptySet(),
scopeRefPosByName: Map<String, Pos> = emptyMap(),
lambdaCaptureEntriesByRef: Map<ValueFnRef, List<LambdaCaptureEntry>> = emptyMap(),
slotTypeDeclByScopeId: Map<Int, Map<Int, TypeDecl>> = emptyMap(),
): Statement {
@@ -124,6 +126,8 @@ class BytecodeStatement private constructor(
callableReturnTypeByName = callableReturnTypeByName,
externCallableNames = externCallableNames,
externBindingNames = externBindingNames,
preparedModuleBindingNames = preparedModuleBindingNames,
scopeRefPosByName = scopeRefPosByName,
lambdaCaptureEntriesByRef = lambdaCaptureEntriesByRef
)
val compiled = compiler.compileStatement(nameHint, statement)
@@ -67,6 +67,8 @@ class CmdBuilder {
scopeSlotIndices: IntArray = IntArray(0),
scopeSlotNames: Array<String?> = emptyArray(),
scopeSlotIsModule: BooleanArray = BooleanArray(0),
scopeSlotRequiresPreparedBinding: BooleanArray = BooleanArray(0),
scopeSlotRefPos: Array<net.sergeych.lyng.Pos?> = emptyArray(),
localSlotNames: Array<String?> = emptyArray(),
localSlotMutables: BooleanArray = BooleanArray(0),
localSlotDelegated: BooleanArray = BooleanArray(0),
@@ -79,6 +81,12 @@ class CmdBuilder {
require(scopeSlotIsModule.isEmpty() || scopeSlotIsModule.size == scopeSlotCount) {
"scope slot module mapping size mismatch"
}
require(scopeSlotRequiresPreparedBinding.isEmpty() || scopeSlotRequiresPreparedBinding.size == scopeSlotCount) {
"scope slot prepared-binding mapping size mismatch"
}
require(scopeSlotRefPos.isEmpty() || scopeSlotRefPos.size == scopeSlotCount) {
"scope slot position mapping size mismatch"
}
require(localSlotNames.size == localSlotMutables.size) { "local slot metadata size mismatch" }
require(localSlotNames.size == localSlotDelegated.size) { "local slot delegation size mismatch" }
require(localSlotNames.size == localSlotCaptures.size) { "local slot capture size mismatch" }
@@ -113,6 +121,8 @@ class CmdBuilder {
scopeSlotIndices = scopeSlotIndices,
scopeSlotNames = if (scopeSlotNames.isEmpty()) Array(scopeSlotCount) { null } else scopeSlotNames,
scopeSlotIsModule = if (scopeSlotIsModule.isEmpty()) BooleanArray(scopeSlotCount) else scopeSlotIsModule,
scopeSlotRequiresPreparedBinding = if (scopeSlotRequiresPreparedBinding.isEmpty()) BooleanArray(scopeSlotCount) else scopeSlotRequiresPreparedBinding,
scopeSlotRefPos = if (scopeSlotRefPos.isEmpty()) Array(scopeSlotCount) { null } else scopeSlotRefPos,
localSlotNames = localSlotNames,
localSlotMutables = localSlotMutables,
localSlotDelegated = localSlotDelegated,
@@ -26,6 +26,8 @@ data class CmdFunction(
val scopeSlotIndices: IntArray,
val scopeSlotNames: Array<String?>,
val scopeSlotIsModule: BooleanArray,
val scopeSlotRequiresPreparedBinding: BooleanArray,
val scopeSlotRefPos: Array<net.sergeych.lyng.Pos?>,
val localSlotNames: Array<String?>,
val localSlotMutables: BooleanArray,
val localSlotDelegated: BooleanArray,
@@ -38,6 +40,8 @@ data class CmdFunction(
require(scopeSlotIndices.size == scopeSlotCount) { "scopeSlotIndices size mismatch" }
require(scopeSlotNames.size == scopeSlotCount) { "scopeSlotNames size mismatch" }
require(scopeSlotIsModule.size == scopeSlotCount) { "scopeSlotIsModule size mismatch" }
require(scopeSlotRequiresPreparedBinding.size == scopeSlotCount) { "scopeSlotRequiresPreparedBinding size mismatch" }
require(scopeSlotRefPos.size == scopeSlotCount) { "scopeSlotRefPos size mismatch" }
require(localSlotNames.size == localSlotMutables.size) { "localSlot metadata size mismatch" }
require(localSlotNames.size == localSlotDelegated.size) { "localSlot delegation size mismatch" }
require(localSlotNames.size == localSlotCaptures.size) { "localSlot capture size mismatch" }
@@ -4112,7 +4112,7 @@ class CmdFrame(
}
fun ensureScope(): Scope {
val pos = posForIp(ip - 1)
val pos = currentErrorPos()
if (pos != null && lastScopePosIp != ip) {
scope.pos = pos
lastScopePosIp = ip
@@ -4189,6 +4189,33 @@ class CmdFrame(
return fn.posByIp.getOrNull(ip)
}
private fun currentErrorPos(): Pos? {
val center = ip - 1
if (center < 0) return null
var fallback: Pos? = null
val maxRadius = maxOf(center, fn.posByIp.size - 1 - center)
for (radius in 0..maxRadius) {
val before = center - radius
if (before >= 0) {
val pos = posForIp(before)
if (pos != null) {
if (pos.source !== Source.builtIn && pos.source !== Source.UNKNOWN) return pos
if (fallback == null) fallback = pos
}
}
if (radius == 0) continue
val after = center + radius
if (after < fn.posByIp.size) {
val pos = posForIp(after)
if (pos != null) {
if (pos.source !== Source.builtIn && pos.source !== Source.UNKNOWN) return pos
if (fallback == null) fallback = pos
}
}
}
return fallback
}
fun pushScope(plan: Map<String, Int>, captures: List<String>) {
if (scope.skipScopeCreation) {
val snapshot = emptyMap<String, Int?>()
@@ -5045,8 +5072,12 @@ class CmdFrame(
if (hadNamedBinding) return
if (record.value !== ObjUnset) return
if (fn.scopeSlotIsModule.getOrNull(slot) != true) return
val pos = fn.scopeSlotRefPos.getOrNull(slot) ?: currentErrorPos() ?: ensureScope().pos
if (fn.scopeSlotRequiresPreparedBinding.getOrNull(slot) != true) {
throw ScriptError(pos, "symbol '$name' is not defined")
}
throw ScriptError(
ensureScope().pos,
pos,
"module binding '$name' is not available in the execution scope; prepare the script imports/module bindings explicitly"
)
}