Skip to content

Commit 9a94c20

Browse files
committed
refactor(ast_codegen): declutter the main file.
same as #4741
1 parent 7345f68 commit 9a94c20

File tree

14 files changed

+330
-292
lines changed

14 files changed

+330
-292
lines changed

tasks/ast_codegen/src/codegen.rs

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
use std::{cell::RefCell, collections::HashMap, path::PathBuf};
2+
3+
use itertools::Itertools;
4+
5+
use crate::{
6+
generators::{Generator, GeneratorOutput},
7+
passes::Pass,
8+
rust_ast::{self, AstRef},
9+
schema::{lower_ast_types, Schema, TypeDef},
10+
Result, TypeId,
11+
};
12+
13+
#[derive(Default)]
14+
pub struct AstCodegen {
15+
files: Vec<PathBuf>,
16+
passes: Vec<Box<dyn Runner<Output = (), Context = EarlyCtx>>>,
17+
generators: Vec<Box<dyn Runner<Output = GeneratorOutput, Context = LateCtx>>>,
18+
}
19+
20+
pub struct AstCodegenResult {
21+
pub schema: Schema,
22+
pub outputs: Vec<(/* generator name */ &'static str, /* output */ GeneratorOutput)>,
23+
}
24+
25+
pub trait Runner {
26+
type Context;
27+
type Output;
28+
fn name(&self) -> &'static str;
29+
fn run(&mut self, ctx: &Self::Context) -> Result<Self::Output>;
30+
}
31+
32+
pub struct EarlyCtx {
33+
ty_table: Vec<AstRef>,
34+
ident_table: HashMap<String, TypeId>,
35+
mods: RefCell<Vec<rust_ast::Module>>,
36+
}
37+
38+
impl EarlyCtx {
39+
fn new(mods: Vec<rust_ast::Module>) -> Self {
40+
// worst case len
41+
let len = mods.iter().fold(0, |acc, it| acc + it.items.len());
42+
let adts = mods.iter().flat_map(|it| it.items.iter());
43+
44+
let mut ty_table = Vec::with_capacity(len);
45+
let mut ident_table = HashMap::with_capacity(len);
46+
for adt in adts {
47+
if let Some(ident) = adt.borrow().ident() {
48+
let ident = ident.to_string();
49+
let type_id = ty_table.len();
50+
ty_table.push(AstRef::clone(adt));
51+
ident_table.insert(ident, type_id);
52+
}
53+
}
54+
55+
Self { ty_table, ident_table, mods: RefCell::new(mods) }
56+
}
57+
58+
pub fn chronological_idents(&self) -> impl Iterator<Item = &String> {
59+
self.ident_table.iter().sorted_by_key(|it| it.1).map(|it| it.0)
60+
}
61+
62+
pub fn mods(&self) -> &RefCell<Vec<rust_ast::Module>> {
63+
&self.mods
64+
}
65+
66+
pub fn find(&self, key: &String) -> Option<AstRef> {
67+
self.type_id(key).map(|id| AstRef::clone(&self.ty_table[id]))
68+
}
69+
70+
pub fn type_id(&self, key: &String) -> Option<TypeId> {
71+
self.ident_table.get(key).copied()
72+
}
73+
74+
pub fn ast_ref(&self, id: TypeId) -> AstRef {
75+
AstRef::clone(&self.ty_table[id])
76+
}
77+
78+
fn into_late_ctx(self) -> LateCtx {
79+
let schema = lower_ast_types(&self);
80+
81+
LateCtx { schema }
82+
}
83+
}
84+
85+
pub struct LateCtx {
86+
schema: Schema,
87+
}
88+
89+
impl LateCtx {
90+
pub fn schema(&self) -> &Schema {
91+
&self.schema
92+
}
93+
94+
pub fn type_def(&self, id: TypeId) -> Option<&TypeDef> {
95+
self.schema.get(id)
96+
}
97+
}
98+
99+
impl AstCodegen {
100+
#[must_use]
101+
pub fn add_file<P>(mut self, path: P) -> Self
102+
where
103+
P: AsRef<str>,
104+
{
105+
self.files.push(path.as_ref().into());
106+
self
107+
}
108+
109+
#[must_use]
110+
pub fn pass<P>(mut self, pass: P) -> Self
111+
where
112+
P: Pass + Runner<Output = (), Context = EarlyCtx> + 'static,
113+
{
114+
self.passes.push(Box::new(pass));
115+
self
116+
}
117+
118+
#[must_use]
119+
pub fn gen<G>(mut self, generator: G) -> Self
120+
where
121+
G: Generator + Runner<Output = GeneratorOutput, Context = LateCtx> + 'static,
122+
{
123+
self.generators.push(Box::new(generator));
124+
self
125+
}
126+
127+
pub fn generate(self) -> Result<AstCodegenResult> {
128+
let modules = self
129+
.files
130+
.into_iter()
131+
.map(rust_ast::Module::from)
132+
.map(rust_ast::Module::load)
133+
.map_ok(rust_ast::Module::expand)
134+
.map_ok(|it| it.map(rust_ast::Module::analyze))
135+
.collect::<Result<Result<Result<Vec<_>>>>>()???;
136+
137+
// early passes
138+
let ctx = {
139+
let ctx = EarlyCtx::new(modules);
140+
_ = self
141+
.passes
142+
.into_iter()
143+
.map(|mut runner| runner.run(&ctx).map(|res| (runner.name(), res)))
144+
.collect::<Result<Vec<_>>>()?;
145+
ctx.into_late_ctx()
146+
};
147+
148+
let outputs = self
149+
.generators
150+
.into_iter()
151+
.map(|mut runner| runner.run(&ctx).map(|res| (runner.name(), res)))
152+
.collect::<Result<Vec<_>>>()?;
153+
154+
Ok(AstCodegenResult { outputs, schema: ctx.schema })
155+
}
156+
}

tasks/ast_codegen/src/generators/assert_layouts.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ use quote::{format_ident, quote};
33
use syn::Type;
44

55
use crate::{
6+
codegen::LateCtx,
67
output,
78
schema::{FieldDef, ToType, TypeDef},
8-
Generator, GeneratorOutput, LateCtx,
9+
Generator, GeneratorOutput,
910
};
1011

1112
use super::{define_generator, generated_header};
@@ -17,9 +18,8 @@ define_generator! {
1718
impl Generator for AssertLayouts {
1819
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput {
1920
let (assertions_64, assertions_32) = ctx
20-
.schema
21-
.definitions
22-
.iter()
21+
.schema()
22+
.into_iter()
2323
.map(|def| {
2424
let typ = def.to_type_elide();
2525
assert_type(&typ, def)

tasks/ast_codegen/src/generators/ast_builder.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ use quote::{format_ident, quote, ToTokens};
99
use syn::{parse_quote, Ident, Type};
1010

1111
use crate::{
12+
codegen::LateCtx,
1213
generators::generated_header,
1314
output,
1415
schema::{
1516
EnumDef, FieldDef, GetIdent, InheritDef, StructDef, ToType, TypeDef, TypeName, VariantDef,
1617
},
1718
util::{TypeAnalysis, TypeWrapper},
18-
Generator, GeneratorOutput, LateCtx,
19+
Generator, GeneratorOutput,
1920
};
2021

2122
use super::define_generator;
@@ -27,9 +28,8 @@ define_generator! {
2728
impl Generator for AstBuilderGenerator {
2829
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput {
2930
let fns = ctx
30-
.schema
31-
.definitions
32-
.iter()
31+
.schema()
32+
.into_iter()
3333
.filter(|it| it.visitable())
3434
.map(|it| generate_builder_fn(it, ctx))
3535
.collect_vec();

tasks/ast_codegen/src/generators/ast_kind.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ use quote::quote;
33
use syn::{parse_quote, Arm, Ident, Type, Variant};
44

55
use crate::{
6+
codegen::LateCtx,
67
output,
78
schema::{GetIdent, ToType, TypeDef},
89
util::ToIdent,
9-
Generator, GeneratorOutput, LateCtx,
10+
Generator, GeneratorOutput,
1011
};
1112

1213
use super::{define_generator, generated_header};
@@ -137,8 +138,8 @@ pub fn process_types(def: &TypeDef, _: &LateCtx) -> Vec<(Ident, Type)> {
137138
impl Generator for AstKindGenerator {
138139
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput {
139140
let have_kinds: Vec<(Ident, Type)> = ctx
140-
.schema.definitions
141-
.iter()
141+
.schema()
142+
.into_iter()
142143
.filter(|it| it.visitable())
143144
.filter(
144145
|maybe_kind| matches!(maybe_kind, kind @ (TypeDef::Enum(_) | TypeDef::Struct(_)) if kind.visitable())

tasks/ast_codegen/src/generators/derive_clone_in.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ use quote::{format_ident, quote};
44
use syn::Ident;
55

66
use crate::{
7+
codegen::LateCtx,
78
output,
89
schema::{EnumDef, GetIdent, StructDef, TypeDef},
9-
GeneratorOutput, LateCtx,
10+
GeneratorOutput,
1011
};
1112

1213
use super::{define_generator, generated_header, Generator};
@@ -18,9 +19,8 @@ define_generator! {
1819
impl Generator for DeriveCloneIn {
1920
fn generate(&mut self, ctx: &LateCtx) -> GeneratorOutput {
2021
let impls: Vec<TokenStream> = ctx
21-
.schema
22-
.definitions
23-
.iter()
22+
.schema()
23+
.into_iter()
2424
.filter(|def| def.generates_derive("CloneIn"))
2525
.map(|def| match &def {
2626
TypeDef::Enum(it) => derive_enum(it),

tasks/ast_codegen/src/generators/derive_get_span.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ use quote::{format_ident, quote};
33
use syn::Ident;
44

55
use crate::{
6+
codegen::LateCtx,
67
output,
78
schema::{EnumDef, GetGenerics, StructDef, ToType, TypeDef},
89
util::ToIdent,
9-
Generator, GeneratorOutput, LateCtx,
10+
Generator, GeneratorOutput,
1011
};
1112

1213
use super::{define_generator, generated_header};
@@ -54,9 +55,8 @@ fn derive(
5455
ctx: &LateCtx,
5556
) -> TokenStream {
5657
let impls: Vec<TokenStream> = ctx
57-
.schema
58-
.definitions
59-
.iter()
58+
.schema()
59+
.into_iter()
6060
.filter(|def| def.visitable())
6161
.map(|def| match &def {
6262
TypeDef::Enum(def) => derive_enum(def, trait_name, method_name, self_type, result_type),

0 commit comments

Comments
 (0)