nandi/rustnimpublic Fork 0
b0ccd80a849033974bea0c5eccff995ecb632c3e
Commits
Clone
git clone https://git.rickub.com/nandi/rustnim.git
git clone ssh://git@rickub.com/nandi/rustnim.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

main.rs · 90 lines · 3.3 KBRust Blame HistoryRaw
Add the differential test runner, and a lowering to measure with it 8ac32af nandithebull 13h ago1//! rustnim — Rust -> Nim transpiler.
2//!
3//! Usage: rustnim <input.rs> [-o <output.nim>]
4
5mod fmt;
6mod lower;
Settle signed-shr and unsigned-wrap semantics against both compilers 87c9cc8 nandi 13h ago7mod ty;
Add the differential test runner, and a lowering to measure with it 8ac32af nandithebull 13h ago8
9use std::path::PathBuf;
10use std::process::ExitCode;
11
12fn main() -> ExitCode {
13 match run() {
14 Ok(()) => ExitCode::SUCCESS,
15 Err(e) => {
16 eprintln!("rustnim: {e}");
17 // Exiting non-zero on any failure is load-bearing: the entire
18 // point of this project is that a transpiler must never report
19 // success for work it did not do.
20 ExitCode::FAILURE
21 }
22 }
23}
24
25fn run() -> Result<(), String> {
26 let mut args = std::env::args_os().skip(1);
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 13h ago27 let mut inputs: Vec<PathBuf> = Vec::new();
Add the differential test runner, and a lowering to measure with it 8ac32af nandithebull 13h ago28 let mut output: Option<PathBuf> = None;
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 13h ago29 let mut features: Vec<String> = Vec::new();
Add the differential test runner, and a lowering to measure with it 8ac32af nandithebull 13h ago30
31 while let Some(a) = args.next() {
32 match a.to_string_lossy().as_ref() {
33 "-o" | "--output" => {
34 output = Some(
35 args.next()
36 .ok_or("`-o` needs a path")?
37 .into(),
38 );
39 }
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 13h ago40 "--cfg" => {
41 let v = args.next().ok_or("`--cfg` needs an argument")?;
42 let v = v.to_string_lossy().into_owned();
43 let f = v
44 .strip_prefix("feature=")
45 .ok_or("only `--cfg feature=<name>` is supported")?;
46 features.push(f.trim_matches('"').to_string());
47 }
Add the differential test runner, and a lowering to measure with it 8ac32af nandithebull 13h ago48 "-h" | "--help" => {
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 13h ago49 println!("usage: rustnim <input.rs>... [--cfg feature=<name>]... [-o <output.nim>]");
50 println!();
51 println!("Several inputs are concatenated into one Nim module, in the");
52 println!("order given. That is how a multi-file crate is handled: Nim");
53 println!("has no equivalent of Rust's per-file `mod`, so the items are");
54 println!("flattened. Names must not collide across the files.");
Add the differential test runner, and a lowering to measure with it 8ac32af nandithebull 13h ago55 return Ok(());
56 }
57 s if s.starts_with('-') => return Err(format!("unknown flag `{s}`")),
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 13h ago58 _ => inputs.push(a.into()),
Add the differential test runner, and a lowering to measure with it 8ac32af nandithebull 13h ago59 }
60 }
61
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 13h ago62 if inputs.is_empty() {
63 return Err("no input file; usage: rustnim <input.rs>... [-o <output.nim>]".into());
64 }
Add the differential test runner, and a lowering to measure with it 8ac32af nandithebull 13h ago65
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 13h ago66 // Several files become one Nim module: Rust's `mod` has no Nim analogue
67 // inside a single output file, so the items are flattened in argument
68 // order. A name collision between two files is a Nim compile error, which
69 // is a loud failure rather than a silently shadowed definition.
70 let mut items = Vec::new();
71 for input in &inputs {
72 let src = std::fs::read_to_string(input)
73 .map_err(|e| format!("cannot read {}: {e}", input.display()))?;
74 let parsed: syn::File = syn::parse_file(&src)
75 .map_err(|e| format!("{}: parse error: {e}", input.display()))?;
76 items.extend(parsed.items);
77 }
78 let file = syn::File { shebang: None, frontmatter: None, attrs: Vec::new(), items };
Add the differential test runner, and a lowering to measure with it 8ac32af nandithebull 13h ago79
Add enums, Option/Result, `?`, and the machinery base16ct needs around them b0ccd80 nandithebull 13h ago80 let mut lowerer = lower::Lowerer::new();
81 lowerer.features = features;
82 let nim = lowerer.lower_file(&file)?;
Add the differential test runner, and a lowering to measure with it 8ac32af nandithebull 13h ago83
84 match output {
85 Some(p) => std::fs::write(&p, nim)
86 .map_err(|e| format!("cannot write {}: {e}", p.display()))?,
87 None => print!("{nim}"),
88 }
89 Ok(())
90}