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 {
let child_ident = format_ident!("{}", vec_child.name());
let child_type_ident = match vec_child.build() {
match vec_child.build() {
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")
};
quote! {
let mut #child_ident: Vec<Box<#child_type_ident>> = vec![]
VecChildToBuild::String => quote! {
let mut #child_ident: Vec<String> = vec![]
}
}
}
fn make_node_child_holder(node_child: &NodeChildToBuild) -> TokenStream {
let child_ident = format_ident!("{}", make_var_name(node_child.build()));
fn make_node_child_holder(name: &str, node_child: &NodeChildToBuild) -> TokenStream {
let child_ident = format_ident!("{}", name);
let child_type_ident = format_ident!("{}", node_child.build());
quote! {
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::MemberChild(member_child) => match member_child.build() {
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) => {
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 {
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) => {
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 => {
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 {
let child_name_ident = format_ident!("{}", make_var_name(node_child.build()));
fn make_node_member_child_match_action(name: &str, node_child: &NodeChildToBuild) -> TokenStream {
let child_name_ident = format_ident!("{}", name);
let build_fn_ident = format_ident!("{}", make_build_fn_name(node_child.build()));
quote! {
#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) => {
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) => {
make_node_member_child_match_action(node_child)
make_node_member_child_match_action(member_child.name(), node_child)
}
MemberChildToBuild::Boolean(boolean_child) => {
make_boolean_member_child_match_action(boolean_child)

View File

@ -1,5 +1,8 @@
use convert_case::{Case, Casing};
use crate::spec::{BooleanChildToBuild, BuildSpec, EnumBuildSpec, EnumRuleChildKind, LeafEnumBuildSpec, LeafStructBuildSpec, LeafStructMemberKind, MemberChildToBuild, NodeChildToBuild, StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild};
use crate::spec::{
BooleanChildToBuild, BuildSpec, EnumBuildSpec, EnumRuleChildKind, LeafEnumBuildSpec,
LeafStructBuildSpec, LeafStructMemberKind, MemberChildToBuild, NodeChildToBuild,
StructBuildSpec, StructChildSpec, VecChild, VecChildToBuild,
};
use proc_macro2::{Ident, TokenStream};
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() {
EnumRuleChildKind::Node(node_child) => {
format_ident!("{}", node_child.build())
},
}
EnumRuleChildKind::Int => format_ident!("i32"),
EnumRuleChildKind::Long => format_ident!("i64"),
EnumRuleChildKind::Double => format_ident!("f64"),
@ -61,11 +64,12 @@ fn handle_vec_child(
vec_child: &VecChild,
member_names: &mut Vec<Ident>,
annotated_members: &mut Vec<TokenStream>,
member_args: &mut Vec<TokenStream>,
accessors: &mut Vec<TokenStream>,
) {
let (child_ident, child_ident_mut) = (
format_ident!("{}", vec_child.name()),
format_ident!("{}", vec_child.name()),
format_ident!("{}_mut", vec_child.name()),
);
let child_type_ident = match vec_child.build() {
VecChildToBuild::Node(vec_node_child) => format_ident!("{}", vec_node_child.build()),
@ -73,28 +77,56 @@ fn handle_vec_child(
};
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> {
self.#child_ident.iter_mut().map(Box::as_mut)
match vec_child.build() {
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(
name: &str,
node_child: &NodeChildToBuild,
member_names: &mut Vec<Ident>,
annotated_members: &mut Vec<TokenStream>,
member_args: &mut Vec<TokenStream>,
accessors: &mut Vec<TokenStream>,
) {
let child_ident = format_ident!("{}", node_child.build().to_case(Case::Snake));
let child_ident_mut = format_ident!("{}_mut", child_ident);
let child_ident = format_ident!("{}", name);
let child_ident_mut = format_ident!("{}_mut", name);
let child_type_ident = format_ident!("{}", node_child.build());
member_names.push(child_ident.clone());
@ -103,9 +135,15 @@ fn handle_node_child(
annotated_members.push(quote! {
#child_ident: Option<Box<#child_type_ident>>
});
member_args.push(quote! {
#child_ident: Option<Box<#child_type_ident>>
});
} else {
annotated_members.push(quote! {
#child_ident: Box<#child_type_ident>
});
member_args.push(quote! {
#child_ident: Box<#child_type_ident>
})
}
if node_child.optional() {
@ -125,7 +163,7 @@ fn handle_node_child(
None
}
}
})
});
} else {
accessors.push(quote! {
pub fn #child_ident(&self) -> &#child_type_ident {
@ -143,6 +181,7 @@ fn handle_boolean_child(
single_boolean_child: &BooleanChildToBuild,
member_names: &mut Vec<Ident>,
annotated_members: &mut Vec<TokenStream>,
member_args: &mut Vec<TokenStream>,
accessors: &mut Vec<TokenStream>,
) {
let child_ident = format_ident!("{}", single_boolean_child.name());
@ -150,16 +189,20 @@ fn handle_boolean_child(
annotated_members.push(quote! {
#child_ident: bool
});
member_args.push(quote! {
#child_ident: bool
});
accessors.push(quote! {
pub fn #child_ident(&self) -> bool {
self.#child_ident
}
})
});
}
fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream {
let mut member_names: Vec<Ident> = vec![];
let mut annotated_members: Vec<TokenStream> = vec![];
let mut member_args: Vec<TokenStream> = vec![];
let mut accessors: Vec<TokenStream> = vec![];
for child_spec in build_spec.children() {
@ -170,6 +213,7 @@ fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream {
vec_child,
&mut member_names,
&mut annotated_members,
&mut member_args,
&mut accessors,
);
}
@ -177,9 +221,11 @@ fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream {
match member_child.build() {
MemberChildToBuild::Node(node_child) => {
handle_node_child(
member_child.name(),
node_child,
&mut member_names,
&mut annotated_members,
&mut member_args,
&mut accessors,
);
}
@ -188,6 +234,7 @@ fn make_struct_type(build_spec: &StructBuildSpec) -> TokenStream {
boolean_child,
&mut member_names,
&mut annotated_members,
&mut member_args,
&mut accessors,
);
}
@ -231,9 +278,30 @@ fn make_leaf_struct_type(build_spec: &LeafStructBuildSpec) -> TokenStream {
})
.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()
.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<_>>();
let accessors = build_spec
@ -258,9 +326,9 @@ fn make_leaf_struct_type(build_spec: &LeafStructBuildSpec) -> TokenStream {
}
impl #type_ident {
pub fn new(#(#annotated_members),*) -> Self {
pub fn new(#(#member_args),*) -> 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> {
match 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::LeafStruct(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_table::{SymbolInsertError, SymbolTable};
pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> {
symbol_table.insert_function_symbol(
FunctionSymbol::new("std::core::println", "println", true, true, None)
.with_parameters(vec![ParameterSymbol::new("msg", None)]),
)?;
symbol_table.insert_function_symbol(
FunctionSymbol::new("std::core::print", "print", true, true, None)
.with_parameters(vec![ParameterSymbol::new("msg", None)]),
)?;
Ok(())
}
// use crate::name_analysis::symbol::{FunctionSymbol, ParameterSymbol};
// use crate::name_analysis::symbol_table::{SymbolInsertError, SymbolTable};
//
// pub fn add_std_core_symbols(symbol_table: &mut SymbolTable) -> Result<(), SymbolInsertError> {
// symbol_table.insert_function_symbol(
// FunctionSymbol::new("std::core::println", "println", true, true, None)
// .with_parameters(vec![ParameterSymbol::new("msg", None)]),
// )?;
// symbol_table.insert_function_symbol(
// FunctionSymbol::new("std::core::print", "print", true, true, None)
// .with_parameters(vec![ParameterSymbol::new("msg", None)]),
// )?;
// Ok(())
// }