From 7546ba29ad913e61bc7f673d6f7c2f7af6fcb0d4 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Mon, 28 Jun 2021 17:26:41 +0200 Subject: [PATCH] Avoid quite a bit of boxing --- .../preserves-schema/src/compiler/context.rs | 8 ++- .../preserves-schema/src/compiler/parsers.rs | 46 ++++++------- .../preserves-schema/src/compiler/types.rs | 14 ++-- .../rust/preserves-schema/src/metaschema.rs | 64 +++++++++---------- 4 files changed, 63 insertions(+), 69 deletions(-) diff --git a/implementations/rust/preserves-schema/src/compiler/context.rs b/implementations/rust/preserves-schema/src/compiler/context.rs index 54a085f..a440afa 100644 --- a/implementations/rust/preserves-schema/src/compiler/context.rs +++ b/implementations/rust/preserves-schema/src/compiler/context.rs @@ -19,6 +19,7 @@ pub struct FunctionContext<'a> { pub struct Capture { pub field_name: String, + pub ty: types::TField, pub source_expr: String, } @@ -56,10 +57,11 @@ impl<'a> FunctionContext<'a> { } } - pub fn capture(&mut self, field_name: &str, source_expr: &str) { + pub fn capture(&mut self, field_name: String, ty: types::TField, source_expr: String) { self.captures.push(Capture { - field_name: field_name.to_owned(), - source_expr: source_expr.to_owned(), + field_name: field_name, + ty: ty, + source_expr: source_expr, }) } diff --git a/implementations/rust/preserves-schema/src/compiler/parsers.rs b/implementations/rust/preserves-schema/src/compiler/parsers.rs index 5814dd2..70bef41 100644 --- a/implementations/rust/preserves-schema/src/compiler/parsers.rs +++ b/implementations/rust/preserves-schema/src/compiler/parsers.rs @@ -23,7 +23,7 @@ pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &IOValue) { 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); + construct(&ctxt, ctorname, false, &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)]) @@ -35,11 +35,11 @@ pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &IOValue) { 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); + construct(&ctxt, item(names::render_constructor(n)), true, &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); + construct(&ctxt, item(names::render_constructor(n)), true, &definition_type(d).unwrap(), dest, &mut body); } item(seq!["impl std::convert::TryFrom", anglebrackets!["&preserves::value::IOValue"], " for ", @@ -54,6 +54,7 @@ pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &IOValue) { fn construct( ctxt: &FunctionContext, ctorname: Item, + is_struct: bool, ty: &TDefinition, dest: Option<&str>, body: &mut Vec, @@ -62,33 +63,27 @@ fn construct( 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, parens![store_wrap(is_struct, 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()), + |c| item(seq![c.field_name.clone(), ": ", store_wrap(is_struct, &c.ty, &c.source_expr)])).collect()), ")"])), } } -fn store_wrap(ty: &TField, expr: &str) -> String { +fn store_wrap(is_struct: bool, 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::Ref(_) => + if is_struct { + expr.to_owned() + } else { + format!("std::boxed::Box::new({})", expr) + }, TField::Base(_) => format!("{}.clone()", expr), } } @@ -139,7 +134,7 @@ fn simple_pattern_parser( 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()), ");"])); + store_wrap(true, &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() , ".."]], @@ -151,7 +146,7 @@ fn simple_pattern_parser( 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()), ");"])); + store_wrap(true, &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(|_| ())?", @@ -165,8 +160,8 @@ fn simple_pattern_parser( 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()), ");"])); + store_wrap(true, &field_type(&fs[0]).unwrap().unwrap(), &key_dest.unwrap()), ", ", + store_wrap(true, &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(|_| ())?", @@ -234,9 +229,10 @@ fn pattern_parser( 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); + let capture_ty = field_type(&r.fields()[1]).unwrap().unwrap(); + ctxt.capture(names::render_fieldname(r.fields()[0].value().as_symbol().unwrap()), + capture_ty, + dest.to_owned()); Some(dest) } "rec" => { diff --git a/implementations/rust/preserves-schema/src/compiler/types.rs b/implementations/rust/preserves-schema/src/compiler/types.rs index 6259bca..08ecf0b 100644 --- a/implementations/rust/preserves-schema/src/compiler/types.rs +++ b/implementations/rust/preserves-schema/src/compiler/types.rs @@ -6,19 +6,19 @@ use super::names; use preserves::value::{IOValue, NestedValue}; use preserves::error::Error; -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] pub enum TDefinition { Union(Vec<(String, TSimple)>), Simple(TSimple), } -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] pub enum TSimple { Field(TField), Record(TRecord), } -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] pub enum TField { Unit, Array(Box), @@ -28,7 +28,7 @@ pub enum TField { Base(String), } -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] pub struct TRecord(pub Vec<(String, TField)>); pub fn definition_type(d: &IOValue) -> Result { @@ -156,15 +156,15 @@ pub fn render_recordlike_type(is_struct: bool, n: &str, d: &TSimple) -> impl Emi seq![names::render_constructor(n), match d { TSimple::Record(TRecord(fs)) => seq![" ", braces( fs.iter().map(|(n, d)| item( - seq![ppub, names::render_fieldname(n), ": ", render_field_type(true, d)] + seq![ppub, names::render_fieldname(n), ": ", render_field_type(!is_struct, d)] )).collect())], TSimple::Field(TField::Unit) => semi, - TSimple::Field(t) => seq![parens![seq![ppub, render_field_type(true, t)]], semi], + TSimple::Field(t) => seq![parens![seq![ppub, render_field_type(!is_struct, t)]], semi], }] } pub fn render_definition_type(n: &str, t: &TDefinition) -> impl Emittable { - seq!["#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]\n", + seq!["#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)]\n", match t { TDefinition::Union(items) => seq!["pub enum ", names::render_constructor(n), " ", braces( diff --git a/implementations/rust/preserves-schema/src/metaschema.rs b/implementations/rust/preserves-schema/src/metaschema.rs index 983206a..daef17b 100644 --- a/implementations/rust/preserves-schema/src/metaschema.rs +++ b/implementations/rust/preserves-schema/src/metaschema.rs @@ -36,16 +36,16 @@ lazy_static! { 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)] +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] 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} +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] +pub struct Binding {pub name: std::string::String, pub pattern: SimplePattern} -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] -pub struct Bundle {pub modules: std::boxed::Box} +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] +pub struct Bundle {pub modules: Modules} -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] pub enum CompoundPattern { Rec {label: std::boxed::Box, fields: std::boxed::Box}, Tuple {patterns: std::vec::Vec}, @@ -56,7 +56,7 @@ pub enum CompoundPattern { Dict {entries: std::boxed::Box} } -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] pub enum Definition { Or { pattern_0: std::boxed::Box, @@ -71,47 +71,47 @@ pub enum Definition { Pattern(std::boxed::Box) } -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] pub struct Definitions(pub preserves::value::Map); -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] pub struct DictionaryEntries(pub preserves::value::Map); -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] pub enum EmbeddedTypeName {Ref(std::boxed::Box), False} -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] pub struct ModulePath(pub std::vec::Vec); -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] pub struct Modules(pub preserves::value::Map); -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] -pub struct NamedAlternative {pub variant_label: std::string::String, pub pattern: std::boxed::Box} +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] +pub struct NamedAlternative {pub variant_label: std::string::String, pub pattern: Pattern} -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] pub enum NamedPattern {Named(std::boxed::Box), Anonymous(std::boxed::Box)} -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] pub enum NamedSimplePattern {Named(std::boxed::Box), Anonymous(std::boxed::Box)} -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] pub enum Pattern { SimplePattern(std::boxed::Box), CompoundPattern(std::boxed::Box) } -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] -pub struct Ref {pub module: std::boxed::Box, pub name: std::string::String} +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] +pub struct Ref {pub module: ModulePath, pub name: std::string::String} -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] pub struct Schema { - pub definitions: std::boxed::Box, - pub embedded_type: std::boxed::Box, - pub version: std::boxed::Box + pub definitions: Definitions, + pub embedded_type: EmbeddedTypeName, + pub version: Version } -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] pub enum SimplePattern { Any, Atom {atom_kind: std::boxed::Box}, @@ -123,7 +123,7 @@ pub enum SimplePattern { Ref(std::boxed::Box) } -#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)] +#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] pub struct Version; fn _parse_atom_kind_boolean(value: &preserves::value::IOValue) -> std::result::Result {if value != &*LIT0 { return Err(()); } let _tmp0 = (); Ok(AtomKind::Boolean)} @@ -171,7 +171,7 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for Binding { 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)}) + Ok(Binding {name: _tmp5.clone(), pattern: _tmp7}) } } @@ -183,7 +183,7 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for Bundle { 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)}) + Ok(Bundle {modules: _tmp5}) } } @@ -370,7 +370,7 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for NamedAlternative { 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)}) + Ok(NamedAlternative {variant_label: _tmp3.clone(), pattern: _tmp5}) } } @@ -440,7 +440,7 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for Ref { 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()}) + Ok(Ref {module: _tmp5, name: _tmp7.clone()}) } } @@ -458,11 +458,7 @@ impl std::convert::TryFrom<&preserves::value::IOValue> for Schema { 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) - }) + Ok(Schema {definitions: _tmp8, embedded_type: _tmp11, version: _tmp14}) } }