Use structopt to derive CLI flags
Instead of using `clap` directly
This commit is contained in:
committed by
Chris Fallin
parent
6ffb02d9f6
commit
cfaa35d8c0
77
cranelift/isle/Cargo.lock
generated
77
cranelift/isle/Cargo.lock
generated
@@ -115,6 +115,15 @@ version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
@@ -143,13 +152,19 @@ dependencies = [
|
||||
name = "islec"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"env_logger",
|
||||
"isle",
|
||||
"log",
|
||||
"miette",
|
||||
"structopt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.101"
|
||||
@@ -232,6 +247,30 @@ version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a61765925aec40abdb23812a3a1a01fafc6ffb9da22768b2ce665a9e84e527c"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.29"
|
||||
@@ -285,6 +324,30 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "structopt"
|
||||
version = "0.3.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf9d950ef167e25e0bdb073cf1d68e9ad2795ac826f2f3f59647817cf23c0bfa"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"lazy_static",
|
||||
"structopt-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "structopt-derive"
|
||||
version = "0.4.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "supports-color"
|
||||
version = "1.1.1"
|
||||
@@ -383,6 +446,12 @@ dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.8"
|
||||
@@ -401,6 +470,12 @@ version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
||||
@@ -10,8 +10,14 @@ pub type Result<T> = std::result::Result<T, Error>;
|
||||
#[derive(thiserror::Error, Diagnostic, Clone, Debug)]
|
||||
pub enum Error {
|
||||
/// An I/O error.
|
||||
#[error(transparent)]
|
||||
IoError(Arc<std::io::Error>),
|
||||
#[error("{context}")]
|
||||
IoError {
|
||||
/// The underlying I/O error.
|
||||
#[source]
|
||||
error: Arc<std::io::Error>,
|
||||
/// The context explaining what caused the I/O error.
|
||||
context: String,
|
||||
},
|
||||
|
||||
/// The input ISLE source has a parse error.
|
||||
#[error("parse error: {msg}")]
|
||||
@@ -53,9 +59,13 @@ pub enum Error {
|
||||
Errors(#[related] Vec<Error>),
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(e: std::io::Error) -> Self {
|
||||
Error::IoError(Arc::new(e))
|
||||
impl Error {
|
||||
/// Create a `isle::Error` from the given I/O error and context.
|
||||
pub fn from_io(error: std::io::Error, context: impl Into<String>) -> Self {
|
||||
Error::IoError {
|
||||
error: Arc::new(error),
|
||||
context: context.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
//! Lexer for the ISLE language.
|
||||
|
||||
use crate::error::Result;
|
||||
use crate::error::{Error, Result};
|
||||
use std::borrow::Cow;
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// The lexer.
|
||||
@@ -90,35 +91,36 @@ impl<'a> Lexer<'a> {
|
||||
}
|
||||
|
||||
/// Create a new lexer from the given files.
|
||||
pub fn from_files<S>(filenames: impl IntoIterator<Item = S>) -> Result<Lexer<'a>>
|
||||
pub fn from_files<P>(file_paths: impl IntoIterator<Item = P>) -> Result<Lexer<'a>>
|
||||
where
|
||||
S: AsRef<str>,
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let filenames: Vec<Arc<str>> = filenames.into_iter().map(|f| f.as_ref().into()).collect();
|
||||
assert!(!filenames.is_empty());
|
||||
let mut filenames = Vec::<Arc<str>>::new();
|
||||
let mut file_texts = Vec::<Arc<str>>::new();
|
||||
|
||||
let file_contents: Vec<Arc<str>> = filenames
|
||||
.iter()
|
||||
.map(|f| {
|
||||
use std::io::Read;
|
||||
let mut f = std::fs::File::open(&**f)?;
|
||||
let mut s = String::new();
|
||||
f.read_to_string(&mut s)?;
|
||||
Ok(s.into())
|
||||
})
|
||||
.collect::<Result<_>>()?;
|
||||
for f in file_paths {
|
||||
let f = f.as_ref();
|
||||
|
||||
filenames.push(f.display().to_string().into());
|
||||
|
||||
let s = std::fs::read_to_string(f)
|
||||
.map_err(|e| Error::from_io(e, format!("failed to read file: {}", f.display())))?;
|
||||
file_texts.push(s.into());
|
||||
}
|
||||
|
||||
assert!(!filenames.is_empty());
|
||||
|
||||
let mut file_starts = vec![];
|
||||
let mut buf = String::new();
|
||||
for file in &file_contents {
|
||||
for text in &file_texts {
|
||||
file_starts.push(buf.len());
|
||||
buf += &file;
|
||||
buf += &text;
|
||||
buf += "\n";
|
||||
}
|
||||
|
||||
let mut l = Lexer {
|
||||
filenames,
|
||||
file_texts: file_contents,
|
||||
file_texts,
|
||||
buf: Cow::Owned(buf.into_bytes()),
|
||||
file_starts,
|
||||
pos: Pos {
|
||||
|
||||
@@ -9,5 +9,5 @@ license = "Apache-2.0 WITH LLVM-exception"
|
||||
log = "0.4"
|
||||
isle = { version = "*", path = "../isle/" }
|
||||
env_logger = { version = "0.8", default-features = false }
|
||||
clap = "2.33"
|
||||
miette = { version = "3.0.0", features = ["fancy"] }
|
||||
structopt = "0.3.23"
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
use clap::{App, Arg};
|
||||
use isle::{compile, lexer, parser};
|
||||
use miette::{IntoDiagnostic, Result};
|
||||
use miette::{Context, IntoDiagnostic, Result};
|
||||
use std::{
|
||||
fs,
|
||||
io::{self, Write},
|
||||
path::PathBuf,
|
||||
};
|
||||
use structopt::StructOpt;
|
||||
|
||||
#[derive(StructOpt)]
|
||||
struct Opts {
|
||||
/// The output file to write the generated Rust code to. `stdout` is used if
|
||||
/// this is not given.
|
||||
#[structopt(short, long, parse(from_os_str))]
|
||||
output: Option<PathBuf>,
|
||||
|
||||
/// The input ISLE DSL source files.
|
||||
#[structopt(parse(from_os_str))]
|
||||
inputs: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let _ = env_logger::try_init();
|
||||
@@ -15,46 +32,33 @@ fn main() -> Result<()> {
|
||||
)
|
||||
}));
|
||||
|
||||
let matches = App::new("isle")
|
||||
.version(env!("CARGO_PKG_VERSION"))
|
||||
.author("Chris Fallin <chris@cfallin.org>")
|
||||
.about("Instruction selection logic engine (ISLE) code generator")
|
||||
.arg(
|
||||
Arg::with_name("input")
|
||||
.short("i")
|
||||
.long("input")
|
||||
.value_name("FILE.isle")
|
||||
.takes_value(true)
|
||||
.multiple(true)
|
||||
.required(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("output")
|
||||
.short("o")
|
||||
.long("output")
|
||||
.value_name("FILE.rs")
|
||||
.takes_value(true)
|
||||
.required(true),
|
||||
)
|
||||
.get_matches();
|
||||
let opts = Opts::from_args();
|
||||
|
||||
let input_files = matches
|
||||
.values_of("input")
|
||||
.unwrap()
|
||||
.map(|s| s.to_string())
|
||||
.collect::<Vec<_>>();
|
||||
let output_file = matches.value_of("output").unwrap();
|
||||
|
||||
let lexer = lexer::Lexer::from_files(input_files)?;
|
||||
let lexer = lexer::Lexer::from_files(opts.inputs)?;
|
||||
let mut parser = parser::Parser::new(lexer);
|
||||
let defs = parser.parse_defs()?;
|
||||
let code = compile::compile(&defs)?;
|
||||
|
||||
{
|
||||
use std::io::Write;
|
||||
let mut f = std::fs::File::create(output_file).into_diagnostic()?;
|
||||
writeln!(&mut f, "{}", code).into_diagnostic()?;
|
||||
}
|
||||
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)
|
||||
.into_diagnostic()
|
||||
.with_context(|| 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())
|
||||
.into_diagnostic()
|
||||
.with_context(|| format!("failed to write to '{}'", output_name))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user