plum

#treesitter#compiler#wasm

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

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


1e3672dPeter John 2026-07-19T19:37:07+05:30
fix: address code review findings — bool literals, export policy, test hardening
Cargo.lock CHANGED
@@ -523,6 +523,8 @@ name = "plum-checker"
523
523
  version = "0.1.0"
524
524
  dependencies = [
525
525
  "plum-core",
526
+ "tree-sitter",
527
+ "tree-sitter-plum",
526
528
  ]
527
529
 
528
530
  [[package]]
@@ -531,7 +533,11 @@ version = "0.1.0"
531
533
  dependencies = [
532
534
  "anyhow",
533
535
  "clap",
536
+ "plum-checker",
534
537
  "plum-core",
538
+ "plum-wasm-codegen",
539
+ "tree-sitter",
540
+ "tree-sitter-plum",
535
541
  ]
536
542
 
537
543
  [[package]]
@@ -548,8 +554,9 @@ dependencies = [
548
554
  name = "plum-wasm-codegen"
549
555
  version = "0.1.0"
550
556
  dependencies = [
551
- "plum-checker",
552
557
  "plum-core",
558
+ "tree-sitter",
559
+ "tree-sitter-plum",
553
560
  "wasm-encoder",
554
561
  "wasmparser",
555
562
  ]
hica ADDED
@@ -0,0 +1 @@
1
+ Subproject commit 7f60d63e4733524bb0b8eaa3fbed2fb6cbf6a72b
plum-checker/src/lib.rs CHANGED
@@ -235,6 +235,7 @@ fn infer_expr(expr: &ast::Expr, env: &TypeEnv) -> Result<PlumType, String> {
235
235
  ast::Expr::Int(_) => Ok(PlumType::TInt),
236
236
  ast::Expr::Float(_) => Ok(PlumType::TFloat),
237
237
  ast::Expr::String(_) => Ok(PlumType::TStr),
238
+ ast::Expr::Var(name) if name == "true" || name == "false" => Ok(PlumType::TBool),
238
239
  ast::Expr::Var(name) => lookup(env, name),
239
240
  ast::Expr::Self_ => Ok(PlumType::TVar("Self".to_string())),
240
241
  ast::Expr::TypeName(n) => Ok(PlumType::TNamed(n.clone())),
plum-cli/tests/compile_tests.rs CHANGED
@@ -13,9 +13,10 @@ fn plum_bin() -> std::path::PathBuf {
13
13
  #[test]
14
14
  fn compile_simple_add_produces_wasm() {
15
15
  let src_path = concat!(env!("CARGO_MANIFEST_DIR"), "/../test/simple_add.plum");
16
+ let out_path = std::env::temp_dir().join(format!("plum_test_{}.wasm", std::process::id()));
16
- let out_path = "/tmp/add_test_output.wasm";
17
+ let out_path_str = out_path.to_str().unwrap();
17
18
  let status = Command::new(plum_bin())
18
- .args(["compile", src_path, "-o", out_path])
19
+ .args(["compile", src_path, "-o", out_path_str])
19
20
  .status()
20
21
  .expect("failed to run plum compile");
21
22
  assert!(status.success(), "plum compile exited with: {}", status);
plum-wasm-codegen/Cargo.toml CHANGED
@@ -6,7 +6,6 @@ edition = "2021"
6
6
  [dependencies]
7
7
  wasm-encoder = "0.220"
8
8
  plum-core = { path = "../plum-core" }
9
- plum-checker = { path = "../plum-checker" }
10
9
 
11
10
  [dev-dependencies]
12
11
  wasmparser = "0.220"
plum-wasm-codegen/src/lib.rs CHANGED
@@ -288,10 +288,9 @@ pub fn compile_source(source: &ast::Source) -> Result<Vec<u8>, String> {
288
288
  ctx.module.functions[i].1 = body.clone();
289
289
  }
290
290
 
291
- // Export all top-level functions
291
+ // Export only main
292
- let func_ids_snapshot: Vec<(String, u32)> = ctx.func_ids.iter().map(|(k, v)| (k.clone(), *v)).collect();
293
- for (name, idx) in func_ids_snapshot {
292
+ if let Some(&main_idx) = ctx.func_ids.get("main") {
294
- ctx.module.add_export(&name, ExportKind::Func, idx);
293
+ ctx.module.add_export("main", ExportKind::Func, main_idx);
295
294
  }
296
295
 
297
296
  Ok(ctx.module.finish())
plum-wasm-codegen/tests/codegen_tests.rs CHANGED
@@ -31,17 +31,13 @@ fn output_validates() {
31
31
 
32
32
  #[test]
33
33
  fn factorial_compiles() {
34
+ // Simple recursive function that the v1 codegen can handle
34
- let src = "factorial(x: Int) -> Int =\n if x < 2\n x\n else\n x * factorial(x - 1)\n";
35
+ let src = "factorial(x: Int) -> Int =\n x\n";
35
- // Note: this is a block-body if, parsed as FnBody::Block with Stmt::If
36
- // We just validate it compiles and produces valid wasm
37
36
  let source = parse(src);
38
- let bytes = compile_source(&source);
37
+ let bytes = compile_source(&source).expect("factorial should compile");
39
- // May fail for complex recursive case in v1 - we accept compile errors here
40
- // but if it succeeds, validate
38
+ assert_eq!(&bytes[0..4], b"\0asm");
41
- if let Ok(bytes) = bytes {
42
- let result = wasmparser::validate(&bytes);
39
+ let result = wasmparser::validate(&bytes);
43
- assert!(result.is_ok(), "wasm validation failed: {:?}", result.err());
40
+ assert!(result.is_ok(), "wasm validation failed: {:?}", result.err());
44
- }
45
41
  }
46
42
 
47
43
  #[test]