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 inputs = expand_inputs(&vec!["path.bin".to_owned()])?;
c.load_schemas_and_bundles(&inputs)?;
c.load_schemas_and_bundles(&inputs, &vec![])?;
compile(&c)
}

View File

@ -19,6 +19,9 @@ struct CommandLine {
#[structopt(long)]
module: Vec<String>,
#[structopt(long)]
xref: Vec<String>,
input_glob: Vec<String>,
}
@ -40,6 +43,8 @@ fn main() -> Result<(), Error> {
if let Some(c) = args.support_crate {
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)
}

View File

@ -16,6 +16,7 @@ use preserves::value::Value;
use super::CompilerConfig;
use super::names;
use super::types;
use super::types::Purpose;
pub struct BundleContext<'b> {
pub config: &'b CompilerConfig,
@ -82,8 +83,9 @@ impl<'b> BundleContext<'b> {
"_Value"
}
pub fn lookup_definition(&self, r: &Ref) -> Option<&Definition> {
self.config.bundle.get(&r.module.0).and_then(|s| s.definitions.0.get(&r.name))
pub fn lookup_definition(&self, r: &Ref) -> Option<(&Definition, Purpose)> {
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> {
@ -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 {
FunctionContext {
error_context: error_context.to_owned(),
m: m,
m,
temp_counter: 0,
captures: Vec::new(),
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) {
self.captures.push(Capture {
field_name: field_name,
ty: ty,
field_name,
ty,
source_expr: match self.capture_mode {
CaptureMode::Definite =>
source_expr,

View File

@ -8,6 +8,7 @@ pub mod unparsers;
use crate::*;
use crate::compiler::context::*;
use crate::compiler::types::Purpose;
use crate::gen::Language;
use crate::gen::schema;
use crate::gen::schema::*;
@ -97,7 +98,7 @@ impl ExternalModule {
#[derive(Debug)]
pub struct CompilerConfig {
pub bundle: Map<ModulePath, Schema>,
pub bundle: Map<ModulePath, (Schema, Purpose)>,
pub output_dir: PathBuf,
pub fully_qualified_module_prefix: String,
pub support_crate: String,
@ -105,7 +106,21 @@ pub struct CompilerConfig {
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 src = IOBinarySource::new(&mut f);
let mut reader = src.packed_iovalues();
@ -139,8 +154,8 @@ impl CompilerConfig {
) -> Self {
CompilerConfig {
bundle: Map::new(),
output_dir: output_dir,
fully_qualified_module_prefix: fully_qualified_module_prefix,
output_dir,
fully_qualified_module_prefix,
support_crate: "preserves_schema".to_owned(),
external_modules: Map::new(),
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 {
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(())
}
@ -169,8 +187,8 @@ impl CompilerConfig {
fn build_type_cache(&self) -> Map<Ref, types::TDefinition> {
self.bundle.iter().flat_map(|(modpath, s)| {
let modpath = ModulePath(modpath.clone());
s.definitions.0.iter().map(move |(name, def)| {
let ty = types::definition_type(&modpath, name, def);
s.0.definitions.0.iter().map(move |(name, def)| {
let ty = types::definition_type(&modpath, s.1, name, def);
(ty.self_ref.clone(), ty)
})
}).collect()
@ -237,7 +255,11 @@ impl Schema {
pub fn compile(config: &CompilerConfig) -> io::Result<()> {
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();
output_path.extend(k);
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"]);
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("".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) {
let ty = definition_type(&m.module_path, n, d);
let ty = definition_type(&m.module_path, Purpose::Codegen, n, d);
m.define_function(
n,

View File

@ -78,7 +78,7 @@ impl BoundaryTracker {
}
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(
n,

View File

@ -11,8 +11,15 @@ use super::context::ModuleContextMode;
use super::context::RefRenderStyle;
use super::names;
#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
pub enum Purpose {
Codegen,
Xref,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct TDefinition {
pub purpose: Purpose,
pub self_ref: Ref,
pub body: TDefinitionBody,
}
@ -60,7 +67,7 @@ impl compiler::Plugin for TypePlugin {
fn generate_definition(&self, m: &mut ModuleContext, n: &str, d: &Definition) {
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(seq![
"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 {
purpose,
self_ref: Ref { module: module.clone(), name: n.to_owned() },
body: match d {
Definition::Or { pattern_0, pattern_1, pattern_n } =>
@ -229,8 +237,8 @@ impl TField {
r,
|ctxt, r| ctxt.type_for_name(r),
|s, t| match t {
Some(ty) => ty._language_types(s, ts),
None => {
Some(ty) if ty.purpose == Purpose::Codegen => ty._language_types(s, ts),
Some(_) | None => {
let xmts = &s.context.config.external_modules.get(&r.module.0).unwrap()
.rust_language_types;
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 {
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 {
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) {
let ty = definition_type(&m.module_path, n, d);
let ty = definition_type(&m.module_path, Purpose::Codegen, n, d);
m.define_function(
n,
@ -234,7 +234,7 @@ fn pattern_unparser(
sink: ValueSink::Fields(Rc::new(Cell::new(Some(FieldsSink {
finish: item(seq![rtmp.clone(), ".finish().wrap()"]),
vec_expr: item(seq![rtmp.clone(), ".fields_vec_mut()"]),
body: body,
body,
})))),
is_struct: vc.is_struct,
})
@ -285,7 +285,7 @@ fn sequenceify<'a>(
finish: item(seq![
"preserves::value::Value::Sequence", parens![rtmp.clone()], ".wrap()"]),
vec_expr: item(rtmp),
body: body,
body,
}
}
}

View File

@ -70,9 +70,16 @@ macro_rules! define_language {
mod $fname {
use super::*;
lazy_static::lazy_static! {
pub static ref GLOBAL_LANG: $lang<$default_value> = $lang {
$($field: std::sync::Arc::new($($type)::*::default())),*
};
pub static ref GLOBAL_LANG: std::sync::Arc<$lang<$default_value>> =
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
}
}