From 8135a066901b5e56d283c06763cc75d3a1be2896 Mon Sep 17 00:00:00 2001 From: Tim Docker Date: Thu, 8 Dec 2022 13:36:29 +1300 Subject: [PATCH] Added an ast cli command --- rust/compiler/src/cli/ast.rs | 25 ++++++++++++++++ rust/compiler/src/cli/mod.rs | 35 ++++++++++++++++++++++ rust/compiler/src/cli/verify.rs | 23 ++++---------- rust/compiler/src/main.rs | 13 ++------ rust/compiler/src/processing/loader.rs | 11 +++++++ rust/compiler/src/processing/primitives.rs | 1 + rust/compiler/src/processing/resolver.rs | 6 ++++ 7 files changed, 87 insertions(+), 27 deletions(-) create mode 100644 rust/compiler/src/cli/ast.rs diff --git a/rust/compiler/src/cli/ast.rs b/rust/compiler/src/cli/ast.rs new file mode 100644 index 00000000..39693152 --- /dev/null +++ b/rust/compiler/src/cli/ast.rs @@ -0,0 +1,25 @@ +use super::AstOpts; + +use anyhow::anyhow; + +use crate::processing::loader::loader_from_search_paths; +use crate::processing::resolver::{Module1, Resolver}; + +pub fn ast(opts: &AstOpts) -> anyhow::Result<()> { + let loader = loader_from_search_paths(&opts.searchdir); + let mut resolver = Resolver::new(loader); + for m in &opts.modules { + let r = resolver.add_module(m); + match r { + Ok(()) => (), + Err(e) => return Err(anyhow!("Failed to load module {}: {:?}", m, e)), + } + } + let modules: Vec<&Module1> = resolver + .get_module_names() + .into_iter() + .map(|mn| resolver.get_module(&mn).unwrap()) + .collect(); + println!("{}", serde_json::to_string_pretty(&modules).unwrap()); + Ok(()) +} diff --git a/rust/compiler/src/cli/mod.rs b/rust/compiler/src/cli/mod.rs index 6d1e0ebe..2d8af122 100644 --- a/rust/compiler/src/cli/mod.rs +++ b/rust/compiler/src/cli/mod.rs @@ -1,8 +1,29 @@ use gumdrop::Options; use std::path::PathBuf; +pub mod ast; pub mod verify; +pub fn run_cli() -> i32 { + let opts = CliOptions::parse_args_default_or_exit(); + + let r = match opts.command { + None => { + println!("{}", CliOptions::self_usage(&opts)); + Ok(()) + } + Some(Command::Verify(opts)) => verify::verify(&opts), + Some(Command::Ast(opts)) => ast::ast(&opts), + }; + match r { + Ok(_) => 0, + Err(err) => { + eprintln!("Error: {}", err); + 1 + } + } +} + // Define options for the program. #[derive(Debug, Options)] pub struct CliOptions { @@ -16,6 +37,8 @@ pub struct CliOptions { pub enum Command { #[options(help = "verify ADL")] Verify(VerifyOpts), + #[options(help = "generate the json AST for some ADL")] + Ast(AstOpts), } #[derive(Debug, Options)] @@ -25,3 +48,15 @@ pub struct VerifyOpts { #[options(free)] pub modules: Vec, } + +#[derive(Debug, Options)] +pub struct AstOpts { + #[options(help = "adds the given directory to the ADL search path", meta = "I")] + pub searchdir: Vec, + + #[options(help = "writes the AST to the specified file", meta = "O")] + pub outfile: Option, + + #[options(free)] + pub modules: Vec, +} diff --git a/rust/compiler/src/cli/verify.rs b/rust/compiler/src/cli/verify.rs index d0338edd..d87e5762 100644 --- a/rust/compiler/src/cli/verify.rs +++ b/rust/compiler/src/cli/verify.rs @@ -1,29 +1,18 @@ -use std::path::PathBuf; - use super::VerifyOpts; -use crate::processing::{ - loader::{AdlLoader, DirTreeLoader, MultiLoader}, - resolver::Resolver, -}; +use anyhow::anyhow; + +use crate::processing::{loader::loader_from_search_paths, resolver::Resolver}; -pub fn verify(opts: &VerifyOpts) { +pub fn verify(opts: &VerifyOpts) -> anyhow::Result<()> { let loader = loader_from_search_paths(&opts.searchdir); let mut resolver = Resolver::new(loader); for m in &opts.modules { let r = resolver.add_module(m); match r { Ok(()) => println!("Verified module {}", m), - Err(e) => println!("Failed to verify module {}: {:?}", m, e), + Err(e) => return Err(anyhow!("Failed to verify module {}: {:?}", m, e)), } } -} - -pub fn loader_from_search_paths(paths: &Vec) -> Box { - let loaders = paths.iter().map(loader_from_dir_tree).collect(); - Box::new(MultiLoader::new(loaders)) -} - -pub fn loader_from_dir_tree(path: &PathBuf) -> Box { - Box::new(DirTreeLoader::new(path.clone())) + Ok(()) } diff --git a/rust/compiler/src/main.rs b/rust/compiler/src/main.rs index e7fd3b65..9ea4c0f4 100644 --- a/rust/compiler/src/main.rs +++ b/rust/compiler/src/main.rs @@ -1,13 +1,6 @@ -use compiler::cli::{CliOptions, Command}; -use gumdrop::Options; - -use compiler::cli::verify::verify; +use compiler::cli::run_cli; fn main() { - let opts = CliOptions::parse_args_default_or_exit(); - - match opts.command { - None => println!("{}", CliOptions::self_usage(&opts)), - Some(Command::Verify(opts)) => verify(&opts), - } + let exit_code = run_cli(); + std::process::exit(exit_code); } diff --git a/rust/compiler/src/processing/loader.rs b/rust/compiler/src/processing/loader.rs index 6836ed46..37a073a0 100644 --- a/rust/compiler/src/processing/loader.rs +++ b/rust/compiler/src/processing/loader.rs @@ -11,6 +11,17 @@ use crate::processing::annotations::apply_explicit_annotations; use super::Module0; + +pub fn loader_from_search_paths(paths: &Vec) -> Box { + let loaders = paths.iter().map(loader_from_dir_tree).collect(); + Box::new(MultiLoader::new(loaders)) +} + +pub fn loader_from_dir_tree(path: &PathBuf) -> Box { + Box::new(DirTreeLoader::new(path.clone())) +} + + pub trait AdlLoader { /// Find and load the specified ADL module fn load(&mut self, module_name: &adlast::ModuleName) -> Result, anyhow::Error>; diff --git a/rust/compiler/src/processing/primitives.rs b/rust/compiler/src/processing/primitives.rs index 00c590bb..629f76a0 100644 --- a/rust/compiler/src/processing/primitives.rs +++ b/rust/compiler/src/processing/primitives.rs @@ -1,3 +1,4 @@ +#[derive(serde::Serialize)] pub enum PrimitiveType { Void, Bool, diff --git a/rust/compiler/src/processing/resolver.rs b/rust/compiler/src/processing/resolver.rs index c4276f79..128b777e 100644 --- a/rust/compiler/src/processing/resolver.rs +++ b/rust/compiler/src/processing/resolver.rs @@ -1,3 +1,4 @@ +use serde::Serialize; use std::collections::{HashMap, HashSet}; use crate::adlgen::sys::adlast2 as adlast; @@ -24,6 +25,7 @@ pub type Decl1 = adlast::Decl; pub type Module1 = adlast::Module; pub type ModuleName = adlast::ModuleName; +#[derive(Serialize)] pub enum TypeRef { ScopedName(adlast::ScopedName), Primitive(PrimitiveType), @@ -91,6 +93,10 @@ impl Resolver { Ok(()) } + pub fn get_module_names(&self) -> Vec { + self.modules.keys().cloned().collect() + } + pub fn get_module(&self, module_name: &ModuleName) -> Option<&Module1> { self.modules.get(module_name) }