Skip to content

Commit c9606fd

Browse files
committed
feat(ast_codegen): add ImplGetSpanGenerator.
1 parent 835e59c commit c9606fd

File tree

6 files changed

+134
-17
lines changed

6 files changed

+134
-17
lines changed

tasks/ast_codegen/schema.json

-776 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use itertools::Itertools;
2+
use proc_macro2::TokenStream;
3+
use syn::{parse_quote, Item, ItemImpl, ItemStruct, Variant};
4+
5+
use crate::{
6+
schema::{REnum, RStruct, RType},
7+
CodegenCtx, Generator, GeneratorOutput,
8+
};
9+
10+
pub struct ImplGetSpanGenerator;
11+
12+
impl Generator for ImplGetSpanGenerator {
13+
fn name(&self) -> &'static str {
14+
"ImplGetSpanGenerator"
15+
}
16+
17+
fn generate(&mut self, ctx: &CodegenCtx) -> GeneratorOutput {
18+
let impls: Vec<ItemImpl> = ctx
19+
.ty_table
20+
.iter()
21+
.filter_map(|maybe_kind| match &*maybe_kind.borrow() {
22+
RType::Enum(it) => Some(impl_enum(it)),
23+
RType::Struct(it) => Some(impl_struct(it)),
24+
_ => None,
25+
})
26+
.collect();
27+
28+
GeneratorOutput::One(parse_quote!(#(#impls)*))
29+
}
30+
}
31+
32+
fn impl_enum(it @ REnum { item, .. }: &REnum) -> ItemImpl {
33+
let typ = it.as_type();
34+
let generics = &item.generics;
35+
let matches: Vec<TokenStream> = item
36+
.variants
37+
.iter()
38+
.map(|Variant { ident, .. }| parse_quote!(Self :: #ident(it) => it.span()))
39+
.collect_vec();
40+
41+
parse_quote! {
42+
impl #generics GetSpan for #typ {
43+
fn span(&self) -> Span {
44+
match self {
45+
#(#matches),*
46+
}
47+
}
48+
}
49+
}
50+
}
51+
52+
fn impl_struct(it @ RStruct { item, .. }: &RStruct) -> ItemImpl {
53+
let typ = it.as_type();
54+
let generics = &item.generics;
55+
parse_quote! {
56+
impl #generics GetSpan for #typ {
57+
fn span(&self) -> Span {
58+
self.span
59+
}
60+
}
61+
}
62+
}
+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
mod ast;
22
mod ast_kind;
3+
mod impl_get_span;
34

45
pub use ast::AstGenerator;
56
pub use ast_kind::AstKindGenerator;
7+
pub use impl_get_span::ImplGetSpanGenerator;

tasks/ast_codegen/src/linker.rs

+35-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,25 @@ pub trait Linker<'a> {
66
fn link(&'a self, linker: impl FnMut(&mut RType, &'a Self) -> Result<bool>) -> Result<&'a ()>;
77
}
88

9+
pub trait Unresolved {
10+
fn unresolved(&self) -> bool;
11+
fn resolved(&self) -> bool {
12+
!self.unresolved()
13+
}
14+
}
15+
16+
impl Unresolved for Inherit {
17+
fn unresolved(&self) -> bool {
18+
matches!(self, Self::Unlinked(_))
19+
}
20+
}
21+
22+
impl Unresolved for Vec<Inherit> {
23+
fn unresolved(&self) -> bool {
24+
self.iter().any(Unresolved::unresolved)
25+
}
26+
}
27+
928
impl<'a> Linker<'a> for CodegenCtx {
1029
fn link(
1130
&'a self,
@@ -43,25 +62,33 @@ pub fn linker(ty: &mut RType, ctx: &CodegenCtx) -> Result<bool> {
4362
return Ok(true);
4463
}
4564

46-
ty.meta.inherits = ty
65+
let inherits = ty
4766
.meta
4867
.inherits
4968
.drain(..)
5069
.map(|it| match it {
51-
Inherit::Unlinked(it) => {
52-
let linkee = ctx.find(&Cow::Owned(it.to_string())).unwrap();
70+
Inherit::Unlinked(ref sup) => {
71+
let linkee = ctx.find(&Cow::Owned(sup.to_string())).unwrap();
5372
let variants = match &*linkee.borrow() {
54-
RType::Enum(enum_) => enum_.item.variants.clone(),
73+
RType::Enum(enum_) => {
74+
if enum_.meta.inherits.unresolved() {
75+
return Err(it);
76+
}
77+
enum_.item.variants.clone()
78+
}
5579
_ => {
5680
panic!("invalid inheritance, you can only inherit from enums and in enums.")
5781
}
5882
};
5983
ty.item.variants.extend(variants.clone());
60-
Inherit::Linked { super_: it.clone(), variants }
84+
Ok(Inherit::Linked { super_: sup.clone(), variants })
6185
}
62-
Inherit::Linked { .. } => it,
86+
Inherit::Linked { .. } => Ok(it),
6387
})
64-
.collect_vec();
88+
.collect::<Vec<std::result::Result<Inherit, Inherit>>>();
89+
let unresolved = inherits.iter().any(|it| it.is_err());
90+
91+
ty.meta.inherits = inherits.into_iter().map(|it| it.unwrap_or_else(|it| it)).collect();
6592

66-
Ok(true)
93+
Ok(!unresolved)
6794
}

tasks/ast_codegen/src/main.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ use generators::{AstGenerator, AstKindGenerator};
1616
use linker::{linker, Linker};
1717
use schema::{Inherit, Module, REnum, RStruct, RType, Schema};
1818

19+
use crate::generators::ImplGetSpanGenerator;
20+
1921
type Result<R> = std::result::Result<R, String>;
2022
type TypeId = usize;
2123
type TypeName = String;
@@ -133,12 +135,26 @@ fn files() -> std::array::IntoIter<String, 4> {
133135

134136
#[allow(clippy::print_stdout)]
135137
fn main() -> Result<()> {
136-
let CodegenResult { schema, .. } = files()
138+
let CodegenResult { schema, outputs } = files()
137139
.fold(AstCodegen::default(), AstCodegen::add_file)
138140
.with(AstGenerator)
139141
.with(AstKindGenerator)
142+
.with(ImplGetSpanGenerator)
140143
.generate()?;
141144

145+
// NOTE: Print Impl GetSpan
146+
println!(
147+
"{}",
148+
outputs
149+
.into_iter()
150+
.find(|it| it.0 == ImplGetSpanGenerator.name())
151+
.map(|(_, output)| {
152+
let GeneratorOutput::One(result) = output else { unreachable!() };
153+
prettyplease::unparse(&parse_file(result.to_string().as_str()).unwrap())
154+
})
155+
.unwrap()
156+
);
157+
142158
// NOTE: Print AstKind
143159
// println!(
144160
// "{}",
@@ -175,7 +191,7 @@ fn main() -> Result<()> {
175191
// .unwrap()
176192
// );
177193

178-
let schema = serde_json::to_string_pretty(&schema).map_err(|e| e.to_string())?;
179-
println!("{schema}");
194+
// let schema = serde_json::to_string_pretty(&schema).map_err(|e| e.to_string())?;
195+
// println!("{schema}");
180196
Ok(())
181197
}

tasks/ast_codegen/src/schema.rs

+16-6
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ impl REnum {
5555
pub fn ident(&self) -> &Ident {
5656
&self.item.ident
5757
}
58+
59+
pub fn as_type(&self) -> Type {
60+
let ident = self.ident();
61+
let generics = &self.item.generics;
62+
parse_quote!(#ident #generics)
63+
}
5864
}
5965

6066
impl From<ItemEnum> for REnum {
@@ -77,6 +83,12 @@ impl RStruct {
7783
pub fn ident(&self) -> &Ident {
7884
&self.item.ident
7985
}
86+
87+
pub fn as_type(&self) -> Type {
88+
let ident = self.ident();
89+
let generics = &self.item.generics;
90+
parse_quote!(#ident #generics)
91+
}
8092
}
8193

8294
impl From<ItemStruct> for RStruct {
@@ -121,12 +133,10 @@ impl RType {
121133
}
122134

123135
pub fn as_type(&self) -> Option<Type> {
124-
if let RType::Enum(REnum { item: ItemEnum { ident, generics, .. }, .. })
125-
| RType::Struct(RStruct { item: ItemStruct { ident, generics, .. }, .. }) = self
126-
{
127-
Some(parse_quote!(#ident #generics))
128-
} else {
129-
None
136+
match self {
137+
RType::Enum(it) => Some(it.as_type()),
138+
RType::Struct(it) => Some(it.as_type()),
139+
_ => None,
130140
}
131141
}
132142
}

0 commit comments

Comments
 (0)