regression fix

This commit is contained in:
Sergey Chernov 2026-04-20 18:48:28 +03:00
parent 4acee56de8
commit 10fa4de4fa
2 changed files with 47 additions and 5 deletions

View File

@ -4174,10 +4174,15 @@ class CmdFrame(
} else {
val value = record.value
if (!record.isMutable && value is FrameSlotRef) {
val resolved = value.peekValue()
val resolved = value.resolvedCaptureValueOrNull()
if (resolved != null) {
if (value.refersTo(frame, localIndex)) continue
frame.setObj(localIndex, value.read())
when (resolved) {
is ObjInt -> frame.setInt(localIndex, resolved.value)
is ObjReal -> frame.setReal(localIndex, resolved.value)
is ObjBool -> frame.setBool(localIndex, resolved.value)
else -> frame.setObj(localIndex, resolved)
}
} else {
frame.setObj(localIndex, value)
}
@ -4213,9 +4218,14 @@ class CmdFrame(
} else {
val value = record.value
if (!record.isMutable && value is FrameSlotRef) {
val resolved = value.peekValue()
val resolved = value.resolvedCaptureValueOrNull()
if (resolved != null) {
frame.setObj(idx, value.read())
when (resolved) {
is ObjInt -> frame.setInt(idx, resolved.value)
is ObjReal -> frame.setReal(idx, resolved.value)
is ObjBool -> frame.setBool(idx, resolved.value)
else -> frame.setObj(idx, resolved)
}
} else {
frame.setObj(idx, value)
}
@ -4279,7 +4289,15 @@ class CmdFrame(
}
} else {
val raw = frame.getRawObj(localIndex)
if (raw == null && name != null) {
// For primitive-typed slots (INT/REAL/BOOL), getRawObj returns null
// but the value exists in the typed slot array. Skip the scope name
// lookup to avoid finding a same-named symbol higher in the scope chain
// (e.g., a List.size property when capturing a `size: Int` parameter).
val isPrimitiveSlot = when (frame.getSlotTypeCode(localIndex)) {
SlotType.INT.code, SlotType.REAL.code, SlotType.BOOL.code -> true
else -> false
}
if (raw == null && name != null && !isPrimitiveSlot) {
val record = findNamedExistingRecord(scope, name)
if (record != null) {
val value = record.value

View File

@ -444,4 +444,28 @@ class StdlibTest {
assertEquals([0, 10, 20, 30, 40], x)
""".trimIndent())
}
@Test
fun testListFill2() = runTest {
eval("""
val b: List<Int> = List.fill(5,10) { it }
println(b)
assertEquals(b, [0,1,2,3,4])
""".trimIndent())
}
@Test
fun testTypedParamCaptureInClosure() = runTest {
// Regression: typed (Int) parameters lost their value when captured into a closure
// because peekValue() returned null for INT-typed frame slots, causing the capture
// to store a FrameSlotRef as OBJ while bytecode expected INT type.
eval("""
fun makeList(n: Int): List<Int> {
List<Int>().also {
for( i in 0..<n ) it += i
}
}
assertEquals([0,1,2,3,4], makeList(5))
assertEquals([], makeList(0))
""".trimIndent())
}
}