plum

#treesitter#compiler#wasm

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

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


743bd76 — Peter John 2026-10-26T13:53:37+05:30
docs(plans): queue T8 near-free closures (inline non-escaping literals)
docs/plans/2026-10-26-zig-generics-and-numbers.md CHANGED
@@ -170,3 +170,18 @@ Tests:
170
170
  - `nullable_ref_no_alloc` (the wasm uses `ref.is_null`, with no struct.new for the Ok path).
171
171
 
172
172
  Update the README's Error handling section, plum-examples/error_propagation.plum (to `T ! [..]` with auto-wrap) and safe_navigation.plum (to `T?`). Migrate std signatures to the sugar where it reads better.
173
+
174
+ ## Later task T8: near-free closures (user request; run after the game-plan language tasks L1-L3)
175
+
176
+ - Every closure literal gets its own type, as in Rust and C++.
177
+ - A closure literal passed directly to a generic or higher-order function (`units.filter(|u| u.hp > minHp)`) specializes that function's instantiation per closure literal and inlines the call. There is no `call_indirect`, and no heap env when the closure doesn't escape (captures become extra params or locals of the specialized copy).
178
+ - Escape analysis: a closure stored in a field, returned, captured by another escaping closure, or passed to an fn-typed param of a non-specialized (extern or recursive-cycle) fn keeps today's heap env plus typed `call_indirect`.
179
+ - Guard: the per-generic instantiation warning (200) counts closure specializations too.
180
+
181
+ Tests:
182
+ - `filter_closure_inlined`: the `List[Int].filter` copy for that literal has no `call_indirect`;
183
+ - `escaping_closure_still_works` (stored in a field and called later);
184
+ - `capture_by_value_semantics_unchanged`;
185
+ - `closure_specializations_counted`.
186
+
187
+ Bench: compare the hot `update`-style loop (10k elements, map+filter+reduce) before and after, and record compile-time impact.