From df8e2279dcd7621ae7a158743ec823e7a81b096e Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Sun, 28 Sep 2025 15:02:20 -0500 Subject: [PATCH] WIP ast node ref enum and AstNode impls. --- ast-generator/src/ast_node/enum_ast_node.rs | 6 ++ .../src/ast_node/leaf_enum_ast_node.rs | 6 ++ .../src/ast_node/leaf_struct_ast_node.rs | 6 ++ ast-generator/src/ast_node/mod.rs | 52 ++++++++++++++++++ .../polymorphic_enum_loop_ast_node.rs | 6 ++ .../src/ast_node/polymorphic_type_ast_node.rs | 6 ++ ast-generator/src/ast_node/struct_ast_node.rs | 55 +++++++++++++++++++ ast-generator/src/lib.rs | 49 ++++++++++++++++- src/ast/mod.rs | 20 +++++++ 9 files changed, 204 insertions(+), 2 deletions(-) create mode 100644 ast-generator/src/ast_node/enum_ast_node.rs create mode 100644 ast-generator/src/ast_node/leaf_enum_ast_node.rs create mode 100644 ast-generator/src/ast_node/leaf_struct_ast_node.rs create mode 100644 ast-generator/src/ast_node/mod.rs create mode 100644 ast-generator/src/ast_node/polymorphic_enum_loop_ast_node.rs create mode 100644 ast-generator/src/ast_node/polymorphic_type_ast_node.rs create mode 100644 ast-generator/src/ast_node/struct_ast_node.rs diff --git a/ast-generator/src/ast_node/enum_ast_node.rs b/ast-generator/src/ast_node/enum_ast_node.rs new file mode 100644 index 0000000..66e579d --- /dev/null +++ b/ast-generator/src/ast_node/enum_ast_node.rs @@ -0,0 +1,6 @@ +use crate::spec::tree_enum_spec::TreeEnumBuildSpec; +use proc_macro2::TokenStream; + +pub fn make_enum_ast_node_impl(enum_spec: &TreeEnumBuildSpec) -> TokenStream { + todo!() +} diff --git a/ast-generator/src/ast_node/leaf_enum_ast_node.rs b/ast-generator/src/ast_node/leaf_enum_ast_node.rs new file mode 100644 index 0000000..0e71db0 --- /dev/null +++ b/ast-generator/src/ast_node/leaf_enum_ast_node.rs @@ -0,0 +1,6 @@ +use proc_macro2::TokenStream; +use crate::spec::leaf_enum_spec::LeafEnumBuildSpec; + +pub fn make_leaf_enum_ast_node_impl(spec: &LeafEnumBuildSpec) -> TokenStream { + todo!() +} \ No newline at end of file diff --git a/ast-generator/src/ast_node/leaf_struct_ast_node.rs b/ast-generator/src/ast_node/leaf_struct_ast_node.rs new file mode 100644 index 0000000..e449ed4 --- /dev/null +++ b/ast-generator/src/ast_node/leaf_struct_ast_node.rs @@ -0,0 +1,6 @@ +use proc_macro2::TokenStream; +use crate::spec::leaf_struct_spec::LeafStructBuildSpec; + +pub fn make_leaf_struct_ast_node_impl(spec: &LeafStructBuildSpec) -> TokenStream { + todo!() +} \ No newline at end of file diff --git a/ast-generator/src/ast_node/mod.rs b/ast-generator/src/ast_node/mod.rs new file mode 100644 index 0000000..5c9464a --- /dev/null +++ b/ast-generator/src/ast_node/mod.rs @@ -0,0 +1,52 @@ +mod enum_ast_node; +mod leaf_enum_ast_node; +mod struct_ast_node; +mod leaf_struct_ast_node; +mod polymorphic_type_ast_node; +mod polymorphic_enum_loop_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::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::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::struct_ast_node::make_struct_ast_node_impl; + +pub fn make_ast_node_impl(build_spec: &BuildSpec) -> Option { + match build_spec { + BuildSpec::Enum(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::LeafStruct(leaf_struct) => { + Some(make_leaf_struct_ast_node_impl(leaf_struct)) + } + BuildSpec::Production(_) => None, + BuildSpec::NodeProduction(_) => None, + BuildSpec::PolymorphicType(polymorphic_type) => { + Some(make_polymorphic_type_ast_node_impl(polymorphic_type)) + } + BuildSpec::PolymorphicEnumLoop(polymorphic_enum_loop) => { + Some(make_polymorphic_enum_loop_ast_node_impl(polymorphic_enum_loop)) + } + BuildSpec::PolymorphicPassThrough(_) => None, + } +} + +pub fn make_ast_enum_member(build_spec: &BuildSpec) -> Option { + match build_spec { + BuildSpec::Struct(struct_spec) => { + let type_ident = format_ident!("{}", struct_spec.build()); + Some(quote! { #type_ident(#type_ident) }) + } + _ => None, + } +} \ No newline at end of file diff --git a/ast-generator/src/ast_node/polymorphic_enum_loop_ast_node.rs b/ast-generator/src/ast_node/polymorphic_enum_loop_ast_node.rs new file mode 100644 index 0000000..3f374eb --- /dev/null +++ b/ast-generator/src/ast_node/polymorphic_enum_loop_ast_node.rs @@ -0,0 +1,6 @@ +use proc_macro2::TokenStream; +use crate::spec::polymorphic_enum_loop_spec::PolymorphicEnumLoopBuildSpec; + +pub fn make_polymorphic_enum_loop_ast_node_impl(spec: &PolymorphicEnumLoopBuildSpec) -> TokenStream { + todo!() +} \ No newline at end of file diff --git a/ast-generator/src/ast_node/polymorphic_type_ast_node.rs b/ast-generator/src/ast_node/polymorphic_type_ast_node.rs new file mode 100644 index 0000000..250359f --- /dev/null +++ b/ast-generator/src/ast_node/polymorphic_type_ast_node.rs @@ -0,0 +1,6 @@ +use proc_macro2::TokenStream; +use crate::spec::polymorphic_type_spec::PolymorphicTypeBuildSpec; + +pub fn make_polymorphic_type_ast_node_impl(spec: &PolymorphicTypeBuildSpec) -> TokenStream { + todo!() +} \ No newline at end of file diff --git a/ast-generator/src/ast_node/struct_ast_node.rs b/ast-generator/src/ast_node/struct_ast_node.rs new file mode 100644 index 0000000..102874f --- /dev/null +++ b/ast-generator/src/ast_node/struct_ast_node.rs @@ -0,0 +1,55 @@ +use crate::spec::struct_spec::{MemberChildBuild, StructChild, StructSpec, VecChildBuild}; +use proc_macro2::TokenStream; +use quote::{format_ident, quote}; + +pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream { + let type_ident = format_ident!("{}", spec.build()); + let child_adders = spec + .children() + .map(|child| match child { + StructChild::SkipChild(_) => None, + StructChild::VecChild(vec_child) => { + match vec_child.build() { + VecChildBuild::String(_) => None, + VecChildBuild::Node(_) => { + let child_ident = format_ident!("{}", vec_child.name()); + let children_stream = quote! { + for child in self.#child_ident().map(AstNode::as_node_ref).collect() { + children.push(child); + } + }; + Some(children_stream) + } + } + } + StructChild::MemberChild(member_child) => { + match member_child.build() { + MemberChildBuild::Node(_) => { + let child_ident = format_ident!("{}", member_child.name()); + let child_stream = quote! { + children.add(self.#child_ident().as_node_ref()) + }; + Some(child_stream) + } + MemberChildBuild::Boolean(_) => None + } + } + }) + .filter(Option::is_some) + .map(Option::unwrap) + .collect::>(); + + quote! { + impl AstNode for #type_ident { + fn children(&self) -> Vec { + let children: Vec = vec![]; + #(#child_adders;)* + children + } + + fn as_node_ref(&self) -> AstNodeRef { + AstNodeRef::#type_ident(&self) + } + } + } +} diff --git a/ast-generator/src/lib.rs b/ast-generator/src/lib.rs index 841ad3c..2703842 100644 --- a/ast-generator/src/lib.rs +++ b/ast-generator/src/lib.rs @@ -1,9 +1,11 @@ +mod ast_node; mod build_fn; mod deserialize; mod pretty_print; mod spec; mod type_gen; +use crate::ast_node::{make_ast_enum_member, make_ast_node_impl}; use crate::build_fn::make_build_fn; use crate::deserialize::deserialize_yaml_spec; use crate::pretty_print::make_pretty_print_impl; @@ -107,7 +109,7 @@ fn generate_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile { .collect::>(); let combined = quote! { use std::range::Range; - + #(#types)* }; AstGeneratedFile { @@ -129,7 +131,7 @@ fn generate_pretty_print_file(build_specs: &[BuildSpec]) -> AstGeneratedFile { .filter(Option::is_some) .map(Option::unwrap) .collect::>(); - + let combined = quote! { use crate::ast::node::*; #(#impls)* @@ -140,6 +142,48 @@ fn generate_pretty_print_file(build_specs: &[BuildSpec]) -> AstGeneratedFile { } } +fn generate_ast_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile { + let impls = build_specs + .iter() + .map(|build_spec| { + let maybe_stream = make_ast_node_impl(build_spec); + if let Some(stream) = &maybe_stream { + debug_built_spec(build_spec, &stream); + } + maybe_stream + }) + .filter(Option::is_some) + .map(Option::unwrap) + .collect::>(); + + let ast_enum_members = build_specs + .iter() + .map(|build_spec| make_ast_enum_member(build_spec)) + .filter(Option::is_some) + .map(Option::unwrap) + .collect::>(); + + let combined = quote! { + use crate::ast::node::*; + + pub enum AstNodeRef { + #(#ast_enum_members,)* + } + + pub trait AstNode { + fn children(&self) -> Vec; + + fn as_node_ref(&self) -> AstNodeRef; + } + + #(#impls)* + }; + AstGeneratedFile { + name: String::from("ast_node.rs"), + contents: token_stream_to_string(combined), + } +} + pub fn get_build_specs(yaml: &str) -> Vec { deserialize_yaml_spec(yaml) } @@ -149,5 +193,6 @@ pub fn generate_files(build_specs: &[BuildSpec]) -> Vec { generate_build_file(build_specs), generate_node_file(build_specs), generate_pretty_print_file(build_specs), + generate_ast_node_file(build_specs), ] } diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 18c6427..5329df4 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -141,3 +141,23 @@ pub mod pretty_print { include!(concat!(env!("OUT_DIR"), "/src/ast/pretty_print.rs")); } + +pub mod ast_node { + include!(concat!(env!("OUT_DIR"), "/src/ast/ast_node.rs")); + + #[cfg(test)] + mod tests { + use crate::ast::ast_node::AstNode; + use crate::ast::node::CompilationUnit; + + fn get_cu() -> CompilationUnit { + todo!() + } + + #[test] + fn simple() { + let cu = get_cu(); + for child in cu.children() {} + } + } +}