forked from adl-lang/adl
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
196 additions
and
115 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
use super::RustOpts; | ||
use std::collections::{HashMap, HashSet}; | ||
use std::path::PathBuf; | ||
|
||
|
||
use crate::adlgen::sys::adlast2::{self as adlast, PrimitiveType}; | ||
use crate::processing::resolver::{Module1, Resolver, TypeExpr1}; | ||
use crate::processing::writer::TreeWriter; | ||
|
||
use crate::cli::rust::rsfile::RSFile; | ||
use crate::fmtln; | ||
|
||
|
||
/// Generate the tree of mod.rs files that link together the generated code | ||
pub fn gen_rs_mod_files(opts: &RustOpts, resolver: &Resolver, writer: &mut TreeWriter) -> anyhow::Result<()> { | ||
|
||
// build a map of parent rust modules and their children | ||
let mut modfiles: HashMap<Vec<String>,HashSet<String>> = HashMap::new(); | ||
for m in resolver.get_module_names() { | ||
let msplit: Vec<&str> = m.split(".").collect(); | ||
for i in 0..msplit.len() { | ||
let rsmod = msplit.get(i).unwrap(); | ||
let parent = &msplit[0..i]; | ||
let parent: Vec<String> = parent.iter().map(|m| m.to_string()).collect(); | ||
let e = modfiles.entry(parent).or_default(); | ||
e.insert(rsmod.to_string()); | ||
} | ||
} | ||
|
||
for (rsmod,children) in modfiles { | ||
let mut path = PathBuf::new(); | ||
path.push(opts.module.clone()); | ||
for el in rsmod { | ||
path.push(el); | ||
} | ||
path.push("mod.rs"); | ||
let lines: Vec<String> = children | ||
.iter() | ||
.map( |m| format!("pub mod {};", m)) | ||
.collect(); | ||
writer.write(&path, lines.join("\n"))? | ||
}; | ||
Ok(()) | ||
} | ||
|
||
pub fn gen_module(m: &Module1) -> anyhow::Result<String> { | ||
let mut out = RSFile::new(); | ||
|
||
for d in m.decls.iter() { | ||
match &d.r#type { | ||
adlast::DeclType::Struct(s) => gen_struct(m, d, &s, &mut out)?, | ||
_ => {} | ||
} | ||
} | ||
Ok(out.to_string()) | ||
} | ||
|
||
|
||
fn gen_struct( | ||
_m: &Module1, | ||
d: &adlast::Decl<TypeExpr1>, | ||
s: &adlast::Struct<TypeExpr1>, | ||
out: &mut RSFile, | ||
) -> anyhow::Result<()> { | ||
fmtln!(out, "pub struct {} {{", d.name); | ||
for f in &s.fields { | ||
fmtln!(out, " {}: {};", f.name, gen_type_expr(&f.type_expr)); | ||
} | ||
fmtln!(out, "}}"); | ||
fmtln!(out, ""); | ||
fmtln!(out, "impl {} {{", d.name); | ||
fmtln!(out, " pub fn new() -> {} {{", d.name); | ||
fmtln!(out, " {} {{", d.name); | ||
fmtln!(out, " }}"); | ||
fmtln!(out, " }}"); | ||
fmtln!(out, "}}"); | ||
fmtln!(out, ""); | ||
Ok(()) | ||
} | ||
|
||
fn gen_type_expr(te: &TypeExpr1) -> String { | ||
match &te.type_ref { | ||
adlast::TypeRef::LocalName(_ln) => "UNIMP.LOCAL_NAME".to_owned(), | ||
adlast::TypeRef::ScopedName(_sn) => "UNIMP.SCOPED_NAME".to_owned(), | ||
adlast::TypeRef::Primitive(p) => gen_primitive_type_expr(p, &te.parameters), | ||
adlast::TypeRef::TypeParam(_t) => "UNIMP.TYPE_PARAM".to_owned(), | ||
} | ||
} | ||
|
||
fn gen_primitive_type_expr(p: &PrimitiveType, _params: &[TypeExpr1]) -> String { | ||
match p { | ||
PrimitiveType::Void => "()".to_owned(), | ||
PrimitiveType::Bool => "bool".to_owned(), | ||
PrimitiveType::Int8 => "i8".to_owned(), | ||
PrimitiveType::Int16 => "i16".to_owned(), | ||
PrimitiveType::Int32 => "i32".to_owned(), | ||
PrimitiveType::Int64 => "i64".to_owned(), | ||
PrimitiveType::Word8 => "u8".to_owned(), | ||
PrimitiveType::Word16 => "u16".to_owned(), | ||
PrimitiveType::Word32 => "u32".to_owned(), | ||
PrimitiveType::Word64 => "u64".to_owned(), | ||
PrimitiveType::Float => "f32".to_owned(), | ||
PrimitiveType::Double => "f64".to_owned(), | ||
PrimitiveType::Json => "UNIMP_JSON".to_owned(), | ||
PrimitiveType::ByteVector => "Vec<u8>".to_owned(), | ||
PrimitiveType::String => "String".to_owned(), | ||
PrimitiveType::Vector => "UNIMP_VECTOR".to_owned(), | ||
PrimitiveType::StringMap => "UNIMP_STRINGMAP".to_owned(), | ||
PrimitiveType::Nullable => "UNIMP_NULLABLE".to_owned(), | ||
PrimitiveType::TypeToken => "UNIMP_TYPETOKEN".to_owned(), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
use super::RustOpts; | ||
use std::path::PathBuf; | ||
|
||
use anyhow::anyhow; | ||
|
||
use crate::adlgen::sys::adlast2::{self as adlast}; | ||
use crate::processing::loader::loader_from_search_paths; | ||
use crate::processing::resolver::{Module1, Resolver}; | ||
use crate::processing::writer::TreeWriter; | ||
|
||
use generate::{gen_module, gen_rs_mod_files}; | ||
|
||
mod rsfile; | ||
mod generate; | ||
|
||
pub fn rust(opts: &RustOpts) -> anyhow::Result<()> { | ||
let loader = loader_from_search_paths(&opts.search.path); | ||
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 mut writer = TreeWriter::new( | ||
opts.output.outdir.clone(), | ||
opts.output.manifest.clone(), | ||
)?; | ||
|
||
for m in modules { | ||
let path = path_from_module_name(opts, m.name.to_owned()); | ||
let code = gen_module(m).unwrap(); | ||
writer.write(path.as_path(), code)?; | ||
} | ||
|
||
gen_rs_mod_files(opts, &resolver, &mut writer)?; | ||
|
||
Ok(()) | ||
} | ||
|
||
fn path_from_module_name(opts: &RustOpts, mname: adlast::ModuleName) -> PathBuf { | ||
let mut path = PathBuf::new(); | ||
path.push(opts.module.clone()); | ||
for el in mname.split(".") { | ||
path.push(el); | ||
} | ||
path.set_extension("rs"); | ||
return path; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
|
||
/// In memory representation of a rust file during codegen | ||
pub struct RSFile { | ||
lines: Vec<String>, | ||
} | ||
|
||
impl RSFile { | ||
pub fn new() -> Self { | ||
RSFile{ | ||
lines: Vec::new(), | ||
} | ||
} | ||
|
||
pub fn pushln(&mut self, text: String ) { | ||
self.lines.push(text); | ||
} | ||
|
||
pub fn to_string(&self) -> String { | ||
self.lines.join("\n") | ||
} | ||
} | ||
|
||
#[macro_export] | ||
macro_rules! fmtln { | ||
($dst:expr, $($arg:tt)*) => { | ||
$dst.pushln(format!($($arg)*)) | ||
}; | ||
} |