ranger-compiler 3.0.5 → 3.1.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 +16 -0
- package/README.md +35 -1
- package/dist/Lang.rgr +3 -19
- package/dist/lib/RangerProcess.rgr +35 -4
- package/dist/rgrc.js +22477 -21980
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [3.1.0] - 2026-06-02
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`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))
|
|
15
|
+
- **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)
|
|
16
|
+
- **Docs** — [PROCESS_UI_NOTIFY.md](PROCESS_UI_NOTIFY.md), [PROCESS_UI_VIEW_MODELS.md](PROCESS_UI_VIEW_MODELS.md); README `@process` quick start
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **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`)
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Version bumped from `3.0.5` to `3.1.0`
|
|
25
|
+
|
|
10
26
|
## [3.0.5] - 2026-05-29
|
|
11
27
|
|
|
12
28
|
### Added
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Ranger cross language compiler
|
|
2
2
|
|
|
3
|
-
**Version 3.0
|
|
3
|
+
**Version 3.1.0** | 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_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).
|
|
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
|
package/dist/Lang.rgr
CHANGED
|
@@ -193,9 +193,11 @@ language {
|
|
|
193
193
|
templates {
|
|
194
194
|
ranger ("(cast " (e 1) " " (e 2) ":" (typeof 2) " )")
|
|
195
195
|
ts ( (e 1) " as " (typeof 2) )
|
|
196
|
+
kotlin ( (e 1) " as " (typeof 2) )
|
|
196
197
|
es6 ( (e 1) )
|
|
197
198
|
java7 ( "((" (typeof 2) ")" (e 1) ")" )
|
|
198
199
|
swift3 ( (e 1) " as " (typeof 2) "" )
|
|
200
|
+
swift6 ( (e 1) " as " (typeof 2) "" )
|
|
199
201
|
cpp ( "mpark::get<" (typeof 2) ">(" (e 1) ")"
|
|
200
202
|
|
|
201
203
|
(plugin 'makefile' ((dep 'variant.hpp' 'https://github.com/mpark/variant/releases/download/v1.2.2/variant.hpp')))
|
|
@@ -5349,25 +5351,7 @@ std::string r_cpp_str_to_uppercase(std::string original)
|
|
|
5349
5351
|
}
|
|
5350
5352
|
}
|
|
5351
5353
|
|
|
5352
|
-
proc_send
|
|
5353
|
-
templates {
|
|
5354
|
-
es6 ( "(() => { const __rgrP = ProcessNameRegistry.__singleton().findByPath(" (e 1) "); if (!__rgrP || __rgrP.__rangerId === 0) return; __rgrP.receiveMessage(" (e 2) "); })()" )
|
|
5355
|
-
kotlin ( "run { val __rgrP = ProcessNameRegistry.__singleton().findByPath(" (e 1) "); if (__rgrP == null || __rgrP.__rangerId == 0) return@run; __rgrP.receiveMessage(" (e 2) ") }" )
|
|
5356
|
-
swift6 ( "{ let __rgrP = ProcessNameRegistry.__singleton().findByPath(" (e 1) "); guard let p = __rgrP, p.__rangerId != 0 else { return }; p.receiveMessage(" (e 2) ") }" )
|
|
5357
|
-
swift3 ( "{ let __rgrP = ProcessNameRegistry.__singleton().findByPath(" (e 1) "); guard let p = __rgrP, p.__rangerId != 0 else { return }; p.receiveMessage(" (e 2) ") }" )
|
|
5358
|
-
* ( "/* proc_send path not implemented */" )
|
|
5359
|
-
}
|
|
5360
|
-
}
|
|
5361
|
-
|
|
5362
|
-
proc_send@(moves@( 2 )) cmdProcSendProc:void (proc:RangerProcessBase msg:Any) {
|
|
5363
|
-
templates {
|
|
5364
|
-
es6 ( "(() => { const __rgrP = " (e 1) "; if (!__rgrP || __rgrP.__rangerId === 0) return; __rgrP.receiveMessage(" (e 2) "); })()" )
|
|
5365
|
-
kotlin ( "run { val __rgrP = " (e 1) "; if (__rgrP.__rangerId == 0) return@run; __rgrP.receiveMessage(" (e 2) ") }" )
|
|
5366
|
-
swift6 ( "{ let __rgrP = " (e 1) "; guard __rgrP.__rangerId != 0 else { return }; __rgrP.receiveMessage(" (e 2) ") }" )
|
|
5367
|
-
swift3 ( "{ let __rgrP = " (e 1) "; guard __rgrP.__rangerId != 0 else { return }; __rgrP.receiveMessage(" (e 2) ") }" )
|
|
5368
|
-
* ( "/* proc_send proc not implemented */" )
|
|
5369
|
-
}
|
|
5370
|
-
}
|
|
5354
|
+
; proc_send is lowered in ng_RangerProcessProcSend.rgr (typed handler methods, overload match).
|
|
5371
5355
|
|
|
5372
5356
|
proc_start@(moves@( 1 )) cmdProcStart:void (proc:RangerProcessBase) {
|
|
5373
5357
|
templates {
|
|
@@ -11,13 +11,27 @@ class RangerProcessBase {
|
|
|
11
11
|
def __rangerParent:RangerProcessBase@(optional)
|
|
12
12
|
def __rangerChildren:[RangerProcessBase]
|
|
13
13
|
|
|
14
|
+
; Bump revision only (e.g. parent sync merging child pending*). Prefer over markStateDirty in sync blocks.
|
|
15
|
+
fn bumpStateGeneration:void () {
|
|
16
|
+
__rangerStateGeneration = __rangerStateGeneration + 1
|
|
17
|
+
}
|
|
18
|
+
|
|
14
19
|
fn markStateDirty:void () {
|
|
15
20
|
__rangerStateGeneration = __rangerStateGeneration + 1
|
|
21
|
+
this.flushUiNotify()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
; Notify host without bumping __rangerStateGeneration (after suppressUiNotify batch).
|
|
25
|
+
fn flushUiNotify:void () {
|
|
26
|
+
def uiHost:ProcessUiHost (ProcessUiHost.__singleton())
|
|
27
|
+
if (uiHost.isUiNotifySuppressed()) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
16
30
|
if ((strlen __rangerPath) > 0) {
|
|
17
|
-
|
|
31
|
+
uiHost.notifyPath(__rangerPath)
|
|
18
32
|
}
|
|
19
33
|
if (__rangerId != 0) {
|
|
20
|
-
|
|
34
|
+
uiHost.notifyId(__rangerId)
|
|
21
35
|
}
|
|
22
36
|
}
|
|
23
37
|
|
|
@@ -57,8 +71,8 @@ class RangerProcessBase {
|
|
|
57
71
|
fn __rangerStopSubtree:void () {
|
|
58
72
|
}
|
|
59
73
|
|
|
60
|
-
;
|
|
61
|
-
fn receiveMessage:void (
|
|
74
|
+
; Legacy hook; prefer typed proc_send → handler methods on @process classes.
|
|
75
|
+
fn receiveMessage:void (name:string value:string) {
|
|
62
76
|
}
|
|
63
77
|
}
|
|
64
78
|
|
|
@@ -123,7 +137,24 @@ class ProcessNameRegistry @singleton(true) {
|
|
|
123
137
|
}
|
|
124
138
|
|
|
125
139
|
; Host-side UI subscriptions (React useProcess wires listeners in TS).
|
|
140
|
+
; Hosts may replace notifyPath/notifyId on the singleton instance; markStateDirty respects suppressUiNotify.
|
|
126
141
|
class ProcessUiHost @singleton(true) {
|
|
142
|
+
def __uiNotifySuppressDepth:int 0
|
|
143
|
+
|
|
144
|
+
fn isUiNotifySuppressed:boolean () {
|
|
145
|
+
return __uiNotifySuppressDepth > 0
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
fn beginSuppressUiNotify:void () {
|
|
149
|
+
__uiNotifySuppressDepth = __uiNotifySuppressDepth + 1
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
fn endSuppressUiNotify:void () {
|
|
153
|
+
if (__uiNotifySuppressDepth > 0) {
|
|
154
|
+
__uiNotifySuppressDepth = __uiNotifySuppressDepth - 1
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
127
158
|
fn notifyPath:void (path:string) {
|
|
128
159
|
}
|
|
129
160
|
|