Make sure that infallible match operations come after fallible ones
Eventually we will probably want to sort by a partial ordering based on pattern subsumption to break ties between rules with the same priority. This local heuristic of making sure infallibilty comes last is good enough for now and handles the cases we care about thus far. Fixes #10
This commit is contained in:
committed by
Chris Fallin
parent
6c6b7a2b78
commit
037db8aab6
@@ -651,7 +651,7 @@ impl<'a> Codegen<'a> {
|
|||||||
indent: &str,
|
indent: &str,
|
||||||
ctx: &mut BodyContext,
|
ctx: &mut BodyContext,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
log::trace!("generate_body: trie {:?}", trie);
|
log::trace!("generate_body:\n{}", trie.pretty());
|
||||||
let mut returned = false;
|
let mut returned = false;
|
||||||
match trie {
|
match trie {
|
||||||
&TrieNode::Empty => {}
|
&TrieNode::Empty => {}
|
||||||
@@ -692,10 +692,16 @@ impl<'a> Codegen<'a> {
|
|||||||
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < edges.len() {
|
while i < edges.len() {
|
||||||
|
// Gather adjacent match variants so that we can turn these
|
||||||
|
// into a `match` rather than a sequence of `if let`s.
|
||||||
let mut last = i;
|
let mut last = i;
|
||||||
let mut adjacent_variants = BTreeSet::new();
|
let mut adjacent_variants = BTreeSet::new();
|
||||||
let mut adjacent_variant_input = None;
|
let mut adjacent_variant_input = None;
|
||||||
log::trace!("edge: {:?}", edges[i]);
|
log::trace!(
|
||||||
|
"edge: range = {:?}, symbol = {:?}",
|
||||||
|
edges[i].range,
|
||||||
|
edges[i].symbol
|
||||||
|
);
|
||||||
while last < edges.len() {
|
while last < edges.len() {
|
||||||
match &edges[last].symbol {
|
match &edges[last].symbol {
|
||||||
&TrieSymbol::Match {
|
&TrieSymbol::Match {
|
||||||
@@ -719,11 +725,11 @@ impl<'a> Codegen<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// edges[i..last] is a run of adjacent
|
// Now `edges[i..last]` is a run of adjacent `MatchVariants`
|
||||||
// MatchVariants (possibly an empty one). Only use
|
// (possibly an empty one). Only use a `match` form if there
|
||||||
// a `match` form if there are at least two
|
// are at least two adjacent options.
|
||||||
// adjacent options.
|
|
||||||
if last - i > 1 {
|
if last - i > 1 {
|
||||||
|
eprintln!("FITZGEN: generating body matches");
|
||||||
self.generate_body_matches(code, depth, &edges[i..last], indent, ctx);
|
self.generate_body_matches(code, depth, &edges[i..last], indent, ctx);
|
||||||
i = last;
|
i = last;
|
||||||
continue;
|
continue;
|
||||||
@@ -738,8 +744,13 @@ impl<'a> Codegen<'a> {
|
|||||||
match symbol {
|
match symbol {
|
||||||
&TrieSymbol::EndOfMatch => {
|
&TrieSymbol::EndOfMatch => {
|
||||||
returned = self.generate_body(code, depth + 1, node, indent, ctx);
|
returned = self.generate_body(code, depth + 1, node, indent, ctx);
|
||||||
|
eprintln!(
|
||||||
|
"FITZGEN: generated end-of-match; returned = {:?}",
|
||||||
|
returned
|
||||||
|
);
|
||||||
}
|
}
|
||||||
&TrieSymbol::Match { ref op } => {
|
&TrieSymbol::Match { ref op } => {
|
||||||
|
eprintln!("FITZGEN: generating [if] let");
|
||||||
let id = InstId(depth);
|
let id = InstId(depth);
|
||||||
let infallible =
|
let infallible =
|
||||||
self.generate_pattern_inst(code, id, op, indent, ctx);
|
self.generate_pattern_inst(code, id, op, indent, ctx);
|
||||||
|
|||||||
@@ -31,15 +31,6 @@ pub enum Value {
|
|||||||
/// A single Pattern instruction.
|
/// A single Pattern instruction.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub enum PatternInst {
|
pub enum PatternInst {
|
||||||
/// Get the Nth input argument, which corresponds to the Nth field
|
|
||||||
/// of the root term.
|
|
||||||
Arg {
|
|
||||||
/// The index of the argument to get.
|
|
||||||
index: usize,
|
|
||||||
/// The type of the argument.
|
|
||||||
ty: TypeId,
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Match a value as equal to another value. Produces no values.
|
/// Match a value as equal to another value. Produces no values.
|
||||||
MatchEqual {
|
MatchEqual {
|
||||||
/// The first value.
|
/// The first value.
|
||||||
@@ -83,6 +74,21 @@ pub enum PatternInst {
|
|||||||
variant: VariantId,
|
variant: VariantId,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// Evaluate an expression and provide the given value as the result of this
|
||||||
|
/// match instruction. The expression has access to the pattern-values up to
|
||||||
|
/// this point in the sequence.
|
||||||
|
Expr {
|
||||||
|
/// The expression to evaluate.
|
||||||
|
seq: ExprSequence,
|
||||||
|
/// The value produced by the expression.
|
||||||
|
output: Value,
|
||||||
|
/// The type of the output value.
|
||||||
|
output_ty: TypeId,
|
||||||
|
},
|
||||||
|
|
||||||
|
// NB: this has to come second-to-last, because it might be infallible, for
|
||||||
|
// the same reasons that `Arg` has to be last.
|
||||||
|
//
|
||||||
/// Invoke an extractor, taking the given values as input (the first is the
|
/// Invoke an extractor, taking the given values as input (the first is the
|
||||||
/// value to extract, the other are the `Input`-polarity extractor args) and
|
/// value to extract, the other are the `Input`-polarity extractor args) and
|
||||||
/// producing an output value for each `Output`-polarity extractor arg.
|
/// producing an output value for each `Output`-polarity extractor arg.
|
||||||
@@ -99,16 +105,17 @@ pub enum PatternInst {
|
|||||||
infallible: bool,
|
infallible: bool,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Evaluate an expression and provide the given value as the result of this
|
// NB: This has to go last, since it is infallible, so that when we sort
|
||||||
/// match instruction. The expression has access to the pattern-values up to
|
// edges in the trie, we visit infallible edges after first having tried the
|
||||||
/// this point in the sequence.
|
// more-specific fallible options.
|
||||||
Expr {
|
//
|
||||||
/// The expression to evaluate.
|
/// Get the Nth input argument, which corresponds to the Nth field
|
||||||
seq: ExprSequence,
|
/// of the root term.
|
||||||
/// The value produced by the expression.
|
Arg {
|
||||||
output: Value,
|
/// The index of the argument to get.
|
||||||
/// The type of the output value.
|
index: usize,
|
||||||
output_ty: TypeId,
|
/// The type of the argument.
|
||||||
|
ty: TypeId,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user