forked from syndicate-lang/preserves
Massive refactor to be more flexible around embedded types
This commit is contained in:
parent
8127033407
commit
352d8ba1b3
|
@ -8,6 +8,7 @@ use convert_case::{Case, Casing};
|
|||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use preserves::value::IOValue;
|
||||
use preserves::value::Map;
|
||||
use preserves::value::NestedValue;
|
||||
use preserves::value::Value;
|
||||
|
@ -16,25 +17,31 @@ use super::CompilerConfig;
|
|||
use super::names;
|
||||
use super::types;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum ModuleContextMode {
|
||||
TargetIOValue,
|
||||
TargetAny,
|
||||
pub struct BundleContext<'b> {
|
||||
pub config: &'b CompilerConfig,
|
||||
pub types: Map<Ref, types::TDefinition>,
|
||||
pub literals: Map<IOValue, String>,
|
||||
}
|
||||
|
||||
pub struct ModuleContext<'m> {
|
||||
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
|
||||
pub enum ModuleContextMode {
|
||||
TargetModule,
|
||||
TargetToplevel,
|
||||
TargetGeneric,
|
||||
}
|
||||
|
||||
pub struct ModuleContext<'m, 'b> {
|
||||
pub bundle: &'m mut BundleContext<'b>,
|
||||
pub module_path: ModulePath,
|
||||
pub config: &'m CompilerConfig,
|
||||
pub literals: Map<_Any, String>,
|
||||
pub schema: &'m Schema,
|
||||
pub typedefs: Vec<Item>,
|
||||
pub functiondefs: Vec<Item>,
|
||||
pub mode: Option<ModuleContextMode>,
|
||||
pub schema: &'m Schema,
|
||||
pub mode: ModuleContextMode,
|
||||
}
|
||||
|
||||
pub struct FunctionContext<'a, 'm> {
|
||||
pub struct FunctionContext<'a, 'm, 'b> {
|
||||
pub error_context: String,
|
||||
pub m: &'a mut ModuleContext<'m>,
|
||||
pub m: &'a mut ModuleContext<'m, 'b>,
|
||||
pub temp_counter: usize,
|
||||
pub captures: Vec<Capture>,
|
||||
pub capture_mode: CaptureMode,
|
||||
|
@ -55,24 +62,22 @@ lazy_static! {
|
|||
static ref ID_RE: regex::Regex = regex::Regex::new(r"^[a-zA-Z][a-zA-Z_0-9]*$").unwrap();
|
||||
}
|
||||
|
||||
impl<'m> ModuleContext<'m> {
|
||||
impl<'b> BundleContext<'b> {
|
||||
pub fn new(
|
||||
config: &'m CompilerConfig,
|
||||
module_path: &ModulePath,
|
||||
schema: &'m Schema,
|
||||
config: &'b CompilerConfig,
|
||||
) -> Self {
|
||||
ModuleContext {
|
||||
module_path: module_path.to_owned(),
|
||||
BundleContext {
|
||||
config,
|
||||
types: config.build_type_cache(),
|
||||
literals: Map::new(),
|
||||
typedefs: Vec::new(),
|
||||
functiondefs: Vec::new(),
|
||||
mode: None,
|
||||
schema,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn define_literal(&mut self, v: &_Any) -> String {
|
||||
pub fn type_for_name(&self, r: &Ref) -> &types::TDefinition {
|
||||
self.types.get(r).unwrap_or_else(|| panic!("{:?} not found", r))
|
||||
}
|
||||
|
||||
pub fn define_literal(&mut self, v: &IOValue) -> String {
|
||||
let prefix = format!("LIT_{}", self.literals.len());
|
||||
let next_id = match v.value() {
|
||||
Value::Boolean(b) => prefix + "_" + &b.to_string(),
|
||||
|
@ -82,7 +87,46 @@ impl<'m> ModuleContext<'m> {
|
|||
_ => prefix
|
||||
};
|
||||
let next_id = next_id.to_case(Case::UpperSnake);
|
||||
"&*".to_owned() + self.target_prefix() + "::" + self.literals.entry(v.clone()).or_insert(next_id)
|
||||
format!("&_ctxt.{}", self.literals.entry(v.clone()).or_insert(next_id))
|
||||
}
|
||||
|
||||
pub fn generate_module<F: FnOnce(&mut ModuleContext)>(
|
||||
&mut self,
|
||||
path: &Vec<String>,
|
||||
schema: &Schema,
|
||||
mode: ModuleContextMode,
|
||||
items: &mut Map<ModuleContextMode, Vec<Item>>,
|
||||
f: F,
|
||||
) {
|
||||
let mut m = ModuleContext::new(self, &ModulePath(path.clone()), schema, mode);
|
||||
f(&mut m);
|
||||
items.entry(mode).or_default().extend(m.extract());
|
||||
}
|
||||
}
|
||||
|
||||
impl<'m, 'b> ModuleContext<'m, 'b> {
|
||||
pub fn new(
|
||||
bundle: &'m mut BundleContext<'b>,
|
||||
module_path: &ModulePath,
|
||||
schema: &'m Schema,
|
||||
mode: ModuleContextMode,
|
||||
) -> Self {
|
||||
ModuleContext {
|
||||
bundle,
|
||||
module_path: module_path.to_owned(),
|
||||
schema,
|
||||
typedefs: Vec::new(),
|
||||
functiondefs: Vec::new(),
|
||||
mode,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_mode(&mut self) {
|
||||
self.mode = ModuleContextMode::TargetToplevel;
|
||||
}
|
||||
|
||||
pub fn define_literal(&mut self, v: &IOValue) -> String {
|
||||
self.bundle.define_literal(v)
|
||||
}
|
||||
|
||||
pub fn define_type(&mut self, i: Item) {
|
||||
|
@ -94,44 +138,79 @@ impl<'m> ModuleContext<'m> {
|
|||
self.functiondefs.push(i)
|
||||
}
|
||||
|
||||
pub fn render_ref(&self, r: &Ref) -> Item {
|
||||
match self.config.module_aliases.get(&r.module.0) {
|
||||
pub fn render_ref(&self, r: &Ref, with_generic_args: bool) -> Item {
|
||||
let base = match self.bundle.config.module_aliases.get(&r.module.0) {
|
||||
None =>
|
||||
if r.module.0.is_empty() {
|
||||
item(r.name.to_owned())
|
||||
} else {
|
||||
let mut items = Vec::new();
|
||||
items.push(item(self.config.fully_qualified_module_prefix.to_owned()));
|
||||
items.push(item(self.bundle.config.fully_qualified_module_prefix.to_owned()));
|
||||
for p in &r.module.0 { items.push(item(names::render_modname(p))) }
|
||||
items.push(item(r.name.to_owned()));
|
||||
item(name(items))
|
||||
}
|
||||
Some(s) =>
|
||||
item(name![s.to_owned(), r.name.to_owned()])
|
||||
};
|
||||
if with_generic_args && self.type_for_name(r).has_embedded(self) {
|
||||
item(seq![base, anglebrackets!["_Any"]])
|
||||
} else {
|
||||
base
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mode(&self) -> ModuleContextMode {
|
||||
self.mode.expect("defined ModuleContextMode")
|
||||
pub fn any_type(&self) -> &'static str {
|
||||
"_Any"
|
||||
}
|
||||
|
||||
pub fn target(&self) -> &'static str {
|
||||
match self.mode() {
|
||||
ModuleContextMode::TargetIOValue => "preserves::value::IOValue",
|
||||
ModuleContextMode::TargetAny => "_Any",
|
||||
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 target_prefix(&self) -> &'static str {
|
||||
match self.mode() {
|
||||
ModuleContextMode::TargetIOValue => "_io_",
|
||||
ModuleContextMode::TargetAny => "_any_",
|
||||
}
|
||||
pub fn type_for_name(&self, r: &Ref) -> &types::TDefinition {
|
||||
self.bundle.type_for_name(&self.qualify(r))
|
||||
}
|
||||
|
||||
pub fn literals_generic_decls(&self) -> Item {
|
||||
item(anglebrackets!["_Any: preserves::value::NestedValue"])
|
||||
}
|
||||
|
||||
pub fn literals_generic_decls_with_defaults(&self) -> Item {
|
||||
item(anglebrackets![
|
||||
seq!["_Any: preserves::value::NestedValue = ",
|
||||
if self.schema.embedded_type == EmbeddedTypeName::False {
|
||||
"preserves::value::IOValue"
|
||||
} else {
|
||||
"_Any"
|
||||
}]])
|
||||
}
|
||||
|
||||
pub fn literals_generic_arg(&self) -> Item {
|
||||
item("<_Any>")
|
||||
}
|
||||
|
||||
pub fn literals_type(&self) -> Item {
|
||||
item(seq!["&", self.literals_base_type(), self.literals_generic_arg()])
|
||||
}
|
||||
|
||||
pub fn literals_base_type(&self) -> Item {
|
||||
item(format!("{}::Literals", self.bundle.config.fully_qualified_module_prefix))
|
||||
}
|
||||
|
||||
pub fn extract(&mut self) -> Vec<Item> {
|
||||
let mut items = std::mem::take(&mut self.typedefs);
|
||||
items.extend(std::mem::take(&mut self.functiondefs));
|
||||
items
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'm> FunctionContext<'a, 'm> {
|
||||
pub fn new(m: &'a mut ModuleContext<'m>, error_context: &str) -> Self {
|
||||
impl<'a, 'm, 'b> FunctionContext<'a, 'm, 'b> {
|
||||
pub fn new(m: &'a mut ModuleContext<'m, 'b>, error_context: &str) -> Self {
|
||||
FunctionContext {
|
||||
error_context: error_context.to_owned(),
|
||||
m: m,
|
||||
|
|
|
@ -6,8 +6,10 @@ pub mod types;
|
|||
pub mod unparsers;
|
||||
|
||||
use crate::*;
|
||||
use crate::compiler::context::*;
|
||||
use crate::gen::Literals;
|
||||
use crate::gen::schema::*;
|
||||
use crate::syntax::block::Formatter;
|
||||
use crate::syntax::block::{Formatter, Item};
|
||||
use crate::syntax::block::constructors::*;
|
||||
|
||||
use glob::glob;
|
||||
|
@ -15,13 +17,10 @@ use preserves::value::BinarySource;
|
|||
use preserves::value::IOBinarySource;
|
||||
use preserves::value::Map;
|
||||
use preserves::value::Reader;
|
||||
use preserves::value::Set;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::DirBuilder;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::BufRead;
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
@ -29,9 +28,11 @@ use std::path::PathBuf;
|
|||
pub type ModulePath = Vec<String>;
|
||||
|
||||
pub trait Plugin: std::fmt::Debug {
|
||||
fn generate(
|
||||
fn generate_module(&self, _module_ctxt: &mut ModuleContext) {}
|
||||
|
||||
fn generate_definition(
|
||||
&self,
|
||||
module_ctxt: &mut context::ModuleContext,
|
||||
module_ctxt: &mut ModuleContext,
|
||||
definition_name: &str,
|
||||
definition: &Definition,
|
||||
);
|
||||
|
@ -73,8 +74,9 @@ impl CompilerConfig {
|
|||
let mut src = IOBinarySource::new(&mut f);
|
||||
let mut reader = src.packed_iovalues();
|
||||
let blob = reader.demand_next(false)?;
|
||||
let literals = Literals::default();
|
||||
|
||||
if let Ok(s) = Schema::try_from(&blob) {
|
||||
if let Ok(s) = Schema::parse(&literals, &blob) {
|
||||
let prefix = i.file_stem().ok_or_else(
|
||||
|| io::Error::new(io::ErrorKind::InvalidData,
|
||||
format!("Bad schema file stem: {:?}", i)))?
|
||||
|
@ -85,7 +87,7 @@ impl CompilerConfig {
|
|||
continue;
|
||||
}
|
||||
|
||||
if let Ok(Bundle { modules }) = Bundle::try_from(&blob) {
|
||||
if let Ok(Bundle { modules }) = Bundle::parse(&literals, &blob) {
|
||||
for (ModulePath(k), v) in modules.0 {
|
||||
self.bundle.insert(k, v);
|
||||
}
|
||||
|
@ -97,6 +99,31 @@ impl CompilerConfig {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_type_cache(&self) -> Map<Ref, types::TDefinition> {
|
||||
self.bundle.iter().flat_map(
|
||||
|(modpath, s)| s.definitions.0.iter().map(
|
||||
move |(name, def)| (Ref { module: ModulePath(modpath.clone()), name: name.clone() },
|
||||
types::definition_type(def))))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn generate_definition(
|
||||
&self,
|
||||
b: &mut BundleContext,
|
||||
k: &ModulePath,
|
||||
v: &Schema,
|
||||
n: &str,
|
||||
d: &Definition,
|
||||
mode: ModuleContextMode,
|
||||
generated: &mut Map<ModuleContextMode, Vec<Item>>,
|
||||
) {
|
||||
b.generate_module(k, v, mode, generated, |m| {
|
||||
for plugin in self.plugins.iter() {
|
||||
plugin.generate_definition(m, n, d);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_inputs(globs: &Vec<String>) -> io::Result<Vec<PathBuf>> {
|
||||
|
@ -130,6 +157,8 @@ impl Schema {
|
|||
}
|
||||
|
||||
pub fn compile(config: &CompilerConfig) -> io::Result<()> {
|
||||
let mut b = BundleContext::new(config);
|
||||
|
||||
for (k, v) in config.bundle.iter() {
|
||||
let mut output_path = config.output_dir.clone();
|
||||
output_path.extend(k);
|
||||
|
@ -137,102 +166,106 @@ pub fn compile(config: &CompilerConfig) -> io::Result<()> {
|
|||
let module_name = names::render_modname(&module_name);
|
||||
output_path.set_file_name(format!("{}.rs", module_name));
|
||||
DirBuilder::new().recursive(true).create(output_path.parent().unwrap())?;
|
||||
let mut m = context::ModuleContext::new(config, &ModulePath(k.clone()), v);
|
||||
|
||||
let mut modes: Vec<context::ModuleContextMode> =
|
||||
vec![context::ModuleContextMode::TargetAny];
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
match &v.embedded_type {
|
||||
EmbeddedTypeName::False => {
|
||||
m.define_type(item(seq!["pub type _Ptr = preserves::value::IOValue;"]));
|
||||
m.define_type(item(seq!["pub type _Any = preserves::value::IOValue;"]));
|
||||
let mut generated = Map::new();
|
||||
|
||||
b.generate_module(k, v, ModuleContextMode::TargetModule, &mut generated, |m| {
|
||||
for plugin in config.plugins.iter() {
|
||||
plugin.generate_module(m);
|
||||
}
|
||||
EmbeddedTypeName::Ref(r) => {
|
||||
modes.push(context::ModuleContextMode::TargetIOValue);
|
||||
m.define_type(item(seq!["pub type _Dom = ", m.render_ref(&**r), ";"]));
|
||||
m.define_type(item(seq!["pub type _Ptr = std::sync::Arc<_Dom>;"]));
|
||||
m.define_type(item(seq!["pub type _Any = preserves::value::ArcValue<_Ptr>;"]));
|
||||
}
|
||||
}
|
||||
|
||||
let modes = modes; // rebind as non-mutable
|
||||
});
|
||||
|
||||
for (n, d) in &v.definitions.0 {
|
||||
for plugin in config.plugins.iter() {
|
||||
plugin.generate(&mut m, n, d);
|
||||
}
|
||||
for mode in &modes {
|
||||
m.mode = Some(*mode);
|
||||
for plugin in config.plugins.iter() {
|
||||
plugin.generate(&mut m, n, d);
|
||||
}
|
||||
}
|
||||
m.mode = None;
|
||||
use ModuleContextMode::*;
|
||||
config.generate_definition(&mut b, k, v, n, d, TargetToplevel, &mut generated);
|
||||
config.generate_definition(&mut b, k, v, n, d, TargetGeneric, &mut generated);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
let mut lines: Vec<String> = Vec::new();
|
||||
|
||||
lines.push("#![allow(unused_parens)]".to_owned());
|
||||
lines.push("#![allow(unused_imports)]".to_owned());
|
||||
lines.push("".to_owned());
|
||||
lines.push("use std::convert::TryFrom;".to_owned());
|
||||
lines.push(format!("use {}::support as _support;", &config.support_crate));
|
||||
lines.push("use _support::Deserialize;".to_owned());
|
||||
lines.push("use _support::preserves;".to_owned());
|
||||
lines.push("use preserves::value::Domain;".to_owned());
|
||||
lines.push("use preserves::value::NestedValue;".to_owned());
|
||||
lines.push("".to_owned());
|
||||
lines.push(Formatter::to_string(vertical(false, seq![
|
||||
"#![allow(unused_parens)]",
|
||||
"#![allow(unused_imports)]",
|
||||
"",
|
||||
"use std::convert::TryFrom;",
|
||||
format!("use {}::support as _support;", &config.support_crate),
|
||||
"use _support::Deserialize;",
|
||||
"use _support::preserves;",
|
||||
"use preserves::value::Domain;",
|
||||
"use preserves::value::NestedValue;",
|
||||
""])));
|
||||
|
||||
for mode in &modes {
|
||||
m.mode = Some(*mode);
|
||||
lines.push(format!("mod {} {{", m.target_prefix()));
|
||||
lines.push(" use super::_Any;".to_owned());
|
||||
lines.push(format!(" use {}::support as _support;", &config.support_crate));
|
||||
lines.push(" _support::lazy_static! {".to_owned());
|
||||
for (value, name) in &m.literals {
|
||||
let bs = preserves::value::PackedWriter::encode_iovalue(&value).unwrap();
|
||||
lines.push(format!(
|
||||
" pub static ref {}: {} = /* {:?} */ _support::decode_lit(&vec!{:?}).unwrap();",
|
||||
name,
|
||||
m.target(),
|
||||
value,
|
||||
bs));
|
||||
let mut emit_items = |items: Vec<Item>| {
|
||||
if !items.is_empty() {
|
||||
lines.push(Formatter::to_string(vertical(true, seq(items))));
|
||||
lines.push("".to_owned());
|
||||
}
|
||||
lines.push(" }".to_owned());
|
||||
lines.push("}".to_owned());
|
||||
lines.push("".to_owned());
|
||||
}
|
||||
m.mode = None;
|
||||
};
|
||||
emit_items(generated.remove(&ModuleContextMode::TargetModule).unwrap());
|
||||
emit_items(generated.remove(&ModuleContextMode::TargetToplevel).unwrap());
|
||||
emit_items(generated.remove(&ModuleContextMode::TargetGeneric).unwrap());
|
||||
|
||||
for i in m.typedefs {
|
||||
lines.push(Formatter::to_string(i));
|
||||
lines.push("".to_owned());
|
||||
}
|
||||
for i in m.functiondefs {
|
||||
lines.push(Formatter::to_string(i));
|
||||
lines.push("".to_owned());
|
||||
}
|
||||
// let mut generic_mod_items: Vec<Item> = vec![
|
||||
// item(vertical(false, seq![
|
||||
// format!("use {}::support as _support;", &config.support_crate),
|
||||
// "use _support::Deserialize;",
|
||||
// "use _support::preserves;"])),
|
||||
// ];
|
||||
// generic_mod_items.extend(generated.remove(&ModuleContextMode::TargetGeneric).unwrap());
|
||||
//
|
||||
// lines.push(Formatter::to_string(seq!["mod __ ", vertical(true, block(generic_mod_items))]));
|
||||
// lines.push("".to_owned());
|
||||
|
||||
{
|
||||
let contents = lines.join("\n");
|
||||
write_if_changed(&output_path, contents.as_bytes())?;
|
||||
}
|
||||
|
||||
{
|
||||
let mut mod_rs = output_path.clone();
|
||||
mod_rs.set_file_name("mod.rs");
|
||||
let mut lines = if !mod_rs.exists() {
|
||||
Set::new()
|
||||
} else {
|
||||
io::BufReader::new(File::open(&mod_rs)?)
|
||||
.lines().collect::<Result<Set<String>, _>>()?
|
||||
};
|
||||
lines.insert(format!("pub mod {};", &module_name));
|
||||
let contents = lines.into_iter().collect::<Vec<String>>().join("\n");
|
||||
write_if_changed(&mod_rs, contents.as_bytes())?;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut mod_rs = config.output_dir.clone();
|
||||
mod_rs.extend(vec!["mod.rs"]);
|
||||
let mut lines = Vec::new();
|
||||
|
||||
for modpath in config.bundle.keys() {
|
||||
lines.push(format!("pub mod {};", names::render_modname(modpath.last().unwrap())));
|
||||
}
|
||||
lines.push("".to_owned());
|
||||
|
||||
lines.push(format!("use {}::support as _support;", &config.support_crate));
|
||||
lines.push("use _support::preserves;".to_owned());
|
||||
lines.push("".to_owned());
|
||||
|
||||
lines.push("#[allow(non_snake_case)]".to_owned());
|
||||
lines.push(Formatter::to_string(item(seq![
|
||||
"pub struct Literals", anglebrackets!["N: preserves::value::NestedValue"], " ",
|
||||
vertical(false, braces(b.literals.iter().map(
|
||||
|(value, name)| item(format!("pub {}: N /* {:?} */", name, value))).collect()))
|
||||
])));
|
||||
lines.push("".to_owned());
|
||||
lines.push(Formatter::to_string(item(seq![
|
||||
"impl", anglebrackets!["N: preserves::value::NestedValue"],
|
||||
" Default for Literals<N> ", block![
|
||||
seq!["fn default() -> Self ", block![
|
||||
seq!["Literals ", vertical(false, braces(b.literals.iter().map(|(value, name)| {
|
||||
let bs = preserves::value::PackedWriter::encode_iovalue(&value).unwrap();
|
||||
item(format!("{}: /* {:?} */ _support::decode_lit(&vec!{:?}).unwrap()",
|
||||
name,
|
||||
value,
|
||||
bs))
|
||||
}).collect()))]
|
||||
]]
|
||||
]
|
||||
])));
|
||||
lines.push("".to_owned());
|
||||
|
||||
let contents = lines.join("\n");
|
||||
write_if_changed(&mod_rs, contents.as_bytes())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -11,14 +11,16 @@ use super::types::*;
|
|||
pub struct ParserPlugin;
|
||||
|
||||
impl compiler::Plugin for ParserPlugin {
|
||||
fn generate(&self, module_ctxt: &mut ModuleContext, definition_name: &str, definition: &Definition) {
|
||||
if module_ctxt.mode.is_some() {
|
||||
fn generate_definition(&self, module_ctxt: &mut ModuleContext, definition_name: &str, definition: &Definition) {
|
||||
if let ModuleContextMode::TargetGeneric = module_ctxt.mode {
|
||||
gen_definition_parser(module_ctxt, definition_name, definition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
||||
let ty = definition_type(d);
|
||||
|
||||
m.define_function(
|
||||
n,
|
||||
|mut ctxt| {
|
||||
|
@ -29,8 +31,7 @@ pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
|||
let mut ps = vec![&**pattern_0, &**pattern_1];
|
||||
ps.extend(pattern_n);
|
||||
for NamedAlternative { variant_label: name, pattern: pat } in ps {
|
||||
let fname = seq![ctxt.m.target_prefix(), "parse_",
|
||||
names::render_fieldname(n), "_", names::render_fieldname(name)];
|
||||
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(
|
||||
&(n.to_owned() + "::" + name),
|
||||
|
@ -39,11 +40,14 @@ pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
|||
let dest = pattern_parser(&mut ctxt, pat, "value", None, &mut body);
|
||||
let dest = dest.as_ref().map(String::as_str);
|
||||
construct(&ctxt, ctorname, false, &pattern_type(pat), dest, &mut body);
|
||||
item(seq!["fn ", fname.clone(), "(value: &", ctxt.m.target(), ") -> ",
|
||||
"std::result::Result<", names::render_constructor(n), ", _support::ParseError> ",
|
||||
block(body)])
|
||||
item(seq!["fn ", fname.clone(), ctxt.m.literals_generic_decls(),
|
||||
"(_ctxt: ", ctxt.m.literals_type(), ", value: &", ctxt.m.any_type(), ") -> ",
|
||||
"std::result::Result<",
|
||||
names::render_constructor(n), ty.generic_arg(ctxt.m),
|
||||
", _support::ParseError> ",
|
||||
codeblock(body)])
|
||||
});
|
||||
body.push(item(seq!["if let Ok(r) = ", fname, "(value) { return Ok(r); }"]));
|
||||
body.push(item(seq!["if let Ok(r) = ", fname, "(_ctxt, value) { return Ok(r); }"]));
|
||||
}
|
||||
body.push(item(seq![ctxt.err_code()]));
|
||||
}
|
||||
|
@ -62,13 +66,36 @@ pub fn gen_definition_parser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
|||
}
|
||||
}
|
||||
|
||||
item(seq!["impl std::convert::TryFrom", anglebrackets![seq!["&", ctxt.m.target()]], " for ",
|
||||
names::render_constructor(n), " ", block![
|
||||
seq!["type Error = _support::ParseError;"],
|
||||
seq!["fn try_from(value: &", ctxt.m.target(), ") -> ",
|
||||
let (topdecl, innerdecl) = if ty.has_embedded(ctxt.m) {
|
||||
(ctxt.m.literals_generic_decls(), item(""))
|
||||
} else {
|
||||
(item(""), ctxt.m.literals_generic_decls())
|
||||
};
|
||||
|
||||
item(seq!["impl", topdecl, " ",
|
||||
names::render_constructor(n), ty.generic_arg(ctxt.m), " ",
|
||||
block![
|
||||
seq!["pub fn parse", innerdecl, "(_ctxt: ", ctxt.m.literals_type(),
|
||||
", value: &", ctxt.m.any_type(), ") -> ",
|
||||
"std::result::Result<Self, _support::ParseError> ",
|
||||
block(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(
|
||||
|
@ -118,12 +145,7 @@ fn simple_pattern_parser(
|
|||
let dest = ctxt.gentempname();
|
||||
match p {
|
||||
SimplePattern::Any => {
|
||||
match ctxt.m.mode() {
|
||||
ModuleContextMode::TargetIOValue =>
|
||||
ctxt.define_atom(body, &dest, item(seq!["_support::decode_embedded", parens![src.to_owned()], "?"])),
|
||||
ModuleContextMode::TargetAny =>
|
||||
ctxt.define_atom(body, &dest, item(src.to_owned())),
|
||||
}
|
||||
ctxt.define_atom(body, &dest, item(src.to_owned()));
|
||||
dest
|
||||
},
|
||||
SimplePattern::Atom { atom_kind: k } => {
|
||||
|
@ -140,16 +162,8 @@ fn simple_pattern_parser(
|
|||
dest
|
||||
},
|
||||
SimplePattern::Embedded { .. } => {
|
||||
match ctxt.m.mode() {
|
||||
ModuleContextMode::TargetIOValue =>
|
||||
ctxt.define_atom(body, &dest, item(seq![
|
||||
"std::sync::Arc::new(_Dom::try_from",
|
||||
parens![seq![src.to_owned(), ".value().to_embedded()?"]],
|
||||
"?)"])),
|
||||
ModuleContextMode::TargetAny =>
|
||||
ctxt.define_atom(body, &dest, item(seq![
|
||||
parens![seq![src.to_owned(), ".value().to_embedded()?"]]])),
|
||||
}
|
||||
ctxt.define_atom(body, &dest, item(seq![
|
||||
parens![seq![src.to_owned(), ".value().to_embedded()?"]]]));
|
||||
dest
|
||||
},
|
||||
SimplePattern::Lit { value } => {
|
||||
|
@ -200,10 +214,10 @@ fn simple_pattern_parser(
|
|||
dest
|
||||
},
|
||||
SimplePattern::Ref(r) => {
|
||||
let tf = name![ctxt.m.render_ref(&**r), "try_from"];
|
||||
let tf = name![ctxt.m.render_ref(&**r, false), "parse"];
|
||||
ctxt.define_atom(body,
|
||||
&dest,
|
||||
item(seq![tf, parens![seq![src.to_owned()]], "?"]));
|
||||
item(seq![tf, parens!["_ctxt", src.to_owned()], "?"]));
|
||||
dest
|
||||
},
|
||||
}
|
||||
|
|
|
@ -7,10 +7,11 @@ use crate::syntax::block::constructors::*;
|
|||
|
||||
use preserves::value::AtomClass;
|
||||
use preserves::value::CompoundClass;
|
||||
use preserves::value::IOValue;
|
||||
use preserves::value::NestedValue;
|
||||
use preserves::value::ValueClass;
|
||||
|
||||
use super::context::{ModuleContext, FunctionContext};
|
||||
use super::context::{ModuleContextMode, ModuleContext, FunctionContext};
|
||||
use super::names;
|
||||
use super::types::*;
|
||||
|
||||
|
@ -18,8 +19,8 @@ use super::types::*;
|
|||
pub struct ReaderPlugin;
|
||||
|
||||
impl compiler::Plugin for ReaderPlugin {
|
||||
fn generate(&self, module_ctxt: &mut ModuleContext, definition_name: &str, definition: &Definition) {
|
||||
if module_ctxt.mode.is_none() {
|
||||
fn generate_definition(&self, module_ctxt: &mut ModuleContext, definition_name: &str, definition: &Definition) {
|
||||
if let ModuleContextMode::TargetGeneric = module_ctxt.mode {
|
||||
gen_definition_reader(module_ctxt, definition_name, definition)
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +75,8 @@ impl BoundaryTracker {
|
|||
}
|
||||
|
||||
pub fn gen_definition_reader(m: &mut ModuleContext, n: &str, d: &Definition) {
|
||||
let ty = definition_type(d);
|
||||
|
||||
m.define_function(
|
||||
n,
|
||||
|mut ctxt| {
|
||||
|
@ -97,9 +100,12 @@ pub fn gen_definition_reader(m: &mut ModuleContext, n: &str, d: &Definition) {
|
|||
item(seq![
|
||||
"fn ", fname.clone(), anglebrackets![
|
||||
"'de",
|
||||
"_Any: preserves::value::NestedValue",
|
||||
"R: _support::Reader<'de, _Any>"],
|
||||
"(r: &mut R) -> ",
|
||||
"std::result::Result<", names::render_constructor(n), ", _support::ParseError> ",
|
||||
"std::result::Result<",
|
||||
names::render_constructor(n), ty.generic_arg(ctxt.m),
|
||||
", _support::ParseError> ",
|
||||
block(body)])
|
||||
});
|
||||
body.push(item(seq![
|
||||
|
@ -132,9 +138,11 @@ pub fn gen_definition_reader(m: &mut ModuleContext, n: &str, d: &Definition) {
|
|||
}
|
||||
|
||||
item(seq![
|
||||
"impl", anglebrackets!["'de", "R: _support::Reader<'de, _Any>"], " ",
|
||||
"impl", anglebrackets!["'de",
|
||||
"_Any: preserves::value::NestedValue",
|
||||
"R: _support::Reader<'de, _Any>"], " ",
|
||||
"_support::Deserialize", anglebrackets!["'de", "_Any", "R"], " ",
|
||||
"for ", names::render_constructor(n), " ", block![
|
||||
"for ", names::render_constructor(n), ty.generic_arg(ctxt.m), " ", block![
|
||||
seq!["fn deserialize(r: &mut R) -> ",
|
||||
"std::result::Result<Self, _support::ParseError> ",
|
||||
block(body)]]])
|
||||
|
@ -207,8 +215,8 @@ where
|
|||
}
|
||||
|
||||
type LiteralContinuation = Box<dyn FnOnce(&mut FunctionContext, &mut Vec<Item>) -> ()>;
|
||||
type LiteralCases = Vec<(_Any, LiteralContinuation)>;
|
||||
type LiteralSeqCases = Vec<(Vec<_Any>, LiteralContinuation)>;
|
||||
type LiteralCases = Vec<(IOValue, LiteralContinuation)>;
|
||||
type LiteralSeqCases = Vec<(Vec<IOValue>, LiteralContinuation)>;
|
||||
|
||||
fn read_expected_literal_seqs(
|
||||
ctxt: &mut FunctionContext,
|
||||
|
@ -418,7 +426,7 @@ fn simple_pattern_reader(
|
|||
dest
|
||||
},
|
||||
SimplePattern::Ref(r) => {
|
||||
let tf = name![ctxt.m.render_ref(&**r), "deserialize"];
|
||||
let tf = name![ctxt.m.render_ref(&**r, false), "deserialize"];
|
||||
ctxt.define_atom(body, &dest, item(seq![tf, "(r)?"]));
|
||||
dest
|
||||
},
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use crate::*;
|
||||
use crate::syntax::block::Emittable;
|
||||
use crate::syntax::block::{Item, Emittable};
|
||||
use crate::syntax::block::constructors::*;
|
||||
use crate::gen::schema::*;
|
||||
|
||||
use super::context::ModuleContext;
|
||||
use preserves::value::Set;
|
||||
|
||||
use super::context::{ModuleContextMode, ModuleContext};
|
||||
use super::names;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
|
@ -37,11 +39,23 @@ pub struct TRecord(pub Vec<(String, TField)>);
|
|||
pub struct TypePlugin;
|
||||
|
||||
impl compiler::Plugin for TypePlugin {
|
||||
fn generate(&self, m: &mut ModuleContext, n: &str, d: &Definition) {
|
||||
if m.mode.is_none() {
|
||||
m.define_type(item(render_definition_type(m, n, &definition_type(d))));
|
||||
fn generate_module(&self, m: &mut ModuleContext) {
|
||||
if let EmbeddedTypeName::Ref(r) = &m.schema.embedded_type {
|
||||
m.define_type(item(vertical(false, seq![
|
||||
seq!["pub type _Dom = ", m.render_ref(&*r, true), ";"],
|
||||
seq!["pub type _Ptr = std::sync::Arc<_Dom>;"],
|
||||
seq!["pub type _Any = preserves::value::ArcValue<_Ptr>;"]
|
||||
])));
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_definition(&self, m: &mut ModuleContext, n: &str, d: &Definition) {
|
||||
if let ModuleContextMode::TargetGeneric = m.mode {
|
||||
let ty = definition_type(d);
|
||||
m.define_type(item(ty.render(m, n)));
|
||||
m.define_type(item(seq![
|
||||
"impl preserves::value::Domain for ", names::render_constructor(n), " {}"]));
|
||||
"impl", ty.generic_decl(m), " preserves::value::Domain for ",
|
||||
names::render_constructor(n), ty.generic_arg(m), " {}"]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -165,59 +179,119 @@ pub fn field_type(p: &SimplePattern) -> TField {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn render_field_type(
|
||||
ctxt: &ModuleContext,
|
||||
box_needed: bool,
|
||||
t: &TField,
|
||||
) -> impl Emittable {
|
||||
match t {
|
||||
TField::Unit => seq!["()"],
|
||||
TField::Any => seq!["_Any"],
|
||||
TField::Embedded => seq!["_Ptr"],
|
||||
TField::Array(t) => seq!["std::vec::Vec<", render_field_type(ctxt, false, t), ">"],
|
||||
TField::Set(t) => seq!["preserves::value::Set<", render_field_type(ctxt, false, t), ">"],
|
||||
TField::Map(k, v) => seq!["preserves::value::Map",
|
||||
anglebrackets![render_field_type(ctxt, false, k),
|
||||
render_field_type(ctxt, false, v)]],
|
||||
TField::Ref(r) =>
|
||||
if box_needed {
|
||||
seq!["std::boxed::Box", anglebrackets![ctxt.render_ref(r)]]
|
||||
} else {
|
||||
seq![ctxt.render_ref(r)]
|
||||
},
|
||||
TField::Base(n) => seq![n.to_owned()],
|
||||
impl TField {
|
||||
fn render(&self, ctxt: &ModuleContext, box_needed: bool) -> impl Emittable {
|
||||
match self {
|
||||
TField::Unit => seq!["()"],
|
||||
TField::Any => seq!["_Any"],
|
||||
TField::Embedded => seq!["_Ptr"],
|
||||
TField::Array(t) => seq!["std::vec::Vec<", t.render(ctxt, false), ">"],
|
||||
TField::Set(t) => seq!["preserves::value::Set<", t.render(ctxt, false), ">"],
|
||||
TField::Map(k, v) => seq!["preserves::value::Map",
|
||||
anglebrackets![k.render(ctxt, false),
|
||||
v.render(ctxt, false)]],
|
||||
TField::Ref(r) =>
|
||||
if box_needed {
|
||||
seq!["std::boxed::Box", anglebrackets![ctxt.render_ref(r, true)]]
|
||||
} else {
|
||||
seq![ctxt.render_ref(r, true)]
|
||||
},
|
||||
TField::Base(n) => seq![n.to_owned()],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_embedded(&self, ctxt: &ModuleContext, seen: &mut Set<Ref>) -> bool {
|
||||
match self {
|
||||
TField::Unit => false,
|
||||
TField::Any => true, // at least potentially true
|
||||
TField::Embedded => true,
|
||||
TField::Array(f) => f.has_embedded(ctxt, seen),
|
||||
TField::Set(f) => f.has_embedded(ctxt, seen),
|
||||
TField::Map(k, v) => k.has_embedded(ctxt, seen) || v.has_embedded(ctxt, seen),
|
||||
TField::Ref(r) => {
|
||||
let r = ctxt.qualify(r);
|
||||
if seen.contains(&r) {
|
||||
false
|
||||
} else {
|
||||
seen.insert(r.clone());
|
||||
ctxt.type_for_name(&r)._has_embedded(ctxt, seen)
|
||||
}
|
||||
}
|
||||
TField::Base(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_recordlike_type(
|
||||
ctxt: &ModuleContext,
|
||||
is_struct: bool,
|
||||
n: &str,
|
||||
d: &TSimple,
|
||||
) -> impl Emittable {
|
||||
let semi = if is_struct { seq![";"] } else { seq![] };
|
||||
let ppub = if is_struct { "pub " } else { "" };
|
||||
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(ctxt, !is_struct, d)]
|
||||
)).collect())],
|
||||
TSimple::Field(TField::Unit) => semi,
|
||||
TSimple::Field(t) => seq![parens![seq![ppub, render_field_type(ctxt, !is_struct, t)]], semi],
|
||||
}]
|
||||
impl TSimple {
|
||||
pub fn render(&self, ctxt: &ModuleContext, ptr: Item, is_struct: bool, n: &str) -> impl Emittable {
|
||||
let semi = if is_struct { seq![";"] } else { seq![] };
|
||||
let ppub = if is_struct { "pub " } else { "" };
|
||||
seq![names::render_constructor(n), ptr.to_owned(),
|
||||
match self {
|
||||
TSimple::Record(TRecord(fs)) => seq![" ", vertical(false, braces(
|
||||
fs.iter().map(|(n, d)| item(
|
||||
seq![ppub, names::render_fieldname(n), ": ", d.render(ctxt, !is_struct)]
|
||||
)).collect()))],
|
||||
TSimple::Field(TField::Unit) => semi,
|
||||
TSimple::Field(t) => seq![parens![seq![ppub, t.render(ctxt, !is_struct)]], semi],
|
||||
}]
|
||||
}
|
||||
|
||||
pub fn has_embedded(&self, ctxt: &ModuleContext, seen: &mut Set<Ref>) -> bool {
|
||||
match self {
|
||||
TSimple::Field(f) => f.has_embedded(ctxt, seen),
|
||||
TSimple::Record(TRecord(fs)) => fs.iter().any(|(_k, v)| v.has_embedded(ctxt, seen)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_definition_type(
|
||||
ctxt: &ModuleContext,
|
||||
n: &str,
|
||||
t: &TDefinition,
|
||||
) -> impl Emittable {
|
||||
seq!["#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)]\n",
|
||||
match t {
|
||||
TDefinition::Union(items) =>
|
||||
seq!["pub enum ", names::render_constructor(n), " ", braces(
|
||||
items.iter().map(|(n, d)| item(render_recordlike_type(ctxt, false, n, d))).collect())],
|
||||
TDefinition::Simple(s) =>
|
||||
seq!["pub struct ", render_recordlike_type(ctxt, true, n, s)],
|
||||
}]
|
||||
impl TDefinition {
|
||||
pub fn generic_decl(&self, ctxt: &ModuleContext) -> Item {
|
||||
if self.has_embedded(ctxt) {
|
||||
ctxt.literals_generic_decls()
|
||||
} else {
|
||||
item("")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generic_decl_with_defaults(&self, ctxt: &ModuleContext) -> Item {
|
||||
if self.has_embedded(ctxt) {
|
||||
ctxt.literals_generic_decls_with_defaults()
|
||||
} else {
|
||||
item("")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generic_arg(&self, ctxt: &ModuleContext) -> Item {
|
||||
if self.has_embedded(ctxt) {
|
||||
ctxt.literals_generic_arg()
|
||||
} else {
|
||||
item("")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(&self, ctxt: &ModuleContext, n: &str) -> impl Emittable {
|
||||
vertical(false, seq![
|
||||
"#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash)]",
|
||||
match self {
|
||||
TDefinition::Union(items) =>
|
||||
seq!["pub enum ",
|
||||
names::render_constructor(n), self.generic_decl_with_defaults(ctxt), " ",
|
||||
vertical(false, braces(items.iter().map(
|
||||
|(n, d)| item(d.render(ctxt, item(""), false, n))).collect()))],
|
||||
TDefinition::Simple(s) =>
|
||||
seq!["pub struct ", s.render(ctxt, self.generic_decl_with_defaults(ctxt), true, n)],
|
||||
}])
|
||||
}
|
||||
|
||||
pub fn has_embedded(&self, ctxt: &ModuleContext) -> bool {
|
||||
self._has_embedded(ctxt, &mut Set::new())
|
||||
}
|
||||
|
||||
fn _has_embedded(&self, ctxt: &ModuleContext, seen: &mut Set<Ref>) -> bool {
|
||||
match self {
|
||||
TDefinition::Union(entries) => entries.iter().any(|(_k, v)| v.has_embedded(ctxt, seen)),
|
||||
TDefinition::Simple(t) => t.has_embedded(ctxt, seen),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ use super::types::*;
|
|||
pub struct UnparserPlugin;
|
||||
|
||||
impl compiler::Plugin for UnparserPlugin {
|
||||
fn generate(&self, module_ctxt: &mut ModuleContext, definition_name: &str, definition: &Definition) {
|
||||
if module_ctxt.mode.is_some() {
|
||||
fn generate_definition(&self, module_ctxt: &mut ModuleContext, definition_name: &str, definition: &Definition) {
|
||||
if let ModuleContextMode::TargetGeneric = module_ctxt.mode {
|
||||
gen_definition_unparser(module_ctxt, definition_name, definition)
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,8 @@ fn normal_src(src: String, is_struct: bool) -> ValueContext {
|
|||
}
|
||||
|
||||
pub fn gen_definition_unparser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
||||
let ty = definition_type(d);
|
||||
|
||||
m.define_function(
|
||||
n,
|
||||
|mut ctxt| {
|
||||
|
@ -70,7 +72,7 @@ pub fn gen_definition_unparser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
|||
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(
|
||||
body.push(item(seq!["match self ", 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));
|
||||
|
@ -81,7 +83,7 @@ pub fn gen_definition_unparser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
|||
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));
|
||||
body.push(item(seq!["let ", patpat, " = value;"]));
|
||||
body.push(item(seq!["let ", patpat, " = self;"]));
|
||||
body.push(item(seq![
|
||||
"preserves::value::merge(vec!", brackets(ps.iter().map(
|
||||
|p| named_pattern_unparser(&mut ctxt, p, &vc)).collect()
|
||||
|
@ -90,16 +92,37 @@ pub fn gen_definition_unparser(m: &mut ModuleContext, n: &str, d: &Definition) {
|
|||
}
|
||||
Definition::Pattern(p) => {
|
||||
let (patpat, vc) = destruct(&mut ctxt, item(names::render_constructor(n)), true, &pattern_type(p));
|
||||
body.push(item(seq!["let ", patpat, " = value;"]));
|
||||
body.push(item(seq!["let ", patpat, " = self;"]));
|
||||
body.push(pattern_unparser(&mut ctxt, p, &vc));
|
||||
}
|
||||
}
|
||||
|
||||
item(seq!["impl std::convert::From", anglebrackets![seq!["&", names::render_constructor(n)]],
|
||||
" for ", ctxt.m.target(), " ", block![
|
||||
seq!["fn from(value: &", names::render_constructor(n), ") -> Self ",
|
||||
block(body)]]])
|
||||
let (topdecl, innerdecl) = if ty.has_embedded(ctxt.m) {
|
||||
(ctxt.m.literals_generic_decls(), item(""))
|
||||
} else {
|
||||
(item(""), ctxt.m.literals_generic_decls())
|
||||
};
|
||||
|
||||
item(seq!["impl", topdecl, " ",
|
||||
names::render_constructor(n), ty.generic_arg(ctxt.m), " ", block![
|
||||
seq!["pub fn unparse", innerdecl,
|
||||
"(&self, _ctxt: ", ctxt.m.literals_type(), ") -> ",
|
||||
ctxt.m.any_type(), " ", block(body)]]])
|
||||
});
|
||||
|
||||
// m.define_function(
|
||||
// n,
|
||||
// |ctxt| {
|
||||
// let ty_arg = item(seq![names::render_constructor(n), ty.generic_arg(ctxt.m)]);
|
||||
// item(seq!["impl", ctxt.m.literals_generic_decls(),
|
||||
// " std::convert::From", anglebrackets![seq!["&", ty_arg.clone()]],
|
||||
// " for ", ctxt.m.any_type(), " ", block![
|
||||
// seq!["fn from(value: &", ty_arg, ") -> Self ",
|
||||
// codeblock![
|
||||
// seq!["Self::unparse(",
|
||||
// ctxt.m.literals_base_type(), "::default()",
|
||||
// ", value)"]]]]])
|
||||
// });
|
||||
}
|
||||
|
||||
fn destruct(
|
||||
|
@ -134,14 +157,8 @@ fn simple_pattern_unparser(
|
|||
) -> Item {
|
||||
let src = &vc.src;
|
||||
match p {
|
||||
SimplePattern::Any => {
|
||||
match ctxt.m.mode() {
|
||||
ModuleContextMode::TargetIOValue =>
|
||||
item(seq!["_support::encode_embedded", parens![src.as_ref().unwrap().to_owned()]]),
|
||||
ModuleContextMode::TargetAny =>
|
||||
item(seq![src.as_ref().unwrap().to_owned(), ".clone()"]),
|
||||
}
|
||||
}
|
||||
SimplePattern::Any =>
|
||||
item(seq![src.as_ref().unwrap().to_owned(), ".clone()"]),
|
||||
SimplePattern::Atom { atom_kind: k } => {
|
||||
match &**k {
|
||||
AtomKind::Symbol =>
|
||||
|
@ -152,14 +169,8 @@ fn simple_pattern_unparser(
|
|||
item(seq!["preserves::value::Value::from(", src.as_ref().unwrap().to_owned(), ").wrap()"])
|
||||
}
|
||||
}
|
||||
SimplePattern::Embedded { .. } => {
|
||||
match ctxt.m.mode() {
|
||||
ModuleContextMode::TargetIOValue =>
|
||||
item(seq!["preserves::value::Value::Embedded(preserves::value::IOValue::from(&**", src.as_ref().unwrap().to_owned(), ")).wrap()"]),
|
||||
ModuleContextMode::TargetAny =>
|
||||
item(seq!["preserves::value::Value::Embedded(", src.as_ref().unwrap().to_owned(), ".clone()).wrap()"]),
|
||||
}
|
||||
}
|
||||
SimplePattern::Embedded { .. } =>
|
||||
item(seq!["preserves::value::Value::Embedded(", src.as_ref().unwrap().to_owned(), ".clone()).wrap()"]),
|
||||
SimplePattern::Lit { value } =>
|
||||
item(seq![parens![ctxt.m.define_literal(value)], ".clone()"]),
|
||||
SimplePattern::Seqof { pattern } => {
|
||||
|
@ -192,9 +203,9 @@ fn simple_pattern_unparser(
|
|||
").collect()).wrap()"])
|
||||
}
|
||||
SimplePattern::Ref(_r) =>
|
||||
item(seq![ctxt.m.target(), "::from(", src.as_ref().unwrap().to_owned(),
|
||||
item(seq![src.as_ref().unwrap().to_owned(),
|
||||
if vc.is_struct { "" } else { ".as_ref()" },
|
||||
")"]),
|
||||
".unparse(_ctxt)"]),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1,73 @@
|
|||
pub mod schema;
|
||||
pub mod schema;
|
||||
|
||||
use crate::support as _support;
|
||||
use _support::preserves;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub struct Literals<N: preserves::value::NestedValue> {
|
||||
pub LIT_15_FALSE: N /* #f */,
|
||||
pub LIT_28_1: N /* 1 */,
|
||||
pub LIT_0_BOOLEAN: N /* Boolean */,
|
||||
pub LIT_5_BYTE_STRING: N /* ByteString */,
|
||||
pub LIT_2_DOUBLE: N /* Double */,
|
||||
pub LIT_1_FLOAT: N /* Float */,
|
||||
pub LIT_3_SIGNED_INTEGER: N /* SignedInteger */,
|
||||
pub LIT_4_STRING: N /* String */,
|
||||
pub LIT_6_SYMBOL: N /* Symbol */,
|
||||
pub LIT_14_AND: N /* and */,
|
||||
pub LIT_21_ANY: N /* any */,
|
||||
pub LIT_22_ATOM: N /* atom */,
|
||||
pub LIT_8_BUNDLE: N /* bundle */,
|
||||
pub LIT_18_DEFINITIONS: N /* definitions */,
|
||||
pub LIT_12_DICT: N /* dict */,
|
||||
pub LIT_27_DICTOF: N /* dictof */,
|
||||
pub LIT_23_EMBEDDED: N /* embedded */,
|
||||
pub LIT_19_EMBEDDED_TYPE: N /* embeddedType */,
|
||||
pub LIT_24_LIT: N /* lit */,
|
||||
pub LIT_7_NAMED: N /* named */,
|
||||
pub LIT_13_OR: N /* or */,
|
||||
pub LIT_9_REC: N /* rec */,
|
||||
pub LIT_16_REF: N /* ref */,
|
||||
pub LIT_17_SCHEMA: N /* schema */,
|
||||
pub LIT_25_SEQOF: N /* seqof */,
|
||||
pub LIT_26_SETOF: N /* setof */,
|
||||
pub LIT_10_TUPLE: N /* tuple */,
|
||||
pub LIT_11_TUPLE_PREFIX: N /* tuplePrefix */,
|
||||
pub LIT_20_VERSION: N /* version */
|
||||
}
|
||||
|
||||
impl<N: preserves::value::NestedValue> Default for Literals<N> {
|
||||
fn default() -> Self {
|
||||
Literals {
|
||||
LIT_15_FALSE: /* #f */ _support::decode_lit(&vec![128]).unwrap(),
|
||||
LIT_28_1: /* 1 */ _support::decode_lit(&vec![145]).unwrap(),
|
||||
LIT_0_BOOLEAN: /* Boolean */ _support::decode_lit(&vec![179, 7, 66, 111, 111, 108, 101, 97, 110]).unwrap(),
|
||||
LIT_5_BYTE_STRING: /* ByteString */ _support::decode_lit(&vec![179, 10, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103]).unwrap(),
|
||||
LIT_2_DOUBLE: /* Double */ _support::decode_lit(&vec![179, 6, 68, 111, 117, 98, 108, 101]).unwrap(),
|
||||
LIT_1_FLOAT: /* Float */ _support::decode_lit(&vec![179, 5, 70, 108, 111, 97, 116]).unwrap(),
|
||||
LIT_3_SIGNED_INTEGER: /* SignedInteger */ _support::decode_lit(&vec![179, 13, 83, 105, 103, 110, 101, 100, 73, 110, 116, 101, 103, 101, 114]).unwrap(),
|
||||
LIT_4_STRING: /* String */ _support::decode_lit(&vec![179, 6, 83, 116, 114, 105, 110, 103]).unwrap(),
|
||||
LIT_6_SYMBOL: /* Symbol */ _support::decode_lit(&vec![179, 6, 83, 121, 109, 98, 111, 108]).unwrap(),
|
||||
LIT_14_AND: /* and */ _support::decode_lit(&vec![179, 3, 97, 110, 100]).unwrap(),
|
||||
LIT_21_ANY: /* any */ _support::decode_lit(&vec![179, 3, 97, 110, 121]).unwrap(),
|
||||
LIT_22_ATOM: /* atom */ _support::decode_lit(&vec![179, 4, 97, 116, 111, 109]).unwrap(),
|
||||
LIT_8_BUNDLE: /* bundle */ _support::decode_lit(&vec![179, 6, 98, 117, 110, 100, 108, 101]).unwrap(),
|
||||
LIT_18_DEFINITIONS: /* definitions */ _support::decode_lit(&vec![179, 11, 100, 101, 102, 105, 110, 105, 116, 105, 111, 110, 115]).unwrap(),
|
||||
LIT_12_DICT: /* dict */ _support::decode_lit(&vec![179, 4, 100, 105, 99, 116]).unwrap(),
|
||||
LIT_27_DICTOF: /* dictof */ _support::decode_lit(&vec![179, 6, 100, 105, 99, 116, 111, 102]).unwrap(),
|
||||
LIT_23_EMBEDDED: /* embedded */ _support::decode_lit(&vec![179, 8, 101, 109, 98, 101, 100, 100, 101, 100]).unwrap(),
|
||||
LIT_19_EMBEDDED_TYPE: /* embeddedType */ _support::decode_lit(&vec![179, 12, 101, 109, 98, 101, 100, 100, 101, 100, 84, 121, 112, 101]).unwrap(),
|
||||
LIT_24_LIT: /* lit */ _support::decode_lit(&vec![179, 3, 108, 105, 116]).unwrap(),
|
||||
LIT_7_NAMED: /* named */ _support::decode_lit(&vec![179, 5, 110, 97, 109, 101, 100]).unwrap(),
|
||||
LIT_13_OR: /* or */ _support::decode_lit(&vec![179, 2, 111, 114]).unwrap(),
|
||||
LIT_9_REC: /* rec */ _support::decode_lit(&vec![179, 3, 114, 101, 99]).unwrap(),
|
||||
LIT_16_REF: /* ref */ _support::decode_lit(&vec![179, 3, 114, 101, 102]).unwrap(),
|
||||
LIT_17_SCHEMA: /* schema */ _support::decode_lit(&vec![179, 6, 115, 99, 104, 101, 109, 97]).unwrap(),
|
||||
LIT_25_SEQOF: /* seqof */ _support::decode_lit(&vec![179, 5, 115, 101, 113, 111, 102]).unwrap(),
|
||||
LIT_26_SETOF: /* setof */ _support::decode_lit(&vec![179, 5, 115, 101, 116, 111, 102]).unwrap(),
|
||||
LIT_10_TUPLE: /* tuple */ _support::decode_lit(&vec![179, 5, 116, 117, 112, 108, 101]).unwrap(),
|
||||
LIT_11_TUPLE_PREFIX: /* tuplePrefix */ _support::decode_lit(&vec![179, 11, 116, 117, 112, 108, 101, 80, 114, 101, 102, 105, 120]).unwrap(),
|
||||
LIT_20_VERSION: /* version */ _support::decode_lit(&vec![179, 7, 118, 101, 114, 115, 105, 111, 110]).unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -31,17 +31,16 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn metaschema_parsing() -> Result<(), std::io::Error> {
|
||||
use preserves::value::{BinarySource, IOBinarySource, IOValue, Reader};
|
||||
use std::convert::TryFrom;
|
||||
use std::convert::From;
|
||||
use preserves::value::{BinarySource, IOBinarySource, Reader};
|
||||
use crate::gen::schema::*;
|
||||
|
||||
let mut f = std::fs::File::open("../../../schema/schema.bin")?;
|
||||
let mut src = IOBinarySource::new(&mut f);
|
||||
let mut reader = src.packed_iovalues();
|
||||
let schema = reader.demand_next(false)?;
|
||||
let parsed = Schema::try_from(&schema).expect("successful parse");
|
||||
assert_eq!(schema, IOValue::from(&parsed));
|
||||
let literals = crate::gen::Literals::default();
|
||||
let parsed = Schema::parse(&literals, &schema).expect("successful parse");
|
||||
assert_eq!(schema, parsed.unparse(&literals));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,10 +14,25 @@ use preserves::value::Value;
|
|||
use std::convert::From;
|
||||
use std::convert::TryFrom;
|
||||
use std::io;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
pub struct Codec<N: NestedValue, L: Default> {
|
||||
pub literals: L,
|
||||
phantom: PhantomData<N>,
|
||||
}
|
||||
|
||||
impl<N: NestedValue, L: Default> Codec<N, L> {
|
||||
pub fn new() -> Self {
|
||||
Codec {
|
||||
literals: L::default(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Deserialize<'de, N: NestedValue, R: Reader<'de, N>>
|
||||
where
|
||||
Self: Sized
|
||||
|
|
|
@ -7,11 +7,24 @@ pub trait Emittable: std::fmt::Debug {
|
|||
fn write_on(&self, f: &mut Formatter);
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub enum VerticalMode {
|
||||
Variable,
|
||||
Normal,
|
||||
ExtraNewline,
|
||||
}
|
||||
|
||||
pub trait Vertical {
|
||||
fn set_vertical_mode(&mut self, mode: VerticalMode);
|
||||
fn write_vertically_on(&self, f: &mut Formatter);
|
||||
}
|
||||
|
||||
pub type Item = std::rc::Rc<dyn Emittable>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Sequence {
|
||||
pub items: Vec<Item>,
|
||||
pub vertical_mode: VerticalMode,
|
||||
pub separator: &'static str,
|
||||
pub terminator: &'static str,
|
||||
}
|
||||
|
@ -80,6 +93,12 @@ impl Formatter {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for VerticalMode {
|
||||
fn default() -> Self {
|
||||
Self::Variable
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
impl Emittable for &str {
|
||||
|
@ -104,48 +123,86 @@ impl<'a, E: Emittable> Emittable for &'a Vec<E> where &'a E: Emittable {
|
|||
|
||||
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
|
||||
if self.vertical_mode != VerticalMode::Variable {
|
||||
self.write_vertically_on(f)
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
if !self.items.is_empty() {
|
||||
self.terminator.write_on(f)
|
||||
}
|
||||
e.write_on(f)
|
||||
}
|
||||
self.terminator.write_on(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Vertical for Sequence {
|
||||
fn set_vertical_mode(&mut self, vertical_mode: VerticalMode) {
|
||||
self.vertical_mode = vertical_mode;
|
||||
}
|
||||
|
||||
fn write_vertically_on(&self, f: &mut Formatter) {
|
||||
let mut i = self.items.len();
|
||||
let mut first = true;
|
||||
for e in self.items.iter() {
|
||||
if !first {
|
||||
if self.vertical_mode == VerticalMode::ExtraNewline {
|
||||
f.write("\n");
|
||||
}
|
||||
f.newline();
|
||||
}
|
||||
first = false;
|
||||
e.write_on(f);
|
||||
let delim = if i == 1 { self.terminator } else { self.separator };
|
||||
delim.trim_end_matches(|c: char| c.is_whitespace() && c != '\n').write_on(f);
|
||||
i = i - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
if self.sequence.vertical_mode != VerticalMode::Variable {
|
||||
self.write_vertically_on(f)
|
||||
} 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()
|
||||
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.write_vertically_on(f)
|
||||
}
|
||||
self.close.write_on(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Vertical for Grouping {
|
||||
fn set_vertical_mode(&mut self, vertical_mode: VerticalMode) {
|
||||
self.sequence.set_vertical_mode(vertical_mode);
|
||||
}
|
||||
|
||||
fn write_vertically_on(&self, f: &mut Formatter) {
|
||||
self.open.write_on(f);
|
||||
if !self.sequence.items.is_empty() {
|
||||
f.with_indent(|f| {
|
||||
f.newline();
|
||||
self.sequence.write_vertically_on(f)
|
||||
});
|
||||
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)
|
||||
|
@ -210,21 +267,23 @@ pub mod constructors {
|
|||
use super::Grouping;
|
||||
use super::Item;
|
||||
use super::Emittable;
|
||||
use super::VerticalMode;
|
||||
use super::Vertical;
|
||||
|
||||
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: "" }
|
||||
Sequence { items: pieces, vertical_mode: VerticalMode::default(), separator: "::", terminator: "" }
|
||||
}
|
||||
|
||||
pub fn seq(items: Vec<Item>) -> Sequence {
|
||||
Sequence { items: items, separator: "", terminator: "" }
|
||||
Sequence { items: items, vertical_mode: VerticalMode::default(), separator: "", terminator: "" }
|
||||
}
|
||||
|
||||
pub fn commas(items: Vec<Item>) -> Sequence {
|
||||
Sequence { items: items, separator: ", ", terminator: "" }
|
||||
Sequence { items: items, vertical_mode: VerticalMode::default(), separator: ", ", terminator: "" }
|
||||
}
|
||||
|
||||
pub fn parens(items: Vec<Item>) -> Grouping {
|
||||
|
@ -245,19 +304,38 @@ pub mod constructors {
|
|||
|
||||
pub fn block(items: Vec<Item>) -> Grouping {
|
||||
Grouping {
|
||||
sequence: Sequence { items: items, separator: " ", terminator: "" },
|
||||
sequence: Sequence {
|
||||
items: items,
|
||||
vertical_mode: VerticalMode::default(),
|
||||
separator: " ",
|
||||
terminator: "",
|
||||
},
|
||||
open: "{",
|
||||
close: "}",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codeblock(items: Vec<Item>) -> Grouping {
|
||||
vertical(false, block(items))
|
||||
}
|
||||
|
||||
pub fn semiblock(items: Vec<Item>) -> Grouping {
|
||||
Grouping {
|
||||
sequence: Sequence { items: items, separator: "; ", terminator: "" },
|
||||
sequence: Sequence {
|
||||
items: items,
|
||||
vertical_mode: VerticalMode::default(),
|
||||
separator: "; ",
|
||||
terminator: "",
|
||||
},
|
||||
open: "{",
|
||||
close: "}",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vertical<V: Vertical>(spaced: bool, mut v: V) -> V {
|
||||
v.set_vertical_mode(if spaced { VerticalMode::ExtraNewline } else { VerticalMode::Normal });
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
pub mod macros {
|
||||
|
@ -301,6 +379,11 @@ pub mod macros {
|
|||
($($item:expr),*) => {crate::syntax::block::constructors::block(vec![$(std::rc::Rc::new($item)),*])}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! codeblock {
|
||||
($($item:expr),*) => {crate::syntax::block::constructors::codeblock(vec![$(std::rc::Rc::new($item)),*])}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! semiblock {
|
||||
($($item:expr),*) => {crate::syntax::block::constructors::semiblock(vec![$(std::rc::Rc::new($item)),*])}
|
||||
|
|
Loading…
Reference in New Issue