ranger-compiler 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,76 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.2.0] - 2026-08-01
11
+
12
+ ### Fixed
13
+
14
+ - **`@serialize(true)` array / hash / property types without the annotation** — the generator assumed every referenced class had `toDictionary` / `fromDictionary` and emitted the call regardless, so the compile failed inside `extension <Class>` with `Could not match argument types for push` / `for case` and never named the real cause. Hash-valued fields were worse: the field was silently dropped from the serialized output. A `@serialize(true)` class that references a class which is neither `@serialize(true)` nor implements the pair by hand now fails at the declaration:
15
+
16
+ ```text
17
+ [FAIL] Parent.kids: [Child] can not be serialized - class Child is not @serialize(true).
18
+ Add @serialize(true) to Child, or implement toDictionary / fromDictionary in it.
19
+ 9 │ def kids:[Child]
20
+ ^── here
21
+ ```
22
+
23
+ - **`@serialize(true)` with mutually referencing classes** — serializer extensions were generated one class at a time and `is_serialized` was set as each was reached, so whichever class came first in the dependency sort saw its peer as non-serializable and emitted primitive element code. All `@serialize(true)` classes are now marked before any extension is generated, which mutual references could not satisfy by sorting.
24
+
25
+ - **`@serialize(true)` element types with hand-written `toDictionary` / `fromDictionary`** — accepted as serializable; the generator now routes them through the object path instead of treating them as primitives.
26
+
27
+ - **Duplicate serializer extension when one file is reached by two import spellings** — a file imported as both `Child.rgr` and `domain/Child.rgr` was expanded twice, and with `@serialize(true)` the second expansion produced `method with the same name and parameter signature declared earlier` pointing at generated code. Fixed since 3.1.1 was published, released here; covered by a regression test.
28
+
29
+ - **`SourceCode` constructed with three arguments in `ng_CodeNode.rgr`** — `SourceCode` takes a single `code_str`, but `vref1`, `vref2`, `newStr`, `newBool` and nine sibling factories passed `(name 0 (strlen name))` or `("" 0 0)`, copying the shape of the adjacent `new CodeNode(code 0 ...)`. JavaScript discards the extra arguments, so this was invisible until the TypeScript API bundle was type checked, where it produced all 13 of the `TS2554: Expected 1 arguments, but got 3` errors that `build:dist:module` reported. Dropping the dead arguments makes `tsc` clean, so the step is `&&`-chained again and a real type error blocks the build instead of scrolling past
30
+
31
+ - **`file_mtime` C++ backend** — added missing `cpp` template in `Lang.rgr` (`stat()` + ms, matching es6 `mtimeMs`); fixes `game_runtime.rgr` hot-reload compile for `game_sdl` native binary
32
+
33
+ - **`TSLexer` UTF-8 / native C++ tokenization** — code-unit length vs byte `charAt` mismatch after multi-byte characters (e.g. em dash in comments) no longer desyncs the lexer; fixes native SDL parse failures on [`invaders.game.tsx`](./gallery/game_engine/scripting/invaders.game.tsx) and similar scripts
34
+
35
+ ### Added
36
+
37
+ - **LPC spritesheet compositor (standalone MVP)** — Ranger-native `gallery/game_engine/lpc/` (`png_decoder.rgr`, layer blit, male walk demo); embedded `pack/demo-male-walk` (~28 KB); `npm run engine:lpc:build` / `engine:lpc:run`; design doc [`LPC_HEADLESS_SPRITESHEET.md`](./gallery/game_engine/LPC_HEADLESS_SPRITESHEET.md)
38
+
39
+ - **JPEG background loading for scripted games** — `GameImageLoader` + `GameRunner` asset queue (`resources()`, `backgroundImage()`, `onLoading()`); `splash_demo.game.tsx` smoke test; `game.d.ts` `ResourceDef` / `LoadingProps` types
40
+
41
+ - **In-process TS hot reload (Path A)** — `TSAstPatcher` (`ts_ast_patch.rgr`), `ComponentEngine.patchScript()`, `GameRunner` runtime options (`setHotReload`, `trackScriptFile`, `maybeHotReload`); `game_sdl --hot-reload` / `--no-hot-reload`; default on for interactive SDL, off for `maxFrames` smoke runs
42
+
43
+ - **SDL + native compiled games (Path B)** — `game_sdl_native_host.rgr`, `invaders_native_sdl_runner.rgr`, `build-game-sdl-native.sh`; `npm run engine:game-sdl-native:run:invaders` runs emitter output in an SDL window without `ComponentEngine`
44
+
45
+ - **`@serialize(true)` regression suite** — `tests/compiler-serialize.test.ts` and `tests/fixtures/serialize/`: round trip over primitives, nested objects, object arrays and object hashes; mutual references; hand-written `toDictionary` / `fromDictionary`; duplicate import spellings; and the three diagnostics above
46
+
47
+ ### Changed
48
+
49
+ - **`prepublishOnly` no longer runs the whole repository suite** — publishing the compiler ran all 56 test files, including the gallery, game-engine and native-toolchain suites. Those need SDL2, `g++`, Cannon and game fixtures that ship with neither the repo nor the package, so `npm publish` failed on the publisher's machine for reasons unrelated to the compiler (missing `SDL2/SDL.h`, `gallery/game_engine/games/ylos/index.tsx` and `physics_race/index.tsx` are absent from the repository entirely). `prepublishOnly` and `.github/workflows/publish.yml` now run `npm run test:publish` — 44 files, 355 tests, ~90s — covering parsing, type checking and code generation for every target backend. `npm test` still runs everything, and `ci.yml` is unchanged.
50
+
51
+ - **`build:dist` now includes `build:dist:module`** — `dist/api.js` was not rebuilt by the release build, which is how it drifted behind `bin/output.js`
52
+
53
+ - **`dist/api.js` rebuilt from current sources** — the committed programmatic-API bundle predated several compiler fixes, so `require("ranger-compiler")` shipped older behaviour than the `rgrc` CLI. `scripts/patch-chain-desugar.js` now patches `dist/api.js` as well as `bin/output.js`, and `build:dist:module` runs it after `tsc`
54
+
55
+ ## [3.1.1] - 2026-06-23
56
+
57
+ ### Changed
58
+
59
+ - Version bump for npm publish — recommended for cloud CI and projects that install `ranger-compiler` from npm (e.g. koodisampo) instead of a sibling `../agent/Ranger` checkout
60
+ - Default `npm test` / `prepublishOnly` skips `compiler-llvm.test.ts` (experimental LLVM/WAT backend); run `npm run test:llvm` when working on native/WASM codegen
61
+
62
+ ### Added
63
+
64
+ - **IsoDate stdlib** — `lib/IsoDate/` (`DateMath`, `IsoDateParse`, `IsoCalendar`) and `lib/IsoDateLib.rgr` for portable ISO calendar dates without host `Date`; see [ai/ISO_DATE.md](ai/ISO_DATE.md)
65
+ - **IsoDate compiler intrinsics** — `iso_add_days`, `iso_compare`, `iso_between` in `Lang.rgr` (Kotlin/Java `java.time.LocalDate`, ES6 UTC-safe helper)
66
+ - **IsoDate regression** — `tests/fixtures/iso_date_ops.rgr` in Kotlin compiler tests
67
+ - **Regex stdlib** — `lib/Regex/` (`RegexMatch`) and `lib/RegexLib.rgr` for string-pattern matching without `/literal/` syntax; see [ai/REGEX.md](ai/REGEX.md)
68
+ - **Regex compiler intrinsic** — `regex_test(pattern, haystack)` in `Lang.rgr` (Kotlin/Java `Regex`/`Pattern`, ES6 `RegExp`, Swift `range(of:options:)`)
69
+ - **Regex regression** — `tests/fixtures/regex_test_ops.rgr` in Kotlin compiler tests
70
+
71
+ - **JavaScript/TypeScript source maps (`-sourcemap`)** — `SourceMapBuilder` with VLQ encoding (`compiler/ng_SourceMap.rgr`); `CodeWriter` line/column tracking, `walkNodeStack`, and `outMapped()`; embedded `sourcesContent` for `.rgr` sources; `.js.map` + `//# sourceMappingURL=` on save; statement/expression mappings via `LiveCompiler.WalkNode` walk context; expression `names` from `node.vref` / parameter names; regression `tests/compiler-sourcemap.test.ts`; README section *JavaScript / TypeScript source maps*
72
+
73
+ ### Fixed
74
+
75
+ - **Source map VLQ line breaks** — `buildMappingsString` no longer resets source/original relative state on `;` (fixes DevTools breakpoints on `.rgr` sources)
76
+ - **Source map original line** — `addMappingFromNode` uses `node.getLine()` from `sp` instead of stale `node.row`
77
+ - **Kotlin `floor` / `int2double`** — `int2double` emits `.toDouble()`; reserved parameter names escaped (`val`, `object`, …)
78
+ - **`proc_send` dispatch wrapping** — turn boundaries around handler calls; `ProcessRuntime.beginDispatchTurn` / `endDispatchTurn`
79
+
10
80
  ## [3.1.0] - 2026-06-02
11
81
 
12
82
  ### Added
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Ranger cross language compiler
2
2
 
3
- **Version 3.1.0** | Status: `experimental`
3
+ **Version 3.1.1** | Status: `experimental`
4
4
 
5
5
  Ranger is a self-hosting cross-language compiler for writing portable algorithms, parsers, generators, and small tools once and compiling them to multiple target languages.
6
6
 
@@ -56,7 +56,7 @@ const host = ProcessUiHost.__singleton();
56
56
  host.notifyPath = (path) => { /* sync view model + re-render */ };
57
57
  ```
58
58
 
59
- **Docs:** [PROCESS_MVP.md](PROCESS_MVP.md) (scope), [PROCESS_STATUS.md](PROCESS_STATUS.md) (compiler checklist), [PROCESS_UI_NOTIFY.md](PROCESS_UI_NOTIFY.md) (notify batching), [PROCESS_UI_VIEW_MODELS.md](PROCESS_UI_VIEW_MODELS.md) (view DTO assignment). **Gallery:** [process_counter_board](gallery/process_counter_board/README.md). **Pilot:** [realtrainer `app-ranger` Active Workout demo](https://github.com/terotests/realtrainer/tree/copilot/create-watch-ui-components/app-ranger/demo/active-workout-process).
59
+ **Docs:** [PROCESS_MVP.md](PROCESS_MVP.md) (scope), [PROCESS_STATUS.md](PROCESS_STATUS.md) (compiler checklist), [PROCESS_RUNTIME_INVARIANTS.md](PROCESS_RUNTIME_INVARIANTS.md) (dispatch turn / one notify), [PROCESS_UI_NOTIFY.md](PROCESS_UI_NOTIFY.md) (notify batching), [PROCESS_UI_VIEW_MODELS.md](PROCESS_UI_VIEW_MODELS.md) (view DTO assignment). **Gallery:** [process_counter_board](gallery/process_counter_board/README.md) (Vite + React host for `@process`).
60
60
 
61
61
  ## Where To Start
62
62
 
@@ -69,6 +69,8 @@ host.notifyPath = (path) => { /* sync view model + re-render */ };
69
69
  - `gallery/js_parser` - substantial parser example with benchmarks and README
70
70
  - `gallery/pdf_writer` - EVG / TSX document tooling and preview server
71
71
  - `gallery/invaders` - cross-target demo game
72
+ - `gallery/game_engine` - retained-mode game runner, SDL launcher, and TSX games (Pong, Breakout, Invaders, Pac-Man); see `gallery/game_engine/scripting/GAME_SCRIPTING.md`
73
+ - `gallery/invaders/llvm/invaders.ll` - checked-in LLVM IR sample from the experimental `-l=llvm` backend
72
74
 
73
75
  ## Compatibility Snapshot
74
76
 
@@ -80,8 +82,26 @@ The project can target `JavaScript`, `Java`, `Go`, `Swift`, `PHP`, `C++`, `C#`,
80
82
  | Self-hosting | Actively used, but full compiler generation quality is strongest in JavaScript |
81
83
  | JavaScript / ES6 | Best baseline target and most reliable place to start |
82
84
  | Go / Swift / Rust / Kotlin / C++ | Useful and increasingly capable, but expect edge cases and target-specific gaps |
85
+ | **LLVM / WASM** (`-l=llvm`) | **Experimental.** Lowers to LLVM IR; optional WAT export for freestanding WASM. Native libc builds work for demos like Space Invaders; browser WASM is still rough. See `npm run test:llvm`, `npm run game:build:llvm`. |
83
86
  | Gallery examples | Good for understanding direction and capability, but some require manual setup or platform-specific tooling |
84
87
 
88
+ ### Conformance suite (Track 1)
89
+
90
+ Cross-target semantic fixtures live in `tests/conformance/`. Run `npx vitest run tests/compiler-conformance.test.ts`.
91
+ Regenerate the fixture list with `node scripts/generate-conformance-table.mjs`.
92
+
93
+ <!-- BEGIN CONFORMANCE_TABLE -->
94
+ | Fixture | Topic | Targets |
95
+ | --- | --- | --- |
96
+ | `array_param_mutate` | array parameters use reference semantics (Issue #58; Go known gap) | ES6, Go, Kotlin (when toolchain present) |
97
+ | `clear_then_push` | clear resets slice without nil, push refills (Issue #59) | ES6, Go, Kotlin (when toolchain present) |
98
+ | `int_division_to_double` | Conformance: integer division promoted to double (Issue #4) | ES6, Go, Kotlin (when toolchain present) |
99
+ | `lf_line_endings` | LF-only source (Issue #12 class must not break operator spacing) | ES6, Go, Kotlin (when toolchain present) |
100
+ | `math_ops` | Conformance: arithmetic and comparisons | ES6, Go, Kotlin (when toolchain present) |
101
+ | `string_codepoint_index` | Conformance: Unicode code-point string indexing (Issue #57) | ES6, Go, Kotlin (when toolchain present) |
102
+ | `while_loop` | Conformance: while loop control flow | ES6, Go, Kotlin (when toolchain present) |
103
+ <!-- END CONFORMANCE_TABLE -->
104
+
85
105
  ## What's New in Version 3.0
86
106
 
87
107
  - **New File Extension** - Transitioning from `.clj` to `.rgr` for Ranger identity
@@ -115,9 +135,9 @@ See [CHANGELOG.md](CHANGELOG.md) for full version history and [PLAN_3.md](PLAN_3
115
135
  The compiler is _self hosting_ which means that it has been written using the compiler itself and thus it can be hosted
116
136
  on several platforms. At the moment the official platform is node.js, because external plugins are only available as npm packages.
117
137
 
118
- The target languages supported are `JavaScript`, `Java`, `Go`, `Swift`, `PHP`, `C++`, `C#`, `Scala`, `Python`, and `Rust`. The quality
119
- of the target translation still varies and at the moment of this writing the compiler can only be compiled fully to JavaScript
120
- target. However, most targets already can compile reasonably good code.
138
+ The target languages supported are `JavaScript`, `Java`, `Go`, `Swift`, `PHP`, `C++`, `C#`, `Scala`, `Python`, and `Rust`. An **experimental LLVM backend** (`-l=llvm`) emits LLVM IR and optional freestanding WAT for WASM toolchains; it is not a separate surface language but another codegen path from the same Ranger sources.
139
+
140
+ The quality of the target translation still varies and at the moment of this writing the compiler can only be compiled fully to JavaScript target. However, most targets already can compile reasonably good code.
121
141
 
122
142
  ## Recent Updates (December 2025)
123
143
 
@@ -394,11 +414,12 @@ See `gallery/pdf_writer/examples/test_for_loop.tsx` for a complete demonstration
394
414
 
395
415
  ### Space Invaders Demo Game
396
416
 
397
- A complete terminal-based Space Invaders game demonstrating Ranger's cross-language capabilities. The same source code compiles to **4 different targets**:
417
+ A complete terminal-based Space Invaders game demonstrating Ranger's cross-language capabilities. The same source code compiles to **several targets**:
398
418
 
399
- | Target | Executable | Build Command |
419
+ | Target | Output | Build Command |
400
420
  | -------------- | ------------------- | --------------------------- |
401
421
  | ES6/JavaScript | `invaders.js` | `npm run game:compile` |
422
+ | **LLVM native**| `tmp/invaders-native/invaders` | `npm run game:build:llvm` |
402
423
  | Rust | `invaders_rust.exe` | `npm run game:build:rust` |
403
424
  | Go | `invaders_go.exe` | `npm run game:build:go` |
404
425
  | Kotlin | `invaders.jar` | `npm run game:build:kotlin` |
@@ -415,8 +436,24 @@ npm run game:build:all
415
436
  npm run game:run # JavaScript
416
437
  npm run game:run:rust # Rust
417
438
  npm run game:run:go # Go
439
+ ./tmp/invaders-native/invaders # LLVM native (after game:build:llvm)
440
+ ```
441
+
442
+ #### Experimental LLVM backend (Space Invaders)
443
+
444
+ Ranger can lower the same `invaders.rgr` through a **Low IR → LLVM IR** pipeline (`-l=llvm`), then link with `clang` and a small C runtime (`runtime/ranger_term.c`) for terminal I/O.
445
+
446
+ ```bash
447
+ npm run compile # refresh bin/output.js after compiler changes
448
+ npm run game:build:llvm # invaders.rgr → tmp/invaders-native/invaders.ll → native binary
449
+ npm run test:llvm # LLVM/WASM fixture tests (vitest)
450
+ npm run demo:wasm # smaller freestanding WASM demo (tests/fixtures/llvm_wasm_demo.rgr)
418
451
  ```
419
452
 
453
+ **Checked-in sample:** [`gallery/invaders/llvm/invaders.ll`](gallery/invaders/llvm/invaders.ll) is LLVM IR kept in the repo so you can inspect codegen without building. Regenerate with `cp tmp/invaders-native/invaders.ll gallery/invaders/llvm/invaders.ll` after `game:build:llvm` (see [`gallery/invaders/llvm/README.md`](gallery/invaders/llvm/README.md)).
454
+
455
+ Status: experimental — libc-linked native builds are the most reliable path. The freestanding WAT/WASM path (`-wasmrc`) now has a reference-counting runtime (free-list heap with `memory.grow`, typedesc-driven recursive object destruction), classes with reference-counted fields, singletons, strings, `[T]`/`[K:V]` collections, and lambdas/closures (function table + `call_indirect`, with value/object capture and mutation); the `gallery/game_engine/games/ranger_autopeli` guest is authored in Ranger and compiles to WASM this way. Terminal-import lowering for the full Space Invaders game is still incomplete. Smaller freestanding demos run under `npm run demo:wasm`.
456
+
420
457
  #### Cross-Compiling the Game
421
458
 
422
459
  The Space Invaders game demonstrates cross-platform compilation from a single source file.
@@ -470,6 +507,15 @@ npm run game:compile:swift # Generates invaders.swift
470
507
  swiftc invaders.swift -o invaders_swift
471
508
  ```
472
509
 
510
+ **LLVM native (macOS / Linux, experimental)**
511
+
512
+ ```bash
513
+ npm run game:build:llvm
514
+ ./tmp/invaders-native/invaders
515
+ ```
516
+
517
+ Requires `clang` on `PATH`. On macOS the script picks `arm64-apple-macos` or `x86_64-apple-macos` automatically.
518
+
473
519
  #### Platform-Specific Keyboard Input
474
520
 
475
521
  The game uses `on_keypress` and `poll_keypress` operators with platform-specific implementations:
@@ -492,6 +538,7 @@ The Space Invaders game provides an interesting comparison of how the same Range
492
538
  | Target | Generated File | Size (bytes) | Lines | Notes |
493
539
  | ---------- | ---------------- | ------------ | ----- | ------------------------------- |
494
540
  | **Ranger** | `invaders.rgr` | 11,289 | ~400 | Original source |
541
+ | **LLVM IR**| `llvm/invaders.ll` | ~60,000 | ~1,700 | Low-level IR (sample in repo) |
495
542
  | Python | `invaders.py` | 9,271 | ~330 | Most compact generated code |
496
543
  | JavaScript | `invaders.js` | 10,301 | ~350 | Clean, readable output |
497
544
  | Swift | `invaders.swift` | 12,554 | ~470 | Verbose type annotations |
@@ -499,11 +546,12 @@ The Space Invaders game provides an interesting comparison of how the same Range
499
546
  | C++ | `invaders.cpp` | 14,148 | ~500 | Headers and type declarations |
500
547
  | Rust | `invaders.rs` | 17,918 | ~600 | Most verbose (ownership, types) |
501
548
 
502
- **Executable Sizes (Windows):**
549
+ **Executable Sizes (native binaries):**
503
550
 
504
551
  | Target | Executable | Size | Notes |
505
552
  | ------ | -------------------- | ------ | --------------------------------- |
506
- | Swift | `invaders_swift.exe` | 76 KB | Smallest native binary |
553
+ | **LLVM** | `tmp/invaders-native/invaders` | ~34 KB (arm64 macOS) | Smallest in recent local builds; libc + minimal runtime |
554
+ | Swift | `invaders_swift.exe` | 76 KB | Dynamic link to system libraries |
507
555
  | Rust | `invaders_rust.exe` | 291 KB | Optimized, statically linked |
508
556
  | Go | `invaders_go.exe` | 2.3 MB | Includes Go runtime |
509
557
  | C++ | `invaders_cpp.exe` | 3.0 MB | Static linking with MinGW/pthread |
@@ -766,6 +814,7 @@ Flags: -<flag>
766
814
  -nodecli Insert node.js command line header #!/usr/bin/env node to the beginning of the JavaScript file
767
815
  -nodemodule Export classes as CommonJS modules using module.exports (disables static main function)
768
816
  -esm Export classes as ES6/ESM modules using export keyword (disables static main function)
817
+ -sourcemap Emit .js.map / .ts.map with embedded .rgr sourcesContent (ES6/TypeScript only)
769
818
  -client the code is ment to be run in the client environment
770
819
  -scalafiddle scalafiddle.io compatible output
771
820
  -compiler recompile the compiler
@@ -800,6 +849,47 @@ node bin/output.js -es6 -esm myfile.rgr -o=myfile.mjs
800
849
  **File Extensions:**
801
850
  The compiler automatically detects JavaScript-related extensions (`.js`, `.ts`, `.mjs`, `.cjs`) and won't double-add them. You can safely specify the full filename with extension.
802
851
 
852
+ ### JavaScript / TypeScript source maps (`-sourcemap`)
853
+
854
+ Use `-sourcemap` with `-es6` or `-typescript` to emit a sibling `.js.map` / `.ts.map` file and append `//# sourceMappingURL=…` to the generated output. Kotlin, Swift, and other non-JS targets ignore this flag.
855
+
856
+ **What you get**
857
+
858
+ | Output | Purpose |
859
+ | --- | --- |
860
+ | `output.js.map` | Source map v3 (VLQ `mappings`, `names`, `sources`) |
861
+ | `sourcesContent` | Full `.rgr` source embedded in the map — Chrome DevTools can open `.rgr` files without a separate file server |
862
+ | Statement + expression mappings | `LiveCompiler.WalkNode` walk context plus `outMapped()` on identifiers, calls, literals |
863
+
864
+ **Compile example**
865
+
866
+ ```bash
867
+ # Standalone ES module + map
868
+ node bin/output.js -es6 -esm -nodemodule -sourcemap ./myapp/App.rgr -o=app.js
869
+
870
+ # Result: bin/app.js and bin/app.js.map
871
+ ```
872
+
873
+ **Debug in Chrome / Edge**
874
+
875
+ 1. Serve the generated `.js` (and `.map` beside it). Vite/webpack are optional when `sourcesContent` is embedded.
876
+ 2. Open DevTools → **Sources**. Original `.rgr` files appear under the map tree (from `sourcesContent`).
877
+ 3. Set breakpoints on **executable** lines (e.g. `def`, `if`, `return`) — not only blank lines or signatures.
878
+ 4. Breakpoints must be **solid red**. A hollow/grey breakpoint means no mapping for that line; rebuild with `-sourcemap` and hard-refresh (disable cache).
879
+
880
+ **Tests**
881
+
882
+ ```bash
883
+ npm run compile
884
+ npx vitest run tests/compiler-sourcemap.test.ts
885
+ ```
886
+
887
+ **Implementation notes** (for compiler hackers)
888
+
889
+ - `compiler/ng_SourceMap.rgr` — `SourceMapBuilder`, VLQ encoder, `addMappingFromNode()` uses `node.getLine()` + `node.code.getColumn(sp)` (not stale `node.row`).
890
+ - `compiler/ng_writer.rgr` — `lineNumber` / `columnNumber` on emit, `walkNodeStack`, `outMapped()`, `.map` write in `CodeFileSystem.saveTo`.
891
+ - Flag: `compiler/ng_Compiler.rgr` → `flag sourcemap`; enabled in `VirtualCompiler.rgr` via `fileSystem.enableSourceMaps()`.
892
+
803
893
  ## Getting started with Hello World
804
894
 
805
895
  Create file `hello.rgr`
@@ -1257,6 +1347,8 @@ this.foo({
1257
1347
  })
1258
1348
  ```
1259
1349
 
1350
+ Lambdas compile on every backend, including the freestanding WASM/WAT path (`-wasmrc`): each body is hoisted to a function-table entry and calls go through `call_indirect`, with the value a reference-counted closure record. Captured variables are copied (values/strings) or retained (objects); a captured object can be mutated through the closure, and a captured value can be shared by boxing it in a heap cell.
1351
+
1260
1352
  # Automatically infixed math support
1261
1353
 
1262
1354
  It is easy to define new mathematical operations in the Lang.clj file or in modules. However, some mathematical operations are automatically infixed