Skip to content

Commit 361b418

Browse files
committed
Go back to external iteration (for all) without generators.
1 parent 575699b commit 361b418

File tree

2 files changed

+279
-119
lines changed

2 files changed

+279
-119
lines changed

src/generate/rust.rs

Lines changed: 38 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,6 @@ impl fmt::Display for CodeLabel {
221221

222222
#[derive(Default)]
223223
pub struct Options {
224-
/// Enable the use of unstable features, such as generators.
225-
pub unstable: bool,
226224
/// Disable generating macros (e.g. `P!(...)` sugar for `_P::...`).
227225
pub no_macros: bool,
228226

@@ -247,34 +245,13 @@ impl<Pat: Ord + Hash + MatchesEmpty + RustInputPat> Grammar<Pat> {
247245
let mut code_labels = OrderMap::new();
248246

249247
put!("
250-
use gll::runtime::{Call, Continuation, ParseNodeKind, CodeLabel, ParseNodeShape, ParseNode, Range, traverse};
248+
use gll::runtime::{Call, Continuation, ParseNodeKind, CodeLabel, ParseNodeShape, ParseNode, Range, traverse, nd::Arrow};
251249
use std::any;
252250
use std::fmt;
253251
use std::marker::PhantomData;");
254-
if options.unstable {
255-
put!("
256-
use std::ops::{GeneratorState, Generator};
257-
");
258-
}
259252
// HACK(eddyb) see `out += out_body` at the end
260253
let out_imports = mem::replace(&mut out, String::new());
261254

262-
if options.unstable {
263-
put!("
264-
struct GenIter<G>(G);
265-
266-
impl<G: Generator<Return = ()>> Iterator for GenIter<G> {
267-
type Item = G::Yield;
268-
269-
fn next(&mut self) -> Option<Self::Item> {
270-
match unsafe { self.0.resume() } {
271-
GeneratorState::Complete(..) => None,
272-
GeneratorState::Yielded(v) => Some(v),
273-
}
274-
}
275-
}
276-
");
277-
}
278255
put!("
279256
#[derive(Debug)]
280257
pub enum ParseError<T> {
@@ -621,13 +598,14 @@ impl<'a, 'i, I: ::gll::runtime::Input> fmt::Debug for Handle<'a, 'i, I, ", name,
621598
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
622599
write!(f, \"{:?} => \", self.source_info())?;
623600
let mut first = true;
624-
self.try_for_each(|x| {
601+
for x in self.all() {
625602
if !first {
626603
write!(f, \" | \")?;
627604
}
628605
first = false;
629-
fmt::Debug::fmt(&x, f)
630-
})
606+
fmt::Debug::fmt(&x, f)?;
607+
}
608+
Ok(())
631609
}
632610
}
633611
@@ -761,76 +739,51 @@ impl<'a, 'i, I: ::gll::runtime::Input> Handle<'a, 'i, I, ", name, "<'a, 'i, I>>
761739
}
762740
put!("
763741
}))().map_err(|::gll::runtime::MoreThanOne| Ambiguity(self))
764-
}");
765-
if options.unstable {
766-
put!("
742+
}
767743
pub fn all(self) -> impl Iterator<Item = ", name, "<'a, 'i, I>> {
768744
let sppf = &self.parser.sppf;
769-
GenIter(move || {
770-
let node = self.node.unpack_alias();");
745+
let node = self.node.unpack_alias();");
771746
if let Some(variants) = &variants {
772747
put!("
773-
for node in sppf.all_choices(node) {
774-
match node.kind {");
775-
for (rule, variant, _) in variants {
748+
#[derive(Clone)]
749+
enum Iter<"); for i in 0..variants.len() { put!("_", i, ","); } put!("> {
750+
"); for i in 0..variants.len() { put!("_", i, "(_", i, "),"); } put!("
751+
}
752+
impl<T, "); for i in 0..variants.len() { put!("_", i, ": Iterator<Item = T>,"); } put!("> Iterator
753+
for Iter<"); for i in 0..variants.len() { put!("_", i, ","); } put!(">
754+
{
755+
type Item = T;
756+
fn next(&mut self) -> Option<T> {
757+
match self {");
758+
for i in 0..variants.len() {
776759
put!("
777-
", rule.parse_node_kind(&parse_nodes), " => {
778-
traverse!(all(sppf, node) ", rule.generate_traverse_shape(false, &parse_nodes), ",
779-
r => yield ", name, "::", variant, "_from_sppf(self.parser, node, r));
780-
}");
760+
Iter::_", i, "(iter) => iter.next(),");
781761
}
782762
put!("
783-
_ => unreachable!(),
784-
}
785-
}");
786-
} else {
787-
put!("
788-
traverse!(all(sppf, node) ", rule.rule.generate_traverse_shape(false, &parse_nodes), ",
789-
r => yield ", name, "::from_sppf(self.parser, node, r));");
790763
}
791-
put!("
792-
})
793-
}");
794764
}
795-
put!("
796-
pub fn for_each(self, mut f: impl FnMut(", name, "<'a, 'i, I>)) {
797-
let sppf = &self.parser.sppf;
798-
let node = self.node.unpack_alias();");
799-
if let Some(variants) = &variants {
800-
put!("
801-
for node in sppf.all_choices(node) {
765+
}
766+
sppf.all_choices(node).flat_map(move |node| {
802767
match node.kind {");
803-
for (rule, variant, _) in variants {
768+
for (i, (rule, variant, _)) in variants.iter().enumerate() {
769+
put!("
770+
", rule.parse_node_kind(&parse_nodes), " => Iter::_", i, "(
771+
traverse!(all(sppf) ", rule.generate_traverse_shape(false, &parse_nodes), ")
772+
.apply(node)
773+
.map(move |r| ", name, "::", variant, "_from_sppf(self.parser, node, r))
774+
),");
775+
}
804776
put!("
805-
", rule.parse_node_kind(&parse_nodes), " => {
806-
traverse!(all(sppf, node) ", rule.generate_traverse_shape(false, &parse_nodes), ",
807-
r => f(", name, "::", variant, "_from_sppf(self.parser, node, r)));
808-
}");
809-
}
810-
put!("
811777
_ => unreachable!(),
812778
}
813-
}");
814-
} else {
779+
})");
780+
} else {
781+
put!("
782+
traverse!(all(sppf) ", rule.rule.generate_traverse_shape(false, &parse_nodes), ")
783+
.apply(node)
784+
.map(move |r| ", name, "::from_sppf(self.parser, node, r))");
785+
}
815786
put!("
816-
traverse!(all(sppf, node) ", rule.rule.generate_traverse_shape(false, &parse_nodes), ",
817-
r => f(", name, "::from_sppf(self.parser, node, r)));");
818-
}
819-
put!("
820-
}
821-
pub fn try_for_each<E>(
822-
self,
823-
mut f: impl FnMut(", name, "<'a, 'i, I>) -> Result<(), E>,
824-
) -> Result<(), E> {
825-
let mut r = Ok(());
826-
self.for_each(|x| {
827-
// FIXME(eddyb) this should stop the iteration early
828-
if r.is_err() {
829-
return;
830-
}
831-
r = f(x);
832-
});
833-
r
834787
}
835788
}");
836789
}
@@ -1523,7 +1476,8 @@ impl<Pat: Ord + Hash + RustInputPat> Rule<Pat> {
15231476
for (i, rule) in rules.iter().enumerate() {
15241477
write!(
15251478
s,
1526-
"{}: {} => {},",
1479+
"{} _{}: {} => {},",
1480+
i,
15271481
i,
15281482
rule.parse_node_kind(parse_nodes),
15291483
rule.generate_traverse_shape(true, parse_nodes)

0 commit comments

Comments
 (0)