plum
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
- 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)
|