Skip to content

Commit

Permalink
wip: rust generation
Browse files Browse the repository at this point in the history
  • Loading branch information
timbod7 committed Mar 15, 2023
1 parent a4328c6 commit 2d3f3aa
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 0 deletions.
19 changes: 19 additions & 0 deletions rust/compiler/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use gumdrop::Options;
use std::path::PathBuf;

pub mod ast;
pub mod rust;
pub mod verify;

pub fn run_cli() -> i32 {
Expand All @@ -14,6 +15,7 @@ pub fn run_cli() -> i32 {
}
Some(Command::Verify(opts)) => verify::verify(&opts),
Some(Command::Ast(opts)) => ast::ast(&opts),
Some(Command::Rust(opts)) => rust::rust(&opts),
};
match r {
Ok(_) => 0,
Expand All @@ -39,6 +41,8 @@ pub enum Command {
Verify(VerifyOpts),
#[options(help = "generate the json AST for some ADL")]
Ast(AstOpts),
#[options(help = "generate rust code for the specified ADL")]
Rust(RustOpts),
}

#[derive(Debug, Options)]
Expand All @@ -60,3 +64,18 @@ pub struct AstOpts {
#[options(free)]
pub modules: Vec<String>,
}

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

#[options(
help = "writes the generated rust to the specified directory",
meta = "O"
)]
pub outdir: PathBuf,

#[options(free)]
pub modules: Vec<String>,
}
76 changes: 76 additions & 0 deletions rust/compiler/src/cli/rust.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use super::RustOpts;
use std::fmt::Write;
use std::path::PathBuf;

use anyhow::anyhow;

use crate::adlgen::sys::adlast2 as adlast;
use crate::processing::loader::loader_from_search_paths;
use crate::processing::resolver::{Module1, Resolver, TypeExpr1};
use crate::processing::writer::TreeWriter;

pub fn rust(opts: &RustOpts) -> 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();

let writer = TreeWriter::new(opts.outdir.clone());

for m in modules {
let path = path_from_module_name(m.name.to_owned());
let code = generate_code(m).unwrap();
writer.write(path.as_path(), code)?;
}

Ok(())
}

fn path_from_module_name(mname: adlast::ModuleName) -> PathBuf {
let mut path = PathBuf::new();
for el in mname.split(".") {
path.push(el);
}
path.set_extension("rs");
return path;
}

fn generate_code(m: &Module1) -> anyhow::Result<String> {
let mut out = String::new();

for d in m.decls.values() {
match &d.r#type {
adlast::DeclType::Struct(s) => gen_struct(m, d, &s, &mut out)?,
_ => {}
}
}
Ok(out)
}

fn gen_struct(
m: &Module1,
d: &adlast::Decl<TypeExpr1>,
s: &adlast::Struct<TypeExpr1>,
out: &mut String,
) -> anyhow::Result<()> {
write!(out, "struct {} {{\n", d.name)?;
for f in &s.fields {
write!(out, " {}: {};\n", f.name, gen_type_expr(&f.type_expr))?;
}
write!(out, "}}\n\n")?;
Ok(())
}

fn gen_type_expr(te: &TypeExpr1) -> String {
"TYPE".to_owned()
}
1 change: 1 addition & 0 deletions rust/compiler/src/processing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub mod checks;
pub mod loader;
pub mod primitives;
pub mod resolver;
pub mod writer;

pub type TypeExpr0 = adlast::TypeExpr<adlast::ScopedName>;
pub type Module0 = adlast::Module<TypeExpr0>;
Expand Down
22 changes: 22 additions & 0 deletions rust/compiler/src/processing/writer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use std::path::{Path, PathBuf};

pub struct TreeWriter {
pub root_dir: PathBuf,
}

impl TreeWriter {
pub fn new(root_dir: PathBuf) -> Self {
TreeWriter { root_dir }
}

/// Write a file to the specifed path, creating parent directories as required
pub fn write(&self, path: &Path, content: String) -> Result<(), std::io::Error> {
let mut file_path = self.root_dir.clone();
file_path.push(path);
log::info!("writing {}", file_path.display());
let dir_path = file_path.parent().unwrap();
std::fs::create_dir_all(dir_path)?;
std::fs::write(file_path, &content)?;
Ok(())
}
}

0 comments on commit 2d3f3aa

Please sign in to comment.