Add polymorphic pass through.
This commit is contained in:
parent
4b59abc989
commit
13e2ae6b0c
@ -8,6 +8,7 @@ use crate::build_fn::struct_build_fn::make_struct_build_fn;
|
||||
use crate::build_fn::tree_enum_build_fn::make_enum_build_fn;
|
||||
use crate::spec::BuildSpec;
|
||||
use proc_macro2::TokenStream;
|
||||
use crate::build_fn::polymorphic_pass_through_build_fn::make_polymorphic_pass_through_build_fn;
|
||||
|
||||
mod leaf_enum_build_fn;
|
||||
mod leaf_struct_build_fn;
|
||||
@ -15,6 +16,7 @@ mod node_production_build_fn;
|
||||
mod polymorphic_build_build_fn;
|
||||
mod polymorphic_enum_build_fn;
|
||||
mod polymorphic_enum_loop_build_fn;
|
||||
mod polymorphic_pass_through_build_fn;
|
||||
mod polymorphic_type_build_fn;
|
||||
mod production_build_fn;
|
||||
mod struct_build_fn;
|
||||
@ -36,5 +38,8 @@ pub fn make_build_fn(build_spec: &BuildSpec) -> TokenStream {
|
||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop_spec) => {
|
||||
make_polymorphic_enum_loop_build_fn(polymorphic_enum_loop_spec)
|
||||
}
|
||||
BuildSpec::PolymorphicPassThrough(polymorphic_pass_through_spec) => {
|
||||
make_polymorphic_pass_through_build_fn(polymorphic_pass_through_spec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
||||
use crate::spec::polymorphic_pass_through_spec::{PolymorphicPassThroughBuildSpec, PolymorphicPassThroughVariant};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
|
||||
pub fn make_polymorphic_pass_through_build_fn(
|
||||
spec: &PolymorphicPassThroughBuildSpec,
|
||||
) -> TokenStream {
|
||||
let build_fn_ident = format_ident!("{}", make_build_fn_name(spec.name()));
|
||||
let pair_ident = format_ident!("{}", make_build_pair(spec.name()));
|
||||
let return_type_ident = format_ident!("{}", spec.build_kind());
|
||||
|
||||
let match_arms = spec.variants()
|
||||
.map(|variant| {
|
||||
match variant {
|
||||
PolymorphicPassThroughVariant::Inner { name, kind} => {
|
||||
let rule_ident = format_ident!("{}", kind);
|
||||
let variant_ident = format_ident!("{}", name);
|
||||
let inner_build_fn_ident = format_ident!("{}", make_build_fn_name(kind));
|
||||
|
||||
quote! {
|
||||
Rule::#rule_ident => {
|
||||
#return_type_ident::#variant_ident(
|
||||
#inner_build_fn_ident(inner_pair)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
PolymorphicPassThroughVariant::PassThrough { name, kind: _kind } => {
|
||||
let rule_ident = format_ident!("{}", name);
|
||||
let inner_build_fn_ident = format_ident!("{}", make_build_fn_name(name));
|
||||
|
||||
quote! {
|
||||
Rule::#rule_ident => #inner_build_fn_ident(inner_pair)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
quote! {
|
||||
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||
let inner_pair = #pair_ident.into_inner().next().unwrap();
|
||||
match inner_pair.as_rule() {
|
||||
#(#match_arms,)*
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@ mod leaf_enum_spec;
|
||||
mod leaf_struct_spec;
|
||||
mod node_production_spec;
|
||||
mod polymorphic_enum_loop_spec;
|
||||
mod polymorphic_pass_through_spec;
|
||||
mod polymorphic_type_spec;
|
||||
mod production_spec;
|
||||
mod struct_spec;
|
||||
@ -18,6 +19,7 @@ use crate::deserialize::struct_spec::deserialize_struct_spec;
|
||||
use crate::deserialize::tree_enum_spec::deserialize_tree_enum;
|
||||
use crate::spec::BuildSpec;
|
||||
use yaml_rust2::{Yaml, YamlLoader};
|
||||
use crate::deserialize::polymorphic_pass_through_spec::deserialize_polymorphic_pass_through;
|
||||
|
||||
fn deserialize_build_spec(build_spec_name: &str, build_spec: &Yaml) -> BuildSpec {
|
||||
if build_spec["struct"].is_hash() {
|
||||
@ -60,6 +62,11 @@ fn deserialize_build_spec(build_spec_name: &str, build_spec: &Yaml) -> BuildSpec
|
||||
build_spec_name,
|
||||
&build_spec["polymorphic_enum_loop_build"],
|
||||
))
|
||||
} else if build_spec["polymorphic_pass_through"].is_hash() {
|
||||
BuildSpec::PolymorphicPassThrough(deserialize_polymorphic_pass_through(
|
||||
build_spec_name,
|
||||
&build_spec["polymorphic_pass_through"],
|
||||
))
|
||||
} else {
|
||||
panic!("Missing or incorrect build type for {}", build_spec_name);
|
||||
}
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
use crate::deserialize::util::unwrap_single_member_hash;
|
||||
use crate::spec::polymorphic_pass_through_spec::{PolymorphicPassThroughBuildSpec, PolymorphicPassThroughVariant};
|
||||
use yaml_rust2::Yaml;
|
||||
|
||||
pub fn deserialize_polymorphic_pass_through(name: &str, props: &Yaml) -> PolymorphicPassThroughBuildSpec {
|
||||
let build_kind = props["build"]["kind"].as_str().unwrap();
|
||||
let variants = props["variants"].as_vec().unwrap()
|
||||
.iter()
|
||||
.map(|variant_yaml| {
|
||||
let (variant_name, variant_props) = unwrap_single_member_hash(variant_yaml);
|
||||
if variant_props["inner"].is_hash() {
|
||||
let inner_kind = variant_props["inner"]["kind"].as_str().unwrap();
|
||||
PolymorphicPassThroughVariant::Inner {
|
||||
name: variant_name,
|
||||
kind: inner_kind.to_string(),
|
||||
}
|
||||
} else if variant_props["pass_through"].is_hash() {
|
||||
let pass_through_kind = variant_props["pass_through"]["kind"].is_hash();
|
||||
PolymorphicPassThroughVariant::PassThrough {
|
||||
name: variant_name,
|
||||
kind: pass_through_kind.to_string(),
|
||||
}
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
})
|
||||
.map(Box::new)
|
||||
.collect();
|
||||
PolymorphicPassThroughBuildSpec::new(name, build_kind, variants)
|
||||
}
|
||||
@ -1,16 +1,18 @@
|
||||
use crate::spec::node_production_spec::NodeProductionBuildSpec;
|
||||
use crate::spec::polymorphic_enum_loop_spec::PolymorphicEnumLoopBuildSpec;
|
||||
use leaf_enum_spec::LeafEnumBuildSpec;
|
||||
use leaf_struct_spec::LeafStructBuildSpec;
|
||||
use polymorphic_type_spec::PolymorphicTypeBuildSpec;
|
||||
use production_spec::ProductionBuildSpec;
|
||||
use struct_spec::StructSpec;
|
||||
use tree_enum_spec::TreeEnumBuildSpec;
|
||||
use crate::spec::polymorphic_enum_loop_spec::PolymorphicEnumLoopBuildSpec;
|
||||
use crate::spec::polymorphic_pass_through_spec::PolymorphicPassThroughBuildSpec;
|
||||
|
||||
pub(crate) mod leaf_enum_spec;
|
||||
pub(crate) mod leaf_struct_spec;
|
||||
pub(crate) mod node_production_spec;
|
||||
pub(crate) mod polymorphic_enum_loop_spec;
|
||||
pub(crate) mod polymorphic_pass_through_spec;
|
||||
pub(crate) mod polymorphic_type_spec;
|
||||
pub(crate) mod production_spec;
|
||||
pub(crate) mod struct_spec;
|
||||
@ -25,4 +27,5 @@ pub enum BuildSpec {
|
||||
NodeProduction(NodeProductionBuildSpec),
|
||||
PolymorphicType(PolymorphicTypeBuildSpec),
|
||||
PolymorphicEnumLoop(PolymorphicEnumLoopBuildSpec),
|
||||
PolymorphicPassThrough(PolymorphicPassThroughBuildSpec)
|
||||
}
|
||||
|
||||
36
ast-generator/src/spec/polymorphic_pass_through_spec.rs
Normal file
36
ast-generator/src/spec/polymorphic_pass_through_spec.rs
Normal file
@ -0,0 +1,36 @@
|
||||
pub struct PolymorphicPassThroughBuildSpec {
|
||||
name: String,
|
||||
build_kind: String,
|
||||
variants: Vec<Box<PolymorphicPassThroughVariant>>,
|
||||
}
|
||||
|
||||
impl PolymorphicPassThroughBuildSpec {
|
||||
pub fn new(
|
||||
name: &str,
|
||||
build_kind: &str,
|
||||
variants: Vec<Box<PolymorphicPassThroughVariant>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
build_kind: build_kind.to_string(),
|
||||
variants,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn build_kind(&self) -> &str {
|
||||
&self.build_kind
|
||||
}
|
||||
|
||||
pub fn variants(&self) -> impl Iterator<Item = &PolymorphicPassThroughVariant> {
|
||||
self.variants.iter().map(Box::as_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum PolymorphicPassThroughVariant {
|
||||
Inner { name: String, kind: String },
|
||||
PassThrough { name: String, kind: String },
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user