Skip to content

Commit a0a7528

Browse files
committed
generate: move the traverse shape into a helper trait.
1 parent c03e14a commit a0a7528

File tree

3 files changed

+188
-257
lines changed

3 files changed

+188
-257
lines changed

src/generate/rust.rs

Lines changed: 46 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,9 @@ where
945945
}
946946
}
947947

948+
// FIXME(eddyb) these two impls cannot be easily implemented by a trait
949+
// because of how `Handle<'a, 'i, I, X<'a, 'i, I>>` links together the
950+
// lifetime parameters of `Handle` and those of `X`.
948951
impl<I: gll::grammer::input::Input> OwnedHandle<I, #ident<'_, '_, I>> {
949952
pub fn with<R>(&self, f: impl for<'a, 'i> FnOnce(Handle<'a, 'i, I, #ident<'a, 'i, I>>) -> R) -> R {
950953
self.forest_and_node.unpack_ref(|_, forest_and_node| {
@@ -957,6 +960,12 @@ where
957960
})
958961
}
959962
}
963+
964+
impl<I: gll::grammer::input::Input> fmt::Debug for OwnedHandle<I, #ident<'_, '_, I>> {
965+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
966+
self.with(|handle| handle.fmt(f))
967+
}
968+
}
960969
)
961970
}
962971

@@ -1025,13 +1034,13 @@ where
10251034
}
10261035
};
10271036
rule_ty_def
1028-
+ rule_debug_impls(cx, name, &rust_adt)
1029-
+ impl_rule_from_forest(name, &rust_adt, cx, rules)
1030-
+ impl_rule_one_and_all(name, rule, &rust_adt, cx, rules)
1037+
+ rule_debug_impl(cx, name, &rust_adt)
1038+
+ impl_rule_traverse_impl(name, rule, &rust_adt, cx, rules)
10311039
}
10321040

1033-
fn impl_rule_from_forest<Pat>(
1041+
fn impl_rule_traverse_impl<Pat>(
10341042
name: IStr,
1043+
rule: RuleWithFields,
10351044
rust_adt: &RustAdt,
10361045
cx: &Context<Pat>,
10371046
rules: &mut RuleMap<'_>,
@@ -1056,7 +1065,7 @@ where
10561065
}
10571066
};
10581067

1059-
let method = match rust_adt {
1068+
let (total_fields, shape, from_shape) = match rust_adt {
10601069
RustAdt::Enum(variants) => {
10611070
let max_fields_len = variants
10621071
.values()
@@ -1075,6 +1084,15 @@ where
10751084
.iter()
10761085
.map(|kind| kind.to_src())
10771086
.collect::<Vec<_>>();
1087+
let variants_shape = variants
1088+
.values()
1089+
.map(|(v_rule, variant)| match variant {
1090+
RustVariant::Newtype(_) => quote!(_),
1091+
RustVariant::StructLike(v_fields) => {
1092+
v_rule.generate_traverse_shape(cx, rules, v_fields)
1093+
}
1094+
})
1095+
.collect::<Vec<_>>();
10781096
let variants_expr = variants.iter().map(|(&v_name, (_, variant))| {
10791097
let variant_ident = Src::ident(&cx[v_name]);
10801098
match variant {
@@ -1093,139 +1111,56 @@ where
10931111
}
10941112
});
10951113

1096-
quote!(
1097-
fn from_forest(
1098-
forest: &'a gll::grammer::forest::ParseForest<'i, _G, I>,
1099-
_r: [Option<Node<'i, _G>>; #max_fields_len + 1],
1100-
) -> Self {
1114+
(
1115+
max_fields_len + 1,
1116+
quote!({ _P; #max_fields_len @ #(#variants_kind_src => #variants_shape,)* }),
1117+
quote!(
11011118
match _r[#max_fields_len].unwrap().kind {
11021119
#(#variants_kind_src => #variants_expr,)*
11031120
_ => unreachable!(),
11041121
}
1105-
}
1122+
),
11061123
)
11071124
}
11081125
RustAdt::Struct(fields) => {
1109-
let fields_len = fields.len();
11101126
let fields_ident = fields.keys().map(|&name| Src::ident(&cx[name]));
11111127
let fields_expr = fields.values().enumerate().map(field_handle_expr);
11121128
let marker_field = if fields.is_empty() {
11131129
Some(quote!(_marker: { let _ = forest; PhantomData },))
11141130
} else {
11151131
None
11161132
};
1117-
quote!(
1118-
fn from_forest(
1119-
forest: &'a gll::grammer::forest::ParseForest<'i, _G, I>,
1120-
_r: [Option<Node<'i, _G>>; #fields_len],
1121-
) -> Self {
1133+
1134+
(
1135+
fields.len(),
1136+
rule.generate_traverse_shape(cx, rules, fields),
1137+
quote!(
11221138
#ident {
11231139
#(#fields_ident: #fields_expr),*
11241140
#marker_field
11251141
}
1126-
}
1142+
),
11271143
)
11281144
}
11291145
};
11301146

1131-
quote!(impl<'a, 'i, I: gll::grammer::input::Input> #ident<'a, 'i, I> {
1132-
#method
1133-
})
1134-
}
1135-
1136-
fn impl_rule_one_and_all<Pat>(
1137-
name: IStr,
1138-
rule: RuleWithFields,
1139-
rust_adt: &RustAdt,
1140-
cx: &Context<Pat>,
1141-
rules: &mut RuleMap<'_>,
1142-
) -> Src
1143-
where
1144-
Pat: RustInputPat,
1145-
{
1146-
let ident = Src::ident(&cx[name]);
1147-
let (total_fields, shape) = match rust_adt {
1148-
RustAdt::Enum(variants) => {
1149-
let max_fields_len = variants
1150-
.values()
1151-
.map(|(_, variant)| match variant {
1152-
RustVariant::Newtype(_) => 0,
1153-
RustVariant::StructLike(v_fields) => v_fields.len(),
1154-
})
1155-
.max()
1156-
.unwrap_or(0);
1157-
// HACK(eddyb) only collected to a `Vec` to avoid `rules` borrow conflicts.
1158-
let variants_kind = variants
1159-
.values()
1160-
.map(|(v_rule, _)| v_rule.rule.node_kind(cx, rules))
1161-
.collect::<Vec<_>>();
1162-
let variants_kind_src = variants_kind
1163-
.iter()
1164-
.map(|kind| kind.to_src())
1165-
.collect::<Vec<_>>();
1166-
let variants_shape = variants
1167-
.values()
1168-
.map(|(v_rule, variant)| match variant {
1169-
RustVariant::Newtype(_) => quote!(_),
1170-
RustVariant::StructLike(v_fields) => {
1171-
v_rule.generate_traverse_shape(cx, rules, v_fields)
1172-
}
1173-
})
1174-
.collect::<Vec<_>>();
1175-
1176-
(
1177-
max_fields_len + 1,
1178-
quote!({ _P; #max_fields_len @ #(#variants_kind_src => #variants_shape,)* }),
1179-
)
1180-
}
1181-
RustAdt::Struct(fields) => (
1182-
fields.len(),
1183-
rule.generate_traverse_shape(cx, rules, fields),
1184-
),
1185-
};
1186-
1187-
quote!(
1188-
impl<'a, 'i, I: gll::grammer::input::Input> #ident<'a, 'i, I> {
1189-
const SHAPE: traverse::ty!(#shape) = traverse::new!(#shape);
1190-
}
1191-
1192-
impl<'a, 'i, I> Handle<'a, 'i, I, #ident<'a, 'i, I>>
1147+
quote!(impl<'a, 'i, I>
1148+
traverse::FromShape<&'a gll::grammer::forest::ParseForest<'i, _G, I>, Node<'i, _G>>
1149+
for #ident<'a, 'i, I>
11931150
where I: gll::grammer::input::Input,
11941151
{
1195-
pub fn one(self) -> Result<#ident<'a, 'i, I>, Ambiguity<Self>> {
1196-
let forest = self.forest;
1197-
let node = forest.unpack_alias(self.node);
1198-
1199-
let mut r = [None; #total_fields];
1200-
#ident::<I>::SHAPE
1201-
.one(forest, node, &mut r)
1202-
.map_err(|gll::grammer::forest::MoreThanOne| Ambiguity(self))?;
1152+
type Shape = traverse::ty!(#shape);
1153+
type Fields = [Option<Node<'i, _G>>; #total_fields];
12031154

1204-
Ok(#ident::from_forest(forest, r))
1205-
}
1155+
const SHAPE: Self::Shape = traverse::new!(#shape);
12061156

1207-
pub fn all(self) -> ::std::iter::Map<
1208-
cursor::IntoIter<
1209-
<traverse::ty!(#shape) as traverse::Shape<'a, 'i, _G>>::All,
1210-
[Option<Node<'i, _G>>; #total_fields],
1211-
[Option<Node<'i, _G>>],
1212-
>,
1213-
impl FnMut([Option<Node<'i, _G>>; #total_fields]) -> #ident<'a, 'i, I>,
1214-
> {
1215-
let forest = self.forest;
1216-
let node = forest.unpack_alias(self.node);
1217-
1218-
#ident::<I>::SHAPE
1219-
.all(forest, node)
1220-
.into_iter()
1221-
.map(move |r| #ident::from_forest(forest, r))
1157+
fn from_shape(
1158+
forest: &'a gll::grammer::forest::ParseForest<'i, _G, I>,
1159+
_r: Self::Fields,
1160+
) -> Self {
1161+
#from_shape
12221162
}
1223-
}
1224-
)
1225-
}
1226-
1227-
fn rule_debug_impls<Pat>(cx: &Context<Pat>, name: IStr, rust_adt: &RustAdt) -> Src {
1228-
rule_debug_impl(cx, name, rust_adt) + rule_handle_debug_impl(cx, name, rust_adt)
1163+
})
12291164
}
12301165

12311166
fn rule_debug_impl<Pat>(cx: &Context<Pat>, name: IStr, rust_adt: &RustAdt) -> Src {
@@ -1306,44 +1241,6 @@ fn rule_debug_impl<Pat>(cx: &Context<Pat>, name: IStr, rust_adt: &RustAdt) -> Sr
13061241
})
13071242
}
13081243

1309-
fn rule_handle_debug_impl<Pat>(cx: &Context<Pat>, name: IStr, rust_adt: &RustAdt) -> Src {
1310-
let ident = Src::ident(&cx[name]);
1311-
let is_opaque = match rust_adt {
1312-
RustAdt::Struct(fields) => fields.is_empty(),
1313-
_ => false,
1314-
};
1315-
let body = if is_opaque {
1316-
quote!()
1317-
} else {
1318-
quote!(
1319-
write!(f, " => ")?;
1320-
let mut first = true;
1321-
for x in self.all() {
1322-
if !first {
1323-
write!(f, " | ")?;
1324-
}
1325-
first = false;
1326-
fmt::Debug::fmt(&x, f)?;
1327-
}
1328-
)
1329-
};
1330-
quote!(
1331-
impl<'a, 'i, I: gll::grammer::input::Input> fmt::Debug for Handle<'a, 'i, I, #ident<'a, 'i, I>> {
1332-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1333-
write!(f, "{:?}", self.source_info())?;
1334-
#body
1335-
Ok(())
1336-
}
1337-
}
1338-
1339-
impl<I: gll::grammer::input::Input> fmt::Debug for OwnedHandle<I, #ident<'_, '_, I>> {
1340-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1341-
self.with(|handle| handle.fmt(f))
1342-
}
1343-
}
1344-
)
1345-
}
1346-
13471244
fn define_parse_fn<Pat>(
13481245
cx: &Context<Pat>,
13491246
rules: &mut RuleMap<'_>,

src/generate/templates/header.rs

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,12 @@ impl<'a, 'i, I: gll::grammer::input::Input, T> From<Ambiguity<Handle<'a, 'i, I,
6464
}
6565
}
6666

67-
impl<I: gll::grammer::input::Input> fmt::Debug for Handle<'_, '_, I, ()> {
68-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69-
write!(f, "{:?}", self.source_info())
70-
}
71-
}
72-
7367
impl<'a, 'i, I: gll::grammer::input::Input, T> fmt::Debug for Handle<'a, 'i, I, [T]>
7468
where
75-
Handle<'a, 'i, I, T>: fmt::Debug,
69+
// FIXME(eddyb) this should be `Handle<'a, 'i, I, T>: fmt::Debug` but that
70+
// runs into overflows looking for `Handle<I, [[[...[[[_]]]...]]]>`.
71+
T: traverse::FromShape<&'a gll::grammer::forest::ParseForest<'i, _G, I>, Node<'i, _G>>,
72+
T: fmt::Debug,
7673
{
7774
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7875
write!(f, "{:?} => ", self.source_info())?;
@@ -225,3 +222,46 @@ impl<'a, 'i, I: gll::grammer::input::Input, T> Handle<'a, 'i, I, [T]> {
225222
)
226223
}
227224
}
225+
226+
// FIXME(eddyb) move Handle somewhere in `runtime` or even `grammer::forest`.
227+
impl<'a, 'i, I, T> fmt::Debug for Handle<'a, 'i, I, T>
228+
where
229+
I: gll::grammer::input::Input,
230+
T: traverse::FromShape<&'a gll::grammer::forest::ParseForest<'i, _G, I>, Node<'i, _G>>,
231+
T: fmt::Debug,
232+
{
233+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
234+
write!(f, "{:?}", self.source_info())?;
235+
if !T::Fields::default().as_mut().is_empty() {
236+
write!(f, " => ")?;
237+
let mut first = true;
238+
for x in self.all() {
239+
if !first {
240+
write!(f, " | ")?;
241+
}
242+
first = false;
243+
fmt::Debug::fmt(&x, f)?;
244+
}
245+
}
246+
Ok(())
247+
}
248+
}
249+
250+
// FIXME(eddyb) move Handle somewhere in `runtime` or even `grammer::forest`.
251+
impl<'a, 'i, I, T> Handle<'a, 'i, I, T>
252+
where
253+
I: gll::grammer::input::Input,
254+
T: traverse::FromShape<&'a gll::grammer::forest::ParseForest<'i, _G, I>, Node<'i, _G>>,
255+
{
256+
pub fn one(self) -> Result<T, Ambiguity<Self>> {
257+
T::one(self.forest, self.forest.unpack_alias(self.node))
258+
.map_err(|gll::grammer::forest::MoreThanOne| Ambiguity(self))
259+
}
260+
261+
pub fn all(
262+
self,
263+
) -> traverse::FromShapeAll<T, &'a gll::grammer::forest::ParseForest<'i, _G, I>, Node<'i, _G>>
264+
{
265+
T::all(self.forest, self.forest.unpack_alias(self.node))
266+
}
267+
}

0 commit comments

Comments
 (0)