plum

#treesitter#compiler#wasm

git clone https://git.pyrossh.dev/plum

A statically typed, imperative programming language inspired by rust, python


7873c08 — Peter John 2026-11-04T20:41:58+05:30
docs: language simplification run A plan
docs/plans/2026-11-04-language-simplification-a.md ADDED
@@ -0,0 +1,120 @@
1
+ # Language simplification, run A: value enums, variadics, generators, error forms, `=`
2
+
3
+ **Review plan:** docs/plans/2026-11-04-language-simplification.review.md
4
+ **Goal:** Remove value enums, variadics (replaced by a `[a, b]` list literal), generators (Seq becomes a step-function struct), the extra error forms, and declare-on-first-use `=`. Std, examples and tests are rewritten first, then the compiler support is deleted.
5
+ **Architecture:** tree-sitter grammar (plum-tooling/tree-sitter-plum), plum-core parser/passes, plum-checker, plum-wasm-codegen, plum-std, plum-examples.
6
+ **Tech stack:** Rust 2021, tree-sitter, Plum.
7
+ **Detail:** contracts
8
+ **Target-min:** 40
9
+
10
+ ## Global constraints
11
+ - Agents cannot run `cargo test` (hook): `cargo build --workspace --tests`, run binaries in `target/debug/deps` (newest by mtime). `touch` edited files. Own scratchpad subdir + CARGO_TARGET_DIR if the shared one is locked.
12
+ - Grammar edits: regenerate with `tree-sitter generate --disable-optimizations` (the default optimizer silently breaks unrelated parses); update corpus fixtures.
13
+ - Gate for every task: workspace test binaries pass and `plum test plum-std plum-examples` passes (678 today; the count may change only by tests this plan deletes or adds, each listed). Wasm bytes may change.
14
+ - Never run `plum format` on real files. Don't commit.
15
+ - Rulings from the user (2026-11-04): list literal syntax `[a, b, c]` (brackets at expression start; `[]` stays generics after a type name), a pure parser desugaring to `List.empty().append(a).append(b).append(c)` — no `init` method on List or Map (both `init`s are deleted); `[]` is `List.empty()` (element type from the annotation or use); a Map literal `["a" => 1, "b" => 2]` desugars to `Map.empty().set("a", 1).set("b", 2)` (coordinator default, user may change); `Seq` becomes a struct holding a `next` step closure returning `T?`, and `for x := s` loops over anything with `next(self) -> T?`.
16
+
17
+ ## Task graph
18
+ ```mermaid
19
+ flowchart LR
20
+ T1[list literal]
21
+ T2[std off variadics]
22
+ T3[Seq step struct]
23
+ T4[std off generators]
24
+ T5[errors and = inventory]
25
+ T6[remove from compiler]
26
+ T7[verify run A]
27
+ %% taskgraph
28
+ T1 --> T2
29
+ T1 --> T3
30
+ T3 --> T4
31
+ T2 --> T6
32
+ T4 --> T6
33
+ T5 --> T6
34
+ T6 --> T7
35
+ ```
36
+ Ruling: sequential - std must stop using a feature before the compiler drops it - cost: longer chain.
37
+
38
+ ## Package A: new forms
39
+ **Probe entry:** run=plum test plum-std plum-examples
40
+
41
+ ### T1 list literal · Complexity 5 · Est. context 50k
42
+ **Owns:** plum-tooling/tree-sitter-plum/grammar.js, plum-tooling/tree-sitter-plum/src/**, plum-tooling/tree-sitter-plum/test/corpus/**, plum-core/src/parser.rs, plum-core/src/ast.rs, plum-std/List.plum, plum-std/Map.plum, plum-core/tests/list_literal_test.rs, plum-examples/list_literal_probe.plum
43
+ **Components:** 2
44
+ **LOC owned:** 140
45
+ **Tests:** slow
46
+ **Model:** opus
47
+ **Produces:** parser desugaring of `[..]` into method chains (no new AST variant needed; a `ListLit` variant only if the parser needs it transiently)
48
+ e.g. `xs := [1, 2, 3]` -> parses as `List.empty().append(1).append(2).append(3)`, a List[Int] of 3
49
+ e.g. `xs: List[Int] := []` -> `List.empty()`
50
+ e.g. `["a" => 1, "b" => 2]` -> `Map.empty().set("a", 1).set("b", 2)`
51
+ **Test code:** parser tests asserting the desugared AST for the three e.g. lines; a `.plum` test block in the probe file checking length/get of each; grammar corpus green. List and Map get `empty()` / `append` / `set` if missing (in plum-std/List.plum and Map.plum — ruling: T1 may add those methods only).
52
+
53
+ ## Package B: std and examples
54
+ **Probe entry:** run=plum test plum-std plum-examples
55
+
56
+ ### T2 std off variadics · Complexity 4 · Est. context 45k
57
+ **Owns:** plum-std/List.plum, plum-std/Map.plum, plum-std/Json.plum, plum-std/Slice.plum, plum-examples/basics.plum, plum-examples/structs_records.plum, plum-wasm-codegen/tests/**, plum-checker/tests/**, plum-core/tests/** except list_literal_test.rs
58
+ **Components:** 1
59
+ **LOC owned:** 120
60
+ **Tests:** slow
61
+ **Consumes:** ast::Expr::ListLit(Vec<Expr>) (T1)
62
+ **Produces:** none
63
+ **Test code:** every `...T` parameter is removed (`List.init`/`Map.init` deleted; other variadic fns take a `List[T]`); every `List(1, 2, 3)` / `Map("a" => 1)` call becomes `[1, 2, 3]` / `["a" => 1]` in std, examples and embedded test sources; all gates pass.
64
+
65
+ ### T3 Seq as a step struct · Complexity 5 · Est. context 50k
66
+ **Owns:** plum-std/Seq.plum, plum-core/src/forms.rs, plum-checker/src/lib.rs, plum-wasm-codegen/src/lib.rs
67
+ **Components:** 2
68
+ **LOC owned:** 160
69
+ **Tests:** slow
70
+ **Consumes:** ast::Expr::ListLit(Vec<Expr>) (T1)
71
+ **Produces:** std Seq[T] { next: fn() -> T? } with map/filter/take/fold as plain fns · `for x := s` over a value with `next(self) -> T?`
72
+ e.g. `for x := Seq.range(0, 3)` binds 0, 1, 2
73
+ e.g. `Seq.range(0, 10).filter(|n| n % 2 == 0).take(2)` -> 0, 2
74
+ **Review Focus:** fusion: `fusion_alloc_test` and the List-chain fusion still pass; report any lost fusion with numbers.
75
+ **Test code:** Seq.plum test blocks for the e.g. lines and every old Seq test rewritten.
76
+
77
+ ### T4 std and examples off generators · Complexity 4 · Est. context 45k
78
+ **Owns:** plum-std/Map.plum, plum-std/Int.plum, plum-std/List.plum, plum-examples/functional.plum, plum-examples/sequences.plum
79
+ **Components:** 1
80
+ **LOC owned:** 100
81
+ **Tests:** slow
82
+ **Consumes:** std Seq[T] { next: fn() -> T? } with map/filter/take/fold as plain fns (T3)
83
+ **Produces:** none
84
+ **Test code:** no `fun*`/`yield` left in plum-std or plum-examples; all gates pass.
85
+
86
+ ### T5 error forms and `=` inventory · Complexity 4 · Est. context 45k
87
+ **Owns:** plum-examples/errors.plum, docs/plans/2026-11-04-language-simplification-a.inventory.md
88
+ **Components:** 1
89
+ **LOC owned:** 60
90
+ **Tests:** slow
91
+ **Produces:** inventory file listing (a) every error form the checker/codegen still accept beyond `T!E` and `T?` with file:line, (b) every `=` that declares on first use in plum-std/plum-examples (found by a temporary local checker build that errors on it — do not commit that build)
92
+ **Test code:** errors.plum rewritten without `?.`; gates pass.
93
+
94
+ ## Package C: remove and verify
95
+ **Probe entry:** run=plum test plum-std plum-examples
96
+
97
+ ### T6 remove from the compiler · Complexity 5 · Est. context 55k
98
+ **Owns:** plum-tooling/tree-sitter-plum/**, plum-core/src/*.rs, plum-checker/src/*.rs, plum-wasm-codegen/src/lib.rs, plum-lsp/src/*.rs, plum-std/**, plum-examples/**, plum-*/tests/**
99
+ **Components:** 3
100
+ **LOC owned:** 120
101
+ **Tests:** slow
102
+ **Produces:** none
103
+ **Review Focus:** each removed form gives a clear compile error naming its replacement (`...T` → `Slice[T]` + `[..]`; `fun*` → Seq; value enum → plain enum; `?.` and other forms → `T!E`/`T?`; first-use `=` → `:=`).
104
+ **Test code:** checker tests for each error message; all gates pass; grep finds none of the removed syntax in std/examples/grammar.
105
+ **Steps:** fix every `=` site from T5's inventory with `:=`; delete grammar rules, AST variants, checker intrinsics (variadic length/at, generator typing, value-enum checks, the `?.`→andThen path, forms already listed in T5), codegen value-enum helpers.
106
+
107
+ ### T7 verify run A · Complexity 2 · Est. context 30k
108
+ **Owns:** docs/plans/2026-11-04-language-simplification-a.results.md
109
+ **Components:** 1
110
+ **LOC owned:** 40
111
+ **Tests:** slow
112
+ **Produces:** none
113
+ **Test code:** workspace binaries, plum test, plum-game host_test, browser game check if available; Rust LOC removed per crate vs the start sha.
114
+
115
+ ## Review Focus
116
+ - Packages A/C (compiler): deep, protocol — grammar conflicts from `[` at expression start; error messages.
117
+ - Package B (std): numeric, state — Seq laziness, fusion.
118
+
119
+ ## Self-review
120
+ Covers run A of the review plan: value enums, variadics, generators, error model, `=`.