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 +41 -0
- package/README.md +114 -8
- package/dist/Lang.rgr +149 -13
- package/dist/lib/IsoDate/DateMath.rgr +219 -0
- package/dist/lib/IsoDate/IsoCalendar.rgr +137 -0
- package/dist/lib/IsoDate/IsoDateParse.rgr +57 -0
- package/dist/lib/IsoDateLib.rgr +15 -0
- package/dist/lib/RangerProcess.rgr +82 -4
- package/dist/lib/Regex/RegexMatch.rgr +134 -0
- package/dist/lib/RegexLib.rgr +10 -0
- package/dist/lib/Time.rgr +2 -1
- package/dist/rgrc.js +30176 -22193
- package/package.json +13 -4
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.
|
|
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`.
|
|
85
|
-
|
|
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 **
|
|
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 |
|
|
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 (
|
|
531
|
+
**Executable Sizes (native binaries):**
|
|
469
532
|
|
|
470
533
|
| Target | Executable | Size | Notes |
|
|
471
534
|
| ------ | -------------------- | ------ | --------------------------------- |
|
|
472
|
-
|
|
|
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`
|