From 95c1da60ed7d9c8fe7142853e828df6bbdc07b0e Mon Sep 17 00:00:00 2001 From: sergeych Date: Mon, 18 Aug 2025 00:56:52 +0300 Subject: [PATCH] better elvis + throw +added run {} --- docs/tutorial.md | 14 +++++++++++++ .../kotlin/net/sergeych/lyng/Compiler.kt | 5 +++++ .../kotlin/net/sergeych/lyng/obj/Obj.kt | 3 +++ lynglib/src/commonTest/kotlin/ScriptTest.kt | 20 +++++++++++++++++++ 4 files changed, 42 insertions(+) diff --git a/docs/tutorial.md b/docs/tutorial.md index 1696f9d..84f74aa 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -225,6 +225,19 @@ It works much like `also`, but is executed in the context of the source object: assertEquals(p, Point(2,3)) >>> void +## run + +Executes a block after it returning the value passed by the block. for example, can be used with elvis operator: + + var someVar = null + val result = someVar ?: run { + someVar = 121 + "reset" + } + assertEquals("reset", result) + assertEquals(121, someVar) + >>> void + ## Math It is rather simple, like everywhere else: @@ -1311,6 +1324,7 @@ See [math functions](math.md). Other general purpose functions are: | flow {} | create flow sequence, see [parallelism] | | delay, launch, yield | see [parallelism] | | cached(builder) | remembers builder() on first invocation and return it then | +| let, also, apply, run | see above, flow controls | # Built-in constants diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt index 725d972..7ef54eb 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt @@ -376,6 +376,11 @@ class Compiler( } + "throw" -> { + val s = parseThrowStatement() + operand = Accessor { s.execute(it).asReadonly } + } + else -> operand?.let { left -> // selector: , '.' , // we replace operand with selector code, that diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/Obj.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/Obj.kt index a8795e9..fd05443 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/Obj.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/Obj.kt @@ -315,6 +315,9 @@ open class Obj { args.firstAndOnly().callOn(copy(Arguments(thisObj))) thisObj } + addFn("run") { + args.firstAndOnly().callOn(this) + } addFn("getAt") { requireExactCount(1) thisObj.getAt(this, requiredArg(0)) diff --git a/lynglib/src/commonTest/kotlin/ScriptTest.kt b/lynglib/src/commonTest/kotlin/ScriptTest.kt index d67d7a9..7a09d8e 100644 --- a/lynglib/src/commonTest/kotlin/ScriptTest.kt +++ b/lynglib/src/commonTest/kotlin/ScriptTest.kt @@ -2961,5 +2961,25 @@ class ScriptTest { """.trimIndent()) } + @Test + fun testElvisAndThrow() = runTest { + eval(""" + val x = assertThrows { + null ?: throw "test" + "x" + } + assertEquals( "testx", x.message) + """.trimIndent()) + } + + @Test + fun testElvisAndRunThrow() = runTest { + eval(""" + val x = assertThrows { + null ?: run { throw "testx" } + } + assertEquals( "testx", x.message) + """.trimIndent()) + } + } \ No newline at end of file