plum

#treesitter#compiler#wasm

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

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


774e6d8 — Peter John 2026-10-26T12:11:35+05:30
docs(plans): value types are a single-constructor value enum, not a struct keyword
Files changed (1) hide show
  1. docs/plans/2026-10-26-game-engine.md +13 -13
docs/plans/2026-10-26-game-engine.md CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  What the user decided:
12
12
  - macroquad is the host, and Plum handles game logic plus rendering.
13
- - `struct` value types and simd128 are wanted.
13
+ - Value types (user: a `value enum` with a single constructor, not a new `struct` keyword) and simd128 are wanted.
14
14
  - Port KaM, with no scripting engine and simpler rules but the same animations and sounds.
15
15
  - It must work in the browser, as the Rust version does today.
16
16
 
@@ -36,15 +36,15 @@ Survey of `../kam_macroquad`:
36
36
  - Input: `isKeyDown(k: Key)`, `isKeyPressed`, `mousePos() -> Vec2`, `isMouseDown(b: MouseButton)` and `mouseWheel() -> Float`.
37
37
  - Audio: `playSound(id: Int, x, y: Float)` (positional, as in KaM), `playMusic(id)` and `stopMusic()`.
38
38
  - Assets, as host lookups by name: `atlasId`, `animFrames(unitKind, action, dir) -> List[Int]` (frame indices, copied once at load) and `animStep`, `loadMap(name) -> MapData`, which copies terrain into Plum `Array[Int]`s once.
39
- - `Color` and `Vec2` are structs flattened across the boundary. `Key` and `MouseButton` are enums matching macroquad's codes.
39
+ - `Color` and `Vec2` are value enums flattened across the boundary. `Key` and `MouseButton` are enums matching macroquad's codes.
40
40
  4. **Language additions this port needs** (beyond the Zig-generics plan and items 5–7 below):
41
41
  - **Unboxed typed arrays.** With copies per type, `Array[Int]` and `Array[Float]` lower to native `array (mut i64)` and `array (mut f64)`. These are for tile grids, fog of war, passability and path costs. Add `Array.filled(n, v)` and a 2D index helper.
42
42
  - **Collections in std:** `Set[T]`, `Deque[T]` (ring buffer) and `Heap[T]` (binary min-heap with a key fn, for A*), all Plum code over `Array`.
43
43
  - **Constants:** large top-level constant tables must parse and be usable in expressions. A probe file with `LIMIT = 10` followed by a `type` failed to parse (cause not yet confirmed), and the notes record a SCREAMING_CASE constant gotcha. The fix needs tests with 1k-entry tables.
44
44
  - **Seeded RNG** (`Random(seed: Int)` with xorshift/PCG) for deterministic AI and simulation.
45
45
  - Lazy iteration is deferred. Hot loops use `for … range`, and it's revisited only if profiling shows `map`/`filter` allocation in `update`.
46
- 5. **Value structs** (`struct Vec2(x: Float, y: Float)`, `Color`, `TilePos(x: Int, y: Int)`): flattened locals and params, multi-value returns, copy semantics and in-place field assignment. They are boxed only inside `List`/`Map`/`Try`, and by then they belong to a generic copy, so a `List[Vec2]` copy stores them as GC structs.
47
- 6. **Duck-typed operators** on structs (`add`/`sub`/`mul`/`neg`/`eq`): `pos + dir * speed`.
46
+ 5. **Value enums** (`value enum Vec2 = | Vec2(x: Float, y: Float)`, `Color`, `TilePos`). Exactly one constructor named like the type, fields only `Int`/`Float`/`Bool` or other value enums (no `Str`/`List`, no recursion). Lowering: flattened locals and params, multi-value returns, copy semantics and in-place field assignment. They are boxed only inside `List`/`Map`/`Try`, and by then they belong to a generic copy, so a `List[Vec2]` copy stores them as GC structs.
47
+ 6. **Duck-typed operators** on value enums (`add`/`sub`/`mul`/`neg`/`eq`): `pos + dir * speed`.
48
48
  7. **SIMD (late):** `f32x4` (wasm v128) and `Mat4`/`Vec4` in `plum-std/Math.plum`. KaM is 2D, so this is low priority for the port and kept for future 3D work.
49
49
  8. **Port scope (simplified KaM):**
50
50
  - Kept:
@@ -78,7 +78,7 @@ Success criteria:
78
78
  ```mermaid
79
79
  flowchart LR
80
80
  L1[typed arrays + collections + consts + RNG]
81
- L2[struct value types]
81
+ L2[value enums]
82
82
  L3[duck-typed operators]
83
83
  H1[plum-game host native + Game.plum]
84
84
  H2[browser bridge]
@@ -116,13 +116,13 @@ Tests:
116
116
  - `const_table_1000_entries`;
117
117
  - `random_seed_deterministic` (same seed gives the same first 100 values).
118
118
 
119
- ### L2 struct value types
120
- Grammar `struct`, flattened lowering, multi-value returns, copy semantics, field assignment, recursion rejected. Tests:
121
- - `struct_copy_semantics`;
122
- - `struct_multi_value_return`;
123
- - `struct_in_list_roundtrip`;
124
- - `struct_eq_fieldwise`;
125
- - `recursive_struct_rejected`.
119
+ ### L2 value enums (`value enum`, single constructor)
120
+ Grammar: a `value` modifier on `enum`, with checker errors for more than one constructor (`value enum X must have exactly one constructor`) and for non-value fields (`value enum field 'name' must be Int, Float, Bool or a value enum`). Flattened lowering, multi-value returns, copy semantics, field assignment, recursion rejected. Tests:
121
+ - `value_copy_semantics`;
122
+ - `value_multi_value_return`;
123
+ - `value_in_list_roundtrip`;
124
+ - `value_eq_fieldwise`;
125
+ - `value_enum_two_constructors_rejected`; `value_enum_str_field_rejected`.
126
126
 
127
127
  ### L3 duck-typed operators
128
128
  `a + b` → `a.add(b)` and so on, resolved per instantiation. Tests:
@@ -148,7 +148,7 @@ Check: a demo scene (sprites, sound, input) runs in Chrome and Firefox. Playwrig
148
148
  Load a KaM map via the host, terrain into `Array[Int]`, tile rendering, camera pan/zoom, minimap. Check: renders the same as the Rust version on 2 maps (screenshot diff tolerance).
149
149
 
150
150
  ### P2 units + animations + sounds
151
- Unit structs, directional animation state machine, walk interpolation, selection, positional sounds. Tests: the animation frame sequence for walk dir 3 equals the Rust table, and the sound fires on the step frames.
151
+ Unit types, directional animation state machine, walk interpolation, selection, positional sounds. Tests: the animation frame sequence for walk dir 3 equals the Rust table, and the sound fires on the step frames.
152
152
 
153
153
  ### P3 pathfinding
154
154
  A* over passability with `Heap`, path smoothing as in `src/pathfinding.rs` (simplified), unit move orders. Tests: shortest-path length on 5 fixture grids matches the Rust implementation, and 300 units repathing stays under 2 ms per frame (native).