From d69787e5ee106a5c2dd2c0ac2d4000e1b5947938 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Tue, 29 Jun 2021 23:19:22 +0200 Subject: [PATCH] Module aliases and embedded pointer types --- .../src/bin/preserves-schema-rs.rs | 18 ++++++++++++- .../preserves-schema/src/compiler/context.rs | 25 ++++++++++++------- .../rust/preserves-schema/src/compiler/mod.rs | 8 +++++- .../preserves-schema/src/compiler/parsers.rs | 5 ++-- .../preserves-schema/src/compiler/types.rs | 15 +++++------ .../src/compiler/unparsers.rs | 11 +++++--- .../rust/preserves-schema/src/gen/schema.rs | 2 ++ 7 files changed, 57 insertions(+), 27 deletions(-) diff --git a/implementations/rust/preserves-schema/src/bin/preserves-schema-rs.rs b/implementations/rust/preserves-schema/src/bin/preserves-schema-rs.rs index a4cc2cb..2f621d4 100644 --- a/implementations/rust/preserves-schema/src/bin/preserves-schema-rs.rs +++ b/implementations/rust/preserves-schema/src/bin/preserves-schema-rs.rs @@ -1,4 +1,5 @@ use std::io::Error; +use std::io::ErrorKind; use std::path::PathBuf; use structopt::StructOpt; @@ -9,18 +10,33 @@ struct CommandLine { #[structopt(short, long)] output_dir: PathBuf, - #[structopt(long)] + #[structopt(short, long)] prefix: String, #[structopt(long)] support_crate: Option, + #[structopt(long)] + module: Vec, + input_glob: Vec, } fn main() -> Result<(), Error> { let args = CommandLine::from_args(); let mut config = CompilerConfig::new(args.output_dir, args.prefix); + for alias in args.module { + let (modulepath_str, target) = { + let pieces: Vec<&str> = alias.split('=').collect(); + if pieces.len() != 2 { + return Err(Error::new(ErrorKind::InvalidData, + format!("Invalid module alias: {:?}", alias))); + } + (pieces[0], pieces[1]) + }; + let modulepath: Vec = modulepath_str.split('.').map(str::to_owned).collect(); + config.module_aliases.insert(modulepath, target.to_owned()); + } if let Some(c) = args.support_crate { config.support_crate = c; } diff --git a/implementations/rust/preserves-schema/src/compiler/context.rs b/implementations/rust/preserves-schema/src/compiler/context.rs index e3c8f5f..673fd9d 100644 --- a/implementations/rust/preserves-schema/src/compiler/context.rs +++ b/implementations/rust/preserves-schema/src/compiler/context.rs @@ -1,7 +1,9 @@ use preserves::value::{Map, IOValue}; +use crate::*; use crate::syntax::block::Item; use crate::syntax::block::constructors::*; +use crate::gen::schema::*; use super::CompilerConfig; use super::types; @@ -49,15 +51,20 @@ impl<'m> ModuleContext<'m> { self.functiondefs.push(i) } - pub fn render_ref(&self, mp: Vec, n: String) -> Item { - if mp.len() == 0 { - item(n) - } else { - let mut items = Vec::new(); - items.push(item(self.config.fully_qualified_module_prefix.to_owned())); - for p in mp { items.push(item(p)); } - items.push(item(n)); - item(name(items)) + pub fn render_ref(&self, r: &Ref) -> Item { + match self.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())); + for p in &r.module.0 { items.push(item(p.to_owned())); } + items.push(item(r.name.to_owned())); + item(name(items)) + } + Some(s) => + item(name![s.to_owned(), r.name.to_owned()]) } } } diff --git a/implementations/rust/preserves-schema/src/compiler/mod.rs b/implementations/rust/preserves-schema/src/compiler/mod.rs index 1c55c4f..8655828 100644 --- a/implementations/rust/preserves-schema/src/compiler/mod.rs +++ b/implementations/rust/preserves-schema/src/compiler/mod.rs @@ -5,6 +5,7 @@ pub mod parsers; pub mod unparsers; pub mod codegen; +use crate::*; use crate::gen::schema::*; use crate::syntax::block::Formatter; use crate::syntax::block::constructors::*; @@ -33,6 +34,7 @@ pub struct CompilerConfig { pub output_dir: PathBuf, pub fully_qualified_module_prefix: String, pub support_crate: String, + pub module_aliases: Map, } impl CompilerConfig { @@ -45,6 +47,7 @@ impl CompilerConfig { output_dir: output_dir, fully_qualified_module_prefix: fully_qualified_module_prefix, support_crate: "preserves_schema".to_owned(), + module_aliases: Map::new(), } } @@ -96,7 +99,10 @@ pub fn compile(config: &CompilerConfig) -> Result<(), std::io::Error> { DirBuilder::new().recursive(true).create(output_path.parent().unwrap())?; let mut m = context::ModuleContext::new(config); - // TODO: embedded type + m.define_type(item(seq!["pub type _Ptr = ", match &v.embedded_type { + EmbeddedTypeName::False => item("preserves::value::IOValue".to_owned()), + EmbeddedTypeName::Ref(r) => m.render_ref(&**r), + }, ";"])); for (n, d) in &v.definitions.0 { m.define_type(item(types::render_definition_type(&m, n, &types::definition_type(d)))); diff --git a/implementations/rust/preserves-schema/src/compiler/parsers.rs b/implementations/rust/preserves-schema/src/compiler/parsers.rs index 9f9bdfc..2f81299 100644 --- a/implementations/rust/preserves-schema/src/compiler/parsers.rs +++ b/implementations/rust/preserves-schema/src/compiler/parsers.rs @@ -85,7 +85,7 @@ fn store_wrap(is_struct: bool, ty: &TField, expr: &str) -> String { | TField::Array(_) | TField::Set(_) | TField::Map(_, _) => expr.to_owned(), - TField::Ref(_, _) => + TField::Ref(_) => if is_struct { expr.to_owned() } else { @@ -173,8 +173,7 @@ fn simple_pattern_parser( dest }, SimplePattern::Ref(r) => { - let Ref { module: ModulePath(module), name } = &**r; - let tf = name![ctxt.m.render_ref(module.clone(), name.to_owned()), "try_from"]; + let tf = name![ctxt.m.render_ref(&**r), "try_from"]; push_let(body, item(dest.to_owned()), item(seq![tf, parens![src.to_owned()], "?"])); diff --git a/implementations/rust/preserves-schema/src/compiler/types.rs b/implementations/rust/preserves-schema/src/compiler/types.rs index 9a6cce8..5e0d32f 100644 --- a/implementations/rust/preserves-schema/src/compiler/types.rs +++ b/implementations/rust/preserves-schema/src/compiler/types.rs @@ -24,7 +24,7 @@ pub enum TField { Array(Box), Set(Box), Map(Box, Box), - Ref(Vec, String), + Ref(Ref), Base(String), } @@ -140,16 +140,13 @@ pub fn field_type(p: &SimplePattern) -> TField { AtomKind::ByteString => TField::Base("std::vec::Vec".to_owned()), AtomKind::Symbol => TField::Base("std::string::String".to_owned()), }, - SimplePattern::Embedded { .. } => TField::Base("_ptr".to_owned()), + SimplePattern::Embedded { .. } => TField::Base("_Ptr".to_owned()), SimplePattern::Lit { .. } => TField::Unit, SimplePattern::Seqof { pattern: t } => TField::Array(Box::new(field_type(t))), SimplePattern::Setof { pattern: t } => TField::Set(Box::new(field_type(t))), SimplePattern::Dictof { key: k, value: v } => TField::Map(Box::new(field_type(k)), Box::new(field_type(v))), - SimplePattern::Ref(r) => { - let Ref { module: ModulePath(mp), name: n } = &**r; - TField::Ref(mp.clone(), n.to_owned()) - } + SimplePattern::Ref(r) => TField::Ref((**r).clone()), } } @@ -165,11 +162,11 @@ pub fn render_field_type( TField::Map(k, v) => seq!["preserves::value::Map", anglebrackets![render_field_type(ctxt, false, k), render_field_type(ctxt, false, v)]], - TField::Ref(mp, n) => + TField::Ref(r) => if box_needed { - seq!["std::boxed::Box", anglebrackets![ctxt.render_ref(mp.clone(), n.to_owned())]] + seq!["std::boxed::Box", anglebrackets![ctxt.render_ref(r)]] } else { - seq![ctxt.render_ref(mp.clone(), n.to_owned())] + seq![ctxt.render_ref(r)] }, TField::Base(n) => seq![n.to_owned()], } diff --git a/implementations/rust/preserves-schema/src/compiler/unparsers.rs b/implementations/rust/preserves-schema/src/compiler/unparsers.rs index 71ca077..1566c97 100644 --- a/implementations/rust/preserves-schema/src/compiler/unparsers.rs +++ b/implementations/rust/preserves-schema/src/compiler/unparsers.rs @@ -123,10 +123,13 @@ fn simple_pattern_unparser( SimplePattern::Any => item(seq![src.as_ref().unwrap().to_owned(), ".clone()"]), SimplePattern::Atom { atom_kind: k } => { - if let AtomKind::Symbol = &**k { - item(seq!["preserves::value::Value::symbol(", src.as_ref().unwrap().to_owned(), ").wrap()"]) - } else { - item(seq!["preserves::value::Value::from(", src.as_ref().unwrap().to_owned(), ").wrap()"]) + match &**k { + AtomKind::Symbol => + item(seq!["preserves::value::Value::symbol(", src.as_ref().unwrap().to_owned(), ").wrap()"]), + AtomKind::ByteString => + item(seq!["preserves::value::Value::ByteString(", src.as_ref().unwrap().to_owned(), ".clone()).wrap()"]), + _ => + item(seq!["preserves::value::Value::from(", src.as_ref().unwrap().to_owned(), ").wrap()"]) } } SimplePattern::Embedded { .. } => diff --git a/implementations/rust/preserves-schema/src/gen/schema.rs b/implementations/rust/preserves-schema/src/gen/schema.rs index fecc552..ea894ed 100644 --- a/implementations/rust/preserves-schema/src/gen/schema.rs +++ b/implementations/rust/preserves-schema/src/gen/schema.rs @@ -36,6 +36,8 @@ lazy_static! { pub static ref LIT20: preserves::value::IOValue = /* version */ preserves::value::packed::from_bytes(&vec![179, 7, 118, 101, 114, 115, 105, 111, 110]).unwrap(); } +pub type _Ptr = preserves::value::IOValue; + #[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone)] pub enum AtomKind {Boolean, Float, Double, SignedInteger, String, ByteString, Symbol}