use std::io;
use case::CaseExt;
use crate::{ast, C_API_VERSION_MIN, VERSION};
#[macro_use]
mod utilities;
mod import;
mod builder;
mod reader;
use self::{builder::GenBuilder, import::GenImport, reader::GenReader};
pub(crate) struct Generator;
impl Generator {
fn title<W: io::Write>(writer: &mut W, title: &str) -> io::Result<()> {
writeln!(writer, "/*")?;
writeln!(writer, " * {}", title)?;
writeln!(writer, " */")?;
writeln!(writer)
}
fn ifndef<W: io::Write>(o: &mut W, name: &str) -> io::Result<()> {
let n = name.to_snake().to_uppercase();
let api_decorator = utilities::API_DECORATOR;
w!(o, "#ifndef {}_H ", n);
w!(o, "#define {}_H ", n);
w!(o, " ");
w!(o, "#ifdef __cplusplus ");
w!(o, "extern \"C\" {{ ");
w!(o, "#endif /* __cplusplus */ ");
w!(o, " ");
w!(o, "#ifndef {} ", api_decorator);
w!(o, "#define __DEFINE_MOLECULE_API_DECORATOR_{} ", n);
w!(o, "#define {} ", api_decorator);
w!(o, "#endif /* {} */ ", api_decorator);
Ok(())
}
fn endif<W: io::Write>(o: &mut W, name: &str) -> io::Result<()> {
let n = name.to_snake().to_uppercase();
let api_decorator = utilities::API_DECORATOR;
w!(o, " ");
w!(o, "#ifdef __DEFINE_MOLECULE_API_DECORATOR_{} ", n);
w!(o, "#undef {} ", api_decorator);
w!(o, "#undef __DEFINE_MOLECULE_API_DECORATOR_{} ", n);
w!(o, "#endif /* __DEFINE_MOLECULE_API_DECORATOR_{} */ ", n);
w!(o, " ");
w!(o, "#ifdef __cplusplus ");
w!(o, "}} ");
w!(o, "#endif /* __cplusplus */ ");
w!(o, " ");
w!(o, "#endif /* {}_H */ ", n);
Ok(())
}
fn define_version<W: io::Write>(o: &mut W) -> io::Result<()> {
let molc_ver = semver::Version::parse(VERSION)
.map(|v| (v.major * 1000 + v.minor) * 1000 + v.patch)
.unwrap();
let api_ver_min = semver::Version::parse(C_API_VERSION_MIN)
.map(|v| (v.major * 1000 + v.minor) * 1000 + v.patch)
.unwrap();
w!(o, "#define MOLECULEC_VERSION {} ", molc_ver);
w!(o, "#define MOLECULE_API_VERSION_MIN {} ", api_ver_min);
Ok(())
}
}
impl super::LanguageGenerator for Generator {
fn generate<W: io::Write>(writer: &mut W, ast: &ast::Ast) -> io::Result<()> {
writeln!(writer, "// Generated by Molecule {}", VERSION)?;
writeln!(writer)?;
Self::define_version(writer)?;
writeln!(writer)?;
writeln!(writer, r#"#include "molecule_reader.h""#)?;
writeln!(writer, r#"#include "molecule_builder.h""#)?;
writeln!(writer)?;
Self::ifndef(writer, ast.namespace())?;
let imports = ast.imports();
if !imports.is_empty() {
writeln!(writer)?;
for import in imports {
import.gen_import(writer)?;
}
}
writeln!(writer)?;
Self::title(writer, "Reader APIs")?;
for decl in ast.major_decls() {
decl.gen_reader_interfaces(writer)?;
}
writeln!(writer)?;
Self::title(writer, "Builder APIs")?;
for decl in ast.major_decls() {
decl.gen_builder_interfaces(writer)?;
}
writeln!(writer)?;
Self::title(writer, "Default Value")?;
writeln!(writer, r#"#define ____ 0x00"#)?;
writeln!(writer)?;
for decl in ast.major_decls() {
decl.gen_default(writer)?;
}
writeln!(writer)?;
writeln!(writer, r#"#undef ____"#)?;
writeln!(writer)?;
Self::title(writer, "Reader Functions")?;
for decl in ast.major_decls() {
decl.gen_reader_functions(writer)?;
}
writeln!(writer)?;
Self::title(writer, "Builder Functions")?;
for decl in ast.major_decls() {
decl.gen_builder_functions(writer)?;
}
Self::endif(writer, ast.namespace())?;
Ok(())
}
}