Attempt to add AstNodeRefMut, but failure.
This commit is contained in:
parent
542d5f6c80
commit
eda25307b0
@ -1,39 +1,50 @@
|
|||||||
|
use crate::spec::tree_enum_spec::{
|
||||||
|
EnumRuleChildKind, TreeEnumBuildSpec, TreeEnumRule,
|
||||||
|
};
|
||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
use crate::spec::tree_enum_spec::{EnumRuleChildKind, TreeEnumBuildSpec};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
fn make_match_arm(rule: &TreeEnumRule, type_ident: &Ident, is_mut: bool) -> TokenStream {
|
||||||
|
let rule_ident = format_ident!("{}", rule.rule());
|
||||||
|
match rule.child() {
|
||||||
|
Some(child) => match child.kind() {
|
||||||
|
EnumRuleChildKind::Node(node_child) => {
|
||||||
|
let child_ident = format_ident!("{}", node_child.node_kind().to_case(Case::Snake));
|
||||||
|
let as_node_ref_ident = if is_mut {
|
||||||
|
quote! { as_node_ref_mut }
|
||||||
|
} else {
|
||||||
|
quote! { as_node_ref }
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
#type_ident::#rule_ident(#child_ident) => vec![
|
||||||
|
#child_ident.#as_node_ref_ident()
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => quote! {
|
||||||
|
#type_ident::#rule_ident(_) => vec![]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
quote! {
|
||||||
|
#type_ident::#rule_ident => vec![]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream {
|
pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream {
|
||||||
let type_ident = format_ident!("{}", enum_spec.build());
|
let type_ident = format_ident!("{}", enum_spec.build());
|
||||||
let match_arms = enum_spec
|
let match_arms = enum_spec
|
||||||
.rules()
|
.rules()
|
||||||
.map(|rule| {
|
.map(|rule| make_match_arm(rule, &type_ident, false))
|
||||||
let rule_ident = format_ident!("{}", rule.rule());
|
|
||||||
match rule.child() {
|
|
||||||
Some(child) => {
|
|
||||||
match child.kind() {
|
|
||||||
EnumRuleChildKind::Node(node_child) => {
|
|
||||||
let child_ident = format_ident!("{}", node_child.node_kind().to_case(Case::Snake));
|
|
||||||
quote! {
|
|
||||||
#type_ident::#rule_ident(#child_ident) => vec![
|
|
||||||
#child_ident.as_node_ref()
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => quote! {
|
|
||||||
#type_ident::#rule_ident(_) => vec![]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
quote! {
|
|
||||||
#type_ident::#rule_ident => vec![]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
let match_arms_mut = enum_spec
|
||||||
|
.rules()
|
||||||
|
.map(|rule| make_match_arm(rule, &type_ident, true))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl AstNode for #type_ident {
|
impl AstNode for #type_ident {
|
||||||
fn children(&self) -> Vec<AstNodeRef> {
|
fn children(&self) -> Vec<AstNodeRef> {
|
||||||
@ -42,9 +53,19 @@ pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn children_mut(&mut self) -> Vec<AstNodeRefMut> {
|
||||||
|
match self {
|
||||||
|
#(#match_arms_mut,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn as_node_ref(&self) -> AstNodeRef {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_node_ref_mut(&mut self) -> AstNodeRefMut {
|
||||||
|
AstNodeRefMut::#type_ident(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
|
use crate::spec::leaf_enum_spec::LeafEnumBuildSpec;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use crate::spec::leaf_enum_spec::LeafEnumBuildSpec;
|
|
||||||
|
|
||||||
pub fn make_leaf_enum_ast_node_impl(spec: &LeafEnumBuildSpec) -> TokenStream {
|
pub fn make_leaf_enum_ast_node_impl(spec: &LeafEnumBuildSpec) -> TokenStream {
|
||||||
let type_ident = format_ident!("{}", spec.build());
|
let type_ident = format_ident!("{}", spec.build());
|
||||||
@ -9,10 +9,18 @@ pub fn make_leaf_enum_ast_node_impl(spec: &LeafEnumBuildSpec) -> TokenStream {
|
|||||||
fn children(&self) -> Vec<AstNodeRef> {
|
fn children(&self) -> Vec<AstNodeRef> {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn children_mut(&mut self) -> Vec<AstNodeRefMut> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
fn as_node_ref(&self) -> AstNodeRef {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_node_ref_mut(&mut self) -> AstNodeRefMut {
|
||||||
|
AstNodeRefMut::#type_ident(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,10 +9,18 @@ pub fn make_leaf_struct_ast_node_impl(spec: &LeafStructBuildSpec) -> TokenStream
|
|||||||
fn children(&self) -> Vec<AstNodeRef> {
|
fn children(&self) -> Vec<AstNodeRef> {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn children_mut(&mut self) -> Vec<AstNodeRefMut> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
fn as_node_ref(&self) -> AstNodeRef {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_node_ref_mut(&mut self) -> AstNodeRefMut {
|
||||||
|
AstNodeRefMut::#type_ident(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,63 +1,47 @@
|
|||||||
mod enum_ast_node;
|
mod enum_ast_node;
|
||||||
mod leaf_enum_ast_node;
|
mod leaf_enum_ast_node;
|
||||||
mod struct_ast_node;
|
|
||||||
mod leaf_struct_ast_node;
|
mod leaf_struct_ast_node;
|
||||||
mod polymorphic_type_ast_node;
|
|
||||||
mod polymorphic_enum_loop_ast_node;
|
mod polymorphic_enum_loop_ast_node;
|
||||||
|
mod polymorphic_type_ast_node;
|
||||||
|
mod struct_ast_node;
|
||||||
|
|
||||||
use crate::spec::BuildSpec;
|
|
||||||
use proc_macro2::TokenStream;
|
|
||||||
use quote::{format_ident, quote};
|
|
||||||
use crate::ast_node::enum_ast_node::make_enum_ast_node_impl;
|
use crate::ast_node::enum_ast_node::make_enum_ast_node_impl;
|
||||||
use crate::ast_node::leaf_enum_ast_node::make_leaf_enum_ast_node_impl;
|
use crate::ast_node::leaf_enum_ast_node::make_leaf_enum_ast_node_impl;
|
||||||
use crate::ast_node::leaf_struct_ast_node::make_leaf_struct_ast_node_impl;
|
use crate::ast_node::leaf_struct_ast_node::make_leaf_struct_ast_node_impl;
|
||||||
use crate::ast_node::polymorphic_enum_loop_ast_node::make_polymorphic_enum_loop_ast_node_impl;
|
use crate::ast_node::polymorphic_enum_loop_ast_node::make_polymorphic_enum_loop_ast_node_impl;
|
||||||
use crate::ast_node::polymorphic_type_ast_node::make_polymorphic_type_ast_node_impl;
|
use crate::ast_node::polymorphic_type_ast_node::make_polymorphic_type_ast_node_impl;
|
||||||
use crate::ast_node::struct_ast_node::make_struct_ast_node_impl;
|
use crate::ast_node::struct_ast_node::make_struct_ast_node_impl;
|
||||||
|
use crate::spec::BuildSpec;
|
||||||
|
use proc_macro2::{Ident, TokenStream};
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
pub fn make_ast_node_impl(build_spec: &BuildSpec) -> Option<TokenStream> {
|
pub fn make_ast_node_impl(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||||
match build_spec {
|
match build_spec {
|
||||||
BuildSpec::Enum(enum_spec) => {
|
BuildSpec::Enum(enum_spec) => Some(make_enum_ast_node_impl(enum_spec)),
|
||||||
Some(make_enum_ast_node_impl(enum_spec))
|
BuildSpec::LeafEnum(leaf_enum) => Some(make_leaf_enum_ast_node_impl(leaf_enum)),
|
||||||
}
|
BuildSpec::Struct(struct_spec) => Some(make_struct_ast_node_impl(struct_spec)),
|
||||||
BuildSpec::LeafEnum(leaf_enum) => {
|
BuildSpec::LeafStruct(leaf_struct) => Some(make_leaf_struct_ast_node_impl(leaf_struct)),
|
||||||
Some(make_leaf_enum_ast_node_impl(leaf_enum))
|
|
||||||
}
|
|
||||||
BuildSpec::Struct(struct_spec) => {
|
|
||||||
Some(make_struct_ast_node_impl(struct_spec))
|
|
||||||
}
|
|
||||||
BuildSpec::LeafStruct(leaf_struct) => {
|
|
||||||
Some(make_leaf_struct_ast_node_impl(leaf_struct))
|
|
||||||
}
|
|
||||||
BuildSpec::Production(_) => None,
|
BuildSpec::Production(_) => None,
|
||||||
BuildSpec::NodeProduction(_) => None,
|
BuildSpec::NodeProduction(_) => None,
|
||||||
BuildSpec::PolymorphicType(polymorphic_type) => {
|
BuildSpec::PolymorphicType(polymorphic_type) => {
|
||||||
Some(make_polymorphic_type_ast_node_impl(polymorphic_type))
|
Some(make_polymorphic_type_ast_node_impl(polymorphic_type))
|
||||||
}
|
}
|
||||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
|
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => Some(
|
||||||
Some(make_polymorphic_enum_loop_ast_node_impl(polymorphic_enum_loop))
|
make_polymorphic_enum_loop_ast_node_impl(polymorphic_enum_loop),
|
||||||
}
|
),
|
||||||
BuildSpec::PolymorphicPassThrough(_) => None,
|
BuildSpec::PolymorphicPassThrough(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option<TokenStream> {
|
fn make_ast_enum_ident(build_spec: &BuildSpec) -> Option<Ident> {
|
||||||
match build_spec {
|
match build_spec {
|
||||||
BuildSpec::Struct(struct_spec) => {
|
BuildSpec::Struct(struct_spec) => Some(format_ident!("{}", struct_spec.build())),
|
||||||
Some(format_ident!("{}", struct_spec.build()))
|
BuildSpec::LeafStruct(leaf_struct) => Some(format_ident!("{}", leaf_struct.build())),
|
||||||
}
|
BuildSpec::Enum(enum_spec) => Some(format_ident!("{}", enum_spec.build())),
|
||||||
BuildSpec::LeafStruct(leaf_struct) => {
|
BuildSpec::LeafEnum(leaf_enum) => Some(format_ident!("{}", leaf_enum.build())),
|
||||||
Some(format_ident!("{}", leaf_struct.build()))
|
|
||||||
}
|
|
||||||
BuildSpec::Enum(enum_spec) => {
|
|
||||||
Some(format_ident!("{}", enum_spec.build()))
|
|
||||||
}
|
|
||||||
BuildSpec::LeafEnum(leaf_enum) => {
|
|
||||||
Some(format_ident!("{}", leaf_enum.build()))
|
|
||||||
}
|
|
||||||
BuildSpec::PolymorphicType(polymorphic_type) => {
|
BuildSpec::PolymorphicType(polymorphic_type) => {
|
||||||
Some(format_ident!("{}", polymorphic_type.name()))
|
Some(format_ident!("{}", polymorphic_type.name()))
|
||||||
},
|
}
|
||||||
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
|
BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => {
|
||||||
Some(format_ident!("{}", polymorphic_enum_loop.name()))
|
Some(format_ident!("{}", polymorphic_enum_loop.name()))
|
||||||
}
|
}
|
||||||
@ -65,9 +49,20 @@ pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option<TokenStream> {
|
|||||||
BuildSpec::Production(_) => None,
|
BuildSpec::Production(_) => None,
|
||||||
BuildSpec::NodeProduction(_) => None,
|
BuildSpec::NodeProduction(_) => None,
|
||||||
}
|
}
|
||||||
.map(|type_ident| {
|
}
|
||||||
quote! {
|
|
||||||
#type_ident(&'a #type_ident)
|
pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||||
}
|
make_ast_enum_ident(build_spec).map(|type_ident| {
|
||||||
})
|
quote! {
|
||||||
}
|
#type_ident(&'a #type_ident)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_ast_enum_member_mut(build_spec: &BuildSpec) -> Option<TokenStream> {
|
||||||
|
make_ast_enum_ident(build_spec).map(|type_ident| {
|
||||||
|
quote! {
|
||||||
|
#type_ident(&'a mut #type_ident)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@ -4,6 +4,33 @@ use crate::spec::polymorphic_enum_loop_spec::{
|
|||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
fn make_child_adder(child: &PolymorphicEnumLoopRuleBuildChild, is_mut: bool) -> TokenStream {
|
||||||
|
let child_ident = {
|
||||||
|
let base = match child {
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
||||||
|
format_ident!("{}", use_current.name())
|
||||||
|
}
|
||||||
|
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
||||||
|
format_ident!("{}", on_each.name())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if is_mut {
|
||||||
|
format_ident!("{}_mut", base)
|
||||||
|
} else {
|
||||||
|
base
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let as_node_ref_ident = if is_mut {
|
||||||
|
quote! { as_node_ref_mut }
|
||||||
|
} else {
|
||||||
|
quote! { as_node_ref }
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
children.push(self.#child_ident().#as_node_ref_ident());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn make_polymorphic_enum_loop_ast_node_impl(
|
pub fn make_polymorphic_enum_loop_ast_node_impl(
|
||||||
spec: &PolymorphicEnumLoopBuildSpec,
|
spec: &PolymorphicEnumLoopBuildSpec,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
@ -18,19 +45,12 @@ pub fn make_polymorphic_enum_loop_ast_node_impl(
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let child_adders = build_rule
|
let child_adders = build_rule
|
||||||
.children()
|
.children()
|
||||||
.map(|child| {
|
.map(|child| make_child_adder(child, false))
|
||||||
let child_ident = match child {
|
.collect::<Vec<_>>();
|
||||||
PolymorphicEnumLoopRuleBuildChild::UseCurrent(use_current) => {
|
|
||||||
format_ident!("{}", use_current.name())
|
let child_adders_mut = build_rule
|
||||||
}
|
.children()
|
||||||
PolymorphicEnumLoopRuleBuildChild::OnEach(on_each) => {
|
.map(|child| make_child_adder(child, true))
|
||||||
format_ident!("{}", on_each.name())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
quote! {
|
|
||||||
children.push(self.#child_ident().as_node_ref())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
@ -41,9 +61,19 @@ pub fn make_polymorphic_enum_loop_ast_node_impl(
|
|||||||
children
|
children
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn children_mut(&mut self) -> Vec<AstNodeRefMut> {
|
||||||
|
let mut children: Vec<AstNodeRefMut> = vec![];
|
||||||
|
#(#child_adders_mut;)*
|
||||||
|
children
|
||||||
|
}
|
||||||
|
|
||||||
fn as_node_ref(&self) -> AstNodeRef {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_node_ref_mut(&mut self) -> AstNodeRefMut {
|
||||||
|
AstNodeRefMut::#type_ident(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,36 @@
|
|||||||
use crate::spec::polymorphic_type_spec::PolymorphicTypeBuildSpec;
|
use crate::spec::polymorphic_type_spec::{PolymorphicTypeBuildSpec, PolymorphicTypeVariant};
|
||||||
use convert_case::{Case, Casing};
|
use convert_case::{Case, Casing};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
fn make_match_arm(
|
||||||
|
variant: &PolymorphicTypeVariant,
|
||||||
|
type_ident: &Ident,
|
||||||
|
is_mut: bool,
|
||||||
|
) -> TokenStream {
|
||||||
|
let variant_ident = format_ident!("{}", variant.name());
|
||||||
|
let child_ident = format_ident!("{}", variant.inner_kind().to_case(Case::Snake));
|
||||||
|
let as_node_ref_ident = if is_mut {
|
||||||
|
quote! { as_node_ref_mut }
|
||||||
|
} else {
|
||||||
|
quote! { as_node_ref }
|
||||||
|
};
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#type_ident::#variant_ident(#child_ident) => vec![#child_ident.#as_node_ref_ident()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn make_polymorphic_type_ast_node_impl(spec: &PolymorphicTypeBuildSpec) -> TokenStream {
|
pub fn make_polymorphic_type_ast_node_impl(spec: &PolymorphicTypeBuildSpec) -> TokenStream {
|
||||||
let type_ident = format_ident!("{}", spec.name());
|
let type_ident = format_ident!("{}", spec.name());
|
||||||
let match_arms = spec
|
let match_arms = spec
|
||||||
.variants()
|
.variants()
|
||||||
.map(|variant| {
|
.map(|variant| make_match_arm(variant, &type_ident, false))
|
||||||
let variant_ident = format_ident!("{}", variant.name());
|
.collect::<Vec<_>>();
|
||||||
let child_ident = format_ident!("{}", variant.inner_kind().to_case(Case::Snake));
|
|
||||||
quote! {
|
let match_arms_mut = spec
|
||||||
#type_ident::#variant_ident(#child_ident) => vec![#child_ident.as_node_ref()]
|
.variants()
|
||||||
}
|
.map(|variant| make_match_arm(variant, &type_ident, true))
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
@ -24,9 +41,19 @@ pub fn make_polymorphic_type_ast_node_impl(spec: &PolymorphicTypeBuildSpec) -> T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn children_mut(&mut self) -> Vec<AstNodeRefMut> {
|
||||||
|
match self {
|
||||||
|
#(#match_arms_mut,)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn as_node_ref(&self) -> AstNodeRef {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_node_ref_mut(&mut self) -> AstNodeRefMut {
|
||||||
|
AstNodeRefMut::#type_ident(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,43 +2,69 @@ use crate::spec::struct_spec::{MemberChildBuild, StructChild, StructSpec, VecChi
|
|||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
fn make_child_adder(child: &StructChild, is_mut: bool) -> Option<TokenStream> {
|
||||||
|
let as_node_ref_ident = if is_mut {
|
||||||
|
format_ident!("as_node_ref_mut")
|
||||||
|
} else {
|
||||||
|
format_ident!("as_node_ref")
|
||||||
|
};
|
||||||
|
|
||||||
|
match child {
|
||||||
|
StructChild::SkipChild(_) => None,
|
||||||
|
StructChild::VecChild(vec_child) => match vec_child.build() {
|
||||||
|
VecChildBuild::String(_) => None,
|
||||||
|
VecChildBuild::Node(_) => {
|
||||||
|
let child_ident = if is_mut {
|
||||||
|
format_ident!("{}_mut", vec_child.name())
|
||||||
|
} else {
|
||||||
|
format_ident!("{}", vec_child.name())
|
||||||
|
};
|
||||||
|
|
||||||
|
let children_stream = quote! {
|
||||||
|
for child in self.#child_ident().map(AstNode::#as_node_ref_ident) {
|
||||||
|
children.push(child);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(children_stream)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
StructChild::MemberChild(member_child) => match member_child.build() {
|
||||||
|
MemberChildBuild::Node(_) => {
|
||||||
|
let child_ident = if is_mut {
|
||||||
|
format_ident!("{}_mut", member_child.name())
|
||||||
|
} else {
|
||||||
|
format_ident!("{}", member_child.name())
|
||||||
|
};
|
||||||
|
if member_child.optional() {
|
||||||
|
Some(quote! {
|
||||||
|
if let Some(#child_ident) = self.#child_ident() {
|
||||||
|
children.push(#child_ident.#as_node_ref_ident());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Some(quote! {
|
||||||
|
children.push(self.#child_ident().#as_node_ref_ident());
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MemberChildBuild::Boolean(_) => None,
|
||||||
|
},
|
||||||
|
StructChild::Special(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
||||||
let type_ident = format_ident!("{}", spec.build());
|
let type_ident = format_ident!("{}", spec.build());
|
||||||
let child_adders = spec
|
let child_adders = spec
|
||||||
.children()
|
.children()
|
||||||
.map(|child| match child {
|
.map(|child| make_child_adder(child, false))
|
||||||
StructChild::SkipChild(_) => None,
|
.filter(Option::is_some)
|
||||||
StructChild::VecChild(vec_child) => match vec_child.build() {
|
.map(Option::unwrap)
|
||||||
VecChildBuild::String(_) => None,
|
.collect::<Vec<_>>();
|
||||||
VecChildBuild::Node(_) => {
|
|
||||||
let child_ident = format_ident!("{}", vec_child.name());
|
let child_adders_mut = spec
|
||||||
let children_stream = quote! {
|
.children()
|
||||||
for child in self.#child_ident().map(AstNode::as_node_ref) {
|
.map(|child| make_child_adder(child, true))
|
||||||
children.push(child);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Some(children_stream)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
StructChild::MemberChild(member_child) => match member_child.build() {
|
|
||||||
MemberChildBuild::Node(_) => {
|
|
||||||
let child_ident = format_ident!("{}", member_child.name());
|
|
||||||
if member_child.optional() {
|
|
||||||
Some(quote! {
|
|
||||||
if let Some(#child_ident) = self.#child_ident() {
|
|
||||||
children.push(#child_ident.as_node_ref());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Some(quote! {
|
|
||||||
children.push(self.#child_ident().as_node_ref())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MemberChildBuild::Boolean(_) => None,
|
|
||||||
},
|
|
||||||
StructChild::Special(_) => None,
|
|
||||||
})
|
|
||||||
.filter(Option::is_some)
|
.filter(Option::is_some)
|
||||||
.map(Option::unwrap)
|
.map(Option::unwrap)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@ -51,9 +77,19 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
|||||||
children
|
children
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn children_mut(&mut self) -> Vec<AstNodeRefMut> {
|
||||||
|
let mut children: Vec<AstNodeRefMut> = vec![];
|
||||||
|
#(#child_adders_mut;)*
|
||||||
|
children
|
||||||
|
}
|
||||||
|
|
||||||
fn as_node_ref(&self) -> AstNodeRef {
|
fn as_node_ref(&self) -> AstNodeRef {
|
||||||
AstNodeRef::#type_ident(&self)
|
AstNodeRef::#type_ident(&self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_node_ref_mut(&mut self) -> AstNodeRefMut {
|
||||||
|
AstNodeRefMut::#type_ident(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@ mod spec;
|
|||||||
mod type_gen;
|
mod type_gen;
|
||||||
mod walk;
|
mod walk;
|
||||||
|
|
||||||
use crate::ast_node::{make_ast_enum_member, make_ast_node_impl};
|
use crate::ast_node::{make_ast_enum_member, make_ast_enum_member_mut, make_ast_node_impl};
|
||||||
use crate::build_fn::make_build_fn;
|
use crate::build_fn::make_build_fn;
|
||||||
use crate::deserialize::deserialize_yaml_spec;
|
use crate::deserialize::deserialize_yaml_spec;
|
||||||
use crate::pretty_print::make_pretty_print_impl;
|
use crate::pretty_print::make_pretty_print_impl;
|
||||||
@ -165,6 +165,13 @@ fn generate_ast_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
|||||||
.map(Option::unwrap)
|
.map(Option::unwrap)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let ast_enum_members_mut = build_specs
|
||||||
|
.iter()
|
||||||
|
.map(|build_spec| make_ast_enum_member_mut(build_spec))
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let combined = quote! {
|
let combined = quote! {
|
||||||
use crate::ast::node::*;
|
use crate::ast::node::*;
|
||||||
|
|
||||||
@ -172,10 +179,18 @@ fn generate_ast_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
|
|||||||
#(#ast_enum_members,)*
|
#(#ast_enum_members,)*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum AstNodeRefMut<'a> {
|
||||||
|
#(#ast_enum_members_mut,)*
|
||||||
|
}
|
||||||
|
|
||||||
pub trait AstNode {
|
pub trait AstNode {
|
||||||
fn children(&self) -> Vec<AstNodeRef>;
|
fn children(&self) -> Vec<AstNodeRef>;
|
||||||
|
|
||||||
|
fn children_mut(&mut self) -> Vec<AstNodeRefMut>;
|
||||||
|
|
||||||
fn as_node_ref(&self) -> AstNodeRef;
|
fn as_node_ref(&self) -> AstNodeRef;
|
||||||
|
|
||||||
|
fn as_node_ref_mut(&mut self) -> AstNodeRefMut;
|
||||||
}
|
}
|
||||||
|
|
||||||
#(#impls)*
|
#(#impls)*
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use crate::ast::node::{
|
|||||||
Class, CompilationUnit, Function, FunctionBody, Identifier, Interface,
|
Class, CompilationUnit, Function, FunctionBody, Identifier, Interface,
|
||||||
InterfaceDefaultFunction, InterfaceDefaultOperatorFunction, InterfaceFunction,
|
InterfaceDefaultFunction, InterfaceDefaultOperatorFunction, InterfaceFunction,
|
||||||
InterfaceOperatorFunction, Member, Module, Namespace, OperatorFunction, PlatformFunction,
|
InterfaceOperatorFunction, Member, Module, Namespace, OperatorFunction, PlatformFunction,
|
||||||
PlatformOperatorFunction, Statement, UseStatement, UseStatementSuffix, VariableDeclaration,
|
PlatformOperatorFunction, UseStatement, UseStatementSuffix, VariableDeclaration, VariableUse,
|
||||||
};
|
};
|
||||||
use crate::diagnostic::DmDiagnostic;
|
use crate::diagnostic::DmDiagnostic;
|
||||||
use crate::name_analysis::fqn_context::FqnContext;
|
use crate::name_analysis::fqn_context::FqnContext;
|
||||||
@ -211,7 +211,7 @@ fn gather_node(
|
|||||||
}
|
}
|
||||||
AstNodeRef::Statement(statement) => {
|
AstNodeRef::Statement(statement) => {
|
||||||
gather_node_children(statement, symbol_table, fqn_context, diagnostics);
|
gather_node_children(statement, symbol_table, fqn_context, diagnostics);
|
||||||
},
|
}
|
||||||
AstNodeRef::VariableDeclaration(variable_declaration) => {
|
AstNodeRef::VariableDeclaration(variable_declaration) => {
|
||||||
gather_variable_declaration(
|
gather_variable_declaration(
|
||||||
variable_declaration,
|
variable_declaration,
|
||||||
@ -228,9 +228,11 @@ fn gather_node(
|
|||||||
AstNodeRef::IfElse(_) => {}
|
AstNodeRef::IfElse(_) => {}
|
||||||
AstNodeRef::WhileStatement(_) => {}
|
AstNodeRef::WhileStatement(_) => {}
|
||||||
AstNodeRef::ForStatement(_) => {}
|
AstNodeRef::ForStatement(_) => {}
|
||||||
AstNodeRef::LValue(_) => {},
|
AstNodeRef::LValue(_) => {}
|
||||||
AstNodeRef::LValueSuffix(_) => {},
|
AstNodeRef::LValueSuffix(_) => {}
|
||||||
AstNodeRef::VariableUse(_) => {},
|
AstNodeRef::VariableUse(variable_use) => {
|
||||||
|
gather_variable_use(variable_use, symbol_table, fqn_context, diagnostics);
|
||||||
|
}
|
||||||
AstNodeRef::Expression(_) => {}
|
AstNodeRef::Expression(_) => {}
|
||||||
AstNodeRef::TernaryExpression(_) => {}
|
AstNodeRef::TernaryExpression(_) => {}
|
||||||
AstNodeRef::TernaryRhs(_) => {}
|
AstNodeRef::TernaryRhs(_) => {}
|
||||||
@ -1024,3 +1026,12 @@ fn gather_variable_declaration(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gather_variable_use(
|
||||||
|
variable_use: &mut VariableUse,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
fqn_context: &mut FqnContext,
|
||||||
|
diagnostics: &mut Vec<DmDiagnostic>,
|
||||||
|
) {
|
||||||
|
variable_use.set_scope_id(symbol_table.current_scope_id());
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user