plum

#treesitter#compiler#wasm

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

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


fe36a46Peter John 2026-07-20T12:01:31+05:30
docs+test: general enum support is complete; update known gaps and example
README.md CHANGED
@@ -321,8 +321,8 @@ Full example: [`examples/strings.plum`](examples/strings.plum).
321
321
  Some things parse and type-check but don't compile to wasm yet — `plum-wasm-codegen` reports a clear error rather than silently producing wrong code:
322
322
 
323
323
  - string interpolation (plain, non-interpolated string literals do compile)
324
- - `match` patterns other than integer literals, bindings, wildcard, and `True`/`False`; non-Bool enum-tag and constructor (`Some(v)`) patterns aren't lowered yet
325
324
  - multi-subject `match` (`match a, b`)
326
- - user-defined generics (they type-check but aren't monomorphized)
325
+ - user-defined generics (they type-check but aren't monomorphized) — this also blocks `libs/std`'s actual `Option`/`Result`/`List`/`Map`, which are declared generically
326
+ - nested constructor patterns inside `match` (`Some(Some(v))`) — a constructor pattern's own sub-patterns must be a bare binding or `_`
327
327
 
328
328
  `closure` (`|params| body`) exists in `grammar.js` but isn't wired into any reachable rule yet, so it doesn't actually parse in context.
examples/match.plum CHANGED
@@ -10,36 +10,39 @@ enum Option =
10
10
  describeNumber(n: Int) -> Str =
11
11
  match n
12
12
  0 =>
13
- "zero"
13
+ return "zero"
14
14
  1 =>
15
- "one"
15
+ return "one"
16
16
  _ =>
17
- "many"
17
+ return "many"
18
18
 
19
19
  describeBool(b: Bool) -> Int =
20
20
  match b
21
21
  True =>
22
- 1
22
+ return 1
23
23
  False =>
24
- 0
24
+ return 0
25
25
 
26
26
  bindExample(n: Int) -> Int =
27
27
  match n
28
28
  x =>
29
- x
29
+ return x
30
30
 
31
31
  describeColor(c: Color) -> Str =
32
32
  match c
33
33
  Red =>
34
- "red"
34
+ return "red"
35
35
  Green =>
36
- "green"
36
+ return "green"
37
37
  Blue =>
38
- "blue"
38
+ return "blue"
39
39
 
40
40
  describeOption(opt: Option) -> Int =
41
41
  match opt
42
42
  Some(v) =>
43
- v
43
+ return v
44
44
  None =>
45
- 0
45
+ return 0
46
+
47
+ main() -> Int =
48
+ describeOption(Some(5))
plum-wasm-codegen/tests/examples_test.rs CHANGED
@@ -66,17 +66,24 @@ fn methods_compiles_and_runs_correctly() {
66
66
  assert_eq!(result, 10);
67
67
  }
68
68
 
69
- /// match.plum and strings.plum intentionally exercise syntax beyond what codegen
69
+ /// match.plum now exercises fully-supported syntax (general enum tag and
70
- /// currently lowers (non-Bool enum-tag/constructor match patterns, string
71
- /// interpolation) they must fail loudly with a clear message, not silently
70
+ /// constructor patterns) and must compile and run correctly end to end.
72
- /// produce wrong wasm.
73
71
  #[test]
74
- fn match_example_reports_clear_unsupported_pattern_errors() {
72
+ fn match_example_compiles_and_runs_correctly() {
75
- let source = parse_file("match.plum");
73
+ let bytes = assert_compiles("match.plum");
74
+ let engine = wasmtime::Engine::default();
75
+ let module = wasmtime::Module::new(&engine, &bytes).expect("module should be loadable");
76
+ let mut store = wasmtime::Store::new(&engine, ());
77
+ let instance = wasmtime::Instance::new(&mut store, &module, &[]).expect("module should instantiate");
78
+ let main = instance
79
+ .get_typed_func::<(), i64>(&mut store, "main")
80
+ .expect("main should have signature () -> i64");
76
- let err = compile_source(&source).expect_err("non-Bool enum-tag patterns are not yet supported");
81
+ let result = main.call(&mut store, ()).expect("main should not trap");
77
- assert!(err.contains("enum variant pattern"), "got: {}", err);
82
+ // describeOption(Some(5)) = 5
83
+ assert_eq!(result, 5);
78
84
  }
79
85
 
86
+ /// strings.plum still exercises string interpolation, which remains unimplemented.
80
87
  #[test]
81
88
  fn strings_example_reports_clear_interpolation_error() {
82
89
  let source = parse_file("strings.plum");