Support xrefs in schema compiler; offer Arc for languages
This commit is contained in:
parent
acbc1c5fe5
commit
7f387d6d71
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue