Initial commit (several days' worth)

This commit is contained in:
Tony Garnock-Jones 2021-06-28 16:35:45 +02:00
parent 60d1be41a3
commit 4144a90b9d
15 changed files with 1568 additions and 0 deletions

View File

@ -1,4 +1,5 @@
[workspace]
members = [
"preserves",
"preserves-schema",
]

View File

@ -0,0 +1,14 @@
[package]
name = "preserves-schema"
version = "0.1.0"
edition = "2018"
[dependencies]
preserves = { path = "../preserves" }
structopt = "0.3.14"
glob = "0.3.0"
convert_case = "0.4.0"
lazy_static = "1.4.0"

View File

@ -0,0 +1,6 @@
all:
@echo please use cargo
regenerate:
cargo run -- -o $(CURDIR)/src --prefix schema ../../../schema/schema.bin > src/metaschema.rs.tmp
mv src/metaschema.rs.tmp src/metaschema.rs

View File

@ -0,0 +1,66 @@
use std::path::PathBuf;
use std::fs::File;
use preserves::value::packed::PackedReader;
use preserves::value::{NestedValue, Reader};
use structopt::StructOpt;
use glob::glob;
use preserves_schema::compiler::{CompilerConfig, compile};
#[derive(Clone, StructOpt, Debug)]
struct CommandLine {
#[structopt(short, long)]
output_dir: PathBuf,
#[structopt(long)]
prefix: Option<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<(), std::io::Error> {
let args = CommandLine::from_args();
let prefix = match &args.prefix {
Some(s) => s.split(".").map(str::to_string).collect(),
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)?;
if let Some(s) = schema.value().as_simple_record("schema", Some(1)) {
config.bundle.insert(prefix.clone(), s[0].clone());
} else if let Some(b) = schema.value().as_simple_record("bundle", Some(1)) {
for (k, v) in b[0].value().to_dictionary()? {
let mut name = prefix.clone();
for p in k.value().to_sequence()? {
name.push(p.value().to_string()?.to_owned());
}
config.bundle.insert(name, v.clone());
}
}
}
compile(&config)
}

View File

@ -0,0 +1,71 @@
use preserves::value::{Map, IOValue};
use crate::syntax::block::Item;
use super::types;
pub struct ModuleContext {
pub literals: Map<IOValue, String>,
pub typedefs: Vec<Item>,
pub functiondefs: Vec<Item>,
}
pub struct FunctionContext<'a> {
pub m: &'a mut ModuleContext,
pub temp_counter: usize,
pub temps: Map<types::TDefinition, Vec<String>>,
pub captures: Vec<Capture>,
}
pub struct Capture {
pub field_name: String,
pub source_expr: String,
}
impl ModuleContext {
pub fn new() -> Self {
ModuleContext {
literals: Map::new(),
typedefs: Vec::new(),
functiondefs: Vec::new(),
}
}
pub fn define_literal(&mut self, v: &IOValue) -> String {
let next_id = format!("LIT{}", self.literals.len());
"&*".to_owned() + self.literals.entry(v.clone()).or_insert(next_id)
}
pub fn define_type(&mut self, i: Item) {
self.typedefs.push(i)
}
pub fn define_function<F: FnOnce(FunctionContext) -> Item>(&mut self, f: F) {
let i = f(FunctionContext::new(self));
self.functiondefs.push(i)
}
}
impl<'a> FunctionContext<'a> {
pub fn new(m: &'a mut ModuleContext) -> Self {
FunctionContext {
m: m,
temp_counter: 0,
temps: Map::new(),
captures: Vec::new(),
}
}
pub fn capture(&mut self, field_name: &str, source_expr: &str) {
self.captures.push(Capture {
field_name: field_name.to_owned(),
source_expr: source_expr.to_owned(),
})
}
pub fn gentempname(&mut self) -> String {
let i = self.temp_counter;
self.temp_counter += 1;
format!("_tmp{}", i)
}
}

View File

@ -0,0 +1,75 @@
pub mod types;
pub mod names;
pub mod context;
pub mod parsers;
use std::path::PathBuf;
use preserves::value::{Map, IOValue, NestedValue, Value};
use crate::syntax::block::constructors::*;
pub type ModulePath = Vec<String>;
pub type Schema = IOValue;
#[derive(Debug)]
pub struct CompilerConfig {
pub bundle: Map<ModulePath, Schema>,
pub output_dir: PathBuf,
}
impl CompilerConfig {
pub fn new(output_dir: PathBuf) -> Self {
CompilerConfig {
bundle: Map::new(),
output_dir: output_dir,
}
}
}
pub fn compile(config: &CompilerConfig) -> Result<(), std::io::Error> {
for (k, v) in config.bundle.iter() {
let mut output_path = config.output_dir.clone();
output_path.extend(k);
output_path.set_extension("rs");
let mut m = context::ModuleContext::new();
// println!("\n{:?}", &output_path);
// TODO: embedded type
let definitions = v.value().to_dictionary()?.get(&Value::symbol("definitions").wrap())
.unwrap().value().to_dictionary()?;
for (n, d) in definitions.iter() {
m.define_type(item(types::render_definition_type(
n.value().to_symbol()?,
&types::definition_type(d)?)));
parsers::gen_definition_parser(&mut m, n.value().to_symbol()?, &d);
}
//---------------------------------------------------------------------------
println!("#![allow(unused_parens)]");
println!();
println!("use std::convert::TryFrom;");
println!("use preserves::value::{{NestedValue, Reader}};");
println!("use lazy_static::lazy_static;");
println!();
println!("lazy_static! {{");
for (value, name) in m.literals {
let bs = preserves::value::PackedWriter::encode(&value).unwrap();
println!(" pub static ref {}: preserves::value::IOValue = /* {:?} */ preserves::value::PackedReader::decode_bytes(&vec!{:?}).demand_next(false).unwrap();",
name,
value,
bs);
}
println!("}}\n");
for i in m.typedefs { println!("{:?}\n", i); }
for i in m.functiondefs { println!("{:?}\n", i); }
}
Ok(())
}

View File

@ -0,0 +1,17 @@
use crate::syntax::block::Emittable;
use crate::syntax::block::constructors::*;
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 {
n.to_case(Case::UpperCamel)
}
pub fn render_fieldname(n: &str) -> String {
n.to_case(Case::Snake)
}

View File

@ -0,0 +1,276 @@
use crate::*;
use crate::syntax::block::Item;
use crate::syntax::block::constructors::*;
use preserves::value::{IOValue, NestedValue};
use super::names;
use super::types::*;
use super::context::{ModuleContext, FunctionContext};
pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &IOValue) {
m.define_function(
|mut ctxt| {
let mut body = Vec::new();
if let Some(fs) = d.value().as_simple_record("or", Some(1)) {
for e in fs[0].value().to_sequence().unwrap() {
let e = e.value().to_sequence().unwrap();
let name = e[0].value().to_string().unwrap();
let pat = &e[1];
let fname = seq!["_parse_", names::render_fieldname(n), "_", names::render_fieldname(name)];
let ctorname = item(name![names::render_constructor(n), names::render_constructor(name)]);
ctxt.m.define_function(
|mut ctxt| {
let mut body = Vec::new();
let dest = pattern_parser(&mut ctxt, pat, "value", None, &mut body);
let dest = dest.as_ref().map(String::as_str);
construct(&ctxt, ctorname, &TDefinition::Simple(simple_type(pat).unwrap()), dest, &mut body);
item(seq!["fn ", fname.clone(), "(value: &preserves::value::IOValue) -> ",
"std::result::Result<", names::render_constructor(n), ", ()> ",
block(body)])
});
body.push(item(seq!["if let Ok(r) = ", fname, "(value) { return Ok(r); }"]));
}
body.push(item(seq!["Err(())"]));
} else if let Some(fs) = d.value().as_simple_record("and", Some(1)) {
for e in fs[0].value().to_sequence().unwrap() {
pattern_parser(&mut ctxt, e, "value", None, &mut body);
}
construct(&ctxt, item(names::render_constructor(n)), &definition_type(d).unwrap(), None, &mut body);
} else {
let dest = pattern_parser(&mut ctxt, d, "value", None, &mut body);
let dest = dest.as_ref().map(String::as_str);
construct(&ctxt, item(names::render_constructor(n)), &definition_type(d).unwrap(), dest, &mut body);
}
item(seq!["impl std::convert::TryFrom", anglebrackets!["&preserves::value::IOValue"], " for ",
names::render_constructor(n), " ", block![
seq!["type Error = ();"],
seq!["fn try_from(value: &preserves::value::IOValue) -> ",
"std::result::Result<Self, Self::Error> ",
block(body)]]])
});
}
fn construct(
ctxt: &FunctionContext,
ctorname: Item,
ty: &TDefinition,
dest: Option<&str>,
body: &mut Vec<Item>,
) {
match ty {
TDefinition::Simple(TSimple::Field(TField::Unit)) =>
body.push(item(seq!["Ok(", ctorname, ")"])),
TDefinition::Simple(TSimple::Field(fieldty)) =>
body.push(item(seq!["Ok(", ctorname, parens![store_wrap(fieldty, dest.unwrap())], ")"])),
_ =>
body.push(item(seq!["Ok(", ctorname, " ", braces(
ctxt.captures.iter().map(
|c| item(seq![c.field_name.clone(), ": ", c.source_expr.clone()])).collect()),
")"])),
}
}
fn store_wrap(ty: &TField, expr: &str) -> String {
match ty {
TField::Unit
| TField::Array(_)
| TField::Set(_)
| TField::Map(_, _) => expr.to_owned(),
TField::Ref(_) => format!("std::boxed::Box::new({})", expr),
TField::Base(_) => format!("{}.clone()", expr),
}
}
fn item_store_wrap(ty: &TField, expr: &str) -> String {
match ty {
TField::Unit
| TField::Array(_)
| TField::Set(_)
| TField::Map(_, _)
| TField::Ref(_) => expr.to_owned(),
TField::Base(_) => format!("{}.clone()", expr),
}
}
fn push_let(body: &mut Vec<Item>, name: &str, expr: Item) {
body.push(item(seq!["let ", name.to_owned(), " = ", expr, ";"]))
}
fn push_let_mut(body: &mut Vec<Item>, name: &str, expr: Item) {
body.push(item(seq!["let mut ", name.to_owned(), " = ", expr, ";"]))
}
fn simple_pattern_parser(
ctxt: &mut FunctionContext,
p: &IOValue,
src: &str,
sequence_base: Option<usize>,
body: &mut Vec<Item>,
) -> Option<String> {
let dest = ctxt.gentempname();
if p.value().as_symbol() == Some(&"any".to_owned()) {
push_let(body, &dest, item(src.to_owned()));
Some(dest)
} else if let Some(fs) = p.value().as_simple_record("atom", Some(1)) {
match fs[0].value().as_symbol().unwrap().as_str() {
"Boolean" => push_let(body, &dest, item(seq![src.to_owned(), ".value().to_boolean().map_err(|_| ())?"])),
"Float" => push_let(body, &dest, item(seq![src.to_owned(), ".value().to_float().map_err(|_| ())?"])),
"Double" => push_let(body, &dest, item(seq![src.to_owned(), ".value().to_double().map_err(|_| ())?"])),
"SignedInteger" => push_let(body, &dest, item(seq![src.to_owned(), ".value().to_signedinteger().map_err(|_| ())?"])),
"String" => push_let(body, &dest, item(seq![src.to_owned(), ".value().to_string().map_err(|_| ())?"])),
"ByteString" => push_let(body, &dest, item(seq![src.to_owned(), ".value().to_bytestring().map_err(|_| ())?"])),
"Symbol" => push_let(body, &dest, item(seq![src.to_owned(), ".value().to_symbol().map_err(|_| ())?"])),
_ => panic!("Unexpected AtomKind"),
}
Some(dest)
} else if let Some(_) = p.value().as_simple_record("embedded", Some(1)) {
push_let(body, &dest, item(seq![src.to_owned(), ".value().to_embedded().map_err(|_| ())?"]));
Some(dest)
} else if let Some(fs) = p.value().as_simple_record("lit", Some(1)) {
body.push(item(seq!["if ", src.to_owned(), " != ", ctxt.m.define_literal(&fs[0]),
" { return Err(()); }"]));
push_let(body, &dest, item("()"));
Some(dest)
} else if let Some(fs) = p.value().as_simple_record("seqof", Some(1)) {
let (src, n) = sequenceify(ctxt, src, sequence_base, body);
let tmp = ctxt.gentempname();
let mut inner = Vec::new();
let item_dest = simple_pattern_parser(ctxt, &fs[0], &tmp, None, &mut inner);
inner.push(item(seq![
dest.to_owned(), ".push(",
item_store_wrap(&field_type(&fs[0]).unwrap().unwrap(), &item_dest.unwrap()), ");"]));
push_let_mut(body, &dest, item("std::vec::Vec::new()"));
body.push(item(seq!["for ", tmp.to_owned(),
" in &", src.to_owned(), brackets![seq![n.to_string() , ".."]],
" ", block(inner)]));
Some(dest)
} else if let Some(fs) = p.value().as_simple_record("setof", Some(1)) {
let tmp = ctxt.gentempname();
let mut inner = Vec::new();
let item_dest = simple_pattern_parser(ctxt, &fs[0], &tmp, None, &mut inner);
inner.push(item(seq![
dest.to_owned(), ".insert(",
item_store_wrap(&field_type(&fs[0]).unwrap().unwrap(), &item_dest.unwrap()), ");"]));
push_let_mut(body, &dest, item("preserves::value::Set::new()"));
body.push(item(seq!["for ", tmp.to_owned(),
" in ", src.to_owned(), ".value().to_set().map_err(|_| ())?",
" ", block(inner)]));
Some(dest)
} else if let Some(fs) = p.value().as_simple_record("dictof", Some(2)) {
let tmp_key = ctxt.gentempname();
let tmp_value = ctxt.gentempname();
let mut inner = Vec::new();
let key_dest = simple_pattern_parser(ctxt, &fs[0], &tmp_key, None, &mut inner);
let value_dest = simple_pattern_parser(ctxt, &fs[1], &tmp_value, None, &mut inner);
inner.push(item(seq![
dest.to_owned(), ".insert(",
item_store_wrap(&field_type(&fs[0]).unwrap().unwrap(), &key_dest.unwrap()), ", ",
item_store_wrap(&field_type(&fs[1]).unwrap().unwrap(), &value_dest.unwrap()), ");"]));
push_let_mut(body, &dest, item("preserves::value::Map::new()"));
body.push(item(seq!["for (", tmp_key.to_owned(), ", ", tmp_value.to_owned(), ")",
" in ", src.to_owned(), ".value().to_dictionary().map_err(|_| ())?",
" ", block(inner)]));
Some(dest)
} else if let Some(fs) = p.value().as_simple_record("ref", Some(2)) {
let mut n: Vec<String> = fs[0].value().to_sequence().unwrap()
.iter().map(|s| s.value().to_symbol().unwrap().to_owned()).collect();
use convert_case::{Case, Casing};
n.push(fs[1].value().to_symbol().unwrap().to_case(Case::UpperCamel));
let tf = name![names::render_ref(n), "try_from"];
push_let(body, &dest, item(seq![tf,
parens![src.to_owned()],
"?"]));
Some(dest)
} else {
None
}
}
fn sequenceify(
ctxt: &mut FunctionContext,
src: &str,
sequence_base: Option<usize>,
body: &mut Vec<Item>,
) -> (String, usize) {
match sequence_base {
Some(n) => (src.to_owned(), n),
None => {
let tmp = ctxt.gentempname();
push_let(body, &tmp, item(seq![src.to_owned(), ".value().to_sequence().map_err(|_| ())?"]));
(tmp, 0)
}
}
}
fn fixed_sequence_parser(
ctxt: &mut FunctionContext,
base: usize,
ps: &[IOValue],
src: &str,
body: &mut Vec<Item>,
) {
let mut i = base;
body.push(item(seq!["if ", src.to_owned(), ".len() - ", base.to_string(), " < ",
ps.len().to_string(), " { return Err(()); }"]));
for p in ps {
pattern_parser(ctxt, p, &format!("(&{}[{}])", src, i), None, body);
i += 1;
}
}
fn pattern_parser(
ctxt: &mut FunctionContext,
p: &IOValue,
src: &str,
sequence_base: Option<usize>,
body: &mut Vec<Item>,
) -> Option<String> {
match simple_pattern_parser(ctxt, p, src, sequence_base, body) {
Some(dest) => Some(dest),
None => {
// Compound
let r = p.value().as_record(None).unwrap();
match r.label().value().as_symbol().unwrap().as_ref() {
"named" => {
let dest = simple_pattern_parser(ctxt, &r.fields()[1], src, sequence_base, body).unwrap();
let capture_expr = store_wrap(&field_type(&r.fields()[1]).unwrap().unwrap(), &dest);
ctxt.capture(&names::render_fieldname(r.fields()[0].value().as_symbol().unwrap()),
&capture_expr);
Some(dest)
}
"rec" => {
let rtmp = ctxt.gentempname();
push_let(body, &rtmp, item(seq![src.to_owned(), ".value().to_record(None).map_err(|_| ())?"]));
pattern_parser(ctxt, &r.fields()[0], &format!("{}.label()", rtmp), None, body);
pattern_parser(ctxt, &r.fields()[1], &format!("{}.fields()", rtmp), Some(0), body);
None
}
"tuple" => {
let (src, n) = sequenceify(ctxt, src, sequence_base, body);
fixed_sequence_parser(ctxt, n, r.fields()[0].value().to_sequence().unwrap(), &src, body);
None
}
"tuplePrefix" => {
let (src, n) = sequenceify(ctxt, src, sequence_base, body);
let fixed = r.fields()[0].value().to_sequence().unwrap();
fixed_sequence_parser(ctxt, n, fixed, &src, body);
pattern_parser(ctxt, &r.fields()[1], &src, Some(n + fixed.len()), body)
}
"dict" => {
let dtmp = ctxt.gentempname();
push_let(body, &dtmp, item(seq![src.to_owned(), ".value().to_dictionary().map_err(|_| ())?"]));
for (key_lit, value_pat) in r.fields()[0].value().to_dictionary().unwrap() {
let vtmp = ctxt.gentempname();
push_let(body, &vtmp, item(seq![
dtmp.to_owned(), ".get", parens![ctxt.m.define_literal(key_lit)],
".ok_or(())?"]));
pattern_parser(ctxt, value_pat, &vtmp, None, body);
}
None
}
_ => panic!("Unexpected compound"),
}
}
}
}

View File

@ -0,0 +1,175 @@
use crate::*;
use crate::syntax::block::Emittable;
use crate::syntax::block::constructors::*;
use super::names;
use preserves::value::{IOValue, NestedValue};
use preserves::error::Error;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum TDefinition {
Union(Vec<(String, TSimple)>),
Simple(TSimple),
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum TSimple {
Field(TField),
Record(TRecord),
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum TField {
Unit,
Array(Box<TField>),
Set(Box<TField>),
Map(Box<TField>, Box<TField>),
Ref(Vec<String>),
Base(String),
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct TRecord(pub Vec<(String, TField)>);
pub fn definition_type(d: &IOValue) -> Result<TDefinition, Error> {
if let Some(fs) = d.value().as_simple_record("or", Some(1)) {
let mut entries = Vec::new();
for e in fs[0].value().to_sequence()?.iter() {
let e = e.value().to_sequence()?;
entries.push((e[0].value().to_string()?.to_owned(), simple_type(&e[1])?));
}
Ok(TDefinition::Union(entries))
} else if let Some(fs) = d.value().as_simple_record("and", Some(1)) {
Ok(TDefinition::Simple(record_type(fs[0].value().to_sequence()?)?))
} else {
Ok(TDefinition::Simple(simple_type(d)?))
}
}
pub fn simple_type(p: &IOValue) -> Result<TSimple, Error> {
if let Some(t) = field_type(p)? {
Ok(TSimple::Field(t))
} else {
record_type(&vec![p.clone()])
}
}
pub fn record_type(ps: &Vec<IOValue>) -> Result<TSimple, Error> {
let fs = gather_fields(ps, Vec::new())?;
if fs.is_empty() {
Ok(TSimple::Field(TField::Unit))
} else {
Ok(TSimple::Record(TRecord(fs)))
}
}
pub fn gather_fields(ps: &Vec<IOValue>, mut fs: Vec<(String, TField)>) ->
Result<Vec<(String, TField)>, Error>
{
for p in ps.iter() {
fs = gather_field(p, fs)?;
}
Ok(fs)
}
pub fn gather_field(p: &IOValue, mut fs: Vec<(String, TField)>) ->
Result<Vec<(String, TField)>, Error>
{
if let Some(n) = p.value().as_simple_record("named", Some(2)) {
let name = n[0].value().to_symbol()?;
fs.push((name.to_owned(), field_type(&n[1])?.unwrap()));
Ok(fs)
} else if let Some(label_and_fields) = p.value().as_simple_record("rec", Some(2)) {
Ok(gather_field(&label_and_fields[1], gather_field(&label_and_fields[0], fs)?)?)
} else if let Some(tfs) = p.value().as_simple_record("tuple", Some(1)) {
Ok(gather_fields(tfs[0].value().to_sequence()?, fs)?)
} else if let Some(tfs) = p.value().as_simple_record("tuplePrefix", Some(2)) {
Ok(gather_field(&tfs[1], gather_fields(tfs[0].value().to_sequence()?, fs)?)?)
} else if let Some(dfs) = p.value().as_simple_record("dict", Some(1)) {
let es = dfs[0].value().to_dictionary()?;
for (_k, p) in es.iter() {
fs = gather_field(p, fs)?;
}
Ok(fs)
} else {
Ok(fs)
}
}
pub fn field_type(p: &IOValue) -> Result<Option<TField>, Error> {
if p.value().as_symbol() == Some(&"any".to_owned()) {
Ok(Some(TField::Base("preserves::value::IOValue".to_owned())))
} else if let Some(fs) = p.value().as_simple_record("atom", Some(1)) {
match fs[0].value().as_symbol().unwrap().as_str() {
"Boolean" => Ok(Some(TField::Base("bool".to_owned()))),
"Float" => Ok(Some(TField::Base("f32".to_owned()))),
"Double" => Ok(Some(TField::Base("f64".to_owned()))),
"SignedInteger" => Ok(Some(TField::Base("preserves::value::signed_integer::SignedInteger".to_owned()))),
"String" => Ok(Some(TField::Base("std::string::String".to_owned()))),
"ByteString" => Ok(Some(TField::Base("std::vec::Vec<u8>".to_owned()))),
"Symbol" => Ok(Some(TField::Base("std::string::String".to_owned()))),
_ => Err(Error::Message("Unexpected AtomKind".to_owned())),
}
} else if let Some(_) = p.value().as_simple_record("embedded", Some(1)) {
Ok(Some(TField::Base("_ptr".to_owned())))
} else if let Some(_) = p.value().as_simple_record("lit", Some(1)) {
Ok(Some(TField::Unit))
} else if let Some(fs) = p.value().as_simple_record("seqof", Some(1)) {
Ok(Some(TField::Array(Box::new(field_type(&fs[0])?.unwrap()))))
} else if let Some(fs) = p.value().as_simple_record("setof", Some(1)) {
Ok(Some(TField::Set(Box::new(field_type(&fs[0])?.unwrap()))))
} else if let Some(fs) = p.value().as_simple_record("dictof", Some(2)) {
Ok(Some(TField::Map(Box::new(field_type(&fs[0])?.unwrap()),
Box::new(field_type(&fs[1])?.unwrap()))))
} else if let Some(fs) = p.value().as_simple_record("ref", Some(2)) {
let mut pieces = fs[0].value().to_sequence()?.iter()
.map(|v| v.value().to_symbol().map(String::to_owned))
.collect::<Result<Vec<String>,_>>()?;
pieces.push(fs[1].value().to_symbol()?.to_owned());
Ok(Some(TField::Ref(pieces)))
} else {
Ok(None)
}
}
pub fn render_field_type(box_needed: bool, t: &TField) -> impl Emittable {
match t {
TField::Unit => seq!["()"],
TField::Array(t) => seq!["std::vec::Vec<", render_field_type(false, t), ">"],
TField::Set(t) => seq!["preserves::value::Set<", render_field_type(false, t), ">"],
TField::Map(k, v) => seq!["preserves::value::Map",
anglebrackets![render_field_type(false, k),
render_field_type(false, v)]],
TField::Ref(pieces) =>
if box_needed {
seq!["std::boxed::Box", anglebrackets![names::render_ref(pieces.clone())]]
} else {
seq![names::render_ref(pieces.clone())]
},
TField::Base(n) => seq![n.to_owned()],
}
}
pub fn render_recordlike_type(is_struct: bool, n: &str, d: &TSimple) -> impl Emittable {
let semi = if is_struct { seq![";"] } else { seq![] };
seq![names::render_constructor(n), match d {
TSimple::Record(TRecord(fs)) => seq![" ", braces(
fs.iter().map(|(n, d)| item(
seq![if is_struct { "pub " } else { "" },
names::render_fieldname(n), ": ", render_field_type(true, d)]
)).collect())],
TSimple::Field(TField::Unit) => semi,
TSimple::Field(t) => seq![parens![render_field_type(true, t)], semi],
}]
}
pub fn render_definition_type(n: &str, t: &TDefinition) -> impl Emittable {
seq!["#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] ",
match t {
TDefinition::Union(items) =>
seq!["pub enum ", names::render_constructor(n), " ", braces(
items.iter().map(|(n, d)| item(render_recordlike_type(false, n, d))).collect())],
TDefinition::Simple(s) =>
seq!["pub struct ", render_recordlike_type(true, n, s)],
}]
}

View File

@ -0,0 +1,43 @@
pub mod syntax;
pub mod compiler;
pub mod metaschema;
#[cfg(test)]
mod tests {
#[test]
fn can_access_preserves_core() {
use preserves::value::*;
assert_eq!(format!("{:?}", UnwrappedIOValue::from(3 + 4)), "7");
}
#[test]
fn simple_rendering() {
use crate::*;
use crate::syntax::block::*;
let code = semiblock![
seq!["f", parens!["a", "b", "c"]],
seq!["f", parens!["a", "b", "c"]],
seq!["f", parens!["a", "b", "c"]],
seq!["f", parens!["a", "b", "c"]],
seq!["f", parens!["a", "b", "c"]],
seq!["f", parens!["a", "b", "c"]],
seq!["g", parens![]],
parens![]
];
println!("{}", Formatter::to_string(&code));
}
#[test]
fn metaschema_parsing() -> Result<(), std::io::Error> {
use preserves::value::Reader;
use std::convert::TryFrom;
let mut f = std::fs::File::open("../../../schema/schema.bin")?;
let mut reader = preserves::value::PackedReader::decode_read(&mut f);
let schema = reader.demand_next(false)?;
println!("{:#?}", crate::metaschema::Schema::try_from(&schema));
Ok(())
}
}

View File

@ -0,0 +1,532 @@
#![allow(unused_parens)]
use std::convert::TryFrom;
use preserves::value::{NestedValue, Reader};
use lazy_static::lazy_static;
lazy_static! {
pub static ref LIT15: preserves::value::IOValue = /* #f */ preserves::value::PackedReader::decode_bytes(&vec![128]).demand_next(false).unwrap();
pub static ref LIT28: preserves::value::IOValue = /* 1 */ preserves::value::PackedReader::decode_bytes(&vec![145]).demand_next(false).unwrap();
pub static ref LIT0: preserves::value::IOValue = /* Boolean */ preserves::value::PackedReader::decode_bytes(&vec![179, 7, 66, 111, 111, 108, 101, 97, 110]).demand_next(false).unwrap();
pub static ref LIT5: preserves::value::IOValue = /* ByteString */ preserves::value::PackedReader::decode_bytes(&vec![179, 10, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103]).demand_next(false).unwrap();
pub static ref LIT2: preserves::value::IOValue = /* Double */ preserves::value::PackedReader::decode_bytes(&vec![179, 6, 68, 111, 117, 98, 108, 101]).demand_next(false).unwrap();
pub static ref LIT1: preserves::value::IOValue = /* Float */ preserves::value::PackedReader::decode_bytes(&vec![179, 5, 70, 108, 111, 97, 116]).demand_next(false).unwrap();
pub static ref LIT3: preserves::value::IOValue = /* SignedInteger */ preserves::value::PackedReader::decode_bytes(&vec![179, 13, 83, 105, 103, 110, 101, 100, 73, 110, 116, 101, 103, 101, 114]).demand_next(false).unwrap();
pub static ref LIT4: preserves::value::IOValue = /* String */ preserves::value::PackedReader::decode_bytes(&vec![179, 6, 83, 116, 114, 105, 110, 103]).demand_next(false).unwrap();
pub static ref LIT6: preserves::value::IOValue = /* Symbol */ preserves::value::PackedReader::decode_bytes(&vec![179, 6, 83, 121, 109, 98, 111, 108]).demand_next(false).unwrap();
pub static ref LIT14: preserves::value::IOValue = /* and */ preserves::value::PackedReader::decode_bytes(&vec![179, 3, 97, 110, 100]).demand_next(false).unwrap();
pub static ref LIT21: preserves::value::IOValue = /* any */ preserves::value::PackedReader::decode_bytes(&vec![179, 3, 97, 110, 121]).demand_next(false).unwrap();
pub static ref LIT22: preserves::value::IOValue = /* atom */ preserves::value::PackedReader::decode_bytes(&vec![179, 4, 97, 116, 111, 109]).demand_next(false).unwrap();
pub static ref LIT8: preserves::value::IOValue = /* bundle */ preserves::value::PackedReader::decode_bytes(&vec![179, 6, 98, 117, 110, 100, 108, 101]).demand_next(false).unwrap();
pub static ref LIT18: preserves::value::IOValue = /* definitions */ preserves::value::PackedReader::decode_bytes(&vec![179, 11, 100, 101, 102, 105, 110, 105, 116, 105, 111, 110, 115]).demand_next(false).unwrap();
pub static ref LIT12: preserves::value::IOValue = /* dict */ preserves::value::PackedReader::decode_bytes(&vec![179, 4, 100, 105, 99, 116]).demand_next(false).unwrap();
pub static ref LIT27: preserves::value::IOValue = /* dictof */ preserves::value::PackedReader::decode_bytes(&vec![179, 6, 100, 105, 99, 116, 111, 102]).demand_next(false).unwrap();
pub static ref LIT23: preserves::value::IOValue = /* embedded */ preserves::value::PackedReader::decode_bytes(&vec![179, 8, 101, 109, 98, 101, 100, 100, 101, 100]).demand_next(false).unwrap();
pub static ref LIT19: preserves::value::IOValue = /* embeddedType */ preserves::value::PackedReader::decode_bytes(&vec![179, 12, 101, 109, 98, 101, 100, 100, 101, 100, 84, 121, 112, 101]).demand_next(false).unwrap();
pub static ref LIT24: preserves::value::IOValue = /* lit */ preserves::value::PackedReader::decode_bytes(&vec![179, 3, 108, 105, 116]).demand_next(false).unwrap();
pub static ref LIT7: preserves::value::IOValue = /* named */ preserves::value::PackedReader::decode_bytes(&vec![179, 5, 110, 97, 109, 101, 100]).demand_next(false).unwrap();
pub static ref LIT13: preserves::value::IOValue = /* or */ preserves::value::PackedReader::decode_bytes(&vec![179, 2, 111, 114]).demand_next(false).unwrap();
pub static ref LIT9: preserves::value::IOValue = /* rec */ preserves::value::PackedReader::decode_bytes(&vec![179, 3, 114, 101, 99]).demand_next(false).unwrap();
pub static ref LIT16: preserves::value::IOValue = /* ref */ preserves::value::PackedReader::decode_bytes(&vec![179, 3, 114, 101, 102]).demand_next(false).unwrap();
pub static ref LIT17: preserves::value::IOValue = /* schema */ preserves::value::PackedReader::decode_bytes(&vec![179, 6, 115, 99, 104, 101, 109, 97]).demand_next(false).unwrap();
pub static ref LIT25: preserves::value::IOValue = /* seqof */ preserves::value::PackedReader::decode_bytes(&vec![179, 5, 115, 101, 113, 111, 102]).demand_next(false).unwrap();
pub static ref LIT26: preserves::value::IOValue = /* setof */ preserves::value::PackedReader::decode_bytes(&vec![179, 5, 115, 101, 116, 111, 102]).demand_next(false).unwrap();
pub static ref LIT10: preserves::value::IOValue = /* tuple */ preserves::value::PackedReader::decode_bytes(&vec![179, 5, 116, 117, 112, 108, 101]).demand_next(false).unwrap();
pub static ref LIT11: preserves::value::IOValue = /* tuplePrefix */ preserves::value::PackedReader::decode_bytes(&vec![179, 11, 116, 117, 112, 108, 101, 80, 114, 101, 102, 105, 120]).demand_next(false).unwrap();
pub static ref LIT20: preserves::value::IOValue = /* version */ preserves::value::PackedReader::decode_bytes(&vec![179, 7, 118, 101, 114, 115, 105, 111, 110]).demand_next(false).unwrap();
}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub enum AtomKind {Boolean, Float, Double, SignedInteger, String, ByteString, Symbol}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub struct Binding {pub name: std::string::String, pub pattern: std::boxed::Box<SimplePattern>}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub struct Bundle {pub modules: std::boxed::Box<Modules>}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub enum CompoundPattern {
Rec {label: std::boxed::Box<NamedPattern>, fields: std::boxed::Box<NamedPattern>},
Tuple {patterns: std::vec::Vec<NamedPattern>},
TuplePrefix {
fixed: std::vec::Vec<NamedPattern>,
variable: std::boxed::Box<NamedSimplePattern>
},
Dict {entries: std::boxed::Box<DictionaryEntries>}
}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub enum Definition {
Or {
pattern_0: std::boxed::Box<NamedAlternative>,
pattern_1: std::boxed::Box<NamedAlternative>,
pattern_n: std::vec::Vec<NamedAlternative>
},
And {
pattern_0: std::boxed::Box<NamedPattern>,
pattern_1: std::boxed::Box<NamedPattern>,
pattern_n: std::vec::Vec<NamedPattern>
},
Pattern(std::boxed::Box<Pattern>)
}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub struct Definitions(preserves::value::Map<std::string::String, Definition>);
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub struct DictionaryEntries(preserves::value::Map<preserves::value::IOValue, NamedSimplePattern>);
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub enum EmbeddedTypeName {Ref(std::boxed::Box<Ref>), False}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub struct ModulePath(std::vec::Vec<std::string::String>);
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub struct Modules(preserves::value::Map<ModulePath, Schema>);
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub struct NamedAlternative {pub variant_label: std::string::String, pub pattern: std::boxed::Box<Pattern>}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub enum NamedPattern {Named(std::boxed::Box<Binding>), Anonymous(std::boxed::Box<Pattern>)}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub enum NamedSimplePattern {Named(std::boxed::Box<Binding>), Anonymous(std::boxed::Box<SimplePattern>)}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub enum Pattern {
SimplePattern(std::boxed::Box<SimplePattern>),
CompoundPattern(std::boxed::Box<CompoundPattern>)
}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub struct Ref {pub module: std::boxed::Box<ModulePath>, pub name: std::string::String}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub struct Schema {
pub definitions: std::boxed::Box<Definitions>,
pub embedded_type: std::boxed::Box<EmbeddedTypeName>,
pub version: std::boxed::Box<Version>
}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub enum SimplePattern {
Any,
Atom {atom_kind: std::boxed::Box<AtomKind>},
Embedded {interface: std::boxed::Box<SimplePattern>},
Lit {value: preserves::value::IOValue},
Seqof {pattern: std::boxed::Box<SimplePattern>},
Setof {pattern: std::boxed::Box<SimplePattern>},
Dictof {key: std::boxed::Box<SimplePattern>, value: std::boxed::Box<SimplePattern>},
Ref(std::boxed::Box<Ref>)
}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] pub struct Version;
fn _parse_atom_kind_boolean(value: &preserves::value::IOValue) -> std::result::Result<AtomKind, ()> {if value != &*LIT0 { return Err(()); } let _tmp0 = (); Ok(AtomKind::Boolean)}
fn _parse_atom_kind_float(value: &preserves::value::IOValue) -> std::result::Result<AtomKind, ()> {if value != &*LIT1 { return Err(()); } let _tmp0 = (); Ok(AtomKind::Float)}
fn _parse_atom_kind_double(value: &preserves::value::IOValue) -> std::result::Result<AtomKind, ()> {if value != &*LIT2 { return Err(()); } let _tmp0 = (); Ok(AtomKind::Double)}
fn _parse_atom_kind_signed_integer(value: &preserves::value::IOValue) -> std::result::Result<AtomKind, ()> {
if value != &*LIT3 { return Err(()); }
let _tmp0 = ();
Ok(AtomKind::SignedInteger)
}
fn _parse_atom_kind_string(value: &preserves::value::IOValue) -> std::result::Result<AtomKind, ()> {if value != &*LIT4 { return Err(()); } let _tmp0 = (); Ok(AtomKind::String)}
fn _parse_atom_kind_byte_string(value: &preserves::value::IOValue) -> std::result::Result<AtomKind, ()> {
if value != &*LIT5 { return Err(()); }
let _tmp0 = ();
Ok(AtomKind::ByteString)
}
fn _parse_atom_kind_symbol(value: &preserves::value::IOValue) -> std::result::Result<AtomKind, ()> {if value != &*LIT6 { return Err(()); } let _tmp0 = (); Ok(AtomKind::Symbol)}
impl std::convert::TryFrom<&preserves::value::IOValue> for AtomKind {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
if let Ok(r) = _parse_atom_kind_boolean(value) { return Ok(r); }
if let Ok(r) = _parse_atom_kind_float(value) { return Ok(r); }
if let Ok(r) = _parse_atom_kind_double(value) { return Ok(r); }
if let Ok(r) = _parse_atom_kind_signed_integer(value) { return Ok(r); }
if let Ok(r) = _parse_atom_kind_string(value) { return Ok(r); }
if let Ok(r) = _parse_atom_kind_byte_string(value) { return Ok(r); }
if let Ok(r) = _parse_atom_kind_symbol(value) { return Ok(r); }
Err(())
}
}
impl std::convert::TryFrom<&preserves::value::IOValue> for Binding {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT7 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 2 { return Err(()); }
let _tmp5 = (&_tmp1.fields()[0]).value().to_symbol().map_err(|_| ())?;
let _tmp7 = SimplePattern::try_from((&_tmp1.fields()[1]))?;
Ok(Binding {name: _tmp5.clone(), pattern: std::boxed::Box::new(_tmp7)})
}
}
impl std::convert::TryFrom<&preserves::value::IOValue> for Bundle {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT8 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 1 { return Err(()); }
let _tmp5 = Modules::try_from((&_tmp1.fields()[0]))?;
Ok(Bundle {modules: std::boxed::Box::new(_tmp5)})
}
}
fn _parse_compound_pattern_rec(value: &preserves::value::IOValue) -> std::result::Result<CompoundPattern, ()> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT9 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 2 { return Err(()); }
let _tmp5 = NamedPattern::try_from((&_tmp1.fields()[0]))?;
let _tmp7 = NamedPattern::try_from((&_tmp1.fields()[1]))?;
Ok(CompoundPattern::Rec {label: std::boxed::Box::new(_tmp5), fields: std::boxed::Box::new(_tmp7)})
}
fn _parse_compound_pattern_tuple(value: &preserves::value::IOValue) -> std::result::Result<CompoundPattern, ()> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT10 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 1 { return Err(()); }
let _tmp6 = (&_tmp1.fields()[0]).value().to_sequence().map_err(|_| ())?;
let mut _tmp5 = std::vec::Vec::new();
for _tmp7 in &_tmp6[0..] {let _tmp8 = NamedPattern::try_from(_tmp7)?; _tmp5.push(_tmp8);}
Ok(CompoundPattern::Tuple {patterns: _tmp5})
}
fn _parse_compound_pattern_tuple_prefix(value: &preserves::value::IOValue) -> std::result::Result<CompoundPattern, ()> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT11 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 2 { return Err(()); }
let _tmp6 = (&_tmp1.fields()[0]).value().to_sequence().map_err(|_| ())?;
let mut _tmp5 = std::vec::Vec::new();
for _tmp7 in &_tmp6[0..] {let _tmp8 = NamedPattern::try_from(_tmp7)?; _tmp5.push(_tmp8);}
let _tmp10 = NamedSimplePattern::try_from((&_tmp1.fields()[1]))?;
Ok(CompoundPattern::TuplePrefix {fixed: _tmp5, variable: std::boxed::Box::new(_tmp10)})
}
fn _parse_compound_pattern_dict(value: &preserves::value::IOValue) -> std::result::Result<CompoundPattern, ()> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT12 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 1 { return Err(()); }
let _tmp5 = DictionaryEntries::try_from((&_tmp1.fields()[0]))?;
Ok(CompoundPattern::Dict {entries: std::boxed::Box::new(_tmp5)})
}
impl std::convert::TryFrom<&preserves::value::IOValue> for CompoundPattern {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
if let Ok(r) = _parse_compound_pattern_rec(value) { return Ok(r); }
if let Ok(r) = _parse_compound_pattern_tuple(value) { return Ok(r); }
if let Ok(r) = _parse_compound_pattern_tuple_prefix(value) { return Ok(r); }
if let Ok(r) = _parse_compound_pattern_dict(value) { return Ok(r); }
Err(())
}
}
fn _parse_definition_or(value: &preserves::value::IOValue) -> std::result::Result<Definition, ()> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT13 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 1 { return Err(()); }
let _tmp5 = (&_tmp1.fields()[0]).value().to_sequence().map_err(|_| ())?;
if _tmp5.len() - 0 < 2 { return Err(()); }
let _tmp7 = NamedAlternative::try_from((&_tmp5[0]))?;
let _tmp9 = NamedAlternative::try_from((&_tmp5[1]))?;
let mut _tmp11 = std::vec::Vec::new();
for _tmp12 in &_tmp5[2..] {let _tmp13 = NamedAlternative::try_from(_tmp12)?; _tmp11.push(_tmp13);}
Ok(Definition::Or {
pattern_0: std::boxed::Box::new(_tmp7),
pattern_1: std::boxed::Box::new(_tmp9),
pattern_n: _tmp11
})
}
fn _parse_definition_and(value: &preserves::value::IOValue) -> std::result::Result<Definition, ()> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT14 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 1 { return Err(()); }
let _tmp5 = (&_tmp1.fields()[0]).value().to_sequence().map_err(|_| ())?;
if _tmp5.len() - 0 < 2 { return Err(()); }
let _tmp7 = NamedPattern::try_from((&_tmp5[0]))?;
let _tmp9 = NamedPattern::try_from((&_tmp5[1]))?;
let mut _tmp11 = std::vec::Vec::new();
for _tmp12 in &_tmp5[2..] {let _tmp13 = NamedPattern::try_from(_tmp12)?; _tmp11.push(_tmp13);}
Ok(Definition::And {
pattern_0: std::boxed::Box::new(_tmp7),
pattern_1: std::boxed::Box::new(_tmp9),
pattern_n: _tmp11
})
}
fn _parse_definition_pattern(value: &preserves::value::IOValue) -> std::result::Result<Definition, ()> {
let _tmp0 = Pattern::try_from(value)?;
Ok(Definition::Pattern(std::boxed::Box::new(_tmp0)))
}
impl std::convert::TryFrom<&preserves::value::IOValue> for Definition {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
if let Ok(r) = _parse_definition_or(value) { return Ok(r); }
if let Ok(r) = _parse_definition_and(value) { return Ok(r); }
if let Ok(r) = _parse_definition_pattern(value) { return Ok(r); }
Err(())
}
}
impl std::convert::TryFrom<&preserves::value::IOValue> for Definitions {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
let mut _tmp0 = preserves::value::Map::new();
for (_tmp1, _tmp2) in value.value().to_dictionary().map_err(|_| ())? {
let _tmp3 = _tmp1.value().to_symbol().map_err(|_| ())?;
let _tmp4 = Definition::try_from(_tmp2)?;
_tmp0.insert(_tmp3.clone(), _tmp4);
}
Ok(Definitions(_tmp0))
}
}
impl std::convert::TryFrom<&preserves::value::IOValue> for DictionaryEntries {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
let mut _tmp0 = preserves::value::Map::new();
for (_tmp1, _tmp2) in value.value().to_dictionary().map_err(|_| ())? {
let _tmp3 = _tmp1;
let _tmp4 = NamedSimplePattern::try_from(_tmp2)?;
_tmp0.insert(_tmp3.clone(), _tmp4);
}
Ok(DictionaryEntries(_tmp0))
}
}
fn _parse_embedded_type_name_ref(value: &preserves::value::IOValue) -> std::result::Result<EmbeddedTypeName, ()> {
let _tmp0 = Ref::try_from(value)?;
Ok(EmbeddedTypeName::Ref(std::boxed::Box::new(_tmp0)))
}
fn _parse_embedded_type_name_false(value: &preserves::value::IOValue) -> std::result::Result<EmbeddedTypeName, ()> {
if value != &*LIT15 { return Err(()); }
let _tmp0 = ();
Ok(EmbeddedTypeName::False)
}
impl std::convert::TryFrom<&preserves::value::IOValue> for EmbeddedTypeName {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
if let Ok(r) = _parse_embedded_type_name_ref(value) { return Ok(r); }
if let Ok(r) = _parse_embedded_type_name_false(value) { return Ok(r); }
Err(())
}
}
impl std::convert::TryFrom<&preserves::value::IOValue> for ModulePath {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
let _tmp1 = value.value().to_sequence().map_err(|_| ())?;
let mut _tmp0 = std::vec::Vec::new();
for _tmp2 in &_tmp1[0..] {
let _tmp3 = _tmp2.value().to_symbol().map_err(|_| ())?;
_tmp0.push(_tmp3.clone());
}
Ok(ModulePath(_tmp0))
}
}
impl std::convert::TryFrom<&preserves::value::IOValue> for Modules {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
let mut _tmp0 = preserves::value::Map::new();
for (_tmp1, _tmp2) in value.value().to_dictionary().map_err(|_| ())? {
let _tmp3 = ModulePath::try_from(_tmp1)?;
let _tmp4 = Schema::try_from(_tmp2)?;
_tmp0.insert(_tmp3, _tmp4);
}
Ok(Modules(_tmp0))
}
}
impl std::convert::TryFrom<&preserves::value::IOValue> for NamedAlternative {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
let _tmp1 = value.value().to_sequence().map_err(|_| ())?;
if _tmp1.len() - 0 < 2 { return Err(()); }
let _tmp3 = (&_tmp1[0]).value().to_string().map_err(|_| ())?;
let _tmp5 = Pattern::try_from((&_tmp1[1]))?;
Ok(NamedAlternative {variant_label: _tmp3.clone(), pattern: std::boxed::Box::new(_tmp5)})
}
}
fn _parse_named_pattern_named(value: &preserves::value::IOValue) -> std::result::Result<NamedPattern, ()> {
let _tmp0 = Binding::try_from(value)?;
Ok(NamedPattern::Named(std::boxed::Box::new(_tmp0)))
}
fn _parse_named_pattern_anonymous(value: &preserves::value::IOValue) -> std::result::Result<NamedPattern, ()> {
let _tmp0 = Pattern::try_from(value)?;
Ok(NamedPattern::Anonymous(std::boxed::Box::new(_tmp0)))
}
impl std::convert::TryFrom<&preserves::value::IOValue> for NamedPattern {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
if let Ok(r) = _parse_named_pattern_named(value) { return Ok(r); }
if let Ok(r) = _parse_named_pattern_anonymous(value) { return Ok(r); }
Err(())
}
}
fn _parse_named_simple_pattern_named(value: &preserves::value::IOValue) -> std::result::Result<NamedSimplePattern, ()> {
let _tmp0 = Binding::try_from(value)?;
Ok(NamedSimplePattern::Named(std::boxed::Box::new(_tmp0)))
}
fn _parse_named_simple_pattern_anonymous(value: &preserves::value::IOValue) -> std::result::Result<NamedSimplePattern, ()> {
let _tmp0 = SimplePattern::try_from(value)?;
Ok(NamedSimplePattern::Anonymous(std::boxed::Box::new(_tmp0)))
}
impl std::convert::TryFrom<&preserves::value::IOValue> for NamedSimplePattern {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
if let Ok(r) = _parse_named_simple_pattern_named(value) { return Ok(r); }
if let Ok(r) = _parse_named_simple_pattern_anonymous(value) { return Ok(r); }
Err(())
}
}
fn _parse_pattern_simple_pattern(value: &preserves::value::IOValue) -> std::result::Result<Pattern, ()> {
let _tmp0 = SimplePattern::try_from(value)?;
Ok(Pattern::SimplePattern(std::boxed::Box::new(_tmp0)))
}
fn _parse_pattern_compound_pattern(value: &preserves::value::IOValue) -> std::result::Result<Pattern, ()> {
let _tmp0 = CompoundPattern::try_from(value)?;
Ok(Pattern::CompoundPattern(std::boxed::Box::new(_tmp0)))
}
impl std::convert::TryFrom<&preserves::value::IOValue> for Pattern {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
if let Ok(r) = _parse_pattern_simple_pattern(value) { return Ok(r); }
if let Ok(r) = _parse_pattern_compound_pattern(value) { return Ok(r); }
Err(())
}
}
impl std::convert::TryFrom<&preserves::value::IOValue> for Ref {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT16 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 2 { return Err(()); }
let _tmp5 = ModulePath::try_from((&_tmp1.fields()[0]))?;
let _tmp7 = (&_tmp1.fields()[1]).value().to_symbol().map_err(|_| ())?;
Ok(Ref {module: std::boxed::Box::new(_tmp5), name: _tmp7.clone()})
}
}
impl std::convert::TryFrom<&preserves::value::IOValue> for Schema {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT17 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 1 { return Err(()); }
let _tmp5 = (&_tmp1.fields()[0]).value().to_dictionary().map_err(|_| ())?;
let _tmp6 = _tmp5.get(&*LIT18).ok_or(())?;
let _tmp8 = Definitions::try_from(_tmp6)?;
let _tmp9 = _tmp5.get(&*LIT19).ok_or(())?;
let _tmp11 = EmbeddedTypeName::try_from(_tmp9)?;
let _tmp12 = _tmp5.get(&*LIT20).ok_or(())?;
let _tmp14 = Version::try_from(_tmp12)?;
Ok(Schema {
definitions: std::boxed::Box::new(_tmp8),
embedded_type: std::boxed::Box::new(_tmp11),
version: std::boxed::Box::new(_tmp14)
})
}
}
fn _parse_simple_pattern_any(value: &preserves::value::IOValue) -> std::result::Result<SimplePattern, ()> {if value != &*LIT21 { return Err(()); } let _tmp0 = (); Ok(SimplePattern::Any)}
fn _parse_simple_pattern_atom(value: &preserves::value::IOValue) -> std::result::Result<SimplePattern, ()> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT22 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 1 { return Err(()); }
let _tmp5 = AtomKind::try_from((&_tmp1.fields()[0]))?;
Ok(SimplePattern::Atom {atom_kind: std::boxed::Box::new(_tmp5)})
}
fn _parse_simple_pattern_embedded(value: &preserves::value::IOValue) -> std::result::Result<SimplePattern, ()> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT23 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 1 { return Err(()); }
let _tmp5 = SimplePattern::try_from((&_tmp1.fields()[0]))?;
Ok(SimplePattern::Embedded {interface: std::boxed::Box::new(_tmp5)})
}
fn _parse_simple_pattern_lit(value: &preserves::value::IOValue) -> std::result::Result<SimplePattern, ()> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT24 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 1 { return Err(()); }
let _tmp5 = (&_tmp1.fields()[0]);
Ok(SimplePattern::Lit {value: _tmp5.clone()})
}
fn _parse_simple_pattern_seqof(value: &preserves::value::IOValue) -> std::result::Result<SimplePattern, ()> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT25 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 1 { return Err(()); }
let _tmp5 = SimplePattern::try_from((&_tmp1.fields()[0]))?;
Ok(SimplePattern::Seqof {pattern: std::boxed::Box::new(_tmp5)})
}
fn _parse_simple_pattern_setof(value: &preserves::value::IOValue) -> std::result::Result<SimplePattern, ()> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT26 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 1 { return Err(()); }
let _tmp5 = SimplePattern::try_from((&_tmp1.fields()[0]))?;
Ok(SimplePattern::Setof {pattern: std::boxed::Box::new(_tmp5)})
}
fn _parse_simple_pattern_dictof(value: &preserves::value::IOValue) -> std::result::Result<SimplePattern, ()> {
let _tmp1 = value.value().to_record(None).map_err(|_| ())?;
if _tmp1.label() != &*LIT27 { return Err(()); }
let _tmp2 = ();
if _tmp1.fields().len() - 0 < 2 { return Err(()); }
let _tmp5 = SimplePattern::try_from((&_tmp1.fields()[0]))?;
let _tmp7 = SimplePattern::try_from((&_tmp1.fields()[1]))?;
Ok(SimplePattern::Dictof {key: std::boxed::Box::new(_tmp5), value: std::boxed::Box::new(_tmp7)})
}
fn _parse_simple_pattern_ref(value: &preserves::value::IOValue) -> std::result::Result<SimplePattern, ()> {
let _tmp0 = Ref::try_from(value)?;
Ok(SimplePattern::Ref(std::boxed::Box::new(_tmp0)))
}
impl std::convert::TryFrom<&preserves::value::IOValue> for SimplePattern {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {
if let Ok(r) = _parse_simple_pattern_any(value) { return Ok(r); }
if let Ok(r) = _parse_simple_pattern_atom(value) { return Ok(r); }
if let Ok(r) = _parse_simple_pattern_embedded(value) { return Ok(r); }
if let Ok(r) = _parse_simple_pattern_lit(value) { return Ok(r); }
if let Ok(r) = _parse_simple_pattern_seqof(value) { return Ok(r); }
if let Ok(r) = _parse_simple_pattern_setof(value) { return Ok(r); }
if let Ok(r) = _parse_simple_pattern_dictof(value) { return Ok(r); }
if let Ok(r) = _parse_simple_pattern_ref(value) { return Ok(r); }
Err(())
}
}
impl std::convert::TryFrom<&preserves::value::IOValue> for Version {
type Error = ();
fn try_from(value: &preserves::value::IOValue) -> std::result::Result<Self, Self::Error> {if value != &*LIT28 { return Err(()); } let _tmp0 = (); Ok(Version)}
}

View File

@ -0,0 +1,274 @@
use std::str;
pub const DEFAULT_WIDTH: usize = 80;
pub trait Emittable: std::fmt::Debug {
fn write_on(&self, f: &mut Formatter);
}
pub type Item = std::rc::Rc<dyn Emittable>;
#[derive(Clone)]
pub struct Sequence {
pub items: Vec<Item>,
pub separator: &'static str,
pub terminator: &'static str,
}
#[derive(Clone)]
pub struct Grouping {
pub sequence: Sequence,
pub open: &'static str,
pub close: &'static str,
}
pub struct Formatter {
pub width: usize,
indent_delta: String,
current_indent: String,
pub buffer: String,
}
impl Formatter {
pub fn new() -> Self {
Formatter {
width: DEFAULT_WIDTH,
indent_delta: " ".to_owned(),
current_indent: "\n".to_owned(),
buffer: String::new(),
}
}
pub fn copy_empty(&self) -> Formatter {
Formatter {
width: self.width,
indent_delta: self.indent_delta.clone(),
current_indent: self.current_indent.clone(),
buffer: String::new(),
}
}
pub fn indent_size(self) -> usize {
self.indent_delta.len()
}
pub fn set_indent_size(&mut self, n: usize) {
self.indent_delta = str::repeat(" ", n)
}
pub fn write<E: Emittable>(&mut self, e: E) {
e.write_on(self)
}
pub fn newline(&mut self) {
self.buffer.push_str(&self.current_indent)
}
pub fn to_string<E: Emittable>(e: E) -> String {
let mut f = Formatter::new();
f.write(e);
f.buffer
}
pub fn with_indent<R, F: FnOnce(&mut Self) -> R>(&mut self, f: F) -> R {
let old_indent = self.current_indent.clone();
self.current_indent += &self.indent_delta;
let r = f(self);
self.current_indent = old_indent;
r
}
}
//---------------------------------------------------------------------------
impl Emittable for &str {
fn write_on(&self, f: &mut Formatter) {
f.buffer.push_str(self)
}
}
impl Emittable for String {
fn write_on(&self, f: &mut Formatter) {
f.write(self.as_str())
}
}
impl<'a, E: Emittable> Emittable for &'a Vec<E> where &'a E: Emittable {
fn write_on(&self, f: &mut Formatter) {
for e in self.iter() {
f.write(e)
}
}
}
impl Emittable for Sequence {
fn write_on(&self, f: &mut Formatter) {
let mut need_sep = false;
for e in self.items.iter() {
if need_sep {
self.separator.write_on(f)
} else {
need_sep = true
}
e.write_on(f)
}
self.terminator.write_on(f)
}
}
impl Emittable for Grouping {
fn write_on(&self, f: &mut Formatter) {
let mut g = f.copy_empty();
self.open.write_on(&mut g);
g.write(&self.sequence);
self.close.write_on(&mut g);
let s = g.buffer;
if s.len() <= f.width {
f.write(&s)
} else {
self.open.write_on(f);
if !self.sequence.items.is_empty() {
f.with_indent(|f| {
let mut i = self.sequence.items.len();
for e in self.sequence.items.iter() {
f.newline();
e.write_on(f);
let delim = if i == 1 { self.sequence.terminator } else { self.sequence.separator };
delim.trim_end().write_on(f);
i = i - 1;
}
});
f.newline()
}
self.close.write_on(f);
}
}
}
impl<'a, E: Emittable> Emittable for &'a E {
fn write_on(&self, f: &mut Formatter) {
(*self).write_on(f)
}
}
impl Emittable for Item {
fn write_on(&self, f: &mut Formatter) {
(**self).write_on(f)
}
}
impl std::fmt::Debug for Sequence {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
f.write_str(&Formatter::to_string(self))
}
}
impl std::fmt::Debug for Grouping {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
f.write_str(&Formatter::to_string(self))
}
}
//---------------------------------------------------------------------------
pub mod constructors {
use super::Sequence;
use super::Grouping;
use super::Item;
use super::Emittable;
pub fn item<E: 'static + Emittable>(i: E) -> Item {
std::rc::Rc::new(i)
}
pub fn name(pieces: Vec<Item>) -> Sequence {
Sequence { items: pieces, separator: "::", terminator: "" }
}
pub fn seq(items: Vec<Item>) -> Sequence {
Sequence { items: items, separator: "", terminator: "" }
}
pub fn commas(items: Vec<Item>) -> Sequence {
Sequence { items: items, separator: ", ", terminator: "" }
}
pub fn parens(items: Vec<Item>) -> Grouping {
Grouping { sequence: commas(items), open: "(", close: ")" }
}
pub fn brackets(items: Vec<Item>) -> Grouping {
Grouping { sequence: commas(items), open: "[", close: "]" }
}
pub fn anglebrackets(items: Vec<Item>) -> Grouping {
Grouping { sequence: commas(items), open: "<", close: ">" }
}
pub fn braces(items: Vec<Item>) -> Grouping {
Grouping { sequence: commas(items), open: "{", close: "}" }
}
pub fn block(items: Vec<Item>) -> Grouping {
Grouping {
sequence: Sequence { items: items, separator: " ", terminator: "" },
open: "{",
close: "}",
}
}
pub fn semiblock(items: Vec<Item>) -> Grouping {
Grouping {
sequence: Sequence { items: items, separator: "; ", terminator: "" },
open: "{",
close: "}",
}
}
}
pub mod macros {
#[macro_export]
macro_rules! name {
($($item:expr),*) => {crate::syntax::block::constructors::name(vec![$(std::rc::Rc::new($item)),*])}
}
#[macro_export]
macro_rules! seq {
($($item:expr),*) => {crate::syntax::block::constructors::seq(vec![$(std::rc::Rc::new($item)),*])}
}
#[macro_export]
macro_rules! commas {
($($item:expr),*) => {crate::syntax::block::constructors::commas(vec![$(std::rc::Rc::new($item)),*])}
}
#[macro_export]
macro_rules! parens {
($($item:expr),*) => {crate::syntax::block::constructors::parens(vec![$(std::rc::Rc::new($item)),*])}
}
#[macro_export]
macro_rules! brackets {
($($item:expr),*) => {crate::syntax::block::constructors::brackets(vec![$(std::rc::Rc::new($item)),*])}
}
#[macro_export]
macro_rules! anglebrackets {
($($item:expr),*) => {crate::syntax::block::constructors::anglebrackets(vec![$(std::rc::Rc::new($item)),*])}
}
#[macro_export]
macro_rules! braces {
($($item:expr),*) => {crate::syntax::block::constructors::braces(vec![$(std::rc::Rc::new($item)),*])}
}
#[macro_export]
macro_rules! block {
($($item:expr),*) => {crate::syntax::block::constructors::block(vec![$(std::rc::Rc::new($item)),*])}
}
#[macro_export]
macro_rules! semiblock {
($($item:expr),*) => {crate::syntax::block::constructors::semiblock(vec![$(std::rc::Rc::new($item)),*])}
}
}

View File

@ -0,0 +1 @@
pub mod block;

View File

@ -21,6 +21,7 @@ pub use repr::Map;
pub use repr::NestedValue;
pub use repr::PlainValue;
pub use repr::RcValue;
pub use repr::Record;
pub use repr::Set;
pub use repr::UnwrappedIOValue;
pub use repr::Value;

View File

@ -720,6 +720,22 @@ impl<N: NestedValue<D>, D: Domain> Value<N, D> {
self.as_dictionary().ok_or_else(|| self.expected(ExpectedKind::Dictionary))
}
pub fn is_embedded(&self) -> bool {
self.as_embedded().is_some()
}
pub fn as_embedded(&self) -> Option<&D> {
if let Value::Domain(ref d) = *self {
Some(d)
} else {
None
}
}
pub fn to_embedded(&self) -> Result<&D, Error> {
self.as_embedded().ok_or_else(|| self.expected(ExpectedKind::Embedded))
}
pub fn copy_via<M: NestedValue<E>, E: Domain, F>(&self, f: &F) -> Value<M, E>
where
F: Fn(&D) -> Value<M, E>