nandi/rustnimpublic Fork 0
8ac32afd8fe6eb71bb6de56905986a93ee2cde00
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.

Add the differential test runner, and a lowering to measure with it 8ac32af · on 8ac32afd8fe6eb71bb6de56905986a93ee2cde00 · nandithebull · 15h ago
main.rs · 68 lines · 2.0 KBRust Blame HistoryRaw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//! rustnim — Rust -> Nim transpiler.
//!
//! Usage: rustnim <input.rs> [-o <output.nim>]

mod fmt;
mod lower;
mod ty;

use std::path::PathBuf;
use std::process::ExitCode;

fn main() -> ExitCode {
    match run() {
        Ok(()) => ExitCode::SUCCESS,
        Err(e) => {
            eprintln!("rustnim: {e}");
            // Exiting non-zero on any failure is load-bearing: the entire
            // point of this project is that a transpiler must never report
            // success for work it did not do.
            ExitCode::FAILURE
        }
    }
}

fn run() -> Result<(), String> {
    let mut args = std::env::args_os().skip(1);
    let mut input: Option<PathBuf> = None;
    let mut output: Option<PathBuf> = None;

    while let Some(a) = args.next() {
        match a.to_string_lossy().as_ref() {
            "-o" | "--output" => {
                output = Some(
                    args.next()
                        .ok_or("`-o` needs a path")?
                        .into(),
                );
            }
            "-h" | "--help" => {
                println!("usage: rustnim <input.rs> [-o <output.nim>]");
                return Ok(());
            }
            s if s.starts_with('-') => return Err(format!("unknown flag `{s}`")),
            _ => {
                if input.is_some() {
                    return Err("more than one input file given".into());
                }
                input = Some(a.into());
            }
        }
    }

    let input = input.ok_or("no input file; usage: rustnim <input.rs> [-o <output.nim>]")?;
    let src = std::fs::read_to_string(&input)
        .map_err(|e| format!("cannot read {}: {e}", input.display()))?;

    let file: syn::File = syn::parse_file(&src)
        .map_err(|e| format!("{}: parse error: {e}", input.display()))?;

    let nim = lower::Lowerer::new().lower_file(&file)?;

    match output {
        Some(p) => std::fs::write(&p, nim)
            .map_err(|e| format!("cannot write {}: {e}", p.display()))?,
        None => print!("{nim}"),
    }
    Ok(())
}