update version, site and docs

This commit is contained in:
Sergey Chernov 2026-02-16 19:29:14 +03:00
parent c5b8871c3a
commit afa4b20070
9 changed files with 192 additions and 52 deletions

View File

@ -1,6 +1,31 @@
## Changelog
## 1.5.0-SNAPSHOT
### Unreleased
### Language Features
- Added `return` statement with local and non-local exit support (`return@label`).
- Support for `abstract` classes, methods, and variables.
- Introduced `interface` as a synonym for `abstract class`.
- Multiple Inheritance (MI) completed and enabled by default (C3 MRO).
- Class properties with custom accessors (`get`, `set`).
- Restricted setter visibility (`private set`, `protected set`).
- Late-initialized `val` fields in classes with `Unset` protection.
- Named arguments (`name: value`) and named splats (`...Map`).
- Assign-if-null operator `?=`.
- Refined `protected` visibility rules and `closed` modifier.
- Transient attribute `@Transient` for serialization and equality.
- Unified Delegation model for `val`, `var`, and `fun`.
- Singleton objects (`object`) and object expressions.
### Standard Library
- Added `with(self, block)` for scoped execution.
- Added `clamp()` function and extension.
- Improved `Exception` and `StackTraceEntry` reporting.
### Tooling and IDE
- **CLI**: Added `fmt` as a first-class subcommand for code formatting.
- **IDEA Plugin**: Lightweight autocompletion (experimental), improved docs, and Grazie integration.
- **Highlighters**: Updated TextMate bundle and website highlighters for new syntax.
### Detailed Changes:
- Language: Refined `protected` visibility rules
- Ancestor classes can now access `protected` members of their descendants, provided the ancestor also defines or inherits a member with the same name (indicating an override of a member known to the ancestor).
@ -109,16 +134,6 @@
- Documentation updated (docs/OOP.md and tutorial quick-start) to reflect MI with active C3 MRO.
Notes:
- Existing single-inheritance code continues to work; resolution reduces to the single base.
- If code previously relied on non-deterministic parent set iteration, C3 MRO provides a predictable order; disambiguate explicitly if needed using `this@Type`/casts.
# Changelog
All notable changes to this project will be documented in this file.
## Unreleased
- CLI: Added `fmt` as a first-class Clikt subcommand.
- Default behavior: formats files to stdout (no in-place edits by default).
- Options:

View File

@ -1,4 +1,4 @@
# Lyng Language AI Specification (V1.3)
# Lyng Language AI Specification (V1.5.0-SNAPSHOT)
High-density specification for LLMs. Reference this for all Lyng code generation.

View File

@ -48,7 +48,7 @@ assertEquals(A.One, A.E.One)
- [Language home](https://lynglang.com)
- [introduction and tutorial](docs/tutorial.md) - start here please
- [What's New in 1.3](docs/whats_new_1_3.md)
- [What's New in 1.5](docs/whats_new_1_5.md)
- [Testing and Assertions](docs/Testing.md)
- [Filesystem and Processes (lyngio)](docs/lyngio.md)
- [Return Statement](docs/return_statement.md)
@ -64,7 +64,7 @@ assertEquals(A.One, A.E.One)
```kotlin
// update to current please:
val lyngVersion = "0.6.1-SNAPSHOT"
val lyngVersion = "1.5.0-SNAPSHOT"
repositories {
// ...
@ -177,7 +177,7 @@ Designed to add scripting to kotlin multiplatform application in easy and effici
# Language Roadmap
We are now at **v1.0**: basic optimization performed, battery included: standard library is 90% here, initial
We are now at **v1.5.0-SNAPSHOT** (stable development cycle): basic optimization performed, battery included: standard library is 90% here, initial
support in HTML, popular editors, and IDEA; tools to syntax highlight and format code are ready. It was released closed to schedule.
Ready features:
@ -217,7 +217,7 @@ Ready features:
All of this is documented in the [language site](https://lynglang.com) and locally [docs/language.md](docs/tutorial.md). the current nightly builds published on the site and in the private maven repository.
## plan: towards v1.5 Enhancing
## plan: towards v2.0 Next Generation
- [x] site with integrated interpreter to give a try
- [x] kotlin part public API good docs, integration focused

View File

@ -1,7 +1,7 @@
# What's New in Lyng
This document highlights the latest additions and improvements to the Lyng language and its ecosystem.
For a programmer-focused migration summary, see `docs/whats_new_1_3.md`.
For a programmer-focused migration summary, see `docs/whats_new_1_5.md`.
## Language Features
@ -102,7 +102,7 @@ Singleton objects are declared using the `object` keyword. They provide a conven
```lyng
object Config {
val version = "1.2.3"
val version = "1.5.0-SNAPSHOT"
fun show() = println("Config version: " + version)
}

93
docs/whats_new_1_5.md Normal file
View File

@ -0,0 +1,93 @@
# What's New in Lyng 1.5 (vs 1.3.* / master)
This document summarizes the significant changes and new features introduced in the 1.5.0-SNAPSHOT development cycle.
## Highlights
- **The `return` Statement**: Added support for local and non-local returns using labels.
- **Abstract Classes and Interfaces**: Full support for `abstract` members and the `interface` keyword.
- **Class Properties with Accessors**: Define `val` and `var` properties with custom `get()` and `set()`.
- **Restricted Setter Visibility**: Use `private set` and `protected set` on fields and properties.
- **Late-initialized `val`**: Support for `val` fields that are initialized in `init` blocks or class bodies.
- **Named Arguments and Splats**: Improved call-site readability with `name: value` and map-based splats.
- **Refined Visibility**: Improved `protected` access and `closed` modifier for better encapsulation.
## Language Features
### The `return` Statement
You can now exit from the innermost enclosing callable (function or lambda) using `return`. Lyng also supports non-local returns to outer scopes using labels.
```lyng
fun findFirst<T>(list: Iterable<T>, predicate: (T)->Bool): T? {
list.forEach {
if (predicate(it)) return@findFirst it
}
null
}
```
### Abstract Classes and Interfaces
Lyng now supports the `abstract` modifier for classes and their members. `interface` is introduced as a synonym for `abstract class`, allowing for rich multi-inheritance patterns.
```lyng
interface Shape {
abstract val area: Real
fun describe() = "Area: %g"(area)
}
class Circle(val radius: Real) : Shape {
override val area get = Math.PI * radius * radius
}
```
### Class Properties with Accessors
Properties can now have custom getters and setters. They do not have automatic backing fields, making them perfect for computed values or delegation.
```lyng
class Rectangle(var width: Real, var height: Real) {
val area: Real get() = width * height
var squareSize: Real
get() = area
set(v) {
width = sqrt(v)
height = width
}
}
```
### Named Arguments and Named Splats
Improve call-site clarity by specifying argument names. You can also expand a Map into named arguments using the splat operator.
```lyng
fun configure(timeout: Int, retry: Int = 3) { ... }
configure(timeout: 5000, retry: 5)
val options = { timeout: 1000, retry: 1 }
configure(...options)
```
### Modern Operators
The `?=` operator allows for concise "assign if null" logic.
```lyng
var cache: Map? = null
cache ?= { "status": "ok" } // Only assigns if cache is null
```
## Tooling and IDE
- **IDEA Plugin**: Significant improvements to autocompletion, documentation tooltips, and natural language support (Grazie integration).
- **CLI**: The `lyng fmt` command is now a first-class tool for formatting code with various options like `--check` and `--in-place`.
- **Performance**: Ongoing optimizations in the bytecode VM and compiler for faster execution and smaller footprint.
## Migration Guide (from 1.3.*)
1. **Check Visibility**: Refined `protected` and `private` rules may catch previously undetected invalid accesses.
2. **Override Keyword**: Ensure all members that override ancestor declarations are marked with the `override` keyword (now mandatory).
3. **Return in Shorthand**: Remember that `return` is forbidden in `=` shorthand functions; use block syntax if you need early exit.
## References
- `docs/OOP.md`
- `docs/return_statement.md`
- `docs/tutorial.md`

View File

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

View File

@ -29,8 +29,8 @@ fun HomePage() {
listOf(
"""
// Everything is an expression
val x = 10
val status = if (x > 0) "Positive" else "Zero or Negative"
val x: Int = 10
val status: String = if (x > 0) "Positive" else "Zero or Negative"
// Even loops return values!
val result = for (i in 1..5) {
@ -40,8 +40,8 @@ fun HomePage() {
println("Result: " + result)
""".trimIndent(),
"""
// Functional power with ranges and collections
val squares = (1..10)
// Functional power with generics and collections
val squares: List<Int> = (1..10)
.filter { it % 2 == 0 }
.map { it * it }
@ -49,20 +49,43 @@ fun HomePage() {
// Output: [4, 16, 36, 64, 100]
""".trimIndent(),
"""
// Generics and type aliases
typealias Num = Int | Real
class Box<out T: Num>(val value: T) {
fun get(): T = value
}
val intBox = Box(42)
val realBox = Box(3.14)
println("Boxes: " + intBox.get() + ", " + realBox.get())
""".trimIndent(),
"""
// Strict compile-time types and symbol resolution
fun greet(name: String, count: Int) {
for (i in 1..count) {
println("Hello, " + name + "!")
}
}
greet("Lyng", 3)
// greet(10, "error") // This would be a compile-time error!
""".trimIndent(),
"""
// Flexible map literals and shorthands
val id = 101
val name = "Lyng"
val base = { id:, name: } // Shorthand for id: id, name: name
val full = { ...base, version: "1.0", status: "active" }
val full = { ...base, version: "1.5.0-SNAPSHOT", status: "active" }
println(full)
""".trimIndent(),
"""
// Modern null safety
var config = null
var config: Map<String, Int>? = null
config ?= { timeout: 30 } // Assign only if null
val timeout = config?.timeout ?: 60
val timeout = config?["timeout"] ?: 60
println("Timeout is: " + timeout)
""".trimIndent(),
"""
@ -76,10 +99,10 @@ fun HomePage() {
"""
// Diamond-safe Multiple Inheritance (C3 MRO)
interface Logger {
fun log(m) = println("[LOG] " + m)
fun log(m: String) = println("[LOG] " + m)
}
interface Auth {
fun login(u) = println("Login: " + u)
fun login(u: String) = println("Login: " + u)
}
class App() : Logger, Auth {
@ -92,30 +115,30 @@ fun HomePage() {
""".trimIndent(),
"""
// Extension functions and properties
fun String.shout() = this.toUpperCase() + "!!!"
fun String.shout(): String = this.uppercase() + "!!!"
println("hello".shout())
val List.second get = this[1]
val List<T>.second: T get() = this[1]
println([10, 20, 30].second)
""".trimIndent(),
"""
// Non-local returns from closures
fun findFirst(list, predicate) {
fun findFirst<T>(list: Iterable<T>, predicate: (T)->Bool): T? {
list.forEach {
if (predicate(it)) return@findFirst it
}
null
}
val found = findFirst([1, 5, 8, 12]) { it > 10 }
val found: Int? = findFirst([1, 5, 8, 12]) { it > 10 }
println("Found: " + found)
""".trimIndent(),
"""
// Easy operator overloading
class Vector(val x, val y) {
override fun plus(other) = Vector(x + other.x, y + other.y)
override fun toString() = "Vector(%g, %g)"(x, y)
class Vector(val x: Real, val y: Real) {
override fun plus(other: Vector): Vector = Vector(x + other.x, y + other.y)
override fun toString(): String = "Vector(%g, %g)"(x, y)
}
val v1 = Vector(1, 2)
@ -125,7 +148,7 @@ fun HomePage() {
"""
// Property delegation to Map
class User() {
var name by Map()
var name: String by Map()
}
val u = User()
@ -165,17 +188,18 @@ fun HomePage() {
Div({ classes("text-center") }) {
H1({ classes("display-5", "fw-bold", "mb-3") }) { Text("Welcome to Lyng") }
P({ classes("lead", "text-muted", "mb-4") }) {
Text("A lightweight, expressive scripting language designed for clarity, composability, and fun. ")
Text("A lightweight, expressive scripting language with strict static typing and functional power. ")
Br()
Text("Run it anywhere Kotlin runs — share logic across JS, JVM, and more.")
}
Div({ classes("d-flex", "justify-content-center", "gap-2", "flex-wrap", "mb-4") }) {
// Benefits pills
listOf(
"Clean, familiar syntax",
"Strict static typing",
"Generics & Type Aliases",
"Implicit coroutines",
"both FP and OOP",
"Batteries-included standard library",
"Embeddable and testable"
"Batteries-included standard library"
).forEach { b ->
Span({ classes("badge", "text-bg-secondary", "rounded-pill") }) { Text(b) }
}
@ -233,7 +257,7 @@ fun HomePage() {
// Short features list
Div({ classes("row", "g-4", "mt-1") }) {
listOf(
Triple("Fast to learn", "Familiar constructs and readable patterns — be productive in minutes.", "lightning"),
Triple("Safe and Robust", "Strict compile-time resolution, generics, and null safety catch errors early.", "shield-check"),
Triple("Portable", "Runs wherever Kotlin runs: reuse logic across platforms.", "globe2"),
Triple("Pragmatic", "A standard library that solves real problems without ceremony.", "gear-fill")
).forEach { (title, text, icon) ->

View File

@ -22,6 +22,7 @@ import net.sergeych.lyng.Script
import net.sergeych.lyng.ScriptError
import net.sergeych.lyng.highlight.TextRange
import net.sergeych.lyng.miniast.CompletionItem
import net.sergeych.lyng.requireScope
import net.sergeych.lyng.tools.LyngDiagnostic
import net.sergeych.lyng.tools.LyngDiagnosticSeverity
import net.sergeych.lyng.tools.LyngSymbolInfo
@ -48,11 +49,18 @@ fun TryLyngPage(route: String) {
var code by remember(initialCode) {
mutableStateOf(
initialCode ?: """
// Welcome to Lyng! Edit and run.
// Try changing the data and press Ctrl+Enter or click Run.
val data = 1..5 // or [1, 2, 3, 4, 5]
data.filter { it % 2 == 0 }.map { it * it }
// Welcome to Lyng! Modern scripting with strict types and generics.
typealias Numeric = Int | Real
fun process<T: Numeric>(items: List<T>): List<T> {
items.filter { it > 0 }.map { it * it }
}
val data: List<Int> = [-2, -1, 0, 1, 2]
println("Processed: " + process(data))
// Try changing data or adding Real numbers!
""".trimIndent()
)
}
@ -94,13 +102,13 @@ fun TryLyngPage(route: String) {
s.addVoidFn("print") {
for ((i, a) in this.args.withIndex()) {
if (i > 0) printed.append(' ')
printed.append(a.toString(this).value)
printed.append(a.toString(this.requireScope()).value)
}
}
s.addVoidFn("println") {
for ((i, a) in this.args.withIndex()) {
if (i > 0) printed.append(' ')
printed.append(a.toString(this).value)
printed.append(a.toString(this.requireScope()).value)
}
printed.append('\n')
}
@ -154,8 +162,8 @@ fun TryLyngPage(route: String) {
fun resetCode() {
code = initialCode ?: """
// Welcome to Lyng! Edit and run.
[1,2,3].map { it * 10 }
// Welcome to Lyng! Modern scripting with strict types and generics.
[1, 2, 3].map { it * 10 }
""".trimIndent()
output = null
error = null

View File

@ -329,7 +329,7 @@
<!-- Top-left version ribbon -->
<div class="corner-ribbon bg-danger text-white">
<span style="margin-left: -5em">
v1.2.0!
v1.5.0-SNAPSHOT!
</span>
</div>
<!-- Fixed top navbar for the whole site -->