diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt index 01f2e90..a3e858a 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt @@ -3266,7 +3266,13 @@ class Compiler( this.currentClassCtx = cls try { (thisObj as? ObjInstance)?.let { i -> - annotatedFnBody.execute(ClosureScope(this, i.instanceScope)) + val execScope = i.instanceScope.createChildScope( + pos = this.pos, + args = this.args, + newThisObj = i + ) + execScope.currentClassCtx = cls + annotatedFnBody.execute(execScope) } ?: annotatedFnBody.execute(thisObj.autoInstanceScope(this)) } finally { this.currentClassCtx = savedCtx diff --git a/lynglib/src/commonTest/kotlin/OOTest.kt b/lynglib/src/commonTest/kotlin/OOTest.kt index 26d3e79..32281f3 100644 --- a/lynglib/src/commonTest/kotlin/OOTest.kt +++ b/lynglib/src/commonTest/kotlin/OOTest.kt @@ -911,4 +911,19 @@ class OOTest { assertEquals("{\"a\":\"foo\",\"b\":\"bar\"}",T("foo", "bar").toJsonString()) """.trimIndent()) } + + @Test + fun testAssignToUnqualifiedParams() = runTest { + eval(""" + class T(x) { + fun setx(v) { x = v } + fun incr(v) { x += v } + } + val t = T(1) + t.setx(2) + assertEquals(2, t.x) + t.incr(3) + assertEquals(5, t.x) + """.trimIndent()) + } } \ No newline at end of file diff --git a/lynglib/src/commonTest/kotlin/ScriptTest.kt b/lynglib/src/commonTest/kotlin/ScriptTest.kt index 80a05fe..a93a045 100644 --- a/lynglib/src/commonTest/kotlin/ScriptTest.kt +++ b/lynglib/src/commonTest/kotlin/ScriptTest.kt @@ -5035,5 +5035,13 @@ class ScriptTest { assertEquals(10.0, 15.5.clamp(0.0..10.0)) """.trimIndent()) } + + @Test + fun testEmptySpreadList() = runTest { + eval(""" + fun t(a, tags=[]) { [a, ...tags] } + assertEquals( [1], t(1) ) + """.trimIndent()) + } } diff --git a/lynglib/src/commonTest/kotlin/ValReassignRegressionTest.kt b/lynglib/src/commonTest/kotlin/ValReassignRegressionTest.kt new file mode 100644 index 0000000..8b7b90e --- /dev/null +++ b/lynglib/src/commonTest/kotlin/ValReassignRegressionTest.kt @@ -0,0 +1,99 @@ +/* + * Copyright 2026 Sergey S. Chernov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import kotlinx.coroutines.test.runTest +import net.sergeych.lyng.eval +import kotlin.test.Test + +class ValReassignRegressionTest { + + @Test + fun reassign_ctor_param_field_should_work() = runTest { + eval( + """ + class Wallet(balance = 0) { + fun add(amount) { + balance += amount + } + fun transfer(amount) { + val balance = 0 + add(amount) + } + fun get() { balance } + } + val w = Wallet() + w.transfer(1) + assertEquals(1, w.get()) + """.trimIndent() + ) + } + + @Test + fun reassign_field_should_not_see_caller_locals() = runTest { + eval( + """ + class Wallet(balance = 0) { + fun add(amount) { balance += amount } + fun get() { balance } + } + fun doTransfer(w, amount) { + val balance = 0 + w.add(amount) + } + val w = Wallet() + doTransfer(w, 2) + assertEquals(2, w.get()) + """.trimIndent() + ) + } + + @Test + fun reassign_field_should_not_see_caller_param() = runTest { + eval( + """ + class Wallet(balance = 0) { + fun add(amount) { balance += amount } + fun get() { balance } + } + fun doTransfer(balance, w, amount) { + w.add(amount) + } + val w = Wallet() + doTransfer(0, w, 3) + assertEquals(3, w.get()) + """.trimIndent() + ) + } + + @Test + fun reassign_field_should_not_see_block_local() = runTest { + eval( + """ + class Wallet(balance = 0) { + fun add(amount) { balance += amount } + fun get() { balance } + } + val w = Wallet() + run { + val balance = 0 + w.add(4) + } + assertEquals(4, w.get()) + """.trimIndent() + ) + } +}