diff --git a/README.md b/README.md index d687332..6fd8584 100644 --- a/README.md +++ b/README.md @@ -48,6 +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) - [Testing and Assertions](docs/Testing.md) - [Filesystem and Processes (lyngio)](docs/lyngio.md) - [Return Statement](docs/return_statement.md) diff --git a/docs/whats_new.md b/docs/whats_new.md index a27e6a6..ccfe62a 100644 --- a/docs/whats_new.md +++ b/docs/whats_new.md @@ -1,6 +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`. ## Language Features diff --git a/docs/whats_new_1_3.md b/docs/whats_new_1_3.md new file mode 100644 index 0000000..184a530 --- /dev/null +++ b/docs/whats_new_1_3.md @@ -0,0 +1,133 @@ +# What's New in Lyng 1.3 (vs 1.2.* / master) + +This is a programmer-focused summary of what changed since the 1.2.* line on `master`. It highlights new language and type-system features, runtime/IDE improvements, and how to migrate code safely. + +## Highlights + +- Generics are now a first-class part of the type system, with bounds, variance, unions, and intersections. +- Type aliases and type-expression checks (`T1 is T2`, `A in T`) enable richer static modeling. +- Nested declarations inside classes, plus lifted enum entries via `enum E*`. +- Stepped ranges (`step`) including iterable open-ended and real ranges. +- Runtime and compiler speedups: more bytecode coverage, direct slot access, call-site caching. + +## Language and type system + +### Generics, bounds, and variance + +You can declare generic functions/classes with `<...>`, restrict them with bounds, and control variance. + +```lyng +fun id(x: T): T = x +class Box(val value: T) + +fun sum(x: T, y: T) = x + y +class Named(val data: T) +``` + +### Type aliases and type expressions + +Type aliases can name any type expression, including unions and intersections. + +```lyng +type Num = Int | Real +type Maybe = T? +``` + +Type expressions can be checked directly: + +```lyng +fun f(xs: List) { + assert( T is Int | String | Bool ) // type-subset check + assert( Int in T ) // same relation as `Int is T` +} +``` + +Value checks remain `x is T`. Type expression equality uses `==` and is structural. + +### Nullable shorthand for parameters + +Untyped parameters and constructor args can use `x?` as shorthand for `x: Object?`: + +```lyng +class A(x?) { ... } +fun f(x?) { x == null } +``` + +### List/map literal inference + +The compiler now infers element and key/value types from literals and spreads. Mixed element types produce unions. + +```lyng +val a = [1, 2, 3] // List +val b = [1, "two", true] // List +val m = { "a": 1, "b": "x" } // Map +``` + +### Compile-time member access only + +Member access is resolved at compile time. On unknown types, only `Object` members are visible; other members require an explicit cast. + +```lyng +fun f(x) { // x: Object + x.toString() // ok + x.size() // compile-time error + (x as List).size() +} +``` + +This removes runtime name-resolution fallbacks and makes errors deterministic. + +### Nested declarations and lifted enums + +Classes, objects, enums, and type aliases can be declared inside another class and accessed by qualifier. Enums can lift entries into the outer namespace with `*`. + +```lyng +class A { + class B(x?) + object Inner { val foo = "bar" } + type Alias = B + enum E* { One, Two } +} + +val b = A.B() +assertEquals(A.One, A.E.One) +``` + +### Stepped ranges + +Ranges now support `step`, and open-ended/real ranges are iterable only with an explicit step. + +```lyng +(1..5 step 2).toList() // [1,3,5] +(0.0..1.0 step 0.25).toList() // [0,0.25,0.5,0.75,1.0] +(0.. step 1).take(3).toList() // [0,1,2] +``` + +## Tooling and performance + +- Bytecode compiler/VM coverage expanded (loops, expressions, calls), improving execution speed and consistency. +- Direct frame-slot access and scoped slot addressing reduce lookup overhead, including in closures. +- Call-site caching and numeric fast paths reduce hot-loop overhead. +- IDE tooling updated for the new type system and nested declarations; MiniAst-based completion work continues. + +## Migration guide (from 1.2.*) + +1) Replace dynamic member access on unknown types +- If you relied on runtime name resolution, add explicit casts or annotate types so the compiler can resolve members. + +2) Adopt new type-system constructs where helpful +- Consider `type` aliases for complex unions/intersections. +- Prefer generic signatures over `Object` when the API is parametric. + +3) Update range iteration where needed +- Use `step` for open-ended or real ranges you want to iterate. + +4) Nullable shorthand is optional +- If you used untyped nullable params, you can keep `x` (Object) or switch to `x?` (Object?) for clarity. + +## References + +- `docs/generics.md` +- `docs/Range.md` +- `docs/OOP.md` +- `docs/BytecodeSpec.md` diff --git a/lynglib/build.gradle.kts b/lynglib/build.gradle.kts index daf1234..84deea0 100644 --- a/lynglib/build.gradle.kts +++ b/lynglib/build.gradle.kts @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.dsl.JvmTarget group = "net.sergeych" -version = "1.5.0-SNAPSHOT" +version = "1.3.0-SNAPSHOT" // Removed legacy buildscript classpath declarations; plugins are applied via the plugins DSL below