plum

#treesitter#compiler#wasm

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

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


1a9a65cPeter John 2026-07-23T21:27:56+05:30
feat(plum-cli): resolve import via --lib-path using the new loader
plum-cli/src/main.rs CHANGED
@@ -6,7 +6,6 @@ use anyhow::{Context, Result};
6
6
  use clap::{Parser, Subcommand};
7
7
 
8
8
  use plum_core::format_source;
9
- use plum_core::AstParser;
10
9
 
11
10
  mod editor;
12
11
  use editor::EditorType;
@@ -38,6 +37,9 @@ enum Command {
38
37
  /// Output path (default: input with .wasm extension)
39
38
  #[arg(short, long)]
40
39
  output: Option<std::path::PathBuf>,
40
+ /// Root directory `import <path>` is resolved against (`import std/x` -> `<lib-path>/std/x.plum`)
41
+ #[arg(long, default_value = "libs")]
42
+ lib_path: std::path::PathBuf,
41
43
  },
42
44
  /// Install Plum syntax highlighting into an editor's configuration
43
45
  Editor {
@@ -60,7 +62,7 @@ fn run() -> Result<()> {
60
62
  let cli = Cli::parse();
61
63
  match cli.command {
62
64
  Command::Format { file, check, stdin } => cmd_format(file, check, stdin),
63
- Command::Compile { file, output } => cmd_compile(file, output),
65
+ Command::Compile { file, output, lib_path } => cmd_compile(file, output, lib_path),
64
66
  Command::Editor { editor, insiders } => editor::install(editor, insiders),
65
67
  }
66
68
  }
@@ -103,20 +105,13 @@ fn cmd_format(
103
105
  Ok(())
104
106
  }
105
107
 
108
+ fn cmd_compile(
109
+ file: std::path::PathBuf,
106
- fn cmd_compile(file: std::path::PathBuf, output: Option<std::path::PathBuf>) -> Result<()> {
110
+ output: Option<std::path::PathBuf>,
111
+ lib_path: std::path::PathBuf,
112
+ ) -> Result<()> {
107
- let source = fs::read_to_string(&file)
113
+ let ast = plum_core::load_and_merge(&file, &lib_path)
108
- .with_context(|| format!("failed to read {}", file.display()))?;
109
-
110
- // Parse
111
- let mut parser = tree_sitter::Parser::new();
112
- parser
113
- .set_language(&tree_sitter_plum::LANGUAGE.into())
114
- .map_err(|e| anyhow::anyhow!("language error: {e}"))?;
114
+ .map_err(|e| anyhow::anyhow!("{e}"))?;
115
- let tree = parser
116
- .parse(&source, None)
117
- .ok_or_else(|| anyhow::anyhow!("parse failed"))?;
118
- let ap = AstParser::new(&source);
119
- let ast = ap.parse_source(tree.root_node());
120
115
 
121
116
  // Type check
122
117
  if let Err(errors) = plum_checker::check_source(&ast) {
plum-cli/tests/compile_tests.rs CHANGED
@@ -23,3 +23,18 @@ fn compile_simple_add_produces_wasm() {
23
23
  let bytes = std::fs::read(out_path).expect("output wasm not found");
24
24
  assert_eq!(&bytes[0..4], b"\0asm");
25
25
  }
26
+
27
+ #[test]
28
+ fn compile_with_import_resolves_via_lib_path() {
29
+ let src_path = concat!(env!("CARGO_MANIFEST_DIR"), "/../test/import_fixtures/main.plum");
30
+ let lib_path = concat!(env!("CARGO_MANIFEST_DIR"), "/../test/import_fixtures");
31
+ let out_path = std::env::temp_dir().join(format!("plum_test_import_{}.wasm", std::process::id()));
32
+ let out_path_str = out_path.to_str().unwrap();
33
+ let status = Command::new(plum_bin())
34
+ .args(["compile", src_path, "--lib-path", lib_path, "-o", out_path_str])
35
+ .status()
36
+ .expect("failed to run plum compile");
37
+ assert!(status.success(), "plum compile exited with: {}", status);
38
+ let bytes = std::fs::read(out_path).expect("output wasm not found");
39
+ assert_eq!(&bytes[0..4], b"\0asm");
40
+ }
test/import_fixtures/helper.plum ADDED
@@ -0,0 +1,4 @@
1
+ module fixtures
2
+
3
+ helperValue() -> Int =
4
+ 42
test/import_fixtures/main.plum ADDED
@@ -0,0 +1,6 @@
1
+ module fixtures
2
+
3
+ import helper
4
+
5
+ main() -> Int =
6
+ helperValue()