Squash bugs with ast gen.

This commit is contained in:
Jesse Brault 2025-09-15 21:41:36 -05:00
parent 608d89645e
commit ac9ff6ecec
3 changed files with 135 additions and 60 deletions

View File

@ -10,19 +10,21 @@ fn make_var_name(s: &str) -> String {
fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream { fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream {
let child_ident = format_ident!("{}", vec_child.name()); let child_ident = format_ident!("{}", vec_child.name());
let child_type_ident = match vec_child.build() { match vec_child.build() {
VecChildToBuild::Node(node_child) => { VecChildToBuild::Node(node_child) => {
format_ident!("{}", node_child.build()) let child_type_ident = format_ident!("{}", node_child.build());
quote! {
let mut #child_ident: Vec<Box<#child_type_ident >> = vec![]
}
}, },
VecChildToBuild::String => format_ident!("{}", "String") VecChildToBuild::String => quote! {
}; let mut #child_ident: Vec<String> = vec![]
quote! { }
let mut #child_ident: Vec<Box<#child_type_ident>> = vec![]
} }
} }
fn make_node_child_holder(node_child: &NodeChildToBuild) -> TokenStream { fn make_node_child_holder(name: &str, node_child: &NodeChildToBuild) -> TokenStream {
let child_ident = format_ident!("{}", make_var_name(node_child.build())); let child_ident = format_ident!("{}", name);
let child_type_ident = format_ident!("{}", node_child.build()); let child_type_ident = format_ident!("{}", node_child.build());
quote! { quote! {
let mut #child_ident: Option<Box<#child_type_ident>> = None let mut #child_ident: Option<Box<#child_type_ident>> = None
@ -42,7 +44,7 @@ fn make_child_holder(child_spec: &StructChildSpec) -> Option<TokenStream> {
StructChildSpec::VecChild(vec_child) => Some(make_vec_child_holder(vec_child)), StructChildSpec::VecChild(vec_child) => Some(make_vec_child_holder(vec_child)),
StructChildSpec::MemberChild(member_child) => match member_child.build() { StructChildSpec::MemberChild(member_child) => match member_child.build() {
MemberChildToBuild::Node(node_child) => { MemberChildToBuild::Node(node_child) => {
Some(make_node_child_holder(node_child)) Some(make_node_child_holder(member_child.name(), node_child))
} }
MemberChildToBuild::Boolean(boolean_child) => { MemberChildToBuild::Boolean(boolean_child) => {
Some(make_boolean_child_holder(boolean_child)) Some(make_boolean_child_holder(boolean_child))
@ -53,21 +55,24 @@ fn make_child_holder(child_spec: &StructChildSpec) -> Option<TokenStream> {
fn make_vec_child_match_action(vec_child: &VecChild) -> TokenStream { fn make_vec_child_match_action(vec_child: &VecChild) -> TokenStream {
let child_name_ident = format_ident!("{}", vec_child.name()); let child_name_ident = format_ident!("{}", vec_child.name());
let build_fn_ident = match vec_child.build() { match vec_child.build() {
VecChildToBuild::Node(vec_node_child) => { VecChildToBuild::Node(vec_node_child) => {
format_ident!("{}", make_build_fn_name(vec_node_child.build())) let build_fn_ident = format_ident!("{}", make_build_fn_name(vec_node_child.build()));
quote! {
#child_name_ident.push(Box::new(#build_fn_ident(inner_pair)))
}
}, },
VecChildToBuild::String => { VecChildToBuild::String => {
format_ident!("{}", make_build_fn_name(vec_child.rule())) let build_fn_ident = format_ident!("{}", make_build_fn_name(vec_child.rule()));
quote! {
#child_name_ident.push(#build_fn_ident(inner_pair))
}
} }
};
quote! {
#child_name_ident.push(Box::new(#build_fn_ident(inner_pair)))
} }
} }
fn make_node_member_child_match_action(node_child: &NodeChildToBuild) -> TokenStream { fn make_node_member_child_match_action(name: &str, node_child: &NodeChildToBuild) -> TokenStream {
let child_name_ident = format_ident!("{}", make_var_name(node_child.build())); let child_name_ident = format_ident!("{}", name);
let build_fn_ident = format_ident!("{}", make_build_fn_name(node_child.build())); let build_fn_ident = format_ident!("{}", make_build_fn_name(node_child.build()));
quote! { quote! {
#child_name_ident = Some(Box::new(#build_fn_ident(inner_pair))) #child_name_ident = Some(Box::new(#build_fn_ident(inner_pair)))
@ -87,9 +92,9 @@ fn make_match_action(child_spec: &StructChildSpec) -> TokenStream {
StructChildSpec::VecChild(vec_child) => { StructChildSpec::VecChild(vec_child) => {
make_vec_child_match_action(vec_child) make_vec_child_match_action(vec_child)
} }
StructChildSpec::MemberChild(single_child) => match single_child.build() { StructChildSpec::MemberChild(member_child) => match member_child.build() {
MemberChildToBuild::Node(node_child) => { MemberChildToBuild::Node(node_child) => {
make_node_member_child_match_action(node_child) make_node_member_child_match_action(member_child.name(), node_child)
} }
MemberChildToBuild::Boolean(boolean_child) => { MemberChildToBuild::Boolean(boolean_child) => {
make_boolean_member_child_match_action(boolean_child) make_boolean_member_child_match_action(boolean_child)

View File

@ -1,5 +1,8 @@
use convert_case::{Case, Casing}; use crate::spec::{
use crate::spec::{BooleanChildToBuild, BuildSpec, EnumBuildSpec, EnumRuleChildKind, LeafEnumBuildSpec, LeafStructBuildSpec, LeafStructMemberKind, MemberChildToBuild, NodeChildToBuild, StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild}; BooleanChildToBuild, BuildSpec, EnumBuildSpec, EnumRuleChildKind, LeafEnumBuildSpec,
LeafStructBuildSpec, LeafStructMemberKind, MemberChildToBuild, NodeChildToBuild,
StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild,
};
use proc_macro2::{Ident, TokenStream}; use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote}; use quote::{format_ident, quote};
@ -12,7 +15,7 @@ fn make_enum_type(build_spec: &EnumBuildSpec) -> TokenStream {
let child_type_ident = match enum_rule_child.kind() { let child_type_ident = match enum_rule_child.kind() {
EnumRuleChildKind::Node(node_child) => { EnumRuleChildKind::Node(node_child) => {
format_ident!("{}", node_child.build()) format_ident!("{}", node_child.build())
}, }
EnumRuleChildKind::Int => format_ident!("i32"), EnumRuleChildKind::Int => format_ident!("i32"),
EnumRuleChildKind::Long => format_ident!("i64"), EnumRuleChildKind::Long => format_ident!("i64"),
EnumRuleChildKind::Double => format_ident!("f64"), EnumRuleChildKind::Double => format_ident!("f64"),
@ -61,11 +64,12 @@ fn handle_vec_child(
vec_child: &VecChild, vec_child: &VecChild,
member_names: &mut Vec<Ident>, member_names: &mut Vec<Ident>,
annotated_members: &mut Vec<TokenStream>, annotated_members: &mut Vec<TokenStream>,
member_args: &mut Vec<TokenStream>,
accessors: &mut Vec<TokenStream>, accessors: &mut Vec<TokenStream>,
) { ) {
let (child_ident, child_ident_mut) = ( let (child_ident, child_ident_mut) = (
format_ident!("{}", vec_child.name()), format_ident!("{}", vec_child.name()),
format_ident!("{}", vec_child.name()), format_ident!("{}_mut", vec_child.name()),
); );
let child_type_ident = match vec_child.build() { let child_type_ident = match vec_child.build() {
VecChildToBuild::Node(vec_node_child) => format_ident!("{}", vec_node_child.build()), VecChildToBuild::Node(vec_node_child) => format_ident!("{}", vec_node_child.build()),
@ -73,39 +77,73 @@ fn handle_vec_child(
}; };
member_names.push(child_ident.clone()); member_names.push(child_ident.clone());
annotated_members.push(quote! {
#child_ident: Vec<Box<#child_type_ident>>
});
accessors.push(quote! {
pub fn #child_ident(&self) -> impl Iterator<Item = &#child_type_ident> {
self.#child_ident.iter().map(Box::as_ref)
}
pub fn #child_ident_mut(&mut self) -> impl Iterator<Item = &mut #child_type_ident> { match vec_child.build() {
self.#child_ident.iter_mut().map(Box::as_mut) VecChildToBuild::Node(_) => {
annotated_members.push(quote! {
#child_ident: Vec<Box<#child_type_ident>>
});
member_args.push(quote! {
#child_ident: Vec<Box<#child_type_ident>>
});
} }
}); VecChildToBuild::String => {
annotated_members.push(quote! {
#child_ident: Vec<String>
});
member_args.push(quote! {
#child_ident: Vec<String>
})
}
}
match vec_child.build() {
VecChildToBuild::Node(_) => {
accessors.push(quote! {
pub fn #child_ident(&self) -> impl Iterator<Item = &#child_type_ident> {
self.#child_ident.iter().map(Box::as_ref)
}
pub fn #child_ident_mut(&mut self) -> impl Iterator<Item = &mut #child_type_ident> {
self.#child_ident.iter_mut().map(Box::as_mut)
}
});
}
VecChildToBuild::String => accessors.push(quote! {
pub fn #child_ident(&self) -> impl Iterator<Item = &str> {
self.#child_ident.iter().map(String::as_str)
}
}),
}
} }
fn handle_node_child( fn handle_node_child(
name: &str,
node_child: &NodeChildToBuild, node_child: &NodeChildToBuild,
member_names: &mut Vec<Ident>, member_names: &mut Vec<Ident>,
annotated_members: &mut Vec<TokenStream>, annotated_members: &mut Vec<TokenStream>,
member_args: &mut Vec<TokenStream>,
accessors: &mut Vec<TokenStream>, accessors: &mut Vec<TokenStream>,
) { ) {
let child_ident = format_ident!("{}", node_child.build().to_case(Case::Snake)); let child_ident = format_ident!("{}", name);
let child_ident_mut = format_ident!("{}_mut", child_ident); let child_ident_mut = format_ident!("{}_mut", name);
let child_type_ident = format_ident!("{}", node_child.build()); let child_type_ident = format_ident!("{}", node_child.build());
member_names.push(child_ident.clone()); member_names.push(child_ident.clone());
if node_child.optional() { if node_child.optional() {
annotated_members.push(quote! { annotated_members.push(quote! {
#child_ident: Option<Box<#child_type_ident>> #child_ident: Option<Box<#child_type_ident>>
}); });
member_args.push(quote! {
#child_ident: Option<Box<#child_type_ident>>
});
} else { } else {
annotated_members.push(quote! { annotated_members.push(quote! {
#child_ident: Box<#child_type_ident> #child_ident: Box<#child_type_ident>
});
member_args.push(quote! {
#child_ident: Box<#child_type_ident>
}) })
} }
if node_child.optional() { if node_child.optional() {
@ -125,7 +163,7 @@ fn handle_node_child(
None None
} }
} }
}) });
} else { } else {
accessors.push(quote! { accessors.push(quote! {
pub fn #child_ident(&self) -> &#child_type_ident { pub fn #child_ident(&self) -> &#child_type_ident {
@ -143,6 +181,7 @@ fn handle_boolean_child(
single_boolean_child: &BooleanChildToBuild, single_boolean_child: &BooleanChildToBuild,
member_names: &mut Vec<Ident>, member_names: &mut Vec<Ident>,
annotated_members: &mut Vec<TokenStream>, annotated_members: &mut Vec<TokenStream>,
member_args: &mut Vec<TokenStream>,
accessors: &mut Vec<TokenStream>, accessors: &mut Vec<TokenStream>,
) { ) {
let child_ident = format_ident!("{}", single_boolean_child.name()); let child_ident = format_ident!("{}", single_boolean_child.name());
@ -150,16 +189,20 @@ fn handle_boolean_child(
annotated_members.push(quote! { annotated_members.push(quote! {
#child_ident: bool #child_ident: bool
}); });
member_args.push(quote! {
#child_ident: bool
});
accessors.push(quote! { accessors.push(quote! {
pub fn #child_ident(&self) -> bool { pub fn #child_ident(&self) -> bool {
self.#child_ident self.#child_ident
} }
}) });
} }
fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream { fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream {
let mut member_names: Vec<Ident> = vec![]; let mut member_names: Vec<Ident> = vec![];
let mut annotated_members: Vec<TokenStream> = vec![]; let mut annotated_members: Vec<TokenStream> = vec![];
let mut member_args: Vec<TokenStream> = vec![];
let mut accessors: Vec<TokenStream> = vec![]; let mut accessors: Vec<TokenStream> = vec![];
for child_spec in build_spec.children() { for child_spec in build_spec.children() {
@ -170,6 +213,7 @@ fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream {
vec_child, vec_child,
&mut member_names, &mut member_names,
&mut annotated_members, &mut annotated_members,
&mut member_args,
&mut accessors, &mut accessors,
); );
} }
@ -177,9 +221,11 @@ fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream {
match member_child.build() { match member_child.build() {
MemberChildToBuild::Node(node_child) => { MemberChildToBuild::Node(node_child) => {
handle_node_child( handle_node_child(
member_child.name(),
node_child, node_child,
&mut member_names, &mut member_names,
&mut annotated_members, &mut annotated_members,
&mut member_args,
&mut accessors, &mut accessors,
); );
} }
@ -188,6 +234,7 @@ fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream {
boolean_child, boolean_child,
&mut member_names, &mut member_names,
&mut annotated_members, &mut annotated_members,
&mut member_args,
&mut accessors, &mut accessors,
); );
} }
@ -231,9 +278,30 @@ fn make_leaf_struct_type(build_spec: &LeafStructBuildSpec) -> TokenStream {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let member_names = build_spec let member_args = build_spec.members().map(|member| {
let name_ident = format_ident!("{}", member.name());
let type_stream = match member.kind() {
LeafStructMemberKind::String => {
quote! { &str }
}
};
quote! {
#name_ident: #type_stream
}
});
let initializers = build_spec
.members() .members()
.map(|leaf_struct_child| format_ident!("{}", leaf_struct_child.name())) .map(|leaf_struct_member| {
let member_ident = format_ident!("{}", leaf_struct_member.name());
match leaf_struct_member.kind() {
LeafStructMemberKind::String => {
quote! {
#member_ident: #member_ident.to_string()
}
}
}
})
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let accessors = build_spec let accessors = build_spec
@ -258,9 +326,9 @@ fn make_leaf_struct_type(build_spec: &LeafStructBuildSpec) -> TokenStream {
} }
impl #type_ident { impl #type_ident {
pub fn new(#(#annotated_members),*) -> Self { pub fn new(#(#member_args),*) -> Self {
Self { Self {
#(#member_names),* #(#initializers),*
} }
} }
@ -272,11 +340,13 @@ fn make_leaf_struct_type(build_spec: &LeafStructBuildSpec) -> TokenStream {
pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> { pub fn make_type(build_spec: &BuildSpec) -> Option<TokenStream> {
match build_spec { match build_spec {
BuildSpec::Enum(enum_build_spec) => Some(make_enum_type(enum_build_spec)), BuildSpec::Enum(enum_build_spec) => Some(make_enum_type(enum_build_spec)),
BuildSpec::LeafEnum(leaf_enum_build_spec) => Some(make_leaf_enum_type(leaf_enum_build_spec)), BuildSpec::LeafEnum(leaf_enum_build_spec) => {
Some(make_leaf_enum_type(leaf_enum_build_spec))
}
BuildSpec::Struct(struct_build_spec) => Some(make_struct_type(struct_build_spec)), BuildSpec::Struct(struct_build_spec) => Some(make_struct_type(struct_build_spec)),
BuildSpec::LeafStruct(leaf_struct_build_spec) => { BuildSpec::LeafStruct(leaf_struct_build_spec) => {
Some(make_leaf_struct_type(leaf_struct_build_spec)) Some(make_leaf_struct_type(leaf_struct_build_spec))
}, }
BuildSpec::Production(production_build_spec) => None BuildSpec::Production(_) => None,
} }
} }

View File

@ -1,14 +1,14 @@
use crate::name_analysis::symbol::{FunctionSymbol, ParameterSymbol}; // use crate::name_analysis::symbol::{FunctionSymbol, ParameterSymbol};
use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable}; // use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable};
//
pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> { // pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> {
symbol_table.insert_function_symbol( // symbol_table.insert_function_symbol(
FunctionSymbol::new("std::core::println", "println", true, true, None) // FunctionSymbol::new("std::core::println", "println", true, true, None)
.with_parameters(vec![ParameterSymbol::new("msg", None)]), // .with_parameters(vec![ParameterSymbol::new("msg", None)]),
)?; // )?;
symbol_table.insert_function_symbol( // symbol_table.insert_function_symbol(
FunctionSymbol::new("std::core::print", "print", true, true, None) // FunctionSymbol::new("std::core::print", "print", true, true, None)
.with_parameters(vec![ParameterSymbol::new("msg", None)]), // .with_parameters(vec![ParameterSymbol::new("msg", None)]),
)?; // )?;
Ok(()) // Ok(())
} // }