Skip to content

Commit e245ea2

Browse files
olwangclaude
andcommitted
docs(spec-todo): resolve every item — finished
Drives spec-todo.md to a finished state: no undecided open work remains. Each former P2/P3 item is now resolved as shipped, shipped-by-design, or a recorded decision: - Shipped: await-in-expression, structured-fix tooling (rss fix), FFI adapter binding, Stream/await-for (already MVP), sum-type v0.7 baseline, registry badges. - Shipped by design (no gap): module visibility — `pub` is enforced at the package boundary; non-pub is package-private by design (§14.8). - Decided out of scope for v0.7 (rationale recorded): spawn, capability objects / dynamic dispatch, cross-isolate API, open enums, two-tier execution, scoped views. - Optional post-v0.7 enhancements separated out as tracked/non-blocking (LSP daemon, pub use, sum named fields, stream combinators, more fix edits). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent b4c8e15 commit e245ea2

1 file changed

Lines changed: 103 additions & 92 deletions

File tree

docs/spec-todo.md

Lines changed: 103 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,110 @@
11
# RSScript language-spec TODO
22

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.
44

55
The spec is a deliberate **superset** of the implementation, in three tiers:
66

77
1. **Executable MVP (§3.1)** — implemented and tested at VM↔compiled parity.
88
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

Comments
 (0)