plum

#treesitter#compiler#wasm

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

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


7a61c06 — Peter John 2026-11-04T13:39:14+05:30
docs: backlog of planned and open items
Files changed (1) hide show
  1. docs/backlog.md +40 -0
docs/backlog.md ADDED
@@ -0,0 +1,40 @@
1
+ # Backlog
2
+
3
+ Open work, in the order the user queued it, plus smaller items found during builds. Each item links where it came from. Decisions behind these are in `docs/decisions/2026-11-language-and-scene-decisions.md`.
4
+
5
+ ## Planned (in order)
6
+
7
+ 1. **Compiler cleanup and architecture** — `docs/plans/2026-11-04-compiler-cleanup.review.md` (written in another session; meant to run after language-restrictions merged). Needs an approve.
8
+ 2. **Native inline variants, then decide union enums** — compile inline variants directly as struct subtypes of their enum and delete the hidden-record lowering (`hoistInlineVariants`, the `List__Cons(Cons(..))` wrappers, union forwarders). Then decide whether user-facing union enums (`enum X = A | B` of records) stay as a thin feature or fold into traits; if they go, `JsonParse` in `plum-std/Json.plum` becomes inline variants and the union examples (`unions.plum`, `struct_union_members.plum`) are rewritten. `unboxed_variants.plum` is really a compiler probe: move it to a codegen test. (Decision record §8b.)
9
+ 3. **Benchmark** before FBIP (user: FBIP waits for it).
10
+ 4. **FBIP: no heap mutation** — persistent std collections updated in place when unique, Koka-style `fip` functions as a checked in-place guarantee, a reference count used only as a uniqueness check if static proof falls short. Worklist = the `mut` fields left today (see below). (Decision record §9.)
11
+ 5. **One product type, `struct`** — after FBIP, merge `record` into an immutable `struct` with compiler-chosen boxing (optional hint, shown by `--explain`). (Decision record §9b.)
12
+ 6. **Deterministic games** — fixed timestep, input recording and replay, seeded `Random` in game state, state checksums; port the design from `../kam_macroquad` (`main.rs` tick accumulator, `game/replay.rs`). The `Io` capability makes recording and replaying host input straightforward. (Decision record §10.)
13
+
14
+ ## FBIP worklist: `mut` fields left after language-restrictions
15
+
16
+ | Type | `mut` fields | Why it is mutable today |
17
+ |---|---|---|
18
+ | `Slice` | data, start, size, cap | grows in place (push, removeAt) |
19
+ | `Buffer` | data, len | in-place byte buffer |
20
+ | `Map` | index, hashes, keys, vals, alive, used, size | open-addressing table |
21
+ | `Deque` | buf, head, size | ring buffer |
22
+ | `JsonParser` | pos, text | parse cursor |
23
+ | `Action` (std/game/pure) | elapsed, current | animations stepped in place; a pure version needs a `stepAll` redesign |
24
+ | imperative `Actor` trait, `Stage`, `Text.text` | all / camera / text | the mutable scene, by design |
25
+ | game shells (`World` etc. in examples) | state, wasDown, … | host shell state |
26
+ | `Ship`, `Orb`, `Mine`, `Star` (games/pure) | clock, vx, vy | actor state changed in `act` |
27
+
28
+ ## Smaller open items
29
+
30
+ - **Spread from a field path** — `Stage(..w.stage, x: 1)` is rejected; only a plain variable can be a spread source. Worked around with small helpers in the pure game. (language-restrictions T14)
31
+ - **Fields declared inside `init` can't be `mut`** (`self.camX: Float = 0.0`) — such fields were moved into the record header. (T8)
32
+ - **Benchmark harness can't pass `--no-fusion`** — `plum-game/web-test` compiles without flags, so fusion-off numbers can't be taken since the env var was removed. (T11)
33
+ - **`Orb`/`Mine` copy their shared `Node` per frame** in the pure game, because `Node`'s x/y/rotation stay immutable in std. Decide during FBIP. (T10)
34
+ - **Uniqueness precision** — `adv(Cell(..))` inlined into `main` reports "s used after its spread" although `s.x` is only read inside the spread value (a false "not in place"). (T10)
35
+ - **Pattern-casing hint for union members** — "did you mean Foo?" doesn't cover a lowercase name that spells a union member (lookup lives in `plum-core/src/unions.rs`). (T1)
36
+ - **Constant `Anim` trees rebuilt every frame** in `games/functional/game_state_view.plum` (`renderTitle`, Ship render) — hoist them into `State` or constants. (F-T23-1)
37
+ - **Static subtree reuse** in functional scenes (build unchanging parts of a picture once). Deferred by the user as a later optimisation. (state-view parity plan)
38
+ - **Structural deep `==` for records** — user chose deep structural equality (like Rust `#[derive(PartialEq)]`), deferred before implementation; until then `==` on records is identity. (state-view parity T7)
39
+ - **Retire PureScene?** — after the component-style functional game, decide whether `std/game/pure` + `games/pure` stay. (Decision record §4b)
40
+ - **`adder(1)(2)`** (calling a returned closure directly) is not supported. (functional-gaps plan)