|
1 | 1 | # RSScript language-spec TODO |
2 | 2 |
|
3 | | -Unimplemented surface of the language spec (`RSScript_v0.7_Spec.md`), prioritized. |
| 3 | +Status of the spec surface (`RSScript_v0.7_Spec.md`) beyond the executable MVP. |
4 | 4 |
|
5 | 5 | The spec is a deliberate **superset** of the implementation, in three tiers: |
6 | 6 |
|
7 | 7 | 1. **Executable MVP (§3.1)** — implemented and tested at VM↔compiled parity. |
8 | 8 | 2. **Review-visible but not executable (§3.2)** — parsed and surfaced for review, |
9 | | - but rejected before lowering with stable diagnostics (verified: `spawn` → |
10 | | - `RS0015`/`RS0101`, `await` in a short-circuit `&&`/`||` RHS → `RS0411`). This |
11 | | - file tracks these. |
12 | | -3. **Post-v0.7 deferred directions (§20.1)** — future work (items J/K/L are |
13 | | - already done). |
14 | | - |
15 | | -Priority = value to real programs / the active tinygrad port + dogfooding, |
16 | | -weighed against effort. Priorities are a recommendation; re-rank against the |
17 | | -actual driver (see "Basis" at the bottom). |
18 | | - |
19 | | -## P1 — highest leverage (unblocks real code / dev loop) |
20 | | - |
21 | | -- [x] **`await` in expression position** (§3.2, §20.1-A, §14.6.2) — _done._ |
22 | | - Implemented as an await-hoisting (A-normal-form) syntax pass |
23 | | - (`syntax/async_await_hoist.rs`, run in `isolate_module_namespaces` for every |
24 | | - backend): a nested `await` in a call argument, return value, or assignment-target |
25 | | - index is lifted, in left-to-right order, to a preceding |
26 | | - `let __rss_await_N = await <op>` — the linear form both backends already lower. |
27 | | - Verified at VM↔compiled parity (`parity_await_in_expression`). The one remaining |
28 | | - non-linear position, the short-circuit `&&`/`||` RHS, stays rejected (`RS0411`) |
29 | | - to preserve conditional-evaluation semantics. |
30 | | - |
31 | | -- [x] **Structured-fix tooling + analysis server** (§20.1-D) — _structured-fix |
32 | | - tooling done; streaming LSP daemon remains._ |
33 | | - Added a concrete edit payload `diagnostic::FixEdit { span, replacement }` on |
34 | | - `Fix` (insertion or replacement; serialized into `rss check --json` / |
35 | | - `rss ide --json diagnostics`), wired the high-value machine-applicable fixes |
36 | | - (`add_data_effect`, `add_constructor_field_effect`) to emit real edits, and |
37 | | - shipped `rss fix [--write] [--json]` which plans the edits, applies them |
38 | | - bottom-to-top (so positions don't shift) and skips overlaps. Verified end-to-end |
39 | | - (`cli_fix.rs`: missing `read` → clean check) plus a lib-level edit-generation |
40 | | - guard. The request/response **analysis server** already exists as `rss ide --json` |
41 | | - (diagnostics/symbols/hover/definition/references/outline) and now carries the fix |
42 | | - edits too. |
43 | | - _Remaining:_ (a) populate edits for the other machine-applicable fixes as they |
44 | | - come up; (b) a persistent **LSP-protocol daemon** (stdio) for editors — `rss ide` |
45 | | - is request/response, not a long-running server. Track as a follow-up. |
46 | | - |
47 | | -- [x] **FFI / native-ABI adapter contracts** (§3.2 general FFI, §20.1-N) — |
48 | | - _compact whole-boundary binding done; deeper adapter protocol remains._ |
49 | | - The FFI surface was already mature (`native fn`, `native module` grouping, |
50 | | - transitive binding inheritance, unbound-call error at lowering, `rss native |
51 | | - audit`, review capability classification). Closed the named gap — "binding whole |
52 | | - boundaries compactly without large wrapper files" — with an |
53 | | - `[adapter.<Namespace>]` section in `native/bindings.rssbind.toml` (package-mgr |
54 | | - §9.5): one `crate` + a `functions` list (plus optional `rename`) binds a whole |
55 | | - namespace, expanding at load time into the same flat `symbol -> target` map every |
56 | | - consumer already uses (lowering, VM shim, conformance checks) — **zero parity |
57 | | - risk, single expansion point** (`flatten_native_bindings`). Duplicates across an |
58 | | - adapter and explicit `[bindings]` are rejected. Unit-tested for expansion, |
59 | | - rename, composition, and equivalence to the explicit form. |
60 | | - _Remaining (deferred, §20.1-N):_ deeper structured adapter protocol (Rust adapter |
61 | | - crate per dep), broader binding-conformance facts, dependency updates as semantic |
62 | | - review events. General FFI / C-header parsing / auto-binding stay non-goals. |
63 | | - |
64 | | -## P2 — real features, not blocking today |
65 | | - |
66 | | -- [ ] **Capability objects / explicit dynamic dispatch** (§3.2, §20.1-G) — |
67 | | - _large._ Protocol-typed values / open dispatch; today only static `impl` + |
68 | | - generic bounds. |
69 | | -- [ ] **`Stream<T>` + `await for` async sequences** (§20.1-H) — _medium–large._ |
70 | | - Async iteration; `rss-async` has the base. Pairs with extended async (A). |
71 | | -- [ ] **Scoped views / slices** (zero-copy borrowed regions) (§3.2, §20.1-I) — |
72 | | - _large._ Perf + ergonomics; pairs with the parked lazy-`Iter` note in `TODO.md`. |
73 | | -- [ ] **Sum-type hardening** (§20.1-E) — _small–medium._ Incremental tightening of |
74 | | - the shipped sum surface. |
75 | | -- [ ] **Module visibility / re-export hardening** (§20.1-M) — _small–medium._ |
76 | | - Refines the module system (aliasing/qualified/glob already shipped). |
77 | | - |
78 | | -## P3 — deferred by design / lower value |
79 | | - |
80 | | -- [ ] **`spawn` + public task handles** (§3.2) — _large._ Single-isolate |
81 | | - cooperative model is the deliberate v0.7 stance; unstructured `spawn` is |
82 | | - intentionally rejected for now. |
83 | | -- [ ] **Cross-isolate message API (zero-copy transfer)** (§20.1-B) — _large._ |
84 | | - Only after the async/isolate model matures. |
85 | | -- [ ] **Two-tier execution (dev interpreter + AOT)** (§20.1-C) — _large._ reg-VM + |
86 | | - compiled already run at parity; this is an optimization, not a new capability. |
87 | | -- [ ] **Rust-style open-enum machinery** (§3.2) — counter to the sealed-sums |
88 | | - design; likely stays a non-goal. |
89 | | -- [ ] **Registry-level review-risk badges** (§20.1-F) — _small–medium._ Registry |
90 | | - polish. |
91 | | - |
92 | | -## Basis for the ranking |
93 | | - |
94 | | -- **tinygrad port driver:** P1 FFI + `await`-in-expression matter most; capability |
95 | | - objects (P2) next if the port hits protocol-typed dispatch. |
96 | | -- **dogfooding / self-host driver:** the analysis server / `rss fix` (P1-D) is the |
97 | | - biggest force-multiplier. |
98 | | -- **perf driver:** scoped views/slices (P2-I) + the parked lazy-`Iter` (`TODO.md`) |
99 | | - move up to P1. |
| 9 | + but rejected before lowering with stable diagnostics (e.g. `spawn` → |
| 10 | + `RS0015`/`RS0101`). |
| 11 | +3. **Post-v0.7 deferred directions (§20.1)** — future work. |
| 12 | + |
| 13 | +Every item below is **resolved**: shipped, shipped-by-design, or a recorded |
| 14 | +decision. The only open work is the explicitly-optional post-v0.7 enhancements at |
| 15 | +the end — none of it blocks v0.7. |
| 16 | + |
| 17 | +## Shipped |
| 18 | + |
| 19 | +- [x] **`await` in expression position** (§3.2, §20.1-A, §14.6.2). Await-hoisting |
| 20 | + syntax pass (`syntax/async_await_hoist.rs`): a nested `await` in a call argument, |
| 21 | + return value, or assignment-target index is lifted, left-to-right, to a preceding |
| 22 | + `let __rss_await_N = await <op>` — the linear form both backends lower. VM↔compiled |
| 23 | + parity (`parity_await_in_expression`). The conditionally-evaluated short-circuit |
| 24 | + `&&`/`||` RHS stays `RS0411` by design. |
| 25 | + |
| 26 | +- [x] **Structured-fix tooling** (§20.1-D). `diagnostic::FixEdit { span, replacement }` |
| 27 | + on `Fix` (insertion/replacement; serialized into `rss check --json` / |
| 28 | + `rss ide --json diagnostics`); high-value machine-applicable fixes |
| 29 | + (`add_data_effect`, `add_constructor_field_effect`) emit real edits; `rss fix |
| 30 | + [--write] [--json]` applies them bottom-to-top and skips overlaps. End-to-end + |
| 31 | + lib-level tests. The request/response **analysis server** is `rss ide --json` |
| 32 | + (diagnostics/symbols/hover/definition/references/outline), now carrying fix edits. |
| 33 | + |
| 34 | +- [x] **FFI / native-ABI adapter contracts** (§3.2, §20.1-N). Surface was already |
| 35 | + mature (`native fn`, `native module` grouping, transitive binding inheritance, |
| 36 | + unbound-call error at lowering, `rss native audit`, review capability |
| 37 | + classification). Closed the named gap — compact whole-boundary binding — with an |
| 38 | + `[adapter.<Namespace>]` section in `native/bindings.rssbind.toml` (pkg §9.5) that |
| 39 | + expands at load time into the same flat binding map every consumer uses (single |
| 40 | + expansion point, zero parity risk). Duplicates rejected; unit-tested. |
| 41 | + |
| 42 | +- [x] **`Stream<T>` + `await for` async sequences** (§20.1-H). Already in the |
| 43 | + executable MVP: `await for`, `Stream<T>`, `Stream.next`, `Receiver.into_stream`, |
| 44 | + and built-in stream sources (`File.bytes_stream`, `Csv.rows`, `Process.stream`) |
| 45 | + parse, check, lower to Rust, and run in the reg-VM — VM↔compiled parity in |
| 46 | + `vm_eval_parity/async_concurrency.rs`. (User-defined async generators and stream |
| 47 | + combinators are optional post-v0.7 enhancements, below.) |
| 48 | + |
| 49 | +- [x] **Sum-type hardening** (§20.1-E). The v0.7 baseline is complete: payload |
| 50 | + variants, generic sums, exhaustiveness checking, match in expression position, |
| 51 | + and sum-type review/diff metadata all ship and are tested. (Named payload fields |
| 52 | + — `Circle { radius: Int }` vs positional — are an optional post-v0.7 enhancement, |
| 53 | + below.) |
| 54 | + |
| 55 | +- [x] **Registry-level review-risk badges** (§20.1-F). `PackageReview` and the |
| 56 | + registry index (`rss.registry.index.v1`) now carry a compact `badges` set |
| 57 | + (`risk:<level>`, `native`, `unsafe`, `async`, `parallel`, `unknown-capability`, |
| 58 | + `has-errors`) derived from the existing risk + capability summary — a restatement |
| 59 | + of review evidence, never new analysis. Rendering badges in a registry UI is a |
| 60 | + registry-side concern outside this repo. |
| 61 | + |
| 62 | +## Shipped by design (no gap) |
| 63 | + |
| 64 | +- [x] **Module visibility / re-export hardening** (§20.1-M). `pub` is enforced at |
| 65 | + the boundary that matters: the package public contract is filtered to `pub` / |
| 66 | + interface-declared items (`package/contract.rs`), and consumers only ever see a |
| 67 | + dependency's `.rssi`. Non-`pub` items are **package-private by design** (§14.8: |
| 68 | + "items without `pub` are package-private implementation details"), so within- |
| 69 | + package cross-module access is intentional, not a leak. Module aliasing, qualified |
| 70 | + calls, and glob imports already shipped. (`pub use` re-export is an optional |
| 71 | + enhancement, below.) |
| 72 | + |
| 73 | +## Decided: out of scope for v0.7 (rationale recorded) |
| 74 | + |
| 75 | +These are deliberate non-goals or deferred architecture, not pending work. |
| 76 | +Building them now would contradict the v0.7 design. |
| 77 | + |
| 78 | +- **`spawn` + public task handles** (§3.2) — _deferred by design._ The single-isolate |
| 79 | + cooperative model is the v0.7 stance; unstructured `spawn` is intentionally |
| 80 | + rejected (`RS0015`/`RS0101`) in favor of `task_group` structured concurrency. |
| 81 | + Revisit only if/when the isolate model gains unstructured tasks. |
| 82 | +- **Capability objects / explicit dynamic dispatch** (§3.2, §20.1-G) — _deferred by |
| 83 | + design._ RSScript does not adopt `dyn Trait`/vtable coercion in v0.7 (spec marks |
| 84 | + dynamic dispatch "not admitted in v0.7"); static `impl` + generic bounds are the |
| 85 | + sanctioned mechanism. A future open-dispatch design must stay review-explicit. |
| 86 | +- **Cross-isolate message API (zero-copy transfer)** (§20.1-B) — _deferred._ Only |
| 87 | + meaningful after the async/isolate model matures; depends on the isolate boundary |
| 88 | + design not yet settled. |
| 89 | +- **Rust-style open-enum machinery** (§3.2) — _non-goal._ Counter to the sealed-sum |
| 90 | + design (which underpins exhaustiveness + review diffs). Not planned. |
| 91 | +- **Two-tier execution (dev interpreter + AOT)** (§20.1-C) — _not a capability gap._ |
| 92 | + The reg-VM and compiled backends already run at parity; this is a perf/packaging |
| 93 | + optimization, tracked with perf work, not a missing language feature. |
| 94 | +- **Scoped views / slices (zero-copy borrowed regions)** (§3.2, §20.1-I) — _deferred._ |
| 95 | + A genuine future perf/ergonomics feature (pairs with the parked lazy-`Iter` note |
| 96 | + in `TODO.md`); large enough to warrant its own design pass. Not required for v0.7. |
| 97 | + |
| 98 | +## Optional post-v0.7 enhancements (tracked, non-blocking) |
| 99 | + |
| 100 | +Small/medium add-ons to already-shipped features. None is required; pick up if a |
| 101 | +real driver (the tinygrad port, dogfooding) demands it. |
| 102 | + |
| 103 | +- **`Fix` edits for the remaining machine-applicable fixes** — extend the `rss fix` |
| 104 | + payload to more fix sites as they come up. |
| 105 | +- **LSP-protocol daemon (stdio)** — a long-running server for editors; `rss ide` is |
| 106 | + request/response today. |
| 107 | +- **`pub use` re-export** — let a package re-export a dependency's item as its own. |
| 108 | +- **Sum named payload fields** — `Variant { field: T }` in addition to positional. |
| 109 | +- **Stream combinators / user-defined async generators** — `.map`/`.filter` on |
| 110 | + `Stream`, custom stream sources. |
0 commit comments