diff --git a/Cargo.lock b/Cargo.lock index fc50f5d9..d8361c72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,6 +70,15 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bytecount" version = "0.6.3" @@ -139,6 +148,7 @@ dependencies = [ "nom", "nom_locate", "regex", + "rust-embed", "serde", "serde_json", ] @@ -152,6 +162,35 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "cpufeatures" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "env_logger" version = "0.10.0" @@ -208,6 +247,16 @@ dependencies = [ "syn", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "gimli" version = "0.27.2" @@ -431,6 +480,40 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bf2521270932c3c7bed1a59151222bd7643c79310f2916f01925e1e16255698" +[[package]] +name = "rust-embed" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b68543d5527e158213414a92832d2aab11a84d2571a5eb021ebe22c43aab066" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "6.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4e0f0ced47ded9a68374ac145edd65a6c1fa13a96447b873660b2a568a0fd7" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "7.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512b0ab6853f7e14e3c8754acb43d6f748bb9ced66aa5915a6553ac8213f7731" +dependencies = [ + "sha2", + "walkdir", +] + [[package]] name = "rustc-demangle" version = "0.1.22" @@ -457,6 +540,15 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "serde" version = "1.0.156" @@ -488,6 +580,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "smallvec" version = "1.10.0" @@ -520,6 +623,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + [[package]] name = "unicode-ident" version = "1.0.8" @@ -538,6 +647,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/rust/compiler/Cargo.toml b/rust/compiler/Cargo.toml index 2ea53b6c..a424fa35 100644 --- a/rust/compiler/Cargo.toml +++ b/rust/compiler/Cargo.toml @@ -22,3 +22,4 @@ genco = "0.17.3" convert_case = "0.6.0" backtrace-on-stack-overflow = "0.3.0" regex = "1.7.3" +rust-embed = "6.6.1" diff --git a/rust/compiler/src/adlstdlib/mod.rs b/rust/compiler/src/adlstdlib/mod.rs new file mode 100644 index 00000000..0dd8f36b --- /dev/null +++ b/rust/compiler/src/adlstdlib/mod.rs @@ -0,0 +1,54 @@ +use std::path::PathBuf; +use std::borrow::Cow; + +use anyhow::anyhow; + +use rust_embed::RustEmbed; + +use crate::adlgen::sys::adlast2::ModuleName; + +#[derive(RustEmbed)] +#[folder = "../../adl/stdlib/"] +struct Asset; + +pub fn std_modules() -> Vec { + let mut mods = vec![]; + for name in Asset::iter() { + let mut path = PathBuf::from(name.to_string()); + if let Some(e) = path.extension() { + if e == "adl" { + path.set_extension(""); + mods.push(path.to_str().unwrap().replace("/", ".")); + } + } + }; + mods +} + +pub fn get_stdlib(mn: &ModuleName, ext: &str) -> Option> { + let mut fname = mn.replace(".", "/"); + fname.push_str(".adl"); + if ext != "" { + fname.push_str("-"); + fname.push_str(ext); + } + if let Some(f) = Asset::get(fname.as_str()) { + return Some(f.data); + } + None +} + +pub(crate) fn dump(opts: &crate::cli::DumpStdlibOpts) -> Result<(), anyhow::Error> { + std::fs::create_dir_all(&opts.outputdir).map_err(|_| anyhow!("can't create output dir '{:?}'", opts.outputdir))?; + for name in Asset::iter() { + let mut path = opts.outputdir.clone(); + path.push(name.as_ref()); + if let Some(data) = Asset::get(name.as_ref()) { + std::fs::create_dir_all(path.parent().unwrap()).map_err(|_| anyhow!("can't create output dir for '{:?}'", &path))?; + std::fs::write(&path, data.data.as_ref()).map_err(|s| anyhow!("can't write file '{:?}' error {}", &path, s))?; + } else { + return Err(anyhow!("could get the contents for {}", name)); + } + } + Ok(()) +} \ No newline at end of file diff --git a/rust/compiler/src/cli/mod.rs b/rust/compiler/src/cli/mod.rs index ba282116..839e5a6b 100644 --- a/rust/compiler/src/cli/mod.rs +++ b/rust/compiler/src/cli/mod.rs @@ -7,10 +7,6 @@ pub mod rust; pub mod tsgen; pub mod verify; - - - - pub fn run_cli() -> i32 { let cli = Cli::parse(); @@ -19,6 +15,7 @@ pub fn run_cli() -> i32 { Command::Ast(opts) => ast::ast(&opts), Command::Rust(opts) => rust::rust(&opts), Command::Tsgen(opts) => tsgen::tsgen(&opts), + Command::WriteStdlib(opts) => crate::adlstdlib::dump(&opts), }; match r { Ok(_) => 0, @@ -48,7 +45,17 @@ pub enum Command { /// generate rust code for the some ADL modules Rust(RustOpts), /// generate typescript code for the some ADL modules + #[clap(name="typescript")] Tsgen(TsOpts), + /// dump the embedded stdlib to the filesystem. + WriteStdlib(DumpStdlibOpts), +} + +#[derive(Debug, Args)] +pub struct DumpStdlibOpts { + /// writes generated code to the specified directory + #[arg(long, short='O', value_name="DIR")] + pub outputdir: PathBuf, } #[derive(Debug, Args)] diff --git a/rust/compiler/src/cli/tsgen/mod.rs b/rust/compiler/src/cli/tsgen/mod.rs index fb676b79..f400b553 100644 --- a/rust/compiler/src/cli/tsgen/mod.rs +++ b/rust/compiler/src/cli/tsgen/mod.rs @@ -73,8 +73,9 @@ pub fn tsgen(opts: &TsOpts) -> anyhow::Result<()> { let mut writer = TreeWriter::new(opts.output.outputdir.clone(), manifest)?; if !opts.include_rt { - if opts.runtime_dir == None || opts.ts_style == None { - return Err(anyhow!("Invalid flags; --runtime-dir and --ts-style only valid if --include-runtime is set")); + if opts.runtime_dir == None { + eprintln!("Invalid flags; --runtime-dir only valid if --include-rt is set"); + // return Err(anyhow!("Invalid flags; --runtime-dir only valid if --include-rt is set")); } } diff --git a/rust/compiler/src/lib.rs b/rust/compiler/src/lib.rs index 8190532a..fde53686 100644 --- a/rust/compiler/src/lib.rs +++ b/rust/compiler/src/lib.rs @@ -4,5 +4,6 @@ pub mod cli; pub mod parser; pub mod processing; pub mod utils; +pub mod adlstdlib; mod adlgen_dev; \ No newline at end of file diff --git a/rust/compiler/src/processing/loader.rs b/rust/compiler/src/processing/loader.rs index 13dccdf7..9f3bba4c 100644 --- a/rust/compiler/src/processing/loader.rs +++ b/rust/compiler/src/processing/loader.rs @@ -27,17 +27,24 @@ pub trait AdlLoader { /// Combines a bunch of loaders pub struct MultiLoader { + embedded: EmbeddedStdlibLoader, loaders: Vec>, } impl MultiLoader { pub fn new(loaders: Vec>) -> Self { - MultiLoader { loaders } + MultiLoader { + embedded: EmbeddedStdlibLoader {}, + loaders, + } } } impl AdlLoader for MultiLoader { fn load(&mut self, module_name: &adlast::ModuleName) -> Result, anyhow::Error> { + if let Some(module) = self.embedded.load(module_name)? { + return Ok(Some(module)); + } for loader in &mut self.loaders { if let Some(module) = loader.load(module_name)? { return Ok(Some(module)); @@ -47,6 +54,20 @@ impl AdlLoader for MultiLoader { } } +pub struct EmbeddedStdlibLoader {} + +impl AdlLoader for EmbeddedStdlibLoader { + fn load(&mut self, module_name: &adlast::ModuleName) -> Result, anyhow::Error> { + match crate::adlstdlib::get_stdlib(module_name, "") { + Some(data) => match std::str::from_utf8(data.as_ref()) { + Ok(content) => return parse(&content).map(|m| Some(m)), + Err(err) => return Err(anyhow::Error::from(err)), + }, + None => return Ok(None), + } + } +} + pub struct DirTreeLoader { root: PathBuf, }