ranger-compiler 3.0.5 → 3.1.1

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,47 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.1.1] - 2026-06-23
11
+
12
+ ### Changed
13
+
14
+ - 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
15
+ - Default `npm test` / `prepublishOnly` skips `compiler-llvm.test.ts` (experimental LLVM/WAT backend); run `npm run test:llvm` when working on native/WASM codegen
16
+
17
+ ### Added
18
+
19
+ - **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)
20
+ - **IsoDate compiler intrinsics** — `iso_add_days`, `iso_compare`, `iso_between` in `Lang.rgr` (Kotlin/Java `java.time.LocalDate`, ES6 UTC-safe helper)
21
+ - **IsoDate regression** — `tests/fixtures/iso_date_ops.rgr` in Kotlin compiler tests
22
+ - **Regex stdlib** — `lib/Regex/` (`RegexMatch`) and `lib/RegexLib.rgr` for string-pattern matching without `/literal/` syntax; see [ai/REGEX.md](ai/REGEX.md)
23
+ - **Regex compiler intrinsic** — `regex_test(pattern, haystack)` in `Lang.rgr` (Kotlin/Java `Regex`/`Pattern`, ES6 `RegExp`, Swift `range(of:options:)`)
24
+ - **Regex regression** — `tests/fixtures/regex_test_ops.rgr` in Kotlin compiler tests
25
+
26
+ - **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*
27
+
28
+ ### Fixed
29
+
30
+ - **Source map VLQ line breaks** — `buildMappingsString` no longer resets source/original relative state on `;` (fixes DevTools breakpoints on `.rgr` sources)
31
+ - **Source map original line** — `addMappingFromNode` uses `node.getLine()` from `sp` instead of stale `node.row`
32
+ - **Kotlin `floor` / `int2double`** — `int2double` emits `.toDouble()`; reserved parameter names escaped (`val`, `object`, …)
33
+ - **`proc_send` dispatch wrapping** — turn boundaries around handler calls; `ProcessRuntime.beginDispatchTurn` / `endDispatchTurn`
34
+
35
+ ## [3.1.0] - 2026-06-02
36
+
37
+ ### Added
38
+
39
+ - **`ProcessUiHost` notify suppress** — `beginSuppressUiNotify` / `endSuppressUiNotify` / `isUiNotifySuppressed` for batching parent↔child sync without re-entrant UI notify loops ([PROCESS_UI_NOTIFY.md](PROCESS_UI_NOTIFY.md))
40
+ - **Process view DTO regression fixture** — [tests/fixtures/process_view_dto_assign.rgr](tests/fixtures/process_view_dto_assign.rgr) (cross-class field assignment with method call on RHS)
41
+ - **Docs** — [PROCESS_UI_NOTIFY.md](PROCESS_UI_NOTIFY.md), [PROCESS_UI_VIEW_MODELS.md](PROCESS_UI_VIEW_MODELS.md); README `@process` quick start
42
+
43
+ ### Fixed
44
+
45
+ - **Parser: assignment RHS method calls** — `row.field = this.helper(index)` no longer splits the call into invalid `=` operands ([PROCESS_UI_VIEW_MODELS.md](PROCESS_UI_VIEW_MODELS.md)); fix in [compiler/ng_RangerFlowParser.rgr](compiler/ng_RangerFlowParser.rgr) (`repairAssignMethodCallRhs`)
46
+
47
+ ### Changed
48
+
49
+ - Version bumped from `3.0.5` to `3.1.0`
50
+
10
51
  ## [3.0.5] - 2026-05-29
11
52
 
12
53
  ### Added
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Ranger cross language compiler
2
2
 
3
- **Version 3.0.5** | 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
 
@@ -25,8 +25,42 @@ Ranger is best approached today as a compiler and language lab with practical mu
25
25
 
26
26
  If you want one sentence of positioning: Ranger is currently more convincing as a portable algorithm compiler / DSL toolchain than as a drop-in replacement for mainstream application languages.
27
27
 
28
+ ## `@process` runtime (experimental)
29
+
30
+ Ranger can mark classes with `@process` to get a **small object runtime** in generated code (especially JavaScript/TypeScript): parent/child tree, instance registry, `proc_start` / `proc_stop`, and UI refresh via `markStateDirty()`.
31
+
32
+ | Piece | What it does |
33
+ | --- | --- |
34
+ | `@process` / `@process(true)` | Process instance with lifecycle hooks (`start`, `stop`, …) |
35
+ | `proc_start` / `proc_stop` | Activate or tear down a process subtree (children first) |
36
+ | `proc_send target handler arg…` | Typed message dispatch to `fn on…` handlers on a live instance |
37
+ | `ProcessNameRegistry.findProcess(path)` | Lookup by `@name("app.foo")` (TypeScript path literals when using `-typescript`) |
38
+ | `markStateDirty()` | Bump generation + notify host (`ProcessUiHost`) for UI binding |
39
+ | `beginSuppressUiNotify` / `endSuppressUiNotify` | Batch parent↔child sync without notify storms |
40
+
41
+ **Typical app shape:** domain logic and UI flags live in `@process` classes; **view DTOs** are plain Ranger classes filled by a builder; React/CLI/native hosts subscribe to `ProcessUiHost` and call `findProcess` — I/O and async work stay in the host (Node, Swift, …), not inside the process bytecode.
42
+
43
+ ```ranger
44
+ class CounterPage @process @name("app.counter") extends RangerProcessBase {
45
+ def count:int 0
46
+ fn onUiIncrement:void () {
47
+ count = count + 1
48
+ this.markStateDirty()
49
+ }
50
+ }
51
+ ```
52
+
53
+ ```typescript
54
+ // Host (TypeScript): wire notify once, then bind UI to process fields
55
+ const host = ProcessUiHost.__singleton();
56
+ host.notifyPath = (path) => { /* sync view model + re-render */ };
57
+ ```
58
+
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
+
28
61
  ## Where To Start
29
62
 
63
+ - [Online playground](https://terotests.github.io/Ranger/) — try Ranger in the browser (`playground/`, Vite + current compiler)
30
64
  - `README.md` - language overview, installation, and syntax notes
31
65
  - `ai/QUICKREF.md` - fast reference for syntax and core concepts
32
66
  - `ai/INSTRUCTIONS.md` - fuller language guide for operators, templates, and compiler concepts
@@ -35,6 +69,7 @@ If you want one sentence of positioning: Ranger is currently more convincing as
35
69
  - `gallery/js_parser` - substantial parser example with benchmarks and README
36
70
  - `gallery/pdf_writer` - EVG / TSX document tooling and preview server
37
71
  - `gallery/invaders` - cross-target demo game
72
+ - `gallery/invaders/llvm/invaders.ll` - checked-in LLVM IR sample from the experimental `-l=llvm` backend
38
73
 
39
74
  ## Compatibility Snapshot
40
75
 
@@ -46,6 +81,7 @@ The project can target `JavaScript`, `Java`, `Go`, `Swift`, `PHP`, `C++`, `C#`,
46
81
  | Self-hosting | Actively used, but full compiler generation quality is strongest in JavaScript |
47
82
  | JavaScript / ES6 | Best baseline target and most reliable place to start |
48
83
  | Go / Swift / Rust / Kotlin / C++ | Useful and increasingly capable, but expect edge cases and target-specific gaps |
84
+ | **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`. |
49
85
  | Gallery examples | Good for understanding direction and capability, but some require manual setup or platform-specific tooling |
50
86
 
51
87
  ## What's New in Version 3.0
@@ -81,9 +117,9 @@ See [CHANGELOG.md](CHANGELOG.md) for full version history and [PLAN_3.md](PLAN_3
81
117
  The compiler is _self hosting_ which means that it has been written using the compiler itself and thus it can be hosted
82
118
  on several platforms. At the moment the official platform is node.js, because external plugins are only available as npm packages.
83
119
 
84
- The target languages supported are `JavaScript`, `Java`, `Go`, `Swift`, `PHP`, `C++`, `C#`, `Scala`, `Python`, and `Rust`. The quality
85
- of the target translation still varies and at the moment of this writing the compiler can only be compiled fully to JavaScript
86
- target. However, most targets already can compile reasonably good code.
120
+ 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.
121
+
122
+ 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.
87
123
 
88
124
  ## Recent Updates (December 2025)
89
125
 
@@ -360,11 +396,12 @@ See `gallery/pdf_writer/examples/test_for_loop.tsx` for a complete demonstration
360
396
 
361
397
  ### Space Invaders Demo Game
362
398
 
363
- A complete terminal-based Space Invaders game demonstrating Ranger's cross-language capabilities. The same source code compiles to **4 different targets**:
399
+ A complete terminal-based Space Invaders game demonstrating Ranger's cross-language capabilities. The same source code compiles to **several targets**:
364
400
 
365
- | Target | Executable | Build Command |
401
+ | Target | Output | Build Command |
366
402
  | -------------- | ------------------- | --------------------------- |
367
403
  | ES6/JavaScript | `invaders.js` | `npm run game:compile` |
404
+ | **LLVM native**| `tmp/invaders-native/invaders` | `npm run game:build:llvm` |
368
405
  | Rust | `invaders_rust.exe` | `npm run game:build:rust` |
369
406
  | Go | `invaders_go.exe` | `npm run game:build:go` |
370
407
  | Kotlin | `invaders.jar` | `npm run game:build:kotlin` |
@@ -381,8 +418,24 @@ npm run game:build:all
381
418
  npm run game:run # JavaScript
382
419
  npm run game:run:rust # Rust
383
420
  npm run game:run:go # Go
421
+ ./tmp/invaders-native/invaders # LLVM native (after game:build:llvm)
384
422
  ```
385
423
 
424
+ #### Experimental LLVM backend (Space Invaders)
425
+
426
+ 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.
427
+
428
+ ```bash
429
+ npm run compile # refresh bin/output.js after compiler changes
430
+ npm run game:build:llvm # invaders.rgr → tmp/invaders-native/invaders.ll → native binary
431
+ npm run test:llvm # LLVM/WASM fixture tests (vitest)
432
+ npm run demo:wasm # smaller freestanding WASM demo (tests/fixtures/llvm_wasm_demo.rgr)
433
+ ```
434
+
435
+ **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)).
436
+
437
+ Status: experimental — libc-linked native builds are the most reliable path; freestanding WAT/WASM for the full game is still incomplete (terminal imports, control-flow lowering). Smaller WASM demos under `npm run demo:wasm` are closer to working in the browser.
438
+
386
439
  #### Cross-Compiling the Game
387
440
 
388
441
  The Space Invaders game demonstrates cross-platform compilation from a single source file.
@@ -436,6 +489,15 @@ npm run game:compile:swift # Generates invaders.swift
436
489
  swiftc invaders.swift -o invaders_swift
437
490
  ```
438
491
 
492
+ **LLVM native (macOS / Linux, experimental)**
493
+
494
+ ```bash
495
+ npm run game:build:llvm
496
+ ./tmp/invaders-native/invaders
497
+ ```
498
+
499
+ Requires `clang` on `PATH`. On macOS the script picks `arm64-apple-macos` or `x86_64-apple-macos` automatically.
500
+
439
501
  #### Platform-Specific Keyboard Input
440
502
 
441
503
  The game uses `on_keypress` and `poll_keypress` operators with platform-specific implementations:
@@ -458,6 +520,7 @@ The Space Invaders game provides an interesting comparison of how the same Range
458
520
  | Target | Generated File | Size (bytes) | Lines | Notes |
459
521
  | ---------- | ---------------- | ------------ | ----- | ------------------------------- |
460
522
  | **Ranger** | `invaders.rgr` | 11,289 | ~400 | Original source |
523
+ | **LLVM IR**| `llvm/invaders.ll` | ~60,000 | ~1,700 | Low-level IR (sample in repo) |
461
524
  | Python | `invaders.py` | 9,271 | ~330 | Most compact generated code |
462
525
  | JavaScript | `invaders.js` | 10,301 | ~350 | Clean, readable output |
463
526
  | Swift | `invaders.swift` | 12,554 | ~470 | Verbose type annotations |
@@ -465,11 +528,12 @@ The Space Invaders game provides an interesting comparison of how the same Range
465
528
  | C++ | `invaders.cpp` | 14,148 | ~500 | Headers and type declarations |
466
529
  | Rust | `invaders.rs` | 17,918 | ~600 | Most verbose (ownership, types) |
467
530
 
468
- **Executable Sizes (Windows):**
531
+ **Executable Sizes (native binaries):**
469
532
 
470
533
  | Target | Executable | Size | Notes |
471
534
  | ------ | -------------------- | ------ | --------------------------------- |
472
- | Swift | `invaders_swift.exe` | 76 KB | Smallest native binary |
535
+ | **LLVM** | `tmp/invaders-native/invaders` | ~34 KB (arm64 macOS) | Smallest in recent local builds; libc + minimal runtime |
536
+ | Swift | `invaders_swift.exe` | 76 KB | Dynamic link to system libraries |
473
537
  | Rust | `invaders_rust.exe` | 291 KB | Optimized, statically linked |
474
538
  | Go | `invaders_go.exe` | 2.3 MB | Includes Go runtime |
475
539
  | C++ | `invaders_cpp.exe` | 3.0 MB | Static linking with MinGW/pthread |
@@ -732,6 +796,7 @@ Flags: -<flag>
732
796
  -nodecli Insert node.js command line header #!/usr/bin/env node to the beginning of the JavaScript file
733
797
  -nodemodule Export classes as CommonJS modules using module.exports (disables static main function)
734
798
  -esm Export classes as ES6/ESM modules using export keyword (disables static main function)
799
+ -sourcemap Emit .js.map / .ts.map with embedded .rgr sourcesContent (ES6/TypeScript only)
735
800
  -client the code is ment to be run in the client environment
736
801
  -scalafiddle scalafiddle.io compatible output
737
802
  -compiler recompile the compiler
@@ -766,6 +831,47 @@ node bin/output.js -es6 -esm myfile.rgr -o=myfile.mjs
766
831
  **File Extensions:**
767
832
  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.
768
833
 
834
+ ### JavaScript / TypeScript source maps (`-sourcemap`)
835
+
836
+ 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.
837
+
838
+ **What you get**
839
+
840
+ | Output | Purpose |
841
+ | --- | --- |
842
+ | `output.js.map` | Source map v3 (VLQ `mappings`, `names`, `sources`) |
843
+ | `sourcesContent` | Full `.rgr` source embedded in the map — Chrome DevTools can open `.rgr` files without a separate file server |
844
+ | Statement + expression mappings | `LiveCompiler.WalkNode` walk context plus `outMapped()` on identifiers, calls, literals |
845
+
846
+ **Compile example**
847
+
848
+ ```bash
849
+ # Standalone ES module + map
850
+ node bin/output.js -es6 -esm -nodemodule -sourcemap ./myapp/App.rgr -o=app.js
851
+
852
+ # Result: bin/app.js and bin/app.js.map
853
+ ```
854
+
855
+ **Debug in Chrome / Edge**
856
+
857
+ 1. Serve the generated `.js` (and `.map` beside it). Vite/webpack are optional when `sourcesContent` is embedded.
858
+ 2. Open DevTools → **Sources**. Original `.rgr` files appear under the map tree (from `sourcesContent`).
859
+ 3. Set breakpoints on **executable** lines (e.g. `def`, `if`, `return`) — not only blank lines or signatures.
860
+ 4. Breakpoints must be **solid red**. A hollow/grey breakpoint means no mapping for that line; rebuild with `-sourcemap` and hard-refresh (disable cache).
861
+
862
+ **Tests**
863
+
864
+ ```bash
865
+ npm run compile
866
+ npx vitest run tests/compiler-sourcemap.test.ts
867
+ ```
868
+
869
+ **Implementation notes** (for compiler hackers)
870
+
871
+ - `compiler/ng_SourceMap.rgr` — `SourceMapBuilder`, VLQ encoder, `addMappingFromNode()` uses `node.getLine()` + `node.code.getColumn(sp)` (not stale `node.row`).
872
+ - `compiler/ng_writer.rgr` — `lineNumber` / `columnNumber` on emit, `walkNodeStack`, `outMapped()`, `.map` write in `CodeFileSystem.saveTo`.
873
+ - Flag: `compiler/ng_Compiler.rgr` → `flag sourcemap`; enabled in `VirtualCompiler.rgr` via `fileSystem.enableSourceMaps()`.
874
+
769
875
  ## Getting started with Hello World
770
876
 
771
877
  Create file `hello.rgr`