There were several issues with ISLE's existing error reporting implementation. - When using Miette for more readable error reports, it would panic if errors were reported from multiple files in the same run. - Miette is pretty heavy-weight for what we're doing, with a lot of dependencies. - The `Error::Errors` enum variant led to normalization steps in many places, to avoid using that variant to represent a single error. This commit: - replaces Miette with codespan-reporting - gets rid of a bunch of cargo-vet exemptions - replaces the `Error::Errors` variant with a new `Errors` type - removes source info from `Error` variants so they're easy to construct - adds source info only when formatting `Errors` - formats `Errors` with a custom `Debug` impl - shares common code between ISLE's callers, islec and cranelift-codegen - includes a source snippet even with fancy-errors disabled I tried to make this a series of smaller commits but I couldn't find any good split points; everything was too entangled with everything else.
50 lines
1.3 KiB
Rust
50 lines
1.3 KiB
Rust
use clap::Parser;
|
|
use cranelift_isle::compile;
|
|
use cranelift_isle::error::Errors;
|
|
use std::{
|
|
default::Default,
|
|
fs,
|
|
io::{self, Write},
|
|
path::PathBuf,
|
|
};
|
|
|
|
#[derive(Parser)]
|
|
struct Opts {
|
|
/// The output file to write the generated Rust code to. `stdout` is used if
|
|
/// this is not given.
|
|
#[clap(short, long)]
|
|
output: Option<PathBuf>,
|
|
|
|
/// The input ISLE DSL source files.
|
|
#[clap(required = true)]
|
|
inputs: Vec<PathBuf>,
|
|
}
|
|
|
|
fn main() -> Result<(), Errors> {
|
|
let _ = env_logger::try_init();
|
|
|
|
let opts = Opts::parse();
|
|
let code = compile::from_files(opts.inputs, &Default::default())?;
|
|
|
|
let stdout = io::stdout();
|
|
let (mut output, output_name): (Box<dyn Write>, _) = match &opts.output {
|
|
Some(f) => {
|
|
let output =
|
|
Box::new(fs::File::create(f).map_err(|e| {
|
|
Errors::from_io(e, format!("failed to create '{}'", f.display()))
|
|
})?);
|
|
(output, f.display().to_string())
|
|
}
|
|
None => {
|
|
let output = Box::new(stdout.lock());
|
|
(output, "<stdout>".to_string())
|
|
}
|
|
};
|
|
|
|
output
|
|
.write_all(code.as_bytes())
|
|
.map_err(|e| Errors::from_io(e, format!("failed to write to '{}'", output_name)))?;
|
|
|
|
Ok(())
|
|
}
|