1use anyhow::Result;2use clap::Parser;3use xshell::{cmd, Shell};45mod sourcegen;67#[derive(Parser)]8enum Opts {9 10 Sourcegen,11 12 Profile {13 #[arg(long, default_value = "true")]14 hyperfine: bool,15 #[arg(long)]16 callgrind: bool,17 #[arg(long)]18 cachegrind: bool,19 #[arg(long, default_value = "x86_64-unknown-linux-gnu")]20 target: String,21 args: Vec<String>,22 },23 24 Lint {25 26 #[arg(long)]27 fix: bool,28 },29}3031fn main() -> Result<()> {32 let sh = Shell::new()?;33 match Opts::parse() {34 Opts::Sourcegen => sourcegen::generate_ungrammar(),35 Opts::Profile {36 hyperfine,37 callgrind,38 cachegrind,39 args,40 target,41 } => {42 let out = sh.create_temp_dir()?;4344 45 cmd!(46 sh,47 "cargo build -Zbuild-std --target={target} --profile releasedebug"48 )49 .run()?;50 let built = format!("./target/{target}/releasedebug/jrsonnet");51 let bench_cmd = format!("{built} {}", args.join(" "));52 if hyperfine {53 cmd!(sh, "hyperfine {bench_cmd}").run()?;54 }55 if callgrind {56 let args = args.clone();57 let mut callgrind_out = out.path().to_owned();58 callgrind_out.push("callgrind.out.1");59 cmd!(sh, "valgrind --tool=callgrind --dump-instr=yes --collect-jumps=yes --callgrind-out-file={callgrind_out} {built} {args...}").run()?;60 cmd!(sh, "kcachegrind {callgrind_out}").run()?;61 }62 if cachegrind {63 let mut cachegrind_out = out.path().to_owned();64 cachegrind_out.push("cachegrind.out.1");65 cmd!(sh, "valgrind --tool=cachegrind --cachegrind-out-file={cachegrind_out} {built} {args...}").run()?;66 cmd!(sh, "kcachegrind {cachegrind_out}").run()?;67 }6869 Ok(())70 }71 Opts::Lint { fix } => {72 let fmt_check = if fix { None } else { Some("--check") };73 cmd!(sh, "cargo fmt {fmt_check...}").run()?;74 Ok(())75 }76 }77}