Better compiler API
This commit is contained in:
parent
dd9e190bed
commit
c3bc678a46
|
@ -2,5 +2,8 @@ all:
|
||||||
@echo please use cargo
|
@echo please use cargo
|
||||||
|
|
||||||
regenerate:
|
regenerate:
|
||||||
cargo run -- -o $(CURDIR)/src --prefix schema ../../../schema/schema.bin > src/metaschema.rs.tmp
|
cargo run -- \
|
||||||
mv src/metaschema.rs.tmp src/metaschema.rs
|
--prefix crate::gen \
|
||||||
|
--support-crate crate \
|
||||||
|
-o $(CURDIR)/src/gen \
|
||||||
|
../../../schema/schema.bin
|
||||||
|
|
|
@ -1,15 +1,8 @@
|
||||||
use glob::glob;
|
|
||||||
use preserves::value::packed::PackedReader;
|
|
||||||
use preserves::value::Reader;
|
|
||||||
use std::convert::TryFrom;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
use std::io::ErrorKind;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
use preserves_schema::compiler::{CompilerConfig, compile};
|
use preserves_schema::compiler::{CompilerConfig, compile, expand_inputs};
|
||||||
use preserves_schema::metaschema::*;
|
|
||||||
|
|
||||||
#[derive(Clone, StructOpt, Debug)]
|
#[derive(Clone, StructOpt, Debug)]
|
||||||
struct CommandLine {
|
struct CommandLine {
|
||||||
|
@ -17,59 +10,20 @@ struct CommandLine {
|
||||||
output_dir: PathBuf,
|
output_dir: PathBuf,
|
||||||
|
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
prefix: Option<String>,
|
prefix: String,
|
||||||
|
|
||||||
|
#[structopt(long)]
|
||||||
|
support_crate: Option<String>,
|
||||||
|
|
||||||
input_glob: Vec<String>,
|
input_glob: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inputs(globs: &Vec<String>) -> Vec<PathBuf> {
|
|
||||||
let mut result = Vec::new();
|
|
||||||
for g in globs.iter() {
|
|
||||||
match glob(g) {
|
|
||||||
Ok(paths) =>
|
|
||||||
for p in paths {
|
|
||||||
match p {
|
|
||||||
Ok(s) => result.push(s),
|
|
||||||
Err(e) => println!("warning: {:?}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => println!("warning: {:?}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
fn main() -> Result<(), Error> {
|
||||||
let args = CommandLine::from_args();
|
let args = CommandLine::from_args();
|
||||||
|
let mut config = CompilerConfig::new(args.output_dir, args.prefix);
|
||||||
let prefix = match &args.prefix {
|
if let Some(c) = args.support_crate {
|
||||||
Some(s) => s.split(".").map(str::to_string).collect(),
|
config.support_crate = c;
|
||||||
None => vec![],
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut config = CompilerConfig::new(args.output_dir);
|
|
||||||
|
|
||||||
for i in inputs(&args.input_glob) {
|
|
||||||
let mut f = File::open(&i)?;
|
|
||||||
let mut reader = PackedReader::decode_read(&mut f);
|
|
||||||
let schema = reader.demand_next(false)?;
|
|
||||||
match Schema::try_from(&schema) {
|
|
||||||
Ok(s) => {
|
|
||||||
config.bundle.insert(prefix.clone(), s);
|
|
||||||
()
|
|
||||||
},
|
|
||||||
Err(()) => match Bundle::try_from(&schema) {
|
|
||||||
Ok(Bundle { modules }) => {
|
|
||||||
for (ModulePath(k), v) in modules.0 {
|
|
||||||
let mut name = prefix.clone();
|
|
||||||
name.extend(k);
|
|
||||||
config.bundle.insert(name, v);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(()) => return Err(ErrorKind::InvalidData)?,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
config.load_schemas_and_bundles(&expand_inputs(&args.input_glob)?)?;
|
||||||
compile(&config)
|
compile(&config)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,20 @@
|
||||||
use preserves::value::{Map, IOValue};
|
use preserves::value::{Map, IOValue};
|
||||||
|
|
||||||
use crate::syntax::block::Item;
|
use crate::syntax::block::Item;
|
||||||
|
use crate::syntax::block::constructors::*;
|
||||||
|
|
||||||
|
use super::CompilerConfig;
|
||||||
use super::types;
|
use super::types;
|
||||||
|
|
||||||
pub struct ModuleContext {
|
pub struct ModuleContext<'m> {
|
||||||
|
pub config: &'m CompilerConfig,
|
||||||
pub literals: Map<IOValue, String>,
|
pub literals: Map<IOValue, String>,
|
||||||
pub typedefs: Vec<Item>,
|
pub typedefs: Vec<Item>,
|
||||||
pub functiondefs: Vec<Item>,
|
pub functiondefs: Vec<Item>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FunctionContext<'a> {
|
pub struct FunctionContext<'a, 'm> {
|
||||||
pub m: &'a mut ModuleContext,
|
pub m: &'a mut ModuleContext<'m>,
|
||||||
pub temp_counter: usize,
|
pub temp_counter: usize,
|
||||||
pub captures: Vec<Capture>,
|
pub captures: Vec<Capture>,
|
||||||
}
|
}
|
||||||
|
@ -22,9 +25,10 @@ pub struct Capture {
|
||||||
pub source_expr: String,
|
pub source_expr: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleContext {
|
impl<'m> ModuleContext<'m> {
|
||||||
pub fn new() -> Self {
|
pub fn new(config: &'m CompilerConfig) -> Self {
|
||||||
ModuleContext {
|
ModuleContext {
|
||||||
|
config: config,
|
||||||
literals: Map::new(),
|
literals: Map::new(),
|
||||||
typedefs: Vec::new(),
|
typedefs: Vec::new(),
|
||||||
functiondefs: Vec::new(),
|
functiondefs: Vec::new(),
|
||||||
|
@ -44,10 +48,22 @@ impl ModuleContext {
|
||||||
let i = f(FunctionContext::new(self));
|
let i = f(FunctionContext::new(self));
|
||||||
self.functiondefs.push(i)
|
self.functiondefs.push(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn render_ref(&self, mp: Vec<String>, n: String) -> Item {
|
||||||
|
if mp.len() == 0 {
|
||||||
|
item(n)
|
||||||
|
} else {
|
||||||
|
let mut items = Vec::new();
|
||||||
|
items.push(item(self.config.fully_qualified_module_prefix.to_owned()));
|
||||||
|
for p in mp { items.push(item(p)); }
|
||||||
|
items.push(item(n));
|
||||||
|
item(name(items))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FunctionContext<'a> {
|
impl<'a, 'm> FunctionContext<'a, 'm> {
|
||||||
pub fn new(m: &'a mut ModuleContext) -> Self {
|
pub fn new(m: &'a mut ModuleContext<'m>) -> Self {
|
||||||
FunctionContext {
|
FunctionContext {
|
||||||
m: m,
|
m: m,
|
||||||
temp_counter: 0,
|
temp_counter: 0,
|
||||||
|
|
|
@ -5,11 +5,25 @@ pub mod parsers;
|
||||||
pub mod unparsers;
|
pub mod unparsers;
|
||||||
pub mod codegen;
|
pub mod codegen;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use crate::gen::schema::*;
|
||||||
use preserves::value::Map;
|
use crate::syntax::block::Formatter;
|
||||||
|
|
||||||
use crate::syntax::block::constructors::*;
|
use crate::syntax::block::constructors::*;
|
||||||
use crate::metaschema::*;
|
|
||||||
|
use glob::glob;
|
||||||
|
use preserves::value::Map;
|
||||||
|
use preserves::value::PackedReader;
|
||||||
|
use preserves::value::Reader;
|
||||||
|
use preserves::value::Set;
|
||||||
|
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
use std::fs::DirBuilder;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::BufRead;
|
||||||
|
use std::io::BufReader;
|
||||||
|
use std::io::Error;
|
||||||
|
use std::io::ErrorKind;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
pub type ModulePath = Vec<String>;
|
pub type ModulePath = Vec<String>;
|
||||||
|
|
||||||
|
@ -17,15 +31,60 @@ pub type ModulePath = Vec<String>;
|
||||||
pub struct CompilerConfig {
|
pub struct CompilerConfig {
|
||||||
pub bundle: Map<ModulePath, Schema>,
|
pub bundle: Map<ModulePath, Schema>,
|
||||||
pub output_dir: PathBuf,
|
pub output_dir: PathBuf,
|
||||||
|
pub fully_qualified_module_prefix: String,
|
||||||
|
pub support_crate: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompilerConfig {
|
impl CompilerConfig {
|
||||||
pub fn new(output_dir: PathBuf) -> Self {
|
pub fn new(
|
||||||
|
output_dir: PathBuf,
|
||||||
|
fully_qualified_module_prefix: String,
|
||||||
|
) -> Self {
|
||||||
CompilerConfig {
|
CompilerConfig {
|
||||||
bundle: Map::new(),
|
bundle: Map::new(),
|
||||||
output_dir: output_dir,
|
output_dir: output_dir,
|
||||||
|
fully_qualified_module_prefix: fully_qualified_module_prefix,
|
||||||
|
support_crate: "preserves_schema".to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn load_schemas_and_bundles(&mut self, inputs: &Vec<PathBuf>) -> Result<(), Error> {
|
||||||
|
for i in inputs {
|
||||||
|
let mut f = File::open(&i)?;
|
||||||
|
let mut reader = PackedReader::decode_read(&mut f);
|
||||||
|
let blob = reader.demand_next(false)?;
|
||||||
|
|
||||||
|
if let Ok(s) = Schema::try_from(&blob) {
|
||||||
|
let prefix = i.file_stem().ok_or_else(
|
||||||
|
|| Error::new(ErrorKind::InvalidData, format!("Bad schema file stem: {:?}", i)))?
|
||||||
|
.to_str().ok_or_else(
|
||||||
|
|| Error::new(ErrorKind::InvalidData, format!("Invalid UTF-8 in schema file name: {:?}", i)))?;
|
||||||
|
self.bundle.insert(vec![prefix.to_owned()], s);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(Bundle { modules }) = Bundle::try_from(&blob) {
|
||||||
|
for (ModulePath(k), v) in modules.0 {
|
||||||
|
self.bundle.insert(k, v);
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(Error::new(ErrorKind::InvalidData,
|
||||||
|
format!("Invalid schema binary blob {:?}", i)));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expand_inputs(globs: &Vec<String>) -> Result<Vec<PathBuf>, Error> {
|
||||||
|
let mut result = Vec::new();
|
||||||
|
for g in globs.iter() {
|
||||||
|
for p in glob(g).map_err(|e| Error::new(ErrorKind::InvalidData, format!("{}", e)))? {
|
||||||
|
result.push(p.map_err(glob::GlobError::into_error)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile(config: &CompilerConfig) -> Result<(), std::io::Error> {
|
pub fn compile(config: &CompilerConfig) -> Result<(), std::io::Error> {
|
||||||
|
@ -33,39 +92,71 @@ pub fn compile(config: &CompilerConfig) -> Result<(), std::io::Error> {
|
||||||
let mut output_path = config.output_dir.clone();
|
let mut output_path = config.output_dir.clone();
|
||||||
output_path.extend(k);
|
output_path.extend(k);
|
||||||
output_path.set_extension("rs");
|
output_path.set_extension("rs");
|
||||||
let mut m = context::ModuleContext::new();
|
let module_name = output_path.file_stem().unwrap().to_str().unwrap().to_owned();
|
||||||
|
DirBuilder::new().recursive(true).create(output_path.parent().unwrap())?;
|
||||||
// println!("\n{:?}", &output_path);
|
let mut m = context::ModuleContext::new(config);
|
||||||
|
|
||||||
// TODO: embedded type
|
// TODO: embedded type
|
||||||
|
|
||||||
for (n, d) in &v.definitions.0 {
|
for (n, d) in &v.definitions.0 {
|
||||||
m.define_type(item(types::render_definition_type(n, &types::definition_type(d))));
|
m.define_type(item(types::render_definition_type(&m, n, &types::definition_type(d))));
|
||||||
parsers::gen_definition_parser(&mut m, n, d);
|
parsers::gen_definition_parser(&mut m, n, d);
|
||||||
unparsers::gen_definition_unparser(&mut m, n, d);
|
unparsers::gen_definition_unparser(&mut m, n, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
println!("#![allow(unused_parens)]");
|
let mut lines: Vec<String> = Vec::new();
|
||||||
println!();
|
|
||||||
println!("use std::convert::TryFrom;");
|
|
||||||
println!("use preserves::value::NestedValue;");
|
|
||||||
println!("use lazy_static::lazy_static;");
|
|
||||||
println!();
|
|
||||||
|
|
||||||
println!("lazy_static! {{");
|
lines.push("#![allow(unused_parens)]".to_owned());
|
||||||
|
lines.push("".to_owned());
|
||||||
|
lines.push("use std::convert::TryFrom;".to_owned());
|
||||||
|
lines.push("use preserves::value::NestedValue;".to_owned());
|
||||||
|
lines.push(format!("use {}::support::*;", &config.support_crate));
|
||||||
|
lines.push("".to_owned());
|
||||||
|
|
||||||
|
lines.push("lazy_static! {".to_owned());
|
||||||
for (value, name) in m.literals {
|
for (value, name) in m.literals {
|
||||||
let bs = preserves::value::PackedWriter::encode(&value).unwrap();
|
let bs = preserves::value::PackedWriter::encode(&value).unwrap();
|
||||||
println!(" pub static ref {}: preserves::value::IOValue = /* {:?} */ preserves::value::packed::from_bytes(&vec!{:?}).unwrap();",
|
lines.push(format!(" pub static ref {}: preserves::value::IOValue = /* {:?} */ preserves::value::packed::from_bytes(&vec!{:?}).unwrap();",
|
||||||
name,
|
name,
|
||||||
value,
|
value,
|
||||||
bs);
|
bs));
|
||||||
}
|
}
|
||||||
println!("}}\n");
|
lines.push("}".to_owned());
|
||||||
|
lines.push("".to_owned());
|
||||||
|
|
||||||
for i in m.typedefs { println!("{:?}\n", i); }
|
for i in m.typedefs {
|
||||||
for i in m.functiondefs { println!("{:?}\n", i); }
|
lines.push(Formatter::to_string(i));
|
||||||
|
lines.push("".to_owned());
|
||||||
|
}
|
||||||
|
for i in m.functiondefs {
|
||||||
|
lines.push(Formatter::to_string(i));
|
||||||
|
lines.push("".to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut f = File::create(&output_path)?;
|
||||||
|
for line in lines {
|
||||||
|
write!(f, "{}\n", line)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut mod_rs = output_path.clone();
|
||||||
|
mod_rs.set_file_name("mod.rs");
|
||||||
|
let mut lines = if !mod_rs.exists() {
|
||||||
|
Set::new()
|
||||||
|
} else {
|
||||||
|
BufReader::new(File::open(&mod_rs)?)
|
||||||
|
.lines().collect::<Result<Set<String>, Error>>()?
|
||||||
|
};
|
||||||
|
lines.insert(format!("pub mod {};", &module_name));
|
||||||
|
let mut f = File::create(mod_rs)?;
|
||||||
|
for line in lines {
|
||||||
|
write!(f, "{}\n", line)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,5 @@
|
||||||
use crate::syntax::block::Emittable;
|
|
||||||
use crate::syntax::block::constructors::*;
|
|
||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
|
|
||||||
pub fn render_ref(pieces: Vec<String>) -> impl Emittable {
|
|
||||||
let mut items = Vec::new();
|
|
||||||
for p in pieces { items.push(item(p)); }
|
|
||||||
name(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render_constructor(n: &str) -> String {
|
pub fn render_constructor(n: &str) -> String {
|
||||||
n.to_case(Case::UpperCamel)
|
n.to_case(Case::UpperCamel)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use crate::metaschema::*;
|
use crate::gen::schema::*;
|
||||||
use crate::syntax::block::Item;
|
use crate::syntax::block::Item;
|
||||||
use crate::syntax::block::constructors::*;
|
use crate::syntax::block::constructors::*;
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ fn store_wrap(is_struct: bool, ty: &TField, expr: &str) -> String {
|
||||||
| TField::Array(_)
|
| TField::Array(_)
|
||||||
| TField::Set(_)
|
| TField::Set(_)
|
||||||
| TField::Map(_, _) => expr.to_owned(),
|
| TField::Map(_, _) => expr.to_owned(),
|
||||||
TField::Ref(_) =>
|
TField::Ref(_, _) =>
|
||||||
if is_struct {
|
if is_struct {
|
||||||
expr.to_owned()
|
expr.to_owned()
|
||||||
} else {
|
} else {
|
||||||
|
@ -174,9 +174,7 @@ fn simple_pattern_parser(
|
||||||
},
|
},
|
||||||
SimplePattern::Ref(r) => {
|
SimplePattern::Ref(r) => {
|
||||||
let Ref { module: ModulePath(module), name } = &**r;
|
let Ref { module: ModulePath(module), name } = &**r;
|
||||||
let mut mp = module.clone();
|
let tf = name![ctxt.m.render_ref(module.clone(), name.to_owned()), "try_from"];
|
||||||
mp.push(name.to_owned());
|
|
||||||
let tf = name![names::render_ref(mp), "try_from"];
|
|
||||||
push_let(body,
|
push_let(body,
|
||||||
item(dest.to_owned()),
|
item(dest.to_owned()),
|
||||||
item(seq![tf, parens![src.to_owned()], "?"]));
|
item(seq![tf, parens![src.to_owned()], "?"]));
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use crate::syntax::block::Emittable;
|
use crate::syntax::block::Emittable;
|
||||||
use crate::syntax::block::constructors::*;
|
use crate::syntax::block::constructors::*;
|
||||||
use crate::metaschema::*;
|
use crate::gen::schema::*;
|
||||||
|
|
||||||
|
use super::context::ModuleContext;
|
||||||
use super::names;
|
use super::names;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
|
@ -22,7 +24,7 @@ pub enum TField {
|
||||||
Array(Box<TField>),
|
Array(Box<TField>),
|
||||||
Set(Box<TField>),
|
Set(Box<TField>),
|
||||||
Map(Box<TField>, Box<TField>),
|
Map(Box<TField>, Box<TField>),
|
||||||
Ref(Vec<String>),
|
Ref(Vec<String>, String),
|
||||||
Base(String),
|
Base(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,51 +148,62 @@ pub fn field_type(p: &SimplePattern) -> TField {
|
||||||
TField::Map(Box::new(field_type(k)), Box::new(field_type(v))),
|
TField::Map(Box::new(field_type(k)), Box::new(field_type(v))),
|
||||||
SimplePattern::Ref(r) => {
|
SimplePattern::Ref(r) => {
|
||||||
let Ref { module: ModulePath(mp), name: n } = &**r;
|
let Ref { module: ModulePath(mp), name: n } = &**r;
|
||||||
let mut pieces = mp.clone();
|
TField::Ref(mp.clone(), n.to_owned())
|
||||||
pieces.push(n.to_owned());
|
|
||||||
TField::Ref(pieces)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_field_type(box_needed: bool, t: &TField) -> impl Emittable {
|
pub fn render_field_type(
|
||||||
|
ctxt: &ModuleContext,
|
||||||
|
box_needed: bool,
|
||||||
|
t: &TField,
|
||||||
|
) -> impl Emittable {
|
||||||
match t {
|
match t {
|
||||||
TField::Unit => seq!["()"],
|
TField::Unit => seq!["()"],
|
||||||
TField::Array(t) => seq!["std::vec::Vec<", render_field_type(false, t), ">"],
|
TField::Array(t) => seq!["std::vec::Vec<", render_field_type(ctxt, false, t), ">"],
|
||||||
TField::Set(t) => seq!["preserves::value::Set<", render_field_type(false, t), ">"],
|
TField::Set(t) => seq!["preserves::value::Set<", render_field_type(ctxt, false, t), ">"],
|
||||||
TField::Map(k, v) => seq!["preserves::value::Map",
|
TField::Map(k, v) => seq!["preserves::value::Map",
|
||||||
anglebrackets![render_field_type(false, k),
|
anglebrackets![render_field_type(ctxt, false, k),
|
||||||
render_field_type(false, v)]],
|
render_field_type(ctxt, false, v)]],
|
||||||
TField::Ref(pieces) =>
|
TField::Ref(mp, n) =>
|
||||||
if box_needed {
|
if box_needed {
|
||||||
seq!["std::boxed::Box", anglebrackets![names::render_ref(pieces.clone())]]
|
seq!["std::boxed::Box", anglebrackets![ctxt.render_ref(mp.clone(), n.to_owned())]]
|
||||||
} else {
|
} else {
|
||||||
seq![names::render_ref(pieces.clone())]
|
seq![ctxt.render_ref(mp.clone(), n.to_owned())]
|
||||||
},
|
},
|
||||||
TField::Base(n) => seq![n.to_owned()],
|
TField::Base(n) => seq![n.to_owned()],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_recordlike_type(is_struct: bool, n: &str, d: &TSimple) -> impl Emittable {
|
pub fn render_recordlike_type(
|
||||||
|
ctxt: &ModuleContext,
|
||||||
|
is_struct: bool,
|
||||||
|
n: &str,
|
||||||
|
d: &TSimple,
|
||||||
|
) -> impl Emittable {
|
||||||
let semi = if is_struct { seq![";"] } else { seq![] };
|
let semi = if is_struct { seq![";"] } else { seq![] };
|
||||||
let ppub = if is_struct { "pub " } else { "" };
|
let ppub = if is_struct { "pub " } else { "" };
|
||||||
seq![names::render_constructor(n), match d {
|
seq![names::render_constructor(n), match d {
|
||||||
TSimple::Record(TRecord(fs)) => seq![" ", braces(
|
TSimple::Record(TRecord(fs)) => seq![" ", braces(
|
||||||
fs.iter().map(|(n, d)| item(
|
fs.iter().map(|(n, d)| item(
|
||||||
seq![ppub, names::render_fieldname(n), ": ", render_field_type(!is_struct, d)]
|
seq![ppub, names::render_fieldname(n), ": ", render_field_type(ctxt, !is_struct, d)]
|
||||||
)).collect())],
|
)).collect())],
|
||||||
TSimple::Field(TField::Unit) => semi,
|
TSimple::Field(TField::Unit) => semi,
|
||||||
TSimple::Field(t) => seq![parens![seq![ppub, render_field_type(!is_struct, t)]], semi],
|
TSimple::Field(t) => seq![parens![seq![ppub, render_field_type(ctxt, !is_struct, t)]], semi],
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_definition_type(n: &str, t: &TDefinition) -> impl Emittable {
|
pub fn render_definition_type(
|
||||||
|
ctxt: &ModuleContext,
|
||||||
|
n: &str,
|
||||||
|
t: &TDefinition,
|
||||||
|
) -> impl Emittable {
|
||||||
seq!["#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)]\n",
|
seq!["#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)]\n",
|
||||||
match t {
|
match t {
|
||||||
TDefinition::Union(items) =>
|
TDefinition::Union(items) =>
|
||||||
seq!["pub enum ", names::render_constructor(n), " ", braces(
|
seq!["pub enum ", names::render_constructor(n), " ", braces(
|
||||||
items.iter().map(|(n, d)| item(render_recordlike_type(false, n, d))).collect())],
|
items.iter().map(|(n, d)| item(render_recordlike_type(ctxt, false, n, d))).collect())],
|
||||||
TDefinition::Simple(s) =>
|
TDefinition::Simple(s) =>
|
||||||
seq!["pub struct ", render_recordlike_type(true, n, s)],
|
seq!["pub struct ", render_recordlike_type(ctxt, true, n, s)],
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use crate::metaschema::*;
|
use crate::gen::schema::*;
|
||||||
use crate::syntax::block::constructors::*;
|
use crate::syntax::block::constructors::*;
|
||||||
use crate::syntax::block::{Emittable, Item};
|
use crate::syntax::block::{Emittable, Item};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod schema;
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use preserves::value::NestedValue;
|
use preserves::value::NestedValue;
|
||||||
use lazy_static::lazy_static;
|
use crate::support::*;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref LIT15: preserves::value::IOValue = /* #f */ preserves::value::packed::from_bytes(&vec![128]).unwrap();
|
pub static ref LIT15: preserves::value::IOValue = /* #f */ preserves::value::packed::from_bytes(&vec![128]).unwrap();
|
|
@ -1,6 +1,7 @@
|
||||||
pub mod syntax;
|
pub mod syntax;
|
||||||
pub mod compiler;
|
pub mod compiler;
|
||||||
pub mod metaschema;
|
pub mod support;
|
||||||
|
pub mod gen;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -37,7 +38,7 @@ mod tests {
|
||||||
let mut f = std::fs::File::open("../../../schema/schema.bin")?;
|
let mut f = std::fs::File::open("../../../schema/schema.bin")?;
|
||||||
let mut reader = preserves::value::PackedReader::decode_read(&mut f);
|
let mut reader = preserves::value::PackedReader::decode_read(&mut f);
|
||||||
let schema = reader.demand_next(false)?;
|
let schema = reader.demand_next(false)?;
|
||||||
let parsed = crate::metaschema::Schema::try_from(&schema).expect("successful parse");
|
let parsed = crate::gen::schema::Schema::try_from(&schema).expect("successful parse");
|
||||||
assert_eq!(schema, IOValue::from(&parsed));
|
assert_eq!(schema, IOValue::from(&parsed));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
pub use lazy_static::lazy_static;
|
||||||
|
|
Loading…
Reference in New Issue