WIP ast node ref enum and AstNode impls.

This commit is contained in:
Jesse Brault 2025-09-28 15:02:20 -05:00
parent 6e37e3a5dd
commit df8e2279dc
9 changed files with 204 additions and 2 deletions

View File

@ -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!()
}

View File

@ -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!()
}

View File

@ -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!()
}

View File

@ -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<TokenStream> {
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<TokenStream> {
match build_spec {
BuildSpec::Struct(struct_spec) => {
let type_ident = format_ident!("{}", struct_spec.build());
Some(quote! { #type_ident(#type_ident) })
}
_ => None,
}
}

View File

@ -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!()
}

View File

@ -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!()
}

View File

@ -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::<Vec<_>>();
quote! {
impl AstNode for #type_ident {
fn children(&self) -> Vec<AstNodeRef> {
let children: Vec<AstNodeRef> = vec![];
#(#child_adders;)*
children
}
fn as_node_ref(&self) -> AstNodeRef {
AstNodeRef::#type_ident(&self)
}
}
}
}

View File

@ -1,9 +1,11 @@
mod ast_node;
mod build_fn; mod build_fn;
mod deserialize; mod deserialize;
mod pretty_print; mod pretty_print;
mod spec; mod spec;
mod type_gen; mod type_gen;
use crate::ast_node::{make_ast_enum_member, 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;
@ -107,7 +109,7 @@ fn generate_node_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let combined = quote! { let combined = quote! {
use std::range::Range; use std::range::Range;
#(#types)* #(#types)*
}; };
AstGeneratedFile { AstGeneratedFile {
@ -129,7 +131,7 @@ fn generate_pretty_print_file(build_specs: &[BuildSpec]) -> AstGeneratedFile {
.filter(Option::is_some) .filter(Option::is_some)
.map(Option::unwrap) .map(Option::unwrap)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let combined = quote! { let combined = quote! {
use crate::ast::node::*; use crate::ast::node::*;
#(#impls)* #(#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::<Vec<_>>();
let ast_enum_members = build_specs
.iter()
.map(|build_spec| make_ast_enum_member(build_spec))
.filter(Option::is_some)
.map(Option::unwrap)
.collect::<Vec<_>>();
let combined = quote! {
use crate::ast::node::*;
pub enum AstNodeRef {
#(#ast_enum_members,)*
}
pub trait AstNode {
fn children(&self) -> Vec<AstNodeRef>;
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<BuildSpec> { pub fn get_build_specs(yaml: &str) -> Vec<BuildSpec> {
deserialize_yaml_spec(yaml) deserialize_yaml_spec(yaml)
} }
@ -149,5 +193,6 @@ pub fn generate_files(build_specs: &[BuildSpec]) -> Vec<AstGeneratedFile> {
generate_build_file(build_specs), generate_build_file(build_specs),
generate_node_file(build_specs), generate_node_file(build_specs),
generate_pretty_print_file(build_specs), generate_pretty_print_file(build_specs),
generate_ast_node_file(build_specs),
] ]
} }

View File

@ -141,3 +141,23 @@ pub mod pretty_print {
include!(concat!(env!("OUT_DIR"), "/src/ast/pretty_print.rs")); 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() {}
}
}
}