Skip to content

Commit

Permalink
Added an ast cli command
Browse files Browse the repository at this point in the history
  • Loading branch information
timbod7 committed Dec 8, 2022
1 parent c8be33c commit 8135a06
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 27 deletions.
25 changes: 25 additions & 0 deletions rust/compiler/src/cli/ast.rs
Original file line number Diff line number Diff line change
@@ -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(())
}
35 changes: 35 additions & 0 deletions rust/compiler/src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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)]
Expand All @@ -25,3 +48,15 @@ pub struct VerifyOpts {
#[options(free)]
pub modules: Vec<String>,
}

#[derive(Debug, Options)]
pub struct AstOpts {
#[options(help = "adds the given directory to the ADL search path", meta = "I")]
pub searchdir: Vec<PathBuf>,

#[options(help = "writes the AST to the specified file", meta = "O")]
pub outfile: Option<PathBuf>,

#[options(free)]
pub modules: Vec<String>,
}
23 changes: 6 additions & 17 deletions rust/compiler/src/cli/verify.rs
Original file line number Diff line number Diff line change
@@ -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<PathBuf>) -> Box<dyn AdlLoader> {
let loaders = paths.iter().map(loader_from_dir_tree).collect();
Box::new(MultiLoader::new(loaders))
}

pub fn loader_from_dir_tree(path: &PathBuf) -> Box<dyn AdlLoader> {
Box::new(DirTreeLoader::new(path.clone()))
Ok(())
}
13 changes: 3 additions & 10 deletions rust/compiler/src/main.rs
Original file line number Diff line number Diff line change
@@ -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);
}
11 changes: 11 additions & 0 deletions rust/compiler/src/processing/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ use crate::processing::annotations::apply_explicit_annotations;

use super::Module0;


pub fn loader_from_search_paths(paths: &Vec<PathBuf>) -> Box<dyn AdlLoader> {
let loaders = paths.iter().map(loader_from_dir_tree).collect();
Box::new(MultiLoader::new(loaders))
}

pub fn loader_from_dir_tree(path: &PathBuf) -> Box<dyn AdlLoader> {
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<Option<Module0>, anyhow::Error>;
Expand Down
1 change: 1 addition & 0 deletions rust/compiler/src/processing/primitives.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[derive(serde::Serialize)]
pub enum PrimitiveType {
Void,
Bool,
Expand Down
6 changes: 6 additions & 0 deletions rust/compiler/src/processing/resolver.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use serde::Serialize;
use std::collections::{HashMap, HashSet};

use crate::adlgen::sys::adlast2 as adlast;
Expand All @@ -24,6 +25,7 @@ pub type Decl1 = adlast::Decl<TypeExpr1>;
pub type Module1 = adlast::Module<TypeExpr1>;
pub type ModuleName = adlast::ModuleName;

#[derive(Serialize)]
pub enum TypeRef {
ScopedName(adlast::ScopedName),
Primitive(PrimitiveType),
Expand Down Expand Up @@ -91,6 +93,10 @@ impl Resolver {
Ok(())
}

pub fn get_module_names(&self) -> Vec<ModuleName> {
self.modules.keys().cloned().collect()
}

pub fn get_module(&self, module_name: &ModuleName) -> Option<&Module1> {
self.modules.get(module_name)
}
Expand Down

0 comments on commit 8135a06

Please sign in to comment.