Skip to content

Commit

Permalink
Rename and reorganize runtime types.
Browse files Browse the repository at this point in the history
  • Loading branch information
anyska authored and eddyb committed Sep 18, 2018
1 parent ce1ceab commit 45e645e
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 74 deletions.
16 changes: 9 additions & 7 deletions src/generate/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,8 +482,9 @@ impl<'a, 'i, 's> ", name, "<'a, 'i, 's> {
callee: ", CodeLabel(name.clone()), ",
range,
};
if !p.gss.calls.contains_key(&call) {
p.gss.threads.spawn(
let mut result = p.memoizer.longest_result(call);
if result.is_none() {
p.threads.spawn(
Continuation {
code: call.callee,
frame: call,
Expand All @@ -492,8 +493,9 @@ impl<'a, 'i, 's> ", name, "<'a, 'i, 's> {
call.range,
);
parse(p);
result = p.memoizer.longest_result(call);
}
if let Some(range) = p.gss.longest_result(call) {
if let Some(range) = result {
return Ok(Handle {
node: ParseNode { kind: ", ParseNodeKind(name.clone()), ", range },
parser: p,
Expand Down Expand Up @@ -760,7 +762,7 @@ impl<'a, 'i, 's> Handle<'a, 'i, 's, ", name, "<'a, 'i, 's>> {
}
put!("
fn parse(p: &mut Parser) {
while let Some(Call { callee: mut c, range: _range }) = p.gss.threads.steal() {
while let Some(Call { callee: mut c, range: _range }) = p.threads.steal() {
match c.code {");
for (name, rule) in &self.rules {
let parse_nodes = if rule.fields.is_empty() {
Expand Down Expand Up @@ -975,7 +977,7 @@ impl<'a> Continuation<'a> {
self.code = Code::Inline(format!(
"
c.code = {};
p.gss.threads.spawn(c, _range);",
p.threads.spawn(c, _range);",
label
));
self.to_inline()
Expand Down Expand Up @@ -1095,7 +1097,7 @@ fn call(callee: CodeLabel) -> Thunk<impl FnOnce(Continuation) -> Continuation> {
cont.code = Code::Inline(format!(
"
c.code = {};
p.gss.call(Call {{ callee: {}, range: _range }}, c);",
p.call(Call {{ callee: {}, range: _range }}, c);",
cont.to_label(),
callee
));
Expand All @@ -1106,7 +1108,7 @@ fn call(callee: CodeLabel) -> Thunk<impl FnOnce(Continuation) -> Continuation> {
fn ret() -> Thunk<impl FnOnce(Continuation) -> Continuation> {
thunk!(
"
p.gss.ret(c.frame, _range);"
p.ret(c.frame, _range);"
) + Thunk::new(|mut cont| {
assert_eq!(cont.to_inline(), "");
cont
Expand Down
140 changes: 73 additions & 67 deletions src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,10 @@ impl InputMatch<RangeInclusive<char>> for str {

pub struct Parser<'i, P: ParseNodeKind, C: CodeLabel, I> {
input: Container<'i, I>,
pub gss: CallGraph<'i, C>,
pub sppf: ParseGraph<'i, P>,
pub threads: Threads<'i, C>,
pub gss: GraphStack<'i, C>,
pub memoizer: Memoizer<'i, C>,
pub sppf: ParseForest<'i, P>,
}

impl<'i, P: ParseNodeKind, C: CodeLabel, I: Trustworthy> Parser<'i, P, C, I> {
Expand All @@ -173,14 +175,17 @@ impl<'i, P: ParseNodeKind, C: CodeLabel, I: Trustworthy> Parser<'i, P, C, I> {
f(
Parser {
input,
gss: CallGraph {
threads: Threads {
queue: BinaryHeap::new(),
seen: BTreeSet::new(),
},
calls: HashMap::new(),
threads: Threads {
queue: BinaryHeap::new(),
seen: BTreeSet::new(),
},
gss: GraphStack {
returns: HashMap::new(),
},
memoizer: Memoizer {
lengths: HashMap::new(),
},
sppf: ParseGraph {
sppf: ParseForest {
children: HashMap::new(),
},
},
Expand Down Expand Up @@ -212,6 +217,42 @@ impl<'i, P: ParseNodeKind, C: CodeLabel, I: Trustworthy> Parser<'i, P, C, I> {
.match_right(pat)
.map(|n| Range(range.split_at(range.len() - n).0))
}
pub fn call(&mut self, call: Call<'i, C>, next: Continuation<'i, C>) {
let returns = self.gss.returns.entry(call).or_default();
if returns.insert(next) {
if returns.len() > 1 {
if let Some(lengths) = self.memoizer.lengths.get(&call) {
for &len in lengths {
self.threads.spawn(next, Range(call.range.split_at(len).1));
}
}
} else {
self.threads.spawn(
Continuation {
code: call.callee,
frame: call,
state: 0,
},
call.range,
);
}
}
}
pub fn ret(&mut self, call: Call<'i, C>, remaining: Range<'i>) {
if self
.memoizer
.lengths
.entry(call)
.or_default()
.insert(call.range.subtract_suffix(remaining).len())
{
if let Some(returns) = self.gss.returns.get(&call) {
for &next in returns {
self.threads.spawn(next, remaining);
}
}
}
}
}

impl<'a, 'i, P: ParseNodeKind, C: CodeLabel> Parser<'i, P, C, &'a Str> {
Expand Down Expand Up @@ -297,31 +338,16 @@ impl<'i, C: Ord> Ord for Call<'i, C> {
}
}

pub struct CallNode<'i, C: CodeLabel> {
returns: BTreeSet<Continuation<'i, C>>,
lengths: BTreeSet<usize>,
}

impl<'i, C: CodeLabel> CallNode<'i, C> {
pub fn new() -> Self {
CallNode {
returns: BTreeSet::new(),
lengths: BTreeSet::new(),
}
}
}

pub struct CallGraph<'i, C: CodeLabel> {
pub threads: Threads<'i, C>,
pub calls: HashMap<Call<'i, C>, CallNode<'i, C>>,
pub struct GraphStack<'i, C: CodeLabel> {
returns: HashMap<Call<'i, C>, BTreeSet<Continuation<'i, C>>>,
}

impl<'i, C: CodeLabel> CallGraph<'i, C> {
impl<'i, C: CodeLabel> GraphStack<'i, C> {
pub fn print(&self, out: &mut Write) -> io::Result<()> {
writeln!(out, "digraph gss {{")?;
writeln!(out, " graph [rankdir=RL]")?;
for (call, node) in &self.calls {
for next in &node.returns {
for (call, returns) in &self.returns {
for next in returns {
writeln!(
out,
r#" "{:?}" -> "{:?}" [label="{:?}"]"#,
Expand All @@ -331,60 +357,40 @@ impl<'i, C: CodeLabel> CallGraph<'i, C> {
}
writeln!(out, "}}")
}
}

pub struct Memoizer<'i, C: CodeLabel> {
lengths: HashMap<Call<'i, C>, BTreeSet<usize>>,
}

impl<'i, C: CodeLabel> Memoizer<'i, C> {
pub fn results<'a>(
&'a self,
call: Call<'i, C>,
) -> impl DoubleEndedIterator<Item = Range<'i>> + 'a {
self.calls.get(&call).into_iter().flat_map(move |node| {
node.lengths
.iter()
.map(move |&len| Range(call.range.split_at(len).0))
})
self.lengths
.get(&call)
.into_iter()
.flat_map(move |lengths| {
lengths
.iter()
.map(move |&len| Range(call.range.split_at(len).0))
})
}
pub fn longest_result(&self, call: Call<'i, C>) -> Option<Range<'i>> {
self.results(call).rev().next()
}
pub fn call(&mut self, call: Call<'i, C>, next: Continuation<'i, C>) {
let node = self.calls.entry(call).or_insert(CallNode::new());
if node.returns.insert(next) {
if node.returns.len() > 1 {
for &len in &node.lengths {
self.threads.spawn(next, Range(call.range.split_at(len).1));
}
} else {
self.threads.spawn(
Continuation {
code: call.callee,
frame: call,
state: 0,
},
call.range,
);
}
}
}
pub fn ret(&mut self, call: Call<'i, C>, remaining: Range<'i>) {
let node = self.calls.entry(call).or_insert(CallNode::new());
if node
.lengths
.insert(call.range.subtract_suffix(remaining).len())
{
for &next in &node.returns {
self.threads.spawn(next, remaining);
}
}
}
}

pub struct ParseGraph<'i, P: ParseNodeKind> {
pub struct ParseForest<'i, P: ParseNodeKind> {
pub children: HashMap<ParseNode<'i, P>, BTreeSet<usize>>,
}

impl<'i, P: ParseNodeKind> ParseGraph<'i, P> {
impl<'i, P: ParseNodeKind> ParseForest<'i, P> {
pub fn add(&mut self, kind: P, range: Range<'i>, child: usize) {
self.children
.entry(ParseNode { kind, range })
.or_insert(BTreeSet::new())
.or_default()
.insert(child);
}

Expand Down

0 comments on commit 45e645e

Please sign in to comment.