v1.1.0-beta1: mini function declarations and working properties

This commit is contained in:
Sergey Chernov 2025-12-23 13:06:46 +01:00
parent 17b4904ae3
commit 8300c2a3ab
5 changed files with 39 additions and 7 deletions

View File

@ -74,14 +74,18 @@ assertEquals("Adult", p.ageCategory)
### Laconic Expression Shorthand
For simple accessors, you can use the `=` shorthand for a more elegant and laconic form:
For simple accessors and methods, you can use the `=` shorthand for a more elegant and laconic form:
```kotlin
class Circle(val radius: Real) {
val area get() = π * radius * radius
val circumference get() = 2 * π * radius
fun diameter() = radius * 2
}
fun median(a, b) = (a + b) / 2
class Counter {
private var _count = 0
var count get() = _count set(v) = _count = v
@ -92,6 +96,7 @@ class Counter {
- **`val` properties** must have a `get()` accessor and cannot have a `set()`.
- **`var` properties** must have both `get()` and `set()` accessors.
- **Functions and methods** can use the `=` shorthand to return the result of a single expression.
- **No Backing Fields**: There is no magic `field` identifier. If you need to store state, you must declare a separate (usually `private`) field.
- **Type Inference**: You can omit the type declaration if it can be inferred or if you don't need strict typing.

View File

@ -21,7 +21,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
group = "net.sergeych"
version = "1.0.10-SNAPSHOT"
version = "1.1.0-beta1"
// Removed legacy buildscript classpath declarations; plugins are applied via the plugins DSL below

View File

@ -2433,7 +2433,20 @@ class Compiler(
val fnStatements = if (isExtern)
statement { raiseError("extern function not provided: $name") }
else
withLocalNames(paramNames) { parseBlock() }
withLocalNames(paramNames) {
val next = cc.peekNextNonWhitespace()
if (next.type == Token.Type.ASSIGN) {
cc.skipWsTokens()
cc.next() // consume '='
val expr = parseExpression() ?: throw ScriptError(cc.current().pos, "Expected function body expression")
// Shorthand function returns the expression value
statement(expr.pos) { scope ->
expr.execute(scope)
}
} else {
parseBlock()
}
}
// Capture and pop the local declarations count for this function
val fnLocalDecls = localDeclCountStack.removeLastOrNull() ?: 0

View File

@ -3697,7 +3697,7 @@ class ScriptTest {
}
// @Test
@Test
fun testMinimumOptimization() = runTest {
for (i in 1..200) {
bm {
@ -4518,4 +4518,18 @@ class ScriptTest {
""".trimIndent()
)
}
@Test
fun testFunMiniDeclaration() = runTest {
eval("""
class T(x) {
fun method() = x + 1
}
fun median(a,b) = (a+b)/2
assertEquals(11, T(10).method())
assertEquals(2, median(1,3))
""".trimIndent())
}
}

View File

@ -647,14 +647,14 @@ private fun detectDeclarationAndParamOverrides(text: String): Map<Pair<Int, Int>
i = p
continue
}
// Generic function call site: ident followed by '(' (after optional spaces)
// Generic function call site: ident followed by '(' or '=' (after optional spaces)
readIdent(i)?.let { (name, endIdx) ->
val startIdx = i
// Avoid keywords; allow member calls too (a.b()) by not checking preceding char
if (name !in kw) {
var q = skipWs(endIdx)
if (q < n && text[q] == '(') {
// Mark as function identifier at call site
if (q < n && (text[q] == '(' || text[q] == '=')) {
// Mark as function identifier at call site or shorthand declaration
result[startIdx to endIdx] = "hl-fn"
i = endIdx
return@let