diff --git a/implementations/rust/preserves-schema/src/compiler/codegen.rs b/implementations/rust/preserves-schema/src/compiler/codegen.rs new file mode 100644 index 0000000..d33f4b5 --- /dev/null +++ b/implementations/rust/preserves-schema/src/compiler/codegen.rs @@ -0,0 +1,11 @@ +use crate::*; +use crate::syntax::block::Item; +use crate::syntax::block::constructors::*; + +pub fn push_let(body: &mut Vec, name: Item, expr: Item) { + body.push(item(seq!["let ", name, " = ", expr, ";"])) +} + +pub fn push_let_mut(body: &mut Vec, name: Item, expr: Item) { + body.push(item(seq!["let mut ", name, " = ", expr, ";"])) +} diff --git a/implementations/rust/preserves-schema/src/compiler/context.rs b/implementations/rust/preserves-schema/src/compiler/context.rs index a440afa..d8dc6c0 100644 --- a/implementations/rust/preserves-schema/src/compiler/context.rs +++ b/implementations/rust/preserves-schema/src/compiler/context.rs @@ -13,7 +13,6 @@ pub struct ModuleContext { pub struct FunctionContext<'a> { pub m: &'a mut ModuleContext, pub temp_counter: usize, - pub temps: Map>, pub captures: Vec, } @@ -52,7 +51,6 @@ impl<'a> FunctionContext<'a> { FunctionContext { m: m, temp_counter: 0, - temps: Map::new(), captures: Vec::new(), } } @@ -65,9 +63,27 @@ impl<'a> FunctionContext<'a> { }) } + pub fn lookup_capture(&self, field_name: &str) -> &Capture { + for c in &self.captures { + if c.field_name == field_name { + return c; + } + } + panic!("No capture for field {:?} available", field_name) + } + pub fn gentempname(&mut self) -> String { let i = self.temp_counter; self.temp_counter += 1; format!("_tmp{}", i) } + + pub fn branch R>(&mut self, f: F) -> R { + let saved_temp_counter = self.temp_counter; + let saved_capture_count = self.captures.len(); + let result = f(self); + self.temp_counter = saved_temp_counter; + self.captures.truncate(saved_capture_count); + result + } } diff --git a/implementations/rust/preserves-schema/src/compiler/mod.rs b/implementations/rust/preserves-schema/src/compiler/mod.rs index abde3f9..218a6f8 100644 --- a/implementations/rust/preserves-schema/src/compiler/mod.rs +++ b/implementations/rust/preserves-schema/src/compiler/mod.rs @@ -2,6 +2,8 @@ pub mod types; pub mod names; pub mod context; pub mod parsers; +pub mod unparsers; +pub mod codegen; use std::path::PathBuf; use preserves::value::Map; @@ -40,6 +42,7 @@ pub fn compile(config: &CompilerConfig) -> Result<(), std::io::Error> { for (n, d) in &v.definitions.0 { m.define_type(item(types::render_definition_type(n, &types::definition_type(d)))); parsers::gen_definition_parser(&mut m, n, d); + unparsers::gen_definition_unparser(&mut m, n, d); } //--------------------------------------------------------------------------- diff --git a/implementations/rust/preserves-schema/src/compiler/parsers.rs b/implementations/rust/preserves-schema/src/compiler/parsers.rs index f110611..7136986 100644 --- a/implementations/rust/preserves-schema/src/compiler/parsers.rs +++ b/implementations/rust/preserves-schema/src/compiler/parsers.rs @@ -1,10 +1,12 @@ use crate::*; +use crate::metaschema::*; use crate::syntax::block::Item; use crate::syntax::block::constructors::*; + +use super::codegen::*; +use super::context::{ModuleContext, FunctionContext}; use super::names; use super::types::*; -use crate::metaschema::*; -use super::context::{ModuleContext, FunctionContext}; pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) { m.define_function( @@ -23,7 +25,7 @@ pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) { 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, false, &TDefinition::Simple(pattern_type(pat)), dest, &mut body); + construct(&ctxt, ctorname, false, &pattern_type(pat), dest, &mut body); item(seq!["fn ", fname.clone(), "(value: &preserves::value::IOValue) -> ", "std::result::Result<", names::render_constructor(n), ", ()> ", block(body)]) @@ -35,15 +37,15 @@ pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) { Definition::And { pattern_0, pattern_1, pattern_n } => { let mut ps = vec![&**pattern_0, &**pattern_1]; ps.extend(pattern_n); - for e in ps { + for e in &ps { named_pattern_parser(&mut ctxt, e, "value", None, &mut body); } - construct(&ctxt, item(names::render_constructor(n)), true, &definition_type(d), None, &mut body); + construct(&ctxt, item(names::render_constructor(n)), true, &record_type(&ps), None, &mut body); } Definition::Pattern(p) => { let dest = pattern_parser(&mut ctxt, p, "value", None, &mut body); let dest = dest.as_ref().map(String::as_str); - construct(&ctxt, item(names::render_constructor(n)), true, &definition_type(d), dest, &mut body); + construct(&ctxt, item(names::render_constructor(n)), true, &pattern_type(p), dest, &mut body); } } @@ -60,16 +62,16 @@ fn construct( ctxt: &FunctionContext, ctorname: Item, is_struct: bool, - ty: &TDefinition, + ty: &TSimple, dest: Option<&str>, body: &mut Vec, ) { match ty { - TDefinition::Simple(TSimple::Field(TField::Unit)) => + TSimple::Field(TField::Unit) => body.push(item(seq!["Ok(", ctorname, ")"])), - TDefinition::Simple(TSimple::Field(fieldty)) => + TSimple::Field(fieldty) => body.push(item(seq!["Ok(", ctorname, parens![store_wrap(is_struct, fieldty, dest.unwrap())], ")"])), - _ => + TSimple::Record(_) => body.push(item(seq!["Ok(", ctorname, " ", braces( ctxt.captures.iter().map( |c| item(seq![c.field_name.clone(), ": ", store_wrap(is_struct, &c.ty, &c.source_expr)])).collect()), @@ -93,14 +95,6 @@ fn store_wrap(is_struct: bool, ty: &TField, expr: &str) -> String { } } -fn push_let(body: &mut Vec, name: &str, expr: Item) { - body.push(item(seq!["let ", name.to_owned(), " = ", expr, ";"])) -} - -fn push_let_mut(body: &mut Vec, name: &str, expr: Item) { - body.push(item(seq!["let mut ", name.to_owned(), " = ", expr, ";"])) -} - fn simple_pattern_parser( ctxt: &mut FunctionContext, p: &SimplePattern, @@ -111,7 +105,7 @@ fn simple_pattern_parser( let dest = ctxt.gentempname(); match p { SimplePattern::Any => { - push_let(body, &dest, item(src.to_owned())); + push_let(body, item(dest.to_owned()), item(src.to_owned())); dest }, SimplePattern::Atom { atom_kind: k } => { @@ -124,17 +118,17 @@ fn simple_pattern_parser( AtomKind::ByteString => "to_bytestring", AtomKind::Symbol => "to_symbol", }; - push_let(body, &dest, item(seq![src.to_owned(), ".value().", converter, "().map_err(|_| ())?"])); + push_let(body, item(dest.to_owned()), item(seq![src.to_owned(), ".value().", converter, "().map_err(|_| ())?"])); dest }, SimplePattern::Embedded { .. } => { - push_let(body, &dest, item(seq![src.to_owned(), ".value().to_embedded().map_err(|_| ())?"])); + push_let(body, item(dest.to_owned()), item(seq![src.to_owned(), ".value().to_embedded().map_err(|_| ())?"])); dest }, SimplePattern::Lit { value } => { body.push(item(seq!["if ", src.to_owned(), " != ", ctxt.m.define_literal(value), " { return Err(()); }"])); - push_let(body, &dest, item("()")); + push_let(body, item(dest.to_owned()), item("()")); dest }, SimplePattern::Seqof { pattern } => { @@ -144,7 +138,7 @@ fn simple_pattern_parser( let item_dest = simple_pattern_parser(ctxt, pattern, &tmp, None, &mut inner); inner.push(item(seq![dest.to_owned(), ".push(", store_wrap(true, &field_type(pattern), &item_dest), ");"])); - push_let_mut(body, &dest, item("std::vec::Vec::new()")); + push_let_mut(body, item(dest.to_owned()), item("std::vec::Vec::new()")); body.push(item(seq!["for ", tmp.to_owned(), " in &", src.to_owned(), brackets![seq![n.to_string() , ".."]], " ", block(inner)])); @@ -156,7 +150,7 @@ fn simple_pattern_parser( let item_dest = simple_pattern_parser(ctxt, pattern, &tmp, None, &mut inner); inner.push(item(seq![dest.to_owned(), ".insert(", store_wrap(true, &field_type(pattern), &item_dest), ");"])); - push_let_mut(body, &dest, item("preserves::value::Set::new()")); + push_let_mut(body, item(dest.to_owned()), item("preserves::value::Set::new()")); body.push(item(seq!["for ", tmp.to_owned(), " in ", src.to_owned(), ".value().to_set().map_err(|_| ())?", " ", block(inner)])); @@ -172,7 +166,7 @@ fn simple_pattern_parser( dest.to_owned(), ".insert(", store_wrap(true, &field_type(key), &key_dest), ", ", store_wrap(true, &field_type(value), &value_dest), ");"])); - push_let_mut(body, &dest, item("preserves::value::Map::new()")); + push_let_mut(body, item(dest.to_owned()), 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)])); @@ -183,9 +177,9 @@ fn simple_pattern_parser( let mut mp = module.clone(); mp.push(name.to_owned()); let tf = name![names::render_ref(mp), "try_from"]; - push_let(body, &dest, item(seq![tf, - parens![src.to_owned()], - "?"])); + push_let(body, + item(dest.to_owned()), + item(seq![tf, parens![src.to_owned()], "?"])); dest }, } @@ -201,7 +195,9 @@ fn sequenceify( 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(|_| ())?"])); + push_let(body, + item(tmp.to_owned()), + item(seq![src.to_owned(), ".value().to_sequence().map_err(|_| ())?"])); (tmp, 0) } } @@ -257,7 +253,7 @@ fn pattern_parser( match &**c { CompoundPattern::Rec { label, fields } => { let rtmp = ctxt.gentempname(); - push_let(body, &rtmp, item(seq![src.to_owned(), ".value().to_record(None).map_err(|_| ())?"])); + push_let(body, item(rtmp.to_owned()), item(seq![src.to_owned(), ".value().to_record(None).map_err(|_| ())?"])); named_pattern_parser(ctxt, &**label, &format!("{}.label()", rtmp), None, body); named_pattern_parser(ctxt, &**fields, &format!("{}.fields()", rtmp), Some(0), body); }, @@ -268,14 +264,14 @@ fn pattern_parser( CompoundPattern::TuplePrefix { fixed, variable } => { let (src, n) = sequenceify(ctxt, src, sequence_base, body); fixed_sequence_parser(ctxt, n, fixed, &src, body); - named_pattern_parser(ctxt, &promote(&**variable), &src, Some(n + fixed.len()), body); + named_pattern_parser(ctxt, &promote(variable), &src, Some(n + fixed.len()), body); }, CompoundPattern::Dict { entries } => { let dtmp = ctxt.gentempname(); - push_let(body, &dtmp, item(seq![src.to_owned(), ".value().to_dictionary().map_err(|_| ())?"])); + push_let(body, item(dtmp.to_owned()), item(seq![src.to_owned(), ".value().to_dictionary().map_err(|_| ())?"])); for (key_lit, value_pat) in entries.0.iter() { let vtmp = ctxt.gentempname(); - push_let(body, &vtmp, item(seq![ + push_let(body, item(vtmp.to_owned()), item(seq![ dtmp.to_owned(), ".get", parens![ctxt.m.define_literal(key_lit)], ".ok_or(())?"])); named_pattern_parser(ctxt, &promote(value_pat), &vtmp, None, body); diff --git a/implementations/rust/preserves-schema/src/compiler/types.rs b/implementations/rust/preserves-schema/src/compiler/types.rs index bf8737f..e6f32d6 100644 --- a/implementations/rust/preserves-schema/src/compiler/types.rs +++ b/implementations/rust/preserves-schema/src/compiler/types.rs @@ -31,24 +31,39 @@ pub struct TRecord(pub Vec<(String, TField)>); pub fn definition_type(d: &Definition) -> TDefinition { match d { - Definition::Or { pattern_0, pattern_1, pattern_n } => { - let mut entries = Vec::new(); - entries.push((pattern_0.variant_label.to_owned(), pattern_type(&pattern_0.pattern))); - entries.push((pattern_1.variant_label.to_owned(), pattern_type(&pattern_1.pattern))); - for e in pattern_n { - entries.push((e.variant_label.to_owned(), pattern_type(&e.pattern))); - } - TDefinition::Union(entries) - }, - Definition::And { pattern_0, pattern_1, pattern_n } => { - let mut arms = vec![&**pattern_0, &**pattern_1]; - arms.extend(pattern_n); - TDefinition::Simple(record_type(&arms)) - }, - Definition::Pattern(p) => TDefinition::Simple(pattern_type(p)), + Definition::Or { pattern_0, pattern_1, pattern_n } => + TDefinition::Union(or_definition_type(pattern_0, pattern_1, pattern_n)), + Definition::And { pattern_0, pattern_1, pattern_n } => + TDefinition::Simple(and_definition_type(pattern_0, pattern_1, pattern_n)), + Definition::Pattern(p) => + TDefinition::Simple(pattern_type(p)), } } +pub fn or_definition_type( + p0: &NamedAlternative, + p1: &NamedAlternative, + pn: &Vec, +) -> Vec<(String, TSimple)> { + let mut entries = Vec::new(); + entries.push((p0.variant_label.to_owned(), pattern_type(&p0.pattern))); + entries.push((p1.variant_label.to_owned(), pattern_type(&p1.pattern))); + for e in pn { + entries.push((e.variant_label.to_owned(), pattern_type(&e.pattern))); + } + entries +} + +pub fn and_definition_type( + p0: &NamedPattern, + p1: &NamedPattern, + pn: &Vec, +) -> TSimple { + let mut arms = vec![p0, p1]; + arms.extend(pn); + record_type(&arms) +} + pub fn pattern_type(p: &Pattern) -> TSimple { match p { Pattern::SimplePattern(p) => diff --git a/implementations/rust/preserves-schema/src/compiler/unparsers.rs b/implementations/rust/preserves-schema/src/compiler/unparsers.rs new file mode 100644 index 0000000..7408473 --- /dev/null +++ b/implementations/rust/preserves-schema/src/compiler/unparsers.rs @@ -0,0 +1,287 @@ +use crate::*; +use crate::metaschema::*; +use crate::syntax::block::constructors::*; +use crate::syntax::block::{Emittable, Item}; + +use std::cell::Cell; +use std::rc::Rc; + +use super::codegen::*; +use super::context::{ModuleContext, FunctionContext}; +use super::names; +use super::types::*; + +type ValueSource = Option; + +#[derive(Clone)] +struct FieldsSink { + finish: Item, + vec_expr: Item, + body: Vec, +} + +#[derive(Clone)] +enum ValueSink { + Normal, + Fields(Rc>>), +} + +impl std::fmt::Debug for ValueSink { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + match self { + ValueSink::Normal => write!(f, "ValueSink::Normal"), + ValueSink::Fields(_) => write!(f, "ValueSink::Normal"), + } + } +} + +#[derive(Debug)] +struct ValueContext { + src: ValueSource, + sink: ValueSink, + is_struct: bool, +} + +fn normal_none(is_struct: bool) -> ValueContext { + ValueContext { src: None, sink: ValueSink::Normal, is_struct: is_struct } +} + +fn normal_src(src: String, is_struct: bool) -> ValueContext { + ValueContext { src: Some(src), sink: ValueSink::Normal, is_struct: is_struct } +} + +pub fn gen_definition_unparser(m: &mut ModuleContext, n: &str, d: &Definition) { + m.define_function( + |mut ctxt| { + let mut body = Vec::new(); + + match d { + Definition::Or { pattern_0, pattern_1, pattern_n } => { + let mut ps = vec![&**pattern_0, &**pattern_1]; + ps.extend(pattern_n); + body.push(item(seq!["match value ", block(ps.iter().map( + | NamedAlternative { variant_label: name, pattern: pat } | ctxt.branch(|ctxt| { + let ctorname = item(name![names::render_constructor(n), names::render_constructor(name)]); + let (patpat, vc) = destruct(ctxt, ctorname, false, &pattern_type(pat)); + item(seq![patpat, " => ", pattern_unparser(ctxt, pat, &vc), ","]) + })).collect())])); + } + Definition::And { pattern_0, pattern_1, pattern_n } => { + let mut ps = vec![&**pattern_0, &**pattern_1]; + ps.extend(pattern_n); + let (patpat, vc) = destruct(&mut ctxt, item(names::render_constructor(n)), true, &record_type(&ps)); + push_let(&mut body, item(patpat), item("value")); + body.push(item(seq!["preserves::value::merge(vec!", brackets(ps.iter().map( + |p| named_pattern_unparser(&mut ctxt, p, &vc)).collect()), ")"])); + } + Definition::Pattern(p) => { + let (patpat, vc) = destruct(&mut ctxt, item(names::render_constructor(n)), true, &pattern_type(p)); + push_let(&mut body, item(patpat), item("value")); + body.push(pattern_unparser(&mut ctxt, p, &vc)); + } + } + + item(seq!["impl std::convert::From", anglebrackets![seq!["&", names::render_constructor(n)]], + " for preserves::value::IOValue ", block![ + seq!["fn from(value: &", names::render_constructor(n), ") -> Self ", + block(body)]]]) + }); +} + +fn destruct( + ctxt: &mut FunctionContext, + ctorname: Item, + is_struct: bool, + ty: &TSimple, +) -> (impl Emittable, ValueContext) { + match ty { + TSimple::Field(TField::Unit) => (seq![ctorname], normal_none(is_struct)), + TSimple::Field(_) => { + let src = ctxt.gentempname(); + (seq![ctorname, parens![src.to_owned()]], normal_src(src, is_struct)) + } + TSimple::Record(TRecord(fs)) => { + for (fname, fty) in fs { + let fsrc = ctxt.gentempname(); + ctxt.capture(names::render_fieldname(fname), fty.clone(), fsrc); + } + (seq![ + ctorname, " ", braces(ctxt.captures.iter().map( + |c| item(seq![c.field_name.clone(), ": ", c.source_expr.clone()])).collect())], + normal_none(is_struct)) + } + } +} + +fn simple_pattern_unparser( + ctxt: &mut FunctionContext, + p: &SimplePattern, + vc: &ValueContext, +) -> Item { + let src = &vc.src; + match p { + SimplePattern::Any => + item(seq![src.as_ref().unwrap().to_owned(), ".clone()"]), + SimplePattern::Atom { atom_kind: k } => { + if let AtomKind::Symbol = &**k { + item(seq!["preserves::value::Value::symbol(", src.as_ref().unwrap().to_owned(), ").wrap()"]) + } else { + item(seq!["preserves::value::Value::from(", src.as_ref().unwrap().to_owned(), ").wrap()"]) + } + } + SimplePattern::Embedded { .. } => + item(seq!["preserves::value::Value::Domain(", src.as_ref().unwrap().to_owned(), ").wrap()"]), + SimplePattern::Lit { value } => + item(seq![parens![ctxt.m.define_literal(value)], ".clone()"]), + SimplePattern::Seqof { pattern } => { + let mut fields_sink = sequenceify(ctxt, vc); + let tmp = ctxt.gentempname(); + fields_sink.body.push(item(seq![ + "for ", tmp.to_owned(), " in ", + src.as_ref().unwrap().to_owned(), " ", block![ + seq![fields_sink.vec_expr.clone(), ".push(", + simple_pattern_unparser(ctxt, + pattern, + &normal_src(tmp, true)), ");"]]])); + finish(fields_sink) + } + SimplePattern::Setof { pattern } => { + let tmp = ctxt.gentempname(); + item(seq!["preserves::value::Value::Set(", + src.as_ref().unwrap().to_owned(), ".iter().map(|", tmp.to_owned(), "| ", + simple_pattern_unparser(ctxt, pattern, &normal_src(tmp, true)), + ").collect()).wrap()"]) + } + SimplePattern::Dictof { key, value } => { + let tmp_key = ctxt.gentempname(); + let tmp_value = ctxt.gentempname(); + item(seq!["preserves::value::Value::Dictionary(", + src.as_ref().unwrap().to_owned(), + ".iter().map(|(", tmp_key.to_owned(), ", ", tmp_value.to_owned(), ")| ", + parens![simple_pattern_unparser(ctxt, key, &normal_src(tmp_key, true)), + simple_pattern_unparser(ctxt, value, &normal_src(tmp_value, true))], + ").collect()).wrap()"]) + } + SimplePattern::Ref(_r) => + item(seq!["preserves::value::IOValue::from(", src.as_ref().unwrap().to_owned(), + if vc.is_struct { "" } else { ".as_ref()" }, + ")"]), + } +} + +fn named_pattern_unparser( + ctxt: &mut FunctionContext, + p: &NamedPattern, + vc: &ValueContext, +) -> Item { + match p { + NamedPattern::Anonymous(p) => + pattern_unparser(ctxt, p, vc), + NamedPattern::Named(b) => { + let Binding { name, pattern} = &**b; + let src = ctxt.lookup_capture(&names::render_fieldname(name)).source_expr.to_owned(); + simple_pattern_unparser(ctxt, pattern, &ValueContext { + src: Some(src), + sink: vc.sink.clone(), + is_struct: vc.is_struct, + }) + } + } +} + +fn pattern_unparser( + ctxt: &mut FunctionContext, + p: &Pattern, + vc: &ValueContext, +) -> Item { + match p { + Pattern::SimplePattern(s) => + simple_pattern_unparser(ctxt, s, vc), + Pattern::CompoundPattern(c) => { + match &**c { + CompoundPattern::Rec { label, fields } => { + let rtmp = ctxt.gentempname(); + let mut body = Vec::new(); + push_let_mut(&mut body, + item(rtmp.to_owned()), + item(seq!["preserves::value::Record(vec![", + named_pattern_unparser(ctxt, label, &normal_none(vc.is_struct)), + "])"])); + named_pattern_unparser(ctxt, fields, &ValueContext { + src: None, + sink: ValueSink::Fields(Rc::new(Cell::new(Some(FieldsSink { + finish: item(seq![rtmp.clone(), ".finish().wrap()"]), + vec_expr: item(seq![rtmp.clone(), ".fields_vec_mut()"]), + body: body, + })))), + is_struct: vc.is_struct, + }) + }, + CompoundPattern::Tuple { patterns } => { + let mut fields_sink = sequenceify(ctxt, vc); + fixed_sequence_parser(ctxt, patterns, &mut fields_sink, vc.is_struct); + finish(fields_sink) + }, + CompoundPattern::TuplePrefix { fixed, variable } => { + let mut fields_sink = sequenceify(ctxt, vc); + fixed_sequence_parser(ctxt, fixed, &mut fields_sink, vc.is_struct); + named_pattern_unparser(ctxt, &promote(variable), &ValueContext { + src: vc.src.clone(), + sink: ValueSink::Fields(Rc::new(Cell::new(Some(fields_sink)))), + is_struct: true, + }) + }, + CompoundPattern::Dict { entries } => { + let dtmp = item(ctxt.gentempname()); + let mut body = Vec::new(); + push_let_mut(&mut body, dtmp.clone(), item("preserves::value::Map::new()")); + for (key_lit, value_pat) in entries.0.iter() { + body.push(item(seq![dtmp.clone(), ".insert", parens![ + seq![parens![ctxt.m.define_literal(key_lit)], ".clone()"], + named_pattern_unparser(ctxt, &promote(value_pat), &normal_none(vc.is_struct))], ";"])); + } + body.push(item(seq!["preserves::value::Value::Dictionary(", dtmp, ").wrap()"])); + item(block(body)) + } + } + }, + } +} + +fn sequenceify<'a>( + ctxt: &mut FunctionContext, + vc: &'a ValueContext, +) -> FieldsSink { + match vc { + ValueContext { sink: ValueSink::Fields(fields_sink), .. } => + (**fields_sink).take().unwrap(), + _ => { + let rtmp = item(ctxt.gentempname()); + let mut body = Vec::new(); + push_let_mut(&mut body, rtmp.clone(), item("vec![]")); + FieldsSink { + finish: item(seq![ + "preserves::value::Value::Sequence", parens![rtmp.clone()], ".wrap()"]), + vec_expr: rtmp, + body: body, + } + } + } +} + +fn finish(mut fields_sink: FieldsSink) -> Item { + fields_sink.body.push(fields_sink.finish); + item(block(fields_sink.body)) +} + +fn fixed_sequence_parser( + ctxt: &mut FunctionContext, + patterns: &Vec, + fields_sink: &mut FieldsSink, + is_struct: bool, +) { + for p in patterns { + fields_sink.body.push(item(seq![fields_sink.vec_expr.clone(), ".push", parens![ + named_pattern_unparser(ctxt, p, &normal_none(is_struct))], ";"])); + } +} diff --git a/implementations/rust/preserves-schema/src/lib.rs b/implementations/rust/preserves-schema/src/lib.rs index 17d620e..bb190e8 100644 --- a/implementations/rust/preserves-schema/src/lib.rs +++ b/implementations/rust/preserves-schema/src/lib.rs @@ -30,14 +30,15 @@ mod tests { #[test] fn metaschema_parsing() -> Result<(), std::io::Error> { - use preserves::value::Reader; + use preserves::value::{IOValue, Reader}; use std::convert::TryFrom; + use std::convert::From; 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)); - + let parsed = crate::metaschema::Schema::try_from(&schema).expect("successful parse"); + assert_eq!(schema, IOValue::from(&parsed)); Ok(()) } } diff --git a/implementations/rust/preserves-schema/src/metaschema.rs b/implementations/rust/preserves-schema/src/metaschema.rs index 4ffa4f5..7827a23 100644 --- a/implementations/rust/preserves-schema/src/metaschema.rs +++ b/implementations/rust/preserves-schema/src/metaschema.rs @@ -162,6 +162,20 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for AtomKind { } } +impl std::convert::From<&AtomKind> for preserves::value::IOValue { + fn from(value: &AtomKind) -> Self { + match value { + AtomKind::Boolean => (&*LIT0).clone(), + AtomKind::Float => (&*LIT1).clone(), + AtomKind::Double => (&*LIT2).clone(), + AtomKind::SignedInteger => (&*LIT3).clone(), + AtomKind::String => (&*LIT4).clone(), + AtomKind::ByteString => (&*LIT5).clone(), + AtomKind::Symbol => (&*LIT6).clone(), + } + } +} + impl std::convert::TryFrom<&preserves::value::IOValue> for Binding { type Error = (); fn try_from(value: &preserves::value::IOValue) -> std::result::Result { @@ -175,6 +189,18 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for Binding { } } +impl std::convert::From<&Binding> for preserves::value::IOValue { + fn from(value: &Binding) -> Self { + let Binding {name: _tmp0, pattern: _tmp1} = value; + { + let mut _tmp2 = preserves::value::Record(vec![(&*LIT7).clone()]); + _tmp2.fields_vec_mut().push(preserves::value::Value::symbol(_tmp0).wrap()); + _tmp2.fields_vec_mut().push(preserves::value::IOValue::from(_tmp1)); + _tmp2.finish().wrap() + } + } +} + impl std::convert::TryFrom<&preserves::value::IOValue> for Bundle { type Error = (); fn try_from(value: &preserves::value::IOValue) -> std::result::Result { @@ -187,6 +213,17 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for Bundle { } } +impl std::convert::From<&Bundle> for preserves::value::IOValue { + fn from(value: &Bundle) -> Self { + let Bundle {modules: _tmp0} = value; + { + let mut _tmp1 = preserves::value::Record(vec![(&*LIT8).clone()]); + _tmp1.fields_vec_mut().push(preserves::value::IOValue::from(_tmp0)); + _tmp1.finish().wrap() + } + } +} + fn _parse_compound_pattern_rec(value: &preserves::value::IOValue) -> std::result::Result { let _tmp0 = value.value().to_record(None).map_err(|_| ())?; if _tmp0.label() != &*LIT9 { return Err(()); } @@ -240,6 +277,47 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for CompoundPattern { } } +impl std::convert::From<&CompoundPattern> for preserves::value::IOValue { + fn from(value: &CompoundPattern) -> Self { + match value { + CompoundPattern::Rec {label: _tmp0, fields: _tmp1} => { + let mut _tmp2 = preserves::value::Record(vec![(&*LIT9).clone()]); + _tmp2.fields_vec_mut().push(preserves::value::IOValue::from(_tmp0.as_ref())); + _tmp2.fields_vec_mut().push(preserves::value::IOValue::from(_tmp1.as_ref())); + _tmp2.finish().wrap() + }, + CompoundPattern::Tuple {patterns: _tmp0} => { + let mut _tmp1 = preserves::value::Record(vec![(&*LIT10).clone()]); + _tmp1.fields_vec_mut().push( + { + let mut _tmp2 = vec![]; + for _tmp3 in _tmp0 {_tmp2.push(preserves::value::IOValue::from(_tmp3));} + preserves::value::Value::Sequence(_tmp2).wrap() + } + ); + _tmp1.finish().wrap() + }, + CompoundPattern::TuplePrefix {fixed: _tmp0, variable: _tmp1} => { + let mut _tmp2 = preserves::value::Record(vec![(&*LIT11).clone()]); + _tmp2.fields_vec_mut().push( + { + let mut _tmp3 = vec![]; + for _tmp4 in _tmp0 {_tmp3.push(preserves::value::IOValue::from(_tmp4));} + preserves::value::Value::Sequence(_tmp3).wrap() + } + ); + _tmp2.fields_vec_mut().push(preserves::value::IOValue::from(_tmp1.as_ref())); + _tmp2.finish().wrap() + }, + CompoundPattern::Dict {entries: _tmp0} => { + let mut _tmp1 = preserves::value::Record(vec![(&*LIT12).clone()]); + _tmp1.fields_vec_mut().push(preserves::value::IOValue::from(_tmp0.as_ref())); + _tmp1.finish().wrap() + }, + } + } +} + fn _parse_definition_or(value: &preserves::value::IOValue) -> std::result::Result { let _tmp0 = value.value().to_record(None).map_err(|_| ())?; if _tmp0.label() != &*LIT13 { return Err(()); } @@ -291,6 +369,40 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for Definition { } } +impl std::convert::From<&Definition> for preserves::value::IOValue { + fn from(value: &Definition) -> Self { + match value { + Definition::Or {pattern_0: _tmp0, pattern_1: _tmp1, pattern_n: _tmp2} => { + let mut _tmp3 = preserves::value::Record(vec![(&*LIT13).clone()]); + _tmp3.fields_vec_mut().push( + { + let mut _tmp4 = vec![]; + _tmp4.push(preserves::value::IOValue::from(_tmp0.as_ref())); + _tmp4.push(preserves::value::IOValue::from(_tmp1.as_ref())); + for _tmp5 in _tmp2 {_tmp4.push(preserves::value::IOValue::from(_tmp5));} + preserves::value::Value::Sequence(_tmp4).wrap() + } + ); + _tmp3.finish().wrap() + }, + Definition::And {pattern_0: _tmp0, pattern_1: _tmp1, pattern_n: _tmp2} => { + let mut _tmp3 = preserves::value::Record(vec![(&*LIT14).clone()]); + _tmp3.fields_vec_mut().push( + { + let mut _tmp4 = vec![]; + _tmp4.push(preserves::value::IOValue::from(_tmp0.as_ref())); + _tmp4.push(preserves::value::IOValue::from(_tmp1.as_ref())); + for _tmp5 in _tmp2 {_tmp4.push(preserves::value::IOValue::from(_tmp5));} + preserves::value::Value::Sequence(_tmp4).wrap() + } + ); + _tmp3.finish().wrap() + }, + Definition::Pattern(_tmp0) => preserves::value::IOValue::from(_tmp0.as_ref()), + } + } +} + impl std::convert::TryFrom<&preserves::value::IOValue> for Definitions { type Error = (); fn try_from(value: &preserves::value::IOValue) -> std::result::Result { @@ -304,6 +416,16 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for Definitions { } } +impl std::convert::From<&Definitions> for preserves::value::IOValue { + fn from(value: &Definitions) -> Self { + let Definitions(_tmp0) = value; + preserves::value::Value::Dictionary(_tmp0.iter().map(|(_tmp1, _tmp2)| ( + preserves::value::Value::symbol(_tmp1).wrap(), + preserves::value::IOValue::from(_tmp2) + )).collect()).wrap() + } +} + impl std::convert::TryFrom<&preserves::value::IOValue> for DictionaryEntries { type Error = (); fn try_from(value: &preserves::value::IOValue) -> std::result::Result { @@ -317,6 +439,13 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for DictionaryEntries { } } +impl std::convert::From<&DictionaryEntries> for preserves::value::IOValue { + fn from(value: &DictionaryEntries) -> Self { + let DictionaryEntries(_tmp0) = value; + preserves::value::Value::Dictionary(_tmp0.iter().map(|(_tmp1, _tmp2)| (_tmp1.clone(), preserves::value::IOValue::from(_tmp2))).collect()).wrap() + } +} + fn _parse_embedded_type_name_ref(value: &preserves::value::IOValue) -> std::result::Result { let _tmp0 = Ref::try_from(value)?; Ok(EmbeddedTypeName::Ref(std::boxed::Box::new(_tmp0))) @@ -337,6 +466,15 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for EmbeddedTypeName { } } +impl std::convert::From<&EmbeddedTypeName> for preserves::value::IOValue { + fn from(value: &EmbeddedTypeName) -> Self { + match value { + EmbeddedTypeName::Ref(_tmp0) => preserves::value::IOValue::from(_tmp0.as_ref()), + EmbeddedTypeName::False => (&*LIT15).clone(), + } + } +} + impl std::convert::TryFrom<&preserves::value::IOValue> for ModulePath { type Error = (); fn try_from(value: &preserves::value::IOValue) -> std::result::Result { @@ -350,6 +488,17 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for ModulePath { } } +impl std::convert::From<&ModulePath> for preserves::value::IOValue { + fn from(value: &ModulePath) -> Self { + let ModulePath(_tmp0) = value; + { + let mut _tmp1 = vec![]; + for _tmp2 in _tmp0 {_tmp1.push(preserves::value::Value::symbol(_tmp2).wrap());} + preserves::value::Value::Sequence(_tmp1).wrap() + } + } +} + impl std::convert::TryFrom<&preserves::value::IOValue> for Modules { type Error = (); fn try_from(value: &preserves::value::IOValue) -> std::result::Result { @@ -363,6 +512,13 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for Modules { } } +impl std::convert::From<&Modules> for preserves::value::IOValue { + fn from(value: &Modules) -> Self { + let Modules(_tmp0) = value; + preserves::value::Value::Dictionary(_tmp0.iter().map(|(_tmp1, _tmp2)| (preserves::value::IOValue::from(_tmp1), preserves::value::IOValue::from(_tmp2))).collect()).wrap() + } +} + impl std::convert::TryFrom<&preserves::value::IOValue> for NamedAlternative { type Error = (); fn try_from(value: &preserves::value::IOValue) -> std::result::Result { @@ -374,6 +530,18 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for NamedAlternative { } } +impl std::convert::From<&NamedAlternative> for preserves::value::IOValue { + fn from(value: &NamedAlternative) -> Self { + let NamedAlternative {variant_label: _tmp0, pattern: _tmp1} = value; + { + let mut _tmp2 = vec![]; + _tmp2.push(preserves::value::Value::from(_tmp0).wrap()); + _tmp2.push(preserves::value::IOValue::from(_tmp1)); + preserves::value::Value::Sequence(_tmp2).wrap() + } + } +} + fn _parse_named_pattern_named(value: &preserves::value::IOValue) -> std::result::Result { let _tmp0 = Binding::try_from(value)?; Ok(NamedPattern::Named(std::boxed::Box::new(_tmp0))) @@ -393,6 +561,15 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for NamedPattern { } } +impl std::convert::From<&NamedPattern> for preserves::value::IOValue { + fn from(value: &NamedPattern) -> Self { + match value { + NamedPattern::Named(_tmp0) => preserves::value::IOValue::from(_tmp0.as_ref()), + NamedPattern::Anonymous(_tmp0) => preserves::value::IOValue::from(_tmp0.as_ref()), + } + } +} + fn _parse_named_simple_pattern_named(value: &preserves::value::IOValue) -> std::result::Result { let _tmp0 = Binding::try_from(value)?; Ok(NamedSimplePattern::Named(std::boxed::Box::new(_tmp0))) @@ -412,6 +589,15 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for NamedSimplePattern { } } +impl std::convert::From<&NamedSimplePattern> for preserves::value::IOValue { + fn from(value: &NamedSimplePattern) -> Self { + match value { + NamedSimplePattern::Named(_tmp0) => preserves::value::IOValue::from(_tmp0.as_ref()), + NamedSimplePattern::Anonymous(_tmp0) => preserves::value::IOValue::from(_tmp0.as_ref()), + } + } +} + fn _parse_pattern_simple_pattern(value: &preserves::value::IOValue) -> std::result::Result { let _tmp0 = SimplePattern::try_from(value)?; Ok(Pattern::SimplePattern(std::boxed::Box::new(_tmp0))) @@ -431,6 +617,15 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for Pattern { } } +impl std::convert::From<&Pattern> for preserves::value::IOValue { + fn from(value: &Pattern) -> Self { + match value { + Pattern::SimplePattern(_tmp0) => preserves::value::IOValue::from(_tmp0.as_ref()), + Pattern::CompoundPattern(_tmp0) => preserves::value::IOValue::from(_tmp0.as_ref()), + } + } +} + impl std::convert::TryFrom<&preserves::value::IOValue> for Ref { type Error = (); fn try_from(value: &preserves::value::IOValue) -> std::result::Result { @@ -444,6 +639,18 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for Ref { } } +impl std::convert::From<&Ref> for preserves::value::IOValue { + fn from(value: &Ref) -> Self { + let Ref {module: _tmp0, name: _tmp1} = value; + { + let mut _tmp2 = preserves::value::Record(vec![(&*LIT16).clone()]); + _tmp2.fields_vec_mut().push(preserves::value::IOValue::from(_tmp0)); + _tmp2.fields_vec_mut().push(preserves::value::Value::symbol(_tmp1).wrap()); + _tmp2.finish().wrap() + } + } +} + impl std::convert::TryFrom<&preserves::value::IOValue> for Schema { type Error = (); fn try_from(value: &preserves::value::IOValue) -> std::result::Result { @@ -462,6 +669,25 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for Schema { } } +impl std::convert::From<&Schema> for preserves::value::IOValue { + fn from(value: &Schema) -> Self { + let Schema {definitions: _tmp0, embedded_type: _tmp1, version: _tmp2} = value; + { + let mut _tmp3 = preserves::value::Record(vec![(&*LIT17).clone()]); + _tmp3.fields_vec_mut().push( + { + let mut _tmp4 = preserves::value::Map::new(); + _tmp4.insert((&*LIT18).clone(), preserves::value::IOValue::from(_tmp0)); + _tmp4.insert((&*LIT19).clone(), preserves::value::IOValue::from(_tmp1)); + _tmp4.insert((&*LIT20).clone(), preserves::value::IOValue::from(_tmp2)); + preserves::value::Value::Dictionary(_tmp4).wrap() + } + ); + _tmp3.finish().wrap() + } + } +} + fn _parse_simple_pattern_any(value: &preserves::value::IOValue) -> std::result::Result {if value != &*LIT21 { return Err(()); } let _tmp0 = (); Ok(SimplePattern::Any)} fn _parse_simple_pattern_atom(value: &preserves::value::IOValue) -> std::result::Result { @@ -539,8 +765,50 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for SimplePattern { } } +impl std::convert::From<&SimplePattern> for preserves::value::IOValue { + fn from(value: &SimplePattern) -> Self { + match value { + SimplePattern::Any => (&*LIT21).clone(), + SimplePattern::Atom {atom_kind: _tmp0} => { + let mut _tmp1 = preserves::value::Record(vec![(&*LIT22).clone()]); + _tmp1.fields_vec_mut().push(preserves::value::IOValue::from(_tmp0.as_ref())); + _tmp1.finish().wrap() + }, + SimplePattern::Embedded {interface: _tmp0} => { + let mut _tmp1 = preserves::value::Record(vec![(&*LIT23).clone()]); + _tmp1.fields_vec_mut().push(preserves::value::IOValue::from(_tmp0.as_ref())); + _tmp1.finish().wrap() + }, + SimplePattern::Lit {value: _tmp0} => { + let mut _tmp1 = preserves::value::Record(vec![(&*LIT24).clone()]); + _tmp1.fields_vec_mut().push(_tmp0.clone()); + _tmp1.finish().wrap() + }, + SimplePattern::Seqof {pattern: _tmp0} => { + let mut _tmp1 = preserves::value::Record(vec![(&*LIT25).clone()]); + _tmp1.fields_vec_mut().push(preserves::value::IOValue::from(_tmp0.as_ref())); + _tmp1.finish().wrap() + }, + SimplePattern::Setof {pattern: _tmp0} => { + let mut _tmp1 = preserves::value::Record(vec![(&*LIT26).clone()]); + _tmp1.fields_vec_mut().push(preserves::value::IOValue::from(_tmp0.as_ref())); + _tmp1.finish().wrap() + }, + SimplePattern::Dictof {key: _tmp0, value: _tmp1} => { + let mut _tmp2 = preserves::value::Record(vec![(&*LIT27).clone()]); + _tmp2.fields_vec_mut().push(preserves::value::IOValue::from(_tmp0.as_ref())); + _tmp2.fields_vec_mut().push(preserves::value::IOValue::from(_tmp1.as_ref())); + _tmp2.finish().wrap() + }, + SimplePattern::Ref(_tmp0) => preserves::value::IOValue::from(_tmp0.as_ref()), + } + } +} + impl std::convert::TryFrom<&preserves::value::IOValue> for Version { type Error = (); fn try_from(value: &preserves::value::IOValue) -> std::result::Result {if value != &*LIT28 { return Err(()); } let _tmp0 = (); Ok(Version)} } +impl std::convert::From<&Version> for preserves::value::IOValue {fn from(value: &Version) -> Self {let Version = value; (&*LIT28).clone()}} + diff --git a/implementations/rust/preserves/src/value/repr.rs b/implementations/rust/preserves/src/value/repr.rs index 15811f8..e91b6e3 100644 --- a/implementations/rust/preserves/src/value/repr.rs +++ b/implementations/rust/preserves/src/value/repr.rs @@ -2,6 +2,7 @@ use num::bigint::BigInt; use num::traits::cast::ToPrimitive; use std::borrow::Cow; use std::cmp::Ordering; +use std::convert::From; use std::convert::TryFrom; use std::convert::TryInto; use std::fmt::Debug; @@ -217,9 +218,11 @@ impl, D: Domain> From for Value { fn from(v: i64) - impl, D: Domain> From for Value { fn from(v: u128) -> Self { Value::SignedInteger(SignedInteger::from(v)) } } impl, D: Domain> From for Value { fn from(v: i128) -> Self { Value::SignedInteger(SignedInteger::from(v)) } } impl, D: Domain> From<&BigInt> for Value { fn from(v: &BigInt) -> Self { Value::SignedInteger(SignedInteger::from(Cow::Borrowed(v))) } } +impl, D: Domain> From<&SignedInteger> for Value { fn from(v: &SignedInteger) -> Self { Value::SignedInteger(v.clone()) } } impl, D: Domain> From<&str> for Value { fn from(v: &str) -> Self { Value::String(String::from(v)) } } impl, D: Domain> From for Value { fn from(v: String) -> Self { Value::String(v) } } +impl, D: Domain> From<&String> for Value { fn from(v: &String) -> Self { Value::String(v.to_owned()) } } impl, D: Domain> From<&[u8]> for Value { fn from(v: &[u8]) -> Self { Value::ByteString(Vec::from(v)) } } // impl, D: Domain> From> for Value { fn from(v: Vec) -> Self { Value::ByteString(v) } }