fixed wrong error message in val ++/--

This commit is contained in:
Sergey Chernov 2026-04-22 08:56:02 +03:00
parent 0973a6afeb
commit d0f51928de
2 changed files with 32 additions and 15 deletions

View File

@ -2559,11 +2559,7 @@ class BytecodeCompiler(
return value
}
if (!localTarget.isMutable || localTarget.isDelegated) {
val msgId = builder.addConst(BytecodeConst.StringVal("can't reassign val ${localTarget.name}"))
val msgSlot = allocSlot()
builder.emit(Opcode.CONST_OBJ, msgId, msgSlot)
val posId = builder.addConst(BytecodeConst.PosVal(localTarget.pos()))
builder.emit(Opcode.THROW, posId, msgSlot)
emitImmutableLocalReassignError(localTarget.name, localTarget.pos())
return value
}
val slot = resolveCapturedOwnerScopeSlot(localTarget)
@ -2607,12 +2603,8 @@ class BytecodeCompiler(
return value
}
if (!isMutable) {
val msgId = builder.addConst(BytecodeConst.StringVal("can't reassign val $nameTarget"))
val msgSlot = allocSlot()
builder.emit(Opcode.CONST_OBJ, msgId, msgSlot)
val pos = (ref.target as? LocalVarRef)?.pos() ?: Pos.builtIn
val posId = builder.addConst(BytecodeConst.PosVal(pos))
builder.emit(Opcode.THROW, posId, msgSlot)
emitImmutableLocalReassignError(nameTarget, pos)
return value
}
if (slot < scopeSlotCount && value.type != SlotType.UNKNOWN) {
@ -3904,7 +3896,10 @@ class BytecodeCompiler(
val errorSlot = emitLoopVarReassignError(target.name, target.pos())
return CompiledValue(errorSlot, SlotType.OBJ)
}
if (!target.isMutable) return null
if (!target.isMutable) {
val errorSlot = emitImmutableLocalReassignError(target.name, target.pos())
return CompiledValue(errorSlot, SlotType.OBJ)
}
if (target.isDelegated) {
val slot = resolveSlot(target) ?: return null
if (slot < scopeSlotCount) return null
@ -4078,6 +4073,10 @@ class BytecodeCompiler(
val errorSlot = emitLoopVarReassignError(varTarget.name, varTarget.pos())
return CompiledValue(errorSlot, SlotType.OBJ)
}
if (resolved != null && !resolved.second) {
val errorSlot = emitImmutableLocalReassignError(varTarget.name, varTarget.pos())
return CompiledValue(errorSlot, SlotType.OBJ)
}
}
val thisFieldTarget = ref.target as? ThisFieldSlotRef
@ -8438,6 +8437,15 @@ class BytecodeCompiler(
builder.emit(Opcode.THROW, posId, msgSlot)
return msgSlot
}
private fun emitImmutableLocalReassignError(name: String, pos: Pos): Int {
val msgId = builder.addConst(BytecodeConst.StringVal("can't reassign val $name"))
val msgSlot = allocSlot()
builder.emit(Opcode.CONST_OBJ, msgId, msgSlot)
val posId = builder.addConst(BytecodeConst.PosVal(pos))
builder.emit(Opcode.THROW, posId, msgSlot)
return msgSlot
}
private fun binaryLeft(ref: BinaryOpRef): ObjRef = ref.left
private fun binaryRight(ref: BinaryOpRef): ObjRef = ref.right
private fun binaryOp(ref: BinaryOpRef): BinOp = ref.op

View File

@ -17,12 +17,12 @@
package net.sergeych.lyng
import kotlinx.coroutines.delay
import kotlinx.coroutines.test.runTest
import net.sergeych.lyng.obj.toInt
import kotlin.test.Test
import kotlin.test.assertContains
import kotlin.test.assertEquals
import kotlin.time.Duration.Companion.milliseconds
import kotlin.test.assertFailsWith
import kotlin.time.TimeSource
class OptTest {
@ -42,7 +42,6 @@ class OptTest {
repeat(3) { pass ->
val size = scope.eval("buildArray(200000)").toInt()
assertEquals(200000, size, "warmup pass ${pass + 1} failed")
delay(100)
}
@ -80,5 +79,15 @@ class OptTest {
""".trimIndent()
)
}
}
@Test
fun testErrorMessage() = runTest {
val ex = assertFailsWith<ScriptError> {
eval("""
val a = 1
a++
""".trimIndent())
}
assertContains(ex.errorMessage, "can't reassign val a")
}
}