Support xrefs in schema compiler; offer Arc for languages

This commit is contained in:
Tony Garnock-Jones 2023-01-28 22:38:14 +01:00
parent acbc1c5fe5
commit 7f387d6d71
9 changed files with 78 additions and 31 deletions

View File

@ -12,7 +12,7 @@ fn main() -> Result<(), Error> {
let mut c = CompilerConfig::new(gen_dir, "crate::schemas".to_owned()); let mut c = CompilerConfig::new(gen_dir, "crate::schemas".to_owned());
let inputs = expand_inputs(&vec!["path.bin".to_owned()])?; let inputs = expand_inputs(&vec!["path.bin".to_owned()])?;
c.load_schemas_and_bundles(&inputs)?; c.load_schemas_and_bundles(&inputs, &vec![])?;
compile(&c) compile(&c)
} }

View File

@ -19,6 +19,9 @@ struct CommandLine {
#[structopt(long)] #[structopt(long)]
module: Vec<String>, module: Vec<String>,
#[structopt(long)]
xref: Vec<String>,
input_glob: Vec<String>, input_glob: Vec<String>,
} }
@ -40,6 +43,8 @@ fn main() -> Result<(), Error> {
if let Some(c) = args.support_crate { if let Some(c) = args.support_crate {
config.support_crate = c; config.support_crate = c;
} }
config.load_schemas_and_bundles(&expand_inputs(&args.input_glob)?)?; config.load_schemas_and_bundles(
&expand_inputs(&args.input_glob)?,
&expand_inputs(&args.xref)?)?;
compile(&config) compile(&config)
} }

View File

@ -16,6 +16,7 @@ use preserves::value::Value;
use super::CompilerConfig; use super::CompilerConfig;
use super::names; use super::names;
use super::types; use super::types;
use super::types::Purpose;
pub struct BundleContext<'b> { pub struct BundleContext<'b> {
pub config: &'b CompilerConfig, pub config: &'b CompilerConfig,
@ -82,8 +83,9 @@ impl<'b> BundleContext<'b> {
"_Value" "_Value"
} }
pub fn lookup_definition(&self, r: &Ref) -> Option<&Definition> { pub fn lookup_definition(&self, r: &Ref) -> Option<(&Definition, Purpose)> {
self.config.bundle.get(&r.module.0).and_then(|s| s.definitions.0.get(&r.name)) self.config.bundle.get(&r.module.0).and_then(
|s| s.0.definitions.0.get(&r.name).map(|d| (d, s.1)))
} }
pub fn type_for_name(&self, r: &Ref) -> Option<&types::TDefinition> { pub fn type_for_name(&self, r: &Ref) -> Option<&types::TDefinition> {
@ -229,7 +231,7 @@ impl<'a, 'm, 'b> FunctionContext<'a, 'm, 'b> {
pub fn new(m: &'a mut ModuleContext<'m, 'b>, error_context: &str) -> Self { pub fn new(m: &'a mut ModuleContext<'m, 'b>, error_context: &str) -> Self {
FunctionContext { FunctionContext {
error_context: error_context.to_owned(), error_context: error_context.to_owned(),
m: m, m,
temp_counter: 0, temp_counter: 0,
captures: Vec::new(), captures: Vec::new(),
capture_mode: CaptureMode::Definite, capture_mode: CaptureMode::Definite,
@ -238,8 +240,8 @@ impl<'a, 'm, 'b> FunctionContext<'a, 'm, 'b> {
pub fn capture(&mut self, field_name: String, ty: types::TField, source_expr: String) { pub fn capture(&mut self, field_name: String, ty: types::TField, source_expr: String) {
self.captures.push(Capture { self.captures.push(Capture {
field_name: field_name, field_name,
ty: ty, ty,
source_expr: match self.capture_mode { source_expr: match self.capture_mode {
CaptureMode::Definite => CaptureMode::Definite =>
source_expr, source_expr,

View File

@ -8,6 +8,7 @@ pub mod unparsers;
use crate::*; use crate::*;
use crate::compiler::context::*; use crate::compiler::context::*;
use crate::compiler::types::Purpose;
use crate::gen::Language; use crate::gen::Language;
use crate::gen::schema; use crate::gen::schema;
use crate::gen::schema::*; use crate::gen::schema::*;
@ -97,7 +98,7 @@ impl ExternalModule {
#[derive(Debug)] #[derive(Debug)]
pub struct CompilerConfig { pub struct CompilerConfig {
pub bundle: Map<ModulePath, Schema>, pub bundle: Map<ModulePath, (Schema, Purpose)>,
pub output_dir: PathBuf, pub output_dir: PathBuf,
pub fully_qualified_module_prefix: String, pub fully_qualified_module_prefix: String,
pub support_crate: String, pub support_crate: String,
@ -105,7 +106,21 @@ pub struct CompilerConfig {
pub plugins: Vec<Box<dyn Plugin>>, pub plugins: Vec<Box<dyn Plugin>>,
} }
pub fn load_schema_or_bundle(bundle: &mut Map<ModulePath, Schema>, i: &PathBuf) -> io::Result<()> { pub fn load_schema_or_bundle_with_purpose(
bundle: &mut Map<ModulePath, (Schema, Purpose)>,
i: &PathBuf,
purpose: Purpose,
) -> io::Result<()> {
let mut inserted = Map::<ModulePath, Schema>::new();
load_schema_or_bundle(&mut inserted, i)?;
for (k, v) in inserted.into_iter() { bundle.insert(k, (v, purpose)); }
Ok(())
}
pub fn load_schema_or_bundle(
bundle: &mut Map<ModulePath, Schema>,
i: &PathBuf,
) -> io::Result<()> {
let mut f = File::open(&i)?; let mut f = File::open(&i)?;
let mut src = IOBinarySource::new(&mut f); let mut src = IOBinarySource::new(&mut f);
let mut reader = src.packed_iovalues(); let mut reader = src.packed_iovalues();
@ -139,8 +154,8 @@ impl CompilerConfig {
) -> Self { ) -> Self {
CompilerConfig { CompilerConfig {
bundle: Map::new(), bundle: Map::new(),
output_dir: output_dir, output_dir,
fully_qualified_module_prefix: fully_qualified_module_prefix, fully_qualified_module_prefix,
support_crate: "preserves_schema".to_owned(), support_crate: "preserves_schema".to_owned(),
external_modules: Map::new(), external_modules: Map::new(),
plugins: vec![ plugins: vec![
@ -159,9 +174,12 @@ impl CompilerConfig {
} }
} }
pub fn load_schemas_and_bundles(&mut self, inputs: &Vec<PathBuf>) -> io::Result<()> { pub fn load_schemas_and_bundles(&mut self, inputs: &Vec<PathBuf>, xrefs: &Vec<PathBuf>) -> io::Result<()> {
for i in inputs { for i in inputs {
load_schema_or_bundle(&mut self.bundle, i)?; load_schema_or_bundle_with_purpose(&mut self.bundle, i, Purpose::Codegen)?;
}
for i in xrefs {
load_schema_or_bundle_with_purpose(&mut self.bundle, i, Purpose::Xref)?;
} }
Ok(()) Ok(())
} }
@ -169,8 +187,8 @@ 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(|(modpath, s)| { self.bundle.iter().flat_map(|(modpath, s)| {
let modpath = ModulePath(modpath.clone()); let modpath = ModulePath(modpath.clone());
s.definitions.0.iter().map(move |(name, def)| { s.0.definitions.0.iter().map(move |(name, def)| {
let ty = types::definition_type(&modpath, name, def); let ty = types::definition_type(&modpath, s.1, name, def);
(ty.self_ref.clone(), ty) (ty.self_ref.clone(), ty)
}) })
}).collect() }).collect()
@ -237,7 +255,11 @@ impl Schema {
pub fn compile(config: &CompilerConfig) -> io::Result<()> { pub fn compile(config: &CompilerConfig) -> io::Result<()> {
let mut b = BundleContext::new(config); let mut b = BundleContext::new(config);
for (k, v) in config.bundle.iter() { for (k, (v, module_purpose)) in config.bundle.iter() {
if *module_purpose != Purpose::Codegen {
continue;
}
let mut output_path = config.output_dir.clone(); let mut output_path = config.output_dir.clone();
output_path.extend(k); output_path.extend(k);
let module_name = output_path.file_stem().unwrap().to_str().unwrap().to_owned(); let module_name = output_path.file_stem().unwrap().to_str().unwrap().to_owned();
@ -300,7 +322,10 @@ pub fn compile(config: &CompilerConfig) -> io::Result<()> {
mod_rs.extend(vec!["mod.rs"]); mod_rs.extend(vec!["mod.rs"]);
let mut lines = Vec::new(); let mut lines = Vec::new();
for modpath in config.bundle.keys() { for (modpath, (_, module_purpose)) in config.bundle.iter() {
if *module_purpose != Purpose::Codegen {
continue;
}
lines.push(format!("pub mod {};", names::render_modname(modpath.last().unwrap()))); lines.push(format!("pub mod {};", names::render_modname(modpath.last().unwrap())));
} }
lines.push("".to_owned()); lines.push("".to_owned());

View File

@ -22,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(&m.module_path, n, d); let ty = definition_type(&m.module_path, Purpose::Codegen, n, d);
m.define_function( m.define_function(
n, n,

View File

@ -78,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(&m.module_path, n, d); let ty = definition_type(&m.module_path, Purpose::Codegen, n, d);
m.define_function( m.define_function(
n, n,

View File

@ -11,8 +11,15 @@ use super::context::ModuleContextMode;
use super::context::RefRenderStyle; use super::context::RefRenderStyle;
use super::names; use super::names;
#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
pub enum Purpose {
Codegen,
Xref,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct TDefinition { pub struct TDefinition {
pub purpose: Purpose,
pub self_ref: Ref, pub self_ref: Ref,
pub body: TDefinitionBody, pub body: TDefinitionBody,
} }
@ -60,7 +67,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(&m.module_path, n, d); let ty = definition_type(&m.module_path, Purpose::Codegen, 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 ",
@ -69,8 +76,9 @@ impl compiler::Plugin for TypePlugin {
} }
} }
pub fn definition_type(module: &ModulePath, n: &str, d: &Definition) -> TDefinition { pub fn definition_type(module: &ModulePath, purpose: Purpose, n: &str, d: &Definition) -> TDefinition {
TDefinition { TDefinition {
purpose,
self_ref: Ref { module: module.clone(), name: n.to_owned() }, self_ref: Ref { module: module.clone(), name: n.to_owned() },
body: match d { body: match d {
Definition::Or { pattern_0, pattern_1, pattern_n } => Definition::Or { pattern_0, pattern_1, pattern_n } =>
@ -229,8 +237,8 @@ impl TField {
r, r,
|ctxt, r| ctxt.type_for_name(r), |ctxt, r| ctxt.type_for_name(r),
|s, t| match t { |s, t| match t {
Some(ty) => ty._language_types(s, ts), Some(ty) if ty.purpose == Purpose::Codegen => ty._language_types(s, ts),
None => { Some(_) | None => {
let xmts = &s.context.config.external_modules.get(&r.module.0).unwrap() let xmts = &s.context.config.external_modules.get(&r.module.0).unwrap()
.rust_language_types; .rust_language_types;
if let Some(f) = xmts.definitions.get(&r.name).or(xmts.fallback.as_ref()) { if let Some(f) = xmts.definitions.get(&r.name).or(xmts.fallback.as_ref()) {

View File

@ -53,15 +53,15 @@ struct ValueContext {
} }
fn normal_none(is_struct: bool) -> ValueContext { fn normal_none(is_struct: bool) -> ValueContext {
ValueContext { src: None, sink: ValueSink::Normal, is_struct: is_struct } ValueContext { src: None, sink: ValueSink::Normal, is_struct }
} }
fn normal_src(src: String, is_struct: bool) -> ValueContext { fn normal_src(src: String, is_struct: bool) -> ValueContext {
ValueContext { src: Some(src), sink: ValueSink::Normal, is_struct: is_struct } ValueContext { src: Some(src), sink: ValueSink::Normal, is_struct }
} }
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(&m.module_path, n, d); let ty = definition_type(&m.module_path, Purpose::Codegen, n, d);
m.define_function( m.define_function(
n, n,
@ -234,7 +234,7 @@ fn pattern_unparser(
sink: ValueSink::Fields(Rc::new(Cell::new(Some(FieldsSink { sink: ValueSink::Fields(Rc::new(Cell::new(Some(FieldsSink {
finish: item(seq![rtmp.clone(), ".finish().wrap()"]), finish: item(seq![rtmp.clone(), ".finish().wrap()"]),
vec_expr: item(seq![rtmp.clone(), ".fields_vec_mut()"]), vec_expr: item(seq![rtmp.clone(), ".fields_vec_mut()"]),
body: body, body,
})))), })))),
is_struct: vc.is_struct, is_struct: vc.is_struct,
}) })
@ -285,7 +285,7 @@ fn sequenceify<'a>(
finish: item(seq![ finish: item(seq![
"preserves::value::Value::Sequence", parens![rtmp.clone()], ".wrap()"]), "preserves::value::Value::Sequence", parens![rtmp.clone()], ".wrap()"]),
vec_expr: item(rtmp), vec_expr: item(rtmp),
body: body, body,
} }
} }
} }

View File

@ -70,9 +70,16 @@ macro_rules! define_language {
mod $fname { mod $fname {
use super::*; use super::*;
lazy_static::lazy_static! { lazy_static::lazy_static! {
pub static ref GLOBAL_LANG: $lang<$default_value> = $lang { pub static ref GLOBAL_LANG: std::sync::Arc<$lang<$default_value>> =
$($field: std::sync::Arc::new($($type)::*::default())),* std::sync::Arc::new($lang {
}; $($field: std::sync::Arc::new($($type)::*::default())),*
});
}
}
impl $lang<$default_value> {
pub fn arc() -> &'static std::sync::Arc<$lang<$default_value>> {
&*$fname::GLOBAL_LANG
} }
} }