Skip to content

Commit 48f7346

Browse files
committed
runtime: encode traverse shapes in types more directly.
1 parent 66df18f commit 48f7346

File tree

3 files changed

+336
-106
lines changed

3 files changed

+336
-106
lines changed

src/generate/rust.rs

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -892,10 +892,6 @@ impl<Pat: RustInputPat> RuleWithFieldsGenerateMethods<Pat> for RuleWithFields {
892892
quote!((#left, #right))
893893
}
894894
Rule::Or(ref cases) => {
895-
let cases_idx = cases
896-
.iter()
897-
.enumerate()
898-
.map(|(i, _)| Src::ident(format!("_{}", i)));
899895
// HACK(eddyb) only collected to a `Vec` to avoid `rules` borrow conflicts.
900896
let cases_shape = cases
901897
.iter()
@@ -906,7 +902,7 @@ impl<Pat: RustInputPat> RuleWithFieldsGenerateMethods<Pat> for RuleWithFields {
906902
.collect::<Vec<_>>();
907903
let cases_node_kind = cases.iter().map(|rule| rule.node_kind(cx, rules));
908904
let cases_node_kind_src = cases_node_kind.map(|kind| kind.to_src());
909-
quote!({ #(#cases_idx: #cases_node_kind_src => #cases_shape,)* })
905+
quote!({ _P; #(#cases_node_kind_src => #cases_shape,)* })
910906
}
911907
Rule::Opt(rule) => {
912908
let shape = child(rule, 0).generate_traverse_shape(cx, rules, rust_fields);
@@ -1133,7 +1129,7 @@ where
11331129
Pat: RustInputPat,
11341130
{
11351131
let ident = Src::ident(&cx[name]);
1136-
let (one, all) = match rust_adt {
1132+
let (consts, one, all) = match rust_adt {
11371133
RustAdt::Enum(variants) => {
11381134
let variants_fields_len = variants.values().map(|(_, variant)| match variant {
11391135
RustVariant::Newtype(_) => 0,
@@ -1156,6 +1152,10 @@ where
11561152
.iter()
11571153
.map(|kind| kind.to_src())
11581154
.collect::<Vec<_>>();
1155+
let variants_shape_ident = variants
1156+
.keys()
1157+
.map(|&v_name| Src::ident(format!("{}_SHAPE", &cx[v_name])))
1158+
.collect::<Vec<_>>();
11591159
let variants_shape = variants
11601160
.values()
11611161
.map(|(v_rule, variant)| match variant {
@@ -1167,16 +1167,22 @@ where
11671167
.collect::<Vec<_>>();
11681168

11691169
(
1170+
quote!(#(
1171+
#[allow(non_upper_case_globals)]
1172+
const #variants_shape_ident: traverse::ty!(#variants_shape) = traverse::new!(#variants_shape);
1173+
)*),
11701174
quote!(
1171-
let node = forest.one_choice(node)?;
1172-
match node.kind {
1175+
forest.one_choice(node).and_then(|node| match node.kind {
11731176
#(#variants_kind_src => {
11741177
let mut r = [None; #variants_fields_len];
1175-
traverse!(one(forest, node, r) #variants_shape);
1176-
#ident::#variants_from_forest_ident(self.forest, node, r)
1178+
#ident::<I>::#variants_shape_ident
1179+
.one(forest, node, &mut r)
1180+
.map(|()| {
1181+
#ident::#variants_from_forest_ident(self.forest, node, r)
1182+
})
11771183
})*
11781184
_ => unreachable!()
1179-
}
1185+
})
11801186
),
11811187
quote!(
11821188
#[derive(Clone)]
@@ -1195,13 +1201,14 @@ where
11951201

11961202
forest.all_choices(node).flat_map(move |node| {
11971203
match node.kind {
1198-
#(#variants_kind_src => Iter::#i_ident(
1199-
traverse!(all(forest, node) #variants_shape)
1204+
#(#variants_kind_src => Iter::#i_ident({
1205+
#ident::<I>::#variants_shape_ident
1206+
.all(forest, node)
12001207
.into_iter()
12011208
.map(move |r| {
12021209
#ident::#variants_from_forest_ident(self.forest, node, r)
12031210
})
1204-
),)*
1211+
}),)*
12051212
_ => unreachable!(),
12061213
}
12071214
})
@@ -1212,13 +1219,19 @@ where
12121219
let fields_len = fields.len();
12131220
let shape = rule.generate_traverse_shape(cx, rules, fields);
12141221
(
1222+
quote!(
1223+
#[allow(non_upper_case_globals)]
1224+
const SHAPE: traverse::ty!(#shape) = traverse::new!(#shape);
1225+
),
12151226
quote!(
12161227
let mut r = [None; #fields_len];
1217-
traverse!(one(forest, node, r) #shape);
1218-
#ident::from_forest(self.forest, node, r)
1228+
#ident::<I>::SHAPE
1229+
.one(forest, node, &mut r)
1230+
.map(|()| #ident::from_forest(self.forest, node, r))
12191231
),
12201232
quote!(
1221-
traverse!(all(forest, node) #shape)
1233+
#ident::<I>::SHAPE
1234+
.all(forest, node)
12221235
.into_iter()
12231236
.map(move |r| {
12241237
#ident::from_forest(self.forest, node, r)
@@ -1228,24 +1241,29 @@ where
12281241
}
12291242
};
12301243

1231-
quote!(impl<'a, 'i, I> Handle<'a, 'i, I, #ident<'a, 'i, I>>
1244+
quote!(
1245+
impl<'a, 'i, I: gll::grammer::input::Input> #ident<'a, 'i, I> {
1246+
#consts
1247+
}
1248+
1249+
impl<'a, 'i, I> Handle<'a, 'i, I, #ident<'a, 'i, I>>
12321250
where I: gll::grammer::input::Input,
12331251
{
1252+
#consts
1253+
12341254
pub fn one(self) -> Result<#ident<'a, 'i, I>, Ambiguity<Self>> {
1235-
// HACK(eddyb) using a closure to catch `Err`s from `?`
1236-
(|| Ok({
1237-
let forest = self.forest;
1238-
let node = forest.unpack_alias(self.node);
1239-
#one
1240-
}))().map_err(|gll::grammer::forest::MoreThanOne| Ambiguity(self))
1255+
let forest = self.forest;
1256+
let node = forest.unpack_alias(self.node);
1257+
#one.map_err(|gll::grammer::forest::MoreThanOne| Ambiguity(self))
12411258
}
12421259

12431260
pub fn all(self) -> impl Iterator<Item = #ident<'a, 'i, I>> {
12441261
let forest = self.forest;
12451262
let node = forest.unpack_alias(self.node);
12461263
#all
12471264
}
1248-
})
1265+
}
1266+
)
12491267
}
12501268

12511269
fn rule_debug_impls<Pat>(cx: &Context<Pat>, name: IStr, rust_adt: &RustAdt) -> Src {

src/generate/templates/imports.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use gll::grammer::forest::{GrammarReflector as _, Node, NodeShape};
2-
use gll::runtime::{cursor::Cursor as _, traverse};
2+
use gll::runtime::{
3+
cursor::Cursor as _,
4+
traverse::{self, Shape as _},
5+
};
36
use std::any;
47
use std::fmt;
58
use std::marker::PhantomData;

0 commit comments

Comments
 (0)