Fix multi-schema bundles after refactor
This commit is contained in:
parent
985a0b6795
commit
e56b62cfbb
|
@ -58,6 +58,11 @@ pub enum CaptureMode {
|
||||||
Indefinite(Vec<Item>),
|
Indefinite(Vec<Item>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum RefRenderStyle {
|
||||||
|
Bare,
|
||||||
|
Qualified,
|
||||||
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref ID_RE: regex::Regex = regex::Regex::new(r"^[a-zA-Z][a-zA-Z_0-9]*$").unwrap();
|
static ref ID_RE: regex::Regex = regex::Regex::new(r"^[a-zA-Z][a-zA-Z_0-9]*$").unwrap();
|
||||||
}
|
}
|
||||||
|
@ -74,7 +79,14 @@ impl<'b> BundleContext<'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_for_name(&self, r: &Ref) -> Option<&types::TDefinition> {
|
pub fn type_for_name(&self, r: &Ref) -> Option<&types::TDefinition> {
|
||||||
self.types.get(r)
|
if r.module.0.is_empty() {
|
||||||
|
panic!("BundleContext::type_for_name with module-relative ref {:?}", r);
|
||||||
|
}
|
||||||
|
let result = self.types.get(r);
|
||||||
|
if result.is_none() && !self.config.module_aliases.contains_key(&r.module.0) {
|
||||||
|
panic!("Attempted to lookup unknown type {:?}", r)
|
||||||
|
}
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn define_literal(&mut self, v: &IOValue) -> String {
|
pub fn define_literal(&mut self, v: &IOValue) -> String {
|
||||||
|
@ -138,7 +150,7 @@ impl<'m, 'b> ModuleContext<'m, 'b> {
|
||||||
self.functiondefs.push(i)
|
self.functiondefs.push(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_ref(&self, r: &Ref, with_generic_args: bool) -> Item {
|
pub fn render_ref(&self, r: &Ref, style: RefRenderStyle) -> Item {
|
||||||
let base = match self.bundle.config.module_aliases.get(&r.module.0) {
|
let base = match self.bundle.config.module_aliases.get(&r.module.0) {
|
||||||
None =>
|
None =>
|
||||||
if r.module.0.is_empty() {
|
if r.module.0.is_empty() {
|
||||||
|
@ -153,43 +165,32 @@ impl<'m, 'b> ModuleContext<'m, 'b> {
|
||||||
Some(s) =>
|
Some(s) =>
|
||||||
item(name![s.to_owned(), r.name.to_owned()])
|
item(name![s.to_owned(), r.name.to_owned()])
|
||||||
};
|
};
|
||||||
if with_generic_args && self.ref_has_embedded(r) {
|
let q = self.ref_has_embedded(r);
|
||||||
item(seq![base, anglebrackets!["_Any"]])
|
match style {
|
||||||
} else {
|
RefRenderStyle::Bare =>
|
||||||
base
|
base,
|
||||||
|
RefRenderStyle::Qualified =>
|
||||||
|
if q { item(seq![base, anglebrackets!["_Value"]]) } else { base },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn any_type(&self) -> &'static str {
|
pub fn any_type(&self) -> &'static str {
|
||||||
"_Any"
|
"_Value"
|
||||||
}
|
|
||||||
|
|
||||||
pub fn qualify(&self, r: &Ref) -> Ref {
|
|
||||||
if r.module.0.is_empty() {
|
|
||||||
Ref { module: self.module_path.clone(), name: r.name.clone() }
|
|
||||||
} else {
|
|
||||||
r.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn type_for_name(&self, r: &Ref) -> Option<&types::TDefinition> {
|
|
||||||
self.bundle.type_for_name(&self.qualify(r))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ref_has_embedded(&self, r: &Ref) -> bool {
|
pub fn ref_has_embedded(&self, r: &Ref) -> bool {
|
||||||
match self.type_for_name(r) {
|
let r = r.qualify(&self.module_path);
|
||||||
Some(ty) => ty.has_embedded(self),
|
self.bundle.type_for_name(&r).map(|ty| ty.has_embedded(self.bundle)).unwrap_or(false)
|
||||||
None => false, // TODO: should this be configurable?
|
// ^ TODO: should the "false" be configurable?
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn literals_generic_decls(&self) -> Item {
|
pub fn literals_generic_decls(&self) -> Item {
|
||||||
item(anglebrackets!["_Any: preserves::value::NestedValue"])
|
item(anglebrackets!["_Value: preserves::value::NestedValue"])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn literals_generic_decls_with_defaults(&self) -> Item {
|
pub fn literals_generic_decls_with_defaults(&self) -> Item {
|
||||||
item(anglebrackets![
|
item(anglebrackets![
|
||||||
seq!["_Any: preserves::value::NestedValue = ",
|
seq!["_Value: preserves::value::NestedValue = ",
|
||||||
if self.schema.embedded_type == EmbeddedTypeName::False {
|
if self.schema.embedded_type == EmbeddedTypeName::False {
|
||||||
"preserves::value::IOValue"
|
"preserves::value::IOValue"
|
||||||
} else {
|
} else {
|
||||||
|
@ -198,11 +199,11 @@ impl<'m, 'b> ModuleContext<'m, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn literals_generic_arg(&self) -> Item {
|
pub fn literals_generic_arg(&self) -> Item {
|
||||||
item("<_Any>")
|
item("<_Value>")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn literals_type(&self) -> Item {
|
pub fn literals_type(&self) -> Item {
|
||||||
item(seq!["&", self.literals_base_type(), self.literals_generic_arg()])
|
item(seq![self.literals_base_type(), self.literals_generic_arg()])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn literals_base_type(&self) -> Item {
|
pub fn literals_base_type(&self) -> Item {
|
||||||
|
|
|
@ -6,8 +6,10 @@ pub mod types;
|
||||||
pub mod unparsers;
|
pub mod unparsers;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
use crate::support::Parse;
|
||||||
use crate::compiler::context::*;
|
use crate::compiler::context::*;
|
||||||
use crate::gen::Literals;
|
use crate::gen::Literals;
|
||||||
|
use crate::gen::schema;
|
||||||
use crate::gen::schema::*;
|
use crate::gen::schema::*;
|
||||||
use crate::syntax::block::{Formatter, Item};
|
use crate::syntax::block::{Formatter, Item};
|
||||||
use crate::syntax::block::constructors::*;
|
use crate::syntax::block::constructors::*;
|
||||||
|
@ -101,11 +103,13 @@ impl CompilerConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_type_cache(&self) -> Map<Ref, types::TDefinition> {
|
fn build_type_cache(&self) -> Map<Ref, types::TDefinition> {
|
||||||
self.bundle.iter().flat_map(
|
self.bundle.iter().flat_map(|(modpath, s)| {
|
||||||
|(modpath, s)| s.definitions.0.iter().map(
|
let modpath = ModulePath(modpath.clone());
|
||||||
move |(name, def)| (Ref { module: ModulePath(modpath.clone()), name: name.clone() },
|
s.definitions.0.iter().map(move |(name, def)| {
|
||||||
types::definition_type(def))))
|
let ty = types::definition_type(&modpath, name, def);
|
||||||
.collect()
|
(ty.self_ref.clone(), ty)
|
||||||
|
})
|
||||||
|
}).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_definition(
|
fn generate_definition(
|
||||||
|
@ -150,6 +154,16 @@ fn write_if_changed(output_path: &PathBuf, contents: &[u8]) -> io::Result<()> {
|
||||||
f.write_all(contents)
|
f.write_all(contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Ref {
|
||||||
|
pub fn qualify(&self, default_module_path: &schema::ModulePath) -> Ref {
|
||||||
|
if self.module.0.is_empty() {
|
||||||
|
Ref { module: default_module_path.clone(), name: self.name.clone() }
|
||||||
|
} else {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Schema {
|
impl Schema {
|
||||||
pub fn has_embedded_type(&self) -> bool {
|
pub fn has_embedded_type(&self) -> bool {
|
||||||
self.embedded_type != EmbeddedTypeName::False
|
self.embedded_type != EmbeddedTypeName::False
|
||||||
|
@ -194,6 +208,8 @@ pub fn compile(config: &CompilerConfig) -> io::Result<()> {
|
||||||
"use std::convert::TryFrom;",
|
"use std::convert::TryFrom;",
|
||||||
format!("use {}::support as _support;", &config.support_crate),
|
format!("use {}::support as _support;", &config.support_crate),
|
||||||
"use _support::Deserialize;",
|
"use _support::Deserialize;",
|
||||||
|
"use _support::Parse;",
|
||||||
|
"use _support::Unparse;",
|
||||||
"use _support::preserves;",
|
"use _support::preserves;",
|
||||||
"use preserves::value::Domain;",
|
"use preserves::value::Domain;",
|
||||||
"use preserves::value::NestedValue;",
|
"use preserves::value::NestedValue;",
|
||||||
|
|
|
@ -3,7 +3,10 @@ use crate::gen::schema::*;
|
||||||
use crate::syntax::block::Item;
|
use crate::syntax::block::Item;
|
||||||
use crate::syntax::block::constructors::*;
|
use crate::syntax::block::constructors::*;
|
||||||
|
|
||||||
use super::context::{ModuleContextMode, ModuleContext, FunctionContext};
|
use super::context::FunctionContext;
|
||||||
|
use super::context::ModuleContext;
|
||||||
|
use super::context::ModuleContextMode;
|
||||||
|
use super::context::RefRenderStyle;
|
||||||
use super::names;
|
use super::names;
|
||||||
use super::types::*;
|
use super::types::*;
|
||||||
|
|
||||||
|
@ -19,7 +22,7 @@ impl compiler::Plugin for ParserPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
||||||
let ty = definition_type(d);
|
let ty = definition_type(&m.module_path, n, d);
|
||||||
|
|
||||||
m.define_function(
|
m.define_function(
|
||||||
n,
|
n,
|
||||||
|
@ -41,7 +44,7 @@ pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
||||||
let dest = dest.as_ref().map(String::as_str);
|
let dest = dest.as_ref().map(String::as_str);
|
||||||
construct(&ctxt, ctorname, false, &pattern_type(pat), dest, &mut body);
|
construct(&ctxt, ctorname, false, &pattern_type(pat), dest, &mut body);
|
||||||
item(seq!["fn ", fname.clone(), ctxt.m.literals_generic_decls(),
|
item(seq!["fn ", fname.clone(), ctxt.m.literals_generic_decls(),
|
||||||
"(_ctxt: ", ctxt.m.literals_type(), ", value: &", ctxt.m.any_type(), ") -> ",
|
"(_ctxt: &", ctxt.m.literals_type(), ", value: &", ctxt.m.any_type(), ") -> ",
|
||||||
"std::result::Result<",
|
"std::result::Result<",
|
||||||
names::render_constructor(n), ty.generic_arg(ctxt.m),
|
names::render_constructor(n), ty.generic_arg(ctxt.m),
|
||||||
", _support::ParseError> ",
|
", _support::ParseError> ",
|
||||||
|
@ -66,36 +69,16 @@ pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (topdecl, innerdecl) = if ty.has_embedded(ctxt.m) {
|
item(seq!["impl", ctxt.m.literals_generic_decls(),
|
||||||
(ctxt.m.literals_generic_decls(), item(""))
|
" _support::Parse", anglebrackets![ctxt.m.literals_type(),
|
||||||
} else {
|
ctxt.m.any_type()], " for ",
|
||||||
(item(""), ctxt.m.literals_generic_decls())
|
|
||||||
};
|
|
||||||
|
|
||||||
item(seq!["impl", topdecl, " ",
|
|
||||||
names::render_constructor(n), ty.generic_arg(ctxt.m), " ",
|
names::render_constructor(n), ty.generic_arg(ctxt.m), " ",
|
||||||
block![
|
block![
|
||||||
seq!["pub fn parse", innerdecl, "(_ctxt: ", ctxt.m.literals_type(),
|
seq!["fn parse(_ctxt: &", ctxt.m.literals_type(),
|
||||||
", value: &", ctxt.m.any_type(), ") -> ",
|
", value: &", ctxt.m.any_type(), ") -> ",
|
||||||
"std::result::Result<Self, _support::ParseError> ",
|
"std::result::Result<Self, _support::ParseError> ",
|
||||||
codeblock(body)]]])
|
codeblock(body)]]])
|
||||||
});
|
});
|
||||||
|
|
||||||
// m.define_function(
|
|
||||||
// n,
|
|
||||||
// |ctxt| {
|
|
||||||
// item(seq!["impl", ctxt.m.literals_generic_decls(),
|
|
||||||
// " std::convert::TryFrom", anglebrackets![seq!["&", ctxt.m.any_type()]], " for ",
|
|
||||||
// names::render_constructor(n), ty.generic_arg(ctxt.m), " ",
|
|
||||||
// block![
|
|
||||||
// seq!["type Error = _support::ParseError;"],
|
|
||||||
// seq!["fn try_from(value: &", ctxt.m.any_type(), ") -> ",
|
|
||||||
// "std::result::Result<Self, _support::ParseError> ",
|
|
||||||
// codeblock![
|
|
||||||
// seq!["Self::parse(",
|
|
||||||
// ctxt.m.literals_base_type(), "::default()",
|
|
||||||
// ", value)"]]]]])
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn construct(
|
fn construct(
|
||||||
|
@ -214,7 +197,7 @@ fn simple_pattern_parser(
|
||||||
dest
|
dest
|
||||||
},
|
},
|
||||||
SimplePattern::Ref(r) => {
|
SimplePattern::Ref(r) => {
|
||||||
let tf = name![ctxt.m.render_ref(&**r, false), "parse"];
|
let tf = name![ctxt.m.render_ref(&**r, RefRenderStyle::Bare), "parse"];
|
||||||
ctxt.define_atom(body,
|
ctxt.define_atom(body,
|
||||||
&dest,
|
&dest,
|
||||||
item(seq![tf, parens!["_ctxt", src.to_owned()], "?"]));
|
item(seq![tf, parens!["_ctxt", src.to_owned()], "?"]));
|
||||||
|
|
|
@ -11,7 +11,10 @@ use preserves::value::IOValue;
|
||||||
use preserves::value::NestedValue;
|
use preserves::value::NestedValue;
|
||||||
use preserves::value::ValueClass;
|
use preserves::value::ValueClass;
|
||||||
|
|
||||||
use super::context::{ModuleContextMode, ModuleContext, FunctionContext};
|
use super::context::FunctionContext;
|
||||||
|
use super::context::ModuleContext;
|
||||||
|
use super::context::ModuleContextMode;
|
||||||
|
use super::context::RefRenderStyle;
|
||||||
use super::names;
|
use super::names;
|
||||||
use super::types::*;
|
use super::types::*;
|
||||||
|
|
||||||
|
@ -75,7 +78,7 @@ impl BoundaryTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_definition_reader(m: &mut ModuleContext, n: &str, d: &Definition) {
|
pub fn gen_definition_reader(m: &mut ModuleContext, n: &str, d: &Definition) {
|
||||||
let ty = definition_type(d);
|
let ty = definition_type(&m.module_path, n, d);
|
||||||
|
|
||||||
m.define_function(
|
m.define_function(
|
||||||
n,
|
n,
|
||||||
|
@ -100,8 +103,8 @@ pub fn gen_definition_reader(m: &mut ModuleContext, n: &str, d: &Definition) {
|
||||||
item(seq![
|
item(seq![
|
||||||
"fn ", fname.clone(), anglebrackets![
|
"fn ", fname.clone(), anglebrackets![
|
||||||
"'de",
|
"'de",
|
||||||
"_Any: preserves::value::NestedValue",
|
"_Value: preserves::value::NestedValue",
|
||||||
"R: _support::Reader<'de, _Any>"],
|
"R: _support::Reader<'de, _Value>"],
|
||||||
"(r: &mut R) -> ",
|
"(r: &mut R) -> ",
|
||||||
"std::result::Result<",
|
"std::result::Result<",
|
||||||
names::render_constructor(n), ty.generic_arg(ctxt.m),
|
names::render_constructor(n), ty.generic_arg(ctxt.m),
|
||||||
|
@ -139,9 +142,9 @@ pub fn gen_definition_reader(m: &mut ModuleContext, n: &str, d: &Definition) {
|
||||||
|
|
||||||
item(seq![
|
item(seq![
|
||||||
"impl", anglebrackets!["'de",
|
"impl", anglebrackets!["'de",
|
||||||
"_Any: preserves::value::NestedValue",
|
"_Value: preserves::value::NestedValue",
|
||||||
"R: _support::Reader<'de, _Any>"], " ",
|
"R: _support::Reader<'de, _Value>"], " ",
|
||||||
"_support::Deserialize", anglebrackets!["'de", "_Any", "R"], " ",
|
"_support::Deserialize", anglebrackets!["'de", "_Value", "R"], " ",
|
||||||
"for ", names::render_constructor(n), ty.generic_arg(ctxt.m), " ", block![
|
"for ", names::render_constructor(n), ty.generic_arg(ctxt.m), " ", block![
|
||||||
seq!["fn deserialize(r: &mut R) -> ",
|
seq!["fn deserialize(r: &mut R) -> ",
|
||||||
"std::result::Result<Self, _support::ParseError> ",
|
"std::result::Result<Self, _support::ParseError> ",
|
||||||
|
@ -426,7 +429,7 @@ fn simple_pattern_reader(
|
||||||
dest
|
dest
|
||||||
},
|
},
|
||||||
SimplePattern::Ref(r) => {
|
SimplePattern::Ref(r) => {
|
||||||
let tf = name![ctxt.m.render_ref(&**r, false), "deserialize"];
|
let tf = name![ctxt.m.render_ref(&**r, RefRenderStyle::Bare), "deserialize"];
|
||||||
ctxt.define_atom(body, &dest, item(seq![tf, "(r)?"]));
|
ctxt.define_atom(body, &dest, item(seq![tf, "(r)?"]));
|
||||||
dest
|
dest
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,13 +5,22 @@ use crate::gen::schema::*;
|
||||||
|
|
||||||
use preserves::value::Set;
|
use preserves::value::Set;
|
||||||
|
|
||||||
use super::context::{ModuleContextMode, ModuleContext};
|
use super::context::BundleContext;
|
||||||
|
use super::context::ModuleContext;
|
||||||
|
use super::context::ModuleContextMode;
|
||||||
|
use super::context::RefRenderStyle;
|
||||||
use super::names;
|
use super::names;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
pub enum TDefinition {
|
pub struct TDefinition {
|
||||||
Union(Vec<(String, TSimple)>),
|
pub self_ref: Ref,
|
||||||
Simple(TSimple),
|
pub body: TDefinitionBody,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
|
pub enum TDefinitionBody {
|
||||||
|
Union(Vec<(String, TSimple)>),
|
||||||
|
Simple(TSimple),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
|
@ -42,7 +51,7 @@ impl compiler::Plugin for TypePlugin {
|
||||||
fn generate_module(&self, m: &mut ModuleContext) {
|
fn generate_module(&self, m: &mut ModuleContext) {
|
||||||
if let EmbeddedTypeName::Ref(r) = &m.schema.embedded_type {
|
if let EmbeddedTypeName::Ref(r) = &m.schema.embedded_type {
|
||||||
m.define_type(item(vertical(false, seq![
|
m.define_type(item(vertical(false, seq![
|
||||||
seq!["pub type _Dom = ", m.render_ref(&*r, true), ";"],
|
seq!["pub type _Dom = ", m.render_ref(&*r, RefRenderStyle::Bare), ";"],
|
||||||
seq!["pub type _Ptr = std::sync::Arc<_Dom>;"],
|
seq!["pub type _Ptr = std::sync::Arc<_Dom>;"],
|
||||||
seq!["pub type _Any = preserves::value::ArcValue<_Ptr>;"]
|
seq!["pub type _Any = preserves::value::ArcValue<_Ptr>;"]
|
||||||
])));
|
])));
|
||||||
|
@ -51,7 +60,7 @@ impl compiler::Plugin for TypePlugin {
|
||||||
|
|
||||||
fn generate_definition(&self, m: &mut ModuleContext, n: &str, d: &Definition) {
|
fn generate_definition(&self, m: &mut ModuleContext, n: &str, d: &Definition) {
|
||||||
if let ModuleContextMode::TargetGeneric = m.mode {
|
if let ModuleContextMode::TargetGeneric = m.mode {
|
||||||
let ty = definition_type(d);
|
let ty = definition_type(&m.module_path, n, d);
|
||||||
m.define_type(item(ty.render(m, n)));
|
m.define_type(item(ty.render(m, n)));
|
||||||
m.define_type(item(seq![
|
m.define_type(item(seq![
|
||||||
"impl", ty.generic_decl(m), " preserves::value::Domain for ",
|
"impl", ty.generic_decl(m), " preserves::value::Domain for ",
|
||||||
|
@ -60,14 +69,17 @@ impl compiler::Plugin for TypePlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn definition_type(d: &Definition) -> TDefinition {
|
pub fn definition_type(module: &ModulePath, n: &str, d: &Definition) -> TDefinition {
|
||||||
match d {
|
TDefinition {
|
||||||
Definition::Or { pattern_0, pattern_1, pattern_n } =>
|
self_ref: Ref { module: module.clone(), name: n.to_owned() },
|
||||||
TDefinition::Union(or_definition_type(pattern_0, pattern_1, pattern_n)),
|
body: match d {
|
||||||
Definition::And { pattern_0, pattern_1, pattern_n } =>
|
Definition::Or { pattern_0, pattern_1, pattern_n } =>
|
||||||
TDefinition::Simple(and_definition_type(pattern_0, pattern_1, pattern_n)),
|
TDefinitionBody::Union(or_definition_type(pattern_0, pattern_1, pattern_n)),
|
||||||
Definition::Pattern(p) =>
|
Definition::And { pattern_0, pattern_1, pattern_n } =>
|
||||||
TDefinition::Simple(pattern_type(p)),
|
TDefinitionBody::Simple(and_definition_type(pattern_0, pattern_1, pattern_n)),
|
||||||
|
Definition::Pattern(p) =>
|
||||||
|
TDefinitionBody::Simple(pattern_type(p)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,8 +195,8 @@ impl TField {
|
||||||
fn render(&self, ctxt: &ModuleContext, box_needed: bool) -> impl Emittable {
|
fn render(&self, ctxt: &ModuleContext, box_needed: bool) -> impl Emittable {
|
||||||
match self {
|
match self {
|
||||||
TField::Unit => seq!["()"],
|
TField::Unit => seq!["()"],
|
||||||
TField::Any => seq!["_Any"],
|
TField::Any => seq!["_Value"],
|
||||||
TField::Embedded => seq!["_Ptr"],
|
TField::Embedded => seq!["_Value::D"],
|
||||||
TField::Array(t) => seq!["std::vec::Vec<", t.render(ctxt, false), ">"],
|
TField::Array(t) => seq!["std::vec::Vec<", t.render(ctxt, false), ">"],
|
||||||
TField::Set(t) => seq!["preserves::value::Set<", t.render(ctxt, false), ">"],
|
TField::Set(t) => seq!["preserves::value::Set<", t.render(ctxt, false), ">"],
|
||||||
TField::Map(k, v) => seq!["preserves::value::Map",
|
TField::Map(k, v) => seq!["preserves::value::Map",
|
||||||
|
@ -192,29 +204,34 @@ impl TField {
|
||||||
v.render(ctxt, false)]],
|
v.render(ctxt, false)]],
|
||||||
TField::Ref(r) =>
|
TField::Ref(r) =>
|
||||||
if box_needed {
|
if box_needed {
|
||||||
seq!["std::boxed::Box", anglebrackets![ctxt.render_ref(r, true)]]
|
seq!["std::boxed::Box", anglebrackets![
|
||||||
|
ctxt.render_ref(r, RefRenderStyle::Qualified)]]
|
||||||
} else {
|
} else {
|
||||||
seq![ctxt.render_ref(r, true)]
|
seq![ctxt.render_ref(r, RefRenderStyle::Qualified)]
|
||||||
},
|
},
|
||||||
TField::Base(n) => seq![n.to_owned()],
|
TField::Base(n) => seq![n.to_owned()],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_embedded(&self, ctxt: &ModuleContext, seen: &mut Set<Ref>) -> bool {
|
pub fn has_embedded(&self, default_module_path: &ModulePath, ctxt: &BundleContext, seen: &mut Set<Ref>) -> bool {
|
||||||
match self {
|
match self {
|
||||||
TField::Unit => false,
|
TField::Unit => false,
|
||||||
TField::Any => true, // at least potentially true
|
TField::Any => true, // at least potentially true
|
||||||
TField::Embedded => true,
|
TField::Embedded => true,
|
||||||
TField::Array(f) => f.has_embedded(ctxt, seen),
|
TField::Array(f) => f.has_embedded(default_module_path, ctxt, seen),
|
||||||
TField::Set(f) => f.has_embedded(ctxt, seen),
|
TField::Set(f) => f.has_embedded(default_module_path, ctxt, seen),
|
||||||
TField::Map(k, v) => k.has_embedded(ctxt, seen) || v.has_embedded(ctxt, seen),
|
TField::Map(k, v) =>
|
||||||
|
k.has_embedded(default_module_path, ctxt, seen) ||
|
||||||
|
v.has_embedded(default_module_path, ctxt, seen),
|
||||||
TField::Ref(r) => {
|
TField::Ref(r) => {
|
||||||
let r = ctxt.qualify(r);
|
let r = r.qualify(default_module_path);
|
||||||
if seen.contains(&r) {
|
if seen.contains(&r) {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
seen.insert(r.clone());
|
seen.insert(r.clone());
|
||||||
ctxt.type_for_name(&r).map(|ty| ty._has_embedded(ctxt, seen)).unwrap_or(false)
|
ctxt.type_for_name(&r).map(|ty| ty._has_embedded(ctxt, seen)).unwrap_or(false)
|
||||||
|
// ^ TODO: should the "false" be configurable?
|
||||||
|
// cf. ModuleContext::ref_has_embedded.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TField::Base(_) => false,
|
TField::Base(_) => false,
|
||||||
|
@ -237,17 +254,19 @@ impl TSimple {
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_embedded(&self, ctxt: &ModuleContext, seen: &mut Set<Ref>) -> bool {
|
pub fn has_embedded(&self, default_module_path: &ModulePath, ctxt: &BundleContext, seen: &mut Set<Ref>) -> bool {
|
||||||
match self {
|
match self {
|
||||||
TSimple::Field(f) => f.has_embedded(ctxt, seen),
|
TSimple::Field(f) =>
|
||||||
TSimple::Record(TRecord(fs)) => fs.iter().any(|(_k, v)| v.has_embedded(ctxt, seen)),
|
f.has_embedded(default_module_path, ctxt, seen),
|
||||||
|
TSimple::Record(TRecord(fs)) =>
|
||||||
|
fs.iter().any(|(_k, v)| v.has_embedded(default_module_path, ctxt, seen)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TDefinition {
|
impl TDefinition {
|
||||||
pub fn generic_decl(&self, ctxt: &ModuleContext) -> Item {
|
pub fn generic_decl(&self, ctxt: &ModuleContext) -> Item {
|
||||||
if self.has_embedded(ctxt) {
|
if self.has_embedded(ctxt.bundle) {
|
||||||
ctxt.literals_generic_decls()
|
ctxt.literals_generic_decls()
|
||||||
} else {
|
} else {
|
||||||
item("")
|
item("")
|
||||||
|
@ -255,7 +274,7 @@ impl TDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generic_decl_with_defaults(&self, ctxt: &ModuleContext) -> Item {
|
pub fn generic_decl_with_defaults(&self, ctxt: &ModuleContext) -> Item {
|
||||||
if self.has_embedded(ctxt) {
|
if self.has_embedded(ctxt.bundle) {
|
||||||
ctxt.literals_generic_decls_with_defaults()
|
ctxt.literals_generic_decls_with_defaults()
|
||||||
} else {
|
} else {
|
||||||
item("")
|
item("")
|
||||||
|
@ -263,7 +282,7 @@ impl TDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generic_arg(&self, ctxt: &ModuleContext) -> Item {
|
pub fn generic_arg(&self, ctxt: &ModuleContext) -> Item {
|
||||||
if self.has_embedded(ctxt) {
|
if self.has_embedded(ctxt.bundle) {
|
||||||
ctxt.literals_generic_arg()
|
ctxt.literals_generic_arg()
|
||||||
} else {
|
} else {
|
||||||
item("")
|
item("")
|
||||||
|
@ -273,25 +292,27 @@ impl TDefinition {
|
||||||
pub fn render(&self, ctxt: &ModuleContext, n: &str) -> impl Emittable {
|
pub fn render(&self, ctxt: &ModuleContext, n: &str) -> impl Emittable {
|
||||||
vertical(false, seq![
|
vertical(false, seq![
|
||||||
"#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)]",
|
"#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)]",
|
||||||
match self {
|
match &self.body {
|
||||||
TDefinition::Union(items) =>
|
TDefinitionBody::Union(items) =>
|
||||||
seq!["pub enum ",
|
seq!["pub enum ",
|
||||||
names::render_constructor(n), self.generic_decl_with_defaults(ctxt), " ",
|
names::render_constructor(n), self.generic_decl_with_defaults(ctxt), " ",
|
||||||
vertical(false, braces(items.iter().map(
|
vertical(false, braces(items.iter().map(
|
||||||
|(n, d)| item(d.render(ctxt, item(""), false, n))).collect()))],
|
|(n, d)| item(d.render(ctxt, item(""), false, n))).collect()))],
|
||||||
TDefinition::Simple(s) =>
|
TDefinitionBody::Simple(s) =>
|
||||||
seq!["pub struct ", s.render(ctxt, self.generic_decl_with_defaults(ctxt), true, n)],
|
seq!["pub struct ", s.render(ctxt, self.generic_decl_with_defaults(ctxt), true, n)],
|
||||||
}])
|
}])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_embedded(&self, ctxt: &ModuleContext) -> bool {
|
pub fn has_embedded(&self, ctxt: &BundleContext) -> bool {
|
||||||
self._has_embedded(ctxt, &mut Set::new())
|
self._has_embedded(ctxt, &mut Set::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _has_embedded(&self, ctxt: &ModuleContext, seen: &mut Set<Ref>) -> bool {
|
fn _has_embedded(&self, ctxt: &BundleContext, seen: &mut Set<Ref>) -> bool {
|
||||||
match self {
|
match &self.body {
|
||||||
TDefinition::Union(entries) => entries.iter().any(|(_k, v)| v.has_embedded(ctxt, seen)),
|
TDefinitionBody::Union(entries) =>
|
||||||
TDefinition::Simple(t) => t.has_embedded(ctxt, seen),
|
entries.iter().any(|(_k, v)| v.has_embedded(&self.self_ref.module, ctxt, seen)),
|
||||||
|
TDefinitionBody::Simple(t) =>
|
||||||
|
t.has_embedded(&self.self_ref.module, ctxt, seen),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ fn normal_src(src: String, is_struct: bool) -> ValueContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_definition_unparser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
pub fn gen_definition_unparser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
||||||
let ty = definition_type(d);
|
let ty = definition_type(&m.module_path, n, d);
|
||||||
|
|
||||||
m.define_function(
|
m.define_function(
|
||||||
n,
|
n,
|
||||||
|
@ -97,17 +97,14 @@ pub fn gen_definition_unparser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (topdecl, innerdecl) = if ty.has_embedded(ctxt.m) {
|
item(seq!["impl", ctxt.m.literals_generic_decls(),
|
||||||
(ctxt.m.literals_generic_decls(), item(""))
|
" _support::Unparse", anglebrackets![ctxt.m.literals_type(),
|
||||||
} else {
|
ctxt.m.any_type()], " for ",
|
||||||
(item(""), ctxt.m.literals_generic_decls())
|
names::render_constructor(n), ty.generic_arg(ctxt.m), " ",
|
||||||
};
|
block![
|
||||||
|
seq!["fn unparse(&self, _ctxt: &", ctxt.m.literals_type(),
|
||||||
item(seq!["impl", topdecl, " ",
|
") -> ", ctxt.m.any_type(), " ",
|
||||||
names::render_constructor(n), ty.generic_arg(ctxt.m), " ", block![
|
block(body)]]])
|
||||||
seq!["pub fn unparse", innerdecl,
|
|
||||||
"(&self, _ctxt: ", ctxt.m.literals_type(), ") -> ",
|
|
||||||
ctxt.m.any_type(), " ", block(body)]]])
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// m.define_function(
|
// m.define_function(
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,6 +3,12 @@ pub mod compiler;
|
||||||
pub mod support;
|
pub mod support;
|
||||||
pub mod gen;
|
pub mod gen;
|
||||||
|
|
||||||
|
pub use support::Codec;
|
||||||
|
pub use support::Deserialize;
|
||||||
|
pub use support::Parse;
|
||||||
|
pub use support::ParseError;
|
||||||
|
pub use support::Unparse;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -32,6 +38,8 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn metaschema_parsing() -> Result<(), std::io::Error> {
|
fn metaschema_parsing() -> Result<(), std::io::Error> {
|
||||||
use preserves::value::{BinarySource, IOBinarySource, Reader};
|
use preserves::value::{BinarySource, IOBinarySource, Reader};
|
||||||
|
use crate::Parse;
|
||||||
|
use crate::Unparse;
|
||||||
use crate::gen::schema::*;
|
use crate::gen::schema::*;
|
||||||
|
|
||||||
let mut f = std::fs::File::open("../../../schema/schema.bin")?;
|
let mut f = std::fs::File::open("../../../schema/schema.bin")?;
|
||||||
|
|
|
@ -19,18 +19,46 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
pub struct Codec<N: NestedValue, L: Default> {
|
pub trait Parse<L, Value: NestedValue>: Sized {
|
||||||
|
fn parse(literals: &L, value: &Value) -> Result<Self, ParseError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L, Value: NestedValue> Parse<L, Value> for Value {
|
||||||
|
fn parse(_literals: &L, value: &Value) -> Result<Self, ParseError> {
|
||||||
|
Ok(value.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Unparse<L, Value: NestedValue> {
|
||||||
|
fn unparse(&self, literals: &L) -> Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L, Value: NestedValue> Unparse<L, Value> for Value {
|
||||||
|
fn unparse(&self, _literals: &L) -> Value {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Codec<L: Default, N: NestedValue> {
|
||||||
pub literals: L,
|
pub literals: L,
|
||||||
phantom: PhantomData<N>,
|
phantom: PhantomData<N>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: NestedValue, L: Default> Codec<N, L> {
|
impl<L: Default, N: NestedValue> Codec<L, N> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Codec {
|
Codec {
|
||||||
literals: L::default(),
|
literals: L::default(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse<T: Parse<L, N>>(&self, value: &N) -> Result<T, ParseError> {
|
||||||
|
T::parse(&self.literals, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unparse<T: Unparse<L, N>>(&self, value: &T) -> N {
|
||||||
|
value.unparse(&self.literals)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Deserialize<'de, N: NestedValue, R: Reader<'de, N>>
|
pub trait Deserialize<'de, N: NestedValue, R: Reader<'de, N>>
|
||||||
|
|
Loading…
Reference in New Issue