optimized up to section 5.11
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rusty-wam"
|
||||
version = "0.5.10"
|
||||
version = "0.5.11"
|
||||
authors = ["Mark Thom"]
|
||||
|
||||
build = "build.rs"
|
||||
|
||||
@@ -11,7 +11,7 @@ pure Prolog.
|
||||
Pure Prolog is implemented as a simple REPL. "Pure Prolog" is Prolog
|
||||
without cut, meta- or extra-logical operators, or side effects of any
|
||||
kind. In terms of the tutorial pacing, the work has progressed to the
|
||||
end of section 5.9, skipping past 5.4. Atoms and lists are the only
|
||||
end of section 5.10, skipping past 5.4. Atoms and lists are the only
|
||||
two data types currently supported.
|
||||
|
||||
While proper environment trimming code is emitted by the code
|
||||
|
||||
148
src/main.rs
148
src/main.rs
@@ -239,6 +239,154 @@ mod tests {
|
||||
assert_eq!(submit(&mut wam, "?- member([X, Y, Y], [a, [b, c], [b, b], [Z, x], [d, f]]).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- member([X, Y, Z], [a, [b, c], [b, b], [Z, x], [d, f]]).").failed_query(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_queries_on_indexed_predicates() {
|
||||
let mut wam = Machine::new();
|
||||
|
||||
submit(&mut wam, "p(a) :- a.
|
||||
p(b) :- b, f(X).
|
||||
p(c) :- c, g(X).
|
||||
p(f(a)) :- a.
|
||||
p(g(b, c)) :- b.
|
||||
p(g(b)) :- b.
|
||||
p([a|b]) :- a.
|
||||
p([]).
|
||||
p(X) :- x.
|
||||
p([c, d, e]).");
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- p(a).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p(b).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p(c).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p(f(a)).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(b, X)).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(Y, X)).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(Y, c)).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(b)).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p([]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c, d, e]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c, d | X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c|X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([Y|X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]]).").failed_query(), false);
|
||||
|
||||
submit(&mut wam, "a.");
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- p(a).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(b).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p(c).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p(f(a)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(b, X)).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(Y, X)).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(Y, c)).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(b)).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p([]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c, d, e]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c, d | X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c|X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([Y|X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]]).").failed_query(), false);
|
||||
|
||||
submit(&mut wam, "b.");
|
||||
submit(&mut wam, "f(x).");
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- p(a).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(b).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(c).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- p(f(a)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(b, X)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(Y, X)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(Y, c)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(b)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c, d, e]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c, d | X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c|X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([Y|X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]]).").failed_query(), false);
|
||||
|
||||
submit(&mut wam, "c.");
|
||||
submit(&mut wam, "g(X).");
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- p(a).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(b).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(c).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(f(a)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(b, X)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(Y, X)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(Y, c)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(b)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c, d, e]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c, d | X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c|X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([Y|X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(blah).").failed_query(), true);
|
||||
|
||||
submit(&mut wam, "x.");
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- p(a).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(b).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(c).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(f(a)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(b, X)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(Y, X)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(Y, c)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(g(b)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c, d, e]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c, d | X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([c|X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([Y|X]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p([Y|[d|Xs]]).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- p(blah).").failed_query(), false);
|
||||
|
||||
submit(&mut wam, "call(or(X, Y)) :- call(X).
|
||||
call(trace) :- trace.
|
||||
call(or(X, Y)) :- call(Y).
|
||||
call(notrace) :- notrace.
|
||||
call(nl) :- nl.
|
||||
call(X) :- builtin(X).
|
||||
call(X) :- extern(X).
|
||||
call(call(X)) :- call(X).
|
||||
call(repeat).
|
||||
call(repeat) :- call(repeat).
|
||||
call(true).");
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- call(repeat).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(true).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(call(repeat)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(call(true)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(notrace).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- call(nl).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- call(builtin(X)).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- call(extern(X)).").failed_query(), true);
|
||||
|
||||
submit(&mut wam, "notrace.");
|
||||
submit(&mut wam, "nl.");
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- call(repeat).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(true).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(call(repeat)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(call(true)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(notrace).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(nl).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(builtin(X)).").failed_query(), true);
|
||||
assert_eq!(submit(&mut wam, "?- call(extern(X)).").failed_query(), true);
|
||||
|
||||
submit(&mut wam, "builtin(X).");
|
||||
submit(&mut wam, "extern(x).");
|
||||
|
||||
assert_eq!(submit(&mut wam, "?- call(repeat).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(true).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(call(repeat)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(call(true)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(notrace).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(nl).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(builtin(X)).").failed_query(), false);
|
||||
assert_eq!(submit(&mut wam, "?- call(extern(X)).").failed_query(), false);
|
||||
}
|
||||
}
|
||||
|
||||
fn prolog_repl() {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use std::cell::Cell;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::ops::{Add, AddAssign};
|
||||
use std::vec::Vec;
|
||||
|
||||
@@ -21,6 +20,13 @@ impl PredicateClause {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn first_arg(&self) -> Option<&Term> {
|
||||
match self {
|
||||
&PredicateClause::Fact(ref t) => t.first_arg(),
|
||||
&PredicateClause::Rule(ref rule) => rule.head.0.first_arg()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arity(&self) -> usize {
|
||||
match self {
|
||||
&PredicateClause::Fact(ref t) => t.arity(),
|
||||
@@ -99,7 +105,7 @@ impl Default for VarReg {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
#[derive(Clone, Hash, PartialEq, Eq)]
|
||||
pub enum Constant {
|
||||
Atom(Atom),
|
||||
EmptyList
|
||||
@@ -135,6 +141,54 @@ pub enum TermRef<'a> {
|
||||
Var(Level, &'a Cell<VarReg>, &'a Var)
|
||||
}
|
||||
|
||||
pub enum ChoiceInstruction {
|
||||
RetryMeElse(usize),
|
||||
TrustMe,
|
||||
TryMeElse(usize)
|
||||
}
|
||||
|
||||
pub enum IndexedChoiceInstruction {
|
||||
Retry(usize),
|
||||
Trust(usize),
|
||||
Try(usize)
|
||||
}
|
||||
|
||||
impl From<IndexedChoiceInstruction> for Line {
|
||||
fn from(i: IndexedChoiceInstruction) -> Self {
|
||||
Line::IndexedChoice(i)
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexedChoiceInstruction {
|
||||
pub fn offset(&self) -> usize {
|
||||
match self {
|
||||
&IndexedChoiceInstruction::Retry(offset) => offset,
|
||||
&IndexedChoiceInstruction::Trust(offset) => offset,
|
||||
&IndexedChoiceInstruction::Try(offset) => offset
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ControlInstruction {
|
||||
Allocate(usize),
|
||||
Call(Atom, usize, usize),
|
||||
Deallocate,
|
||||
Execute(Atom, usize),
|
||||
Proceed
|
||||
}
|
||||
|
||||
pub enum IndexingInstruction {
|
||||
SwitchOnTerm(usize, usize, usize, usize),
|
||||
SwitchOnConstant(usize, HashMap<Constant, usize>),
|
||||
SwitchOnStructure(usize, HashMap<(Atom, usize), usize>)
|
||||
}
|
||||
|
||||
impl From<IndexingInstruction> for Line {
|
||||
fn from(i: IndexingInstruction) -> Self {
|
||||
Line::Indexing(i)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum FactInstruction {
|
||||
GetConstant(Level, Constant, RegType),
|
||||
GetList(Level, RegType),
|
||||
@@ -162,20 +216,6 @@ pub enum QueryInstruction {
|
||||
SetVoid(usize)
|
||||
}
|
||||
|
||||
pub enum ChoiceInstruction {
|
||||
RetryMeElse(usize),
|
||||
TrustMe,
|
||||
TryMeElse(usize)
|
||||
}
|
||||
|
||||
pub enum ControlInstruction {
|
||||
Allocate(usize),
|
||||
Call(Atom, usize, usize),
|
||||
Deallocate,
|
||||
Execute(Atom, usize),
|
||||
Proceed
|
||||
}
|
||||
|
||||
pub type CompiledFact = Vec<FactInstruction>;
|
||||
|
||||
pub type CompiledQuery = Vec<QueryInstruction>;
|
||||
@@ -184,6 +224,8 @@ pub enum Line {
|
||||
Choice(ChoiceInstruction),
|
||||
Control(ControlInstruction),
|
||||
Fact(CompiledFact),
|
||||
Indexing(IndexingInstruction),
|
||||
IndexedChoice(IndexedChoiceInstruction),
|
||||
Query(CompiledQuery)
|
||||
}
|
||||
|
||||
@@ -198,8 +240,11 @@ impl<'a> From<&'a Line> for LineOrCodeOffset<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub type ThirdLevelIndex = Vec<IndexedChoiceInstruction>;
|
||||
|
||||
pub type Code = Vec<Line>;
|
||||
|
||||
pub type CodeDeque = VecDeque<Line>;
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum Addr {
|
||||
@@ -287,26 +332,6 @@ impl HeapCellValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Ref {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
match (*self, *other) {
|
||||
(Ref::HeapCell(hc1), Ref::HeapCell(hc2)) =>
|
||||
Some(hc1.cmp(&hc2)),
|
||||
(Ref::HeapCell(_), _) =>
|
||||
Some(Ordering::Less),
|
||||
(Ref::StackCell(fr1, sc1), Ref::StackCell(fr2, sc2)) =>
|
||||
if fr1 < fr2 {
|
||||
Some(Ordering::Less)
|
||||
} else if fr1 == fr2 {
|
||||
Some(sc1.cmp(&sc2))
|
||||
} else {
|
||||
Some(Ordering::Greater)
|
||||
},
|
||||
_ => Some(Ordering::Greater)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum CodePtr {
|
||||
DirEntry(usize),
|
||||
@@ -344,6 +369,14 @@ pub type Heap = Vec<HeapCellValue>;
|
||||
pub type Registers = Vec<Addr>;
|
||||
|
||||
impl Term {
|
||||
pub fn first_arg(&self) -> Option<&Term> {
|
||||
match self {
|
||||
&Term::Clause(_, _, ref terms) =>
|
||||
terms.first().map(|bt| bt.as_ref()),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_clause(&self) -> bool {
|
||||
if let &Term::Clause(_, _, _) = self {
|
||||
true
|
||||
|
||||
@@ -3,7 +3,8 @@ use prolog::iterators::{FactIterator, QueryIterator};
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::cmp::max;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::hash::Hash;
|
||||
use std::vec::Vec;
|
||||
|
||||
trait CompilationTarget<'a> {
|
||||
@@ -244,6 +245,239 @@ impl<'a> TermMarker<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum IntIndex {
|
||||
External(usize), Fail, Internal(usize)
|
||||
}
|
||||
|
||||
impl Into<usize> for IntIndex {
|
||||
fn into(self) -> usize {
|
||||
match self {
|
||||
IntIndex::Internal(i) => i,
|
||||
_ => 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CodeOffsets {
|
||||
constants: HashMap<Constant, ThirdLevelIndex>,
|
||||
lists: ThirdLevelIndex,
|
||||
structures: HashMap<(Atom, usize), ThirdLevelIndex>
|
||||
}
|
||||
|
||||
impl CodeOffsets {
|
||||
fn new() -> Self {
|
||||
CodeOffsets {
|
||||
constants: HashMap::new(),
|
||||
lists: Vec::new(),
|
||||
structures: HashMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn cap_choice_seq_with_trust(prelude: &mut ThirdLevelIndex) {
|
||||
prelude.last_mut().map(|instr| {
|
||||
match instr {
|
||||
&mut IndexedChoiceInstruction::Retry(i) =>
|
||||
*instr = IndexedChoiceInstruction::Trust(i),
|
||||
_ => {}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
fn add_index(is_first_index: bool, index: usize) -> IndexedChoiceInstruction {
|
||||
if is_first_index {
|
||||
IndexedChoiceInstruction::Try(index)
|
||||
} else {
|
||||
IndexedChoiceInstruction::Retry(index)
|
||||
}
|
||||
}
|
||||
|
||||
fn index_term(&mut self, first_arg: &Term, index: usize) {
|
||||
match first_arg {
|
||||
&Term::Clause(_, ref name, ref terms) => {
|
||||
let code = self.structures.entry((name.clone(), terms.len()))
|
||||
.or_insert(Vec::new());
|
||||
|
||||
let is_initial_index = code.is_empty();
|
||||
code.push(Self::add_index(is_initial_index, index));
|
||||
},
|
||||
&Term::Cons(_, _, _) => {
|
||||
let is_initial_index = self.lists.is_empty();
|
||||
self.lists.push(Self::add_index(is_initial_index, index));
|
||||
},
|
||||
&Term::Constant(_, ref constant) => {
|
||||
let code = self.constants.entry(constant.clone())
|
||||
.or_insert(Vec::new());
|
||||
|
||||
let is_initial_index = code.is_empty();
|
||||
code.push(Self::add_index(is_initial_index, index));
|
||||
},
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
fn second_level_index<Index>(indices: HashMap<Index, ThirdLevelIndex>,
|
||||
prelude: &mut CodeDeque)
|
||||
-> HashMap<Index, IntIndex>
|
||||
where Index: Eq + Hash
|
||||
{
|
||||
let mut index_locs = HashMap::new();
|
||||
|
||||
for (key, mut code) in indices.into_iter() {
|
||||
if code.len() > 1 {
|
||||
index_locs.insert(key, IntIndex::Internal(prelude.len()));
|
||||
Self::cap_choice_seq_with_trust(&mut code);
|
||||
prelude.extend(code.into_iter().map(|code| Line::from(code)));
|
||||
} else {
|
||||
code.first().map(|i| {
|
||||
index_locs.insert(key, IntIndex::External(i.offset()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
index_locs
|
||||
}
|
||||
|
||||
fn no_indices(&self) -> bool {
|
||||
let no_constants = self.constants.is_empty();
|
||||
let no_structures = self.structures.is_empty();
|
||||
let no_lists = self.lists.is_empty();
|
||||
|
||||
no_constants && no_structures && no_lists
|
||||
}
|
||||
|
||||
fn flatten_index<Index>(index: HashMap<Index, IntIndex>, len: usize)
|
||||
-> HashMap<Index, usize>
|
||||
where Index: Eq + Hash
|
||||
{
|
||||
let mut flattened_index = HashMap::new();
|
||||
|
||||
for (key, int_index) in index.into_iter() {
|
||||
match int_index {
|
||||
IntIndex::External(offset) => {
|
||||
flattened_index.insert(key, offset + len + 1);
|
||||
},
|
||||
IntIndex::Internal(offset) => {
|
||||
flattened_index.insert(key, offset + 1);
|
||||
},
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
flattened_index
|
||||
}
|
||||
|
||||
fn switch_on_constant(con_ind: HashMap<Constant, ThirdLevelIndex>,
|
||||
prelude: &mut CodeDeque)
|
||||
-> IntIndex
|
||||
{
|
||||
let con_ind = Self::second_level_index(con_ind, prelude);
|
||||
|
||||
if con_ind.len() > 1 {
|
||||
let index = Self::flatten_index(con_ind, prelude.len());
|
||||
let instr = IndexingInstruction::SwitchOnConstant(index.len(), index);
|
||||
|
||||
prelude.push_front(Line::from(instr));
|
||||
|
||||
IntIndex::Internal(1)
|
||||
} else {
|
||||
con_ind.values().next()
|
||||
.map(|i| *i)
|
||||
.unwrap_or(IntIndex::Fail)
|
||||
}
|
||||
}
|
||||
|
||||
fn switch_on_list(mut lists: ThirdLevelIndex, prelude: &mut CodeDeque) -> IntIndex
|
||||
{
|
||||
if lists.len() > 1 {
|
||||
Self::cap_choice_seq_with_trust(&mut lists);
|
||||
prelude.extend(lists.into_iter().map(|i| Line::from(i)));
|
||||
IntIndex::Internal(0)
|
||||
} else {
|
||||
lists.first()
|
||||
.map(|i| IntIndex::External(i.offset()))
|
||||
.unwrap_or(IntIndex::Fail)
|
||||
}
|
||||
}
|
||||
|
||||
fn switch_on_structure(str_ind: HashMap<(Atom, usize), ThirdLevelIndex>,
|
||||
prelude: &mut CodeDeque)
|
||||
-> IntIndex
|
||||
{
|
||||
let str_ind = Self::second_level_index(str_ind, prelude);
|
||||
|
||||
if str_ind.len() > 1 {
|
||||
let index = Self::flatten_index(str_ind, prelude.len());
|
||||
let instr = IndexingInstruction::SwitchOnStructure(index.len(), index);
|
||||
|
||||
prelude.push_front(Line::from(instr));
|
||||
|
||||
IntIndex::Internal(1)
|
||||
} else {
|
||||
str_ind.values().next()
|
||||
.map(|i| *i)
|
||||
.unwrap_or(IntIndex::Fail)
|
||||
}
|
||||
}
|
||||
|
||||
fn add_indices(self, code: &mut Code, mut code_body: Code)
|
||||
{
|
||||
if self.no_indices() {
|
||||
*code = code_body;
|
||||
return;
|
||||
}
|
||||
|
||||
let mut prelude = VecDeque::new();
|
||||
|
||||
let lst_step = Self::switch_on_list(self.lists, &mut prelude);
|
||||
let lst_offset = prelude.len();
|
||||
|
||||
let str_step = Self::switch_on_structure(self.structures, &mut prelude);
|
||||
let con_step = Self::switch_on_constant(self.constants, &mut prelude);
|
||||
|
||||
let prelude_length = prelude.len();
|
||||
|
||||
for (index, line) in prelude.iter_mut().enumerate() {
|
||||
match line {
|
||||
&mut Line::IndexedChoice(IndexedChoiceInstruction::Try(ref mut i))
|
||||
| &mut Line::IndexedChoice(IndexedChoiceInstruction::Retry(ref mut i))
|
||||
| &mut Line::IndexedChoice(IndexedChoiceInstruction::Trust(ref mut i)) =>
|
||||
*i += prelude_length - index,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let str_step = match str_step {
|
||||
IntIndex::External(o) => o + prelude.len() + 1,
|
||||
IntIndex::Fail => 0,
|
||||
IntIndex::Internal(_) => match con_step {
|
||||
IntIndex::Internal(_) => 2,
|
||||
_ => 1
|
||||
}
|
||||
};
|
||||
let con_step = match con_step {
|
||||
IntIndex::External(offset) => offset + prelude.len() + 1,
|
||||
IntIndex::Fail => 0,
|
||||
IntIndex::Internal(offset) => offset,
|
||||
};
|
||||
let lst_step = match lst_step {
|
||||
IntIndex::External(o) => o + prelude.len() + 1,
|
||||
IntIndex::Fail => 0,
|
||||
IntIndex::Internal(_) => prelude.len() - lst_offset + 1
|
||||
};
|
||||
|
||||
let switch_instr = IndexingInstruction::SwitchOnTerm(prelude.len() + 1,
|
||||
con_step,
|
||||
lst_step,
|
||||
str_step);
|
||||
|
||||
prelude.push_front(Line::from(switch_instr));
|
||||
|
||||
*code = Vec::from(prelude);
|
||||
code.append(&mut code_body);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum VarStatus {
|
||||
New, Old, Permanent(usize)
|
||||
@@ -643,7 +877,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
Self::add_conditional_call(&mut body, p1, perm_vars);
|
||||
|
||||
body = clauses.iter().enumerate()
|
||||
.map(|(i, ref term)| {
|
||||
.map(|(i, term)| {
|
||||
let num_vars = Self::vars_above_threshold(&vs, i+1);
|
||||
self.compile_internal_query(term, num_vars)
|
||||
})
|
||||
@@ -751,9 +985,35 @@ impl<'a> CodeGenerator<'a> {
|
||||
code
|
||||
}
|
||||
|
||||
pub fn compile_predicate(&mut self, clauses: &'a Vec<PredicateClause>) -> Code
|
||||
fn split_predicate(clauses: &Vec<PredicateClause>) -> Vec<(usize, usize)>
|
||||
{
|
||||
let mut code = Vec::new();
|
||||
let mut subseqs = Vec::new();
|
||||
let mut left_index = 0;
|
||||
|
||||
for (right_index, clause) in clauses.iter().enumerate() {
|
||||
if let Some(&Term::Var(_, _)) = clause.first_arg() {
|
||||
if left_index < right_index {
|
||||
subseqs.push((left_index, right_index));
|
||||
}
|
||||
|
||||
subseqs.push((right_index, right_index + 1));
|
||||
left_index = right_index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if left_index < clauses.len() {
|
||||
subseqs.push((left_index, clauses.len()));
|
||||
}
|
||||
|
||||
subseqs
|
||||
}
|
||||
|
||||
fn compile_pred_subseq(&mut self, clauses: &'a [PredicateClause]) -> Code
|
||||
{
|
||||
let mut code_body = Vec::new();
|
||||
let mut code_offsets = CodeOffsets::new();
|
||||
|
||||
let multi_clause = clauses.len() > 1;
|
||||
|
||||
for (i, clause) in clauses.iter().enumerate() {
|
||||
self.marker.reset();
|
||||
@@ -765,14 +1025,50 @@ impl<'a> CodeGenerator<'a> {
|
||||
self.compile_rule(rule)
|
||||
};
|
||||
|
||||
if multi_clause {
|
||||
let choice = match i {
|
||||
0 => ChoiceInstruction::TryMeElse(clause_code.len() + 1),
|
||||
_ if i == clauses.len() - 1 => ChoiceInstruction::TrustMe,
|
||||
_ => ChoiceInstruction::RetryMeElse(clause_code.len() + 1)
|
||||
};
|
||||
|
||||
code_body.push(Line::Choice(choice));
|
||||
}
|
||||
|
||||
clause.first_arg().map(|arg| {
|
||||
let index = code_body.len();
|
||||
code_offsets.index_term(arg, index);
|
||||
});
|
||||
|
||||
code_body.append(&mut clause_code);
|
||||
}
|
||||
|
||||
let mut code = Vec::new();
|
||||
|
||||
code_offsets.add_indices(&mut code, code_body);
|
||||
code
|
||||
}
|
||||
|
||||
pub fn compile_predicate(&mut self, clauses: &'a Vec<PredicateClause>) -> Code
|
||||
{
|
||||
let mut code = Vec::new();
|
||||
let split_pred = Self::split_predicate(clauses);
|
||||
let multi_seq = split_pred.len() > 1;
|
||||
|
||||
for &(l, r) in split_pred.iter() {
|
||||
let mut code_segment = self.compile_pred_subseq(&clauses[l .. r]);
|
||||
|
||||
if multi_seq {
|
||||
let choice = match l {
|
||||
0 => ChoiceInstruction::TryMeElse(code_segment.len() + 1),
|
||||
_ if r == clauses.len() => ChoiceInstruction::TrustMe,
|
||||
_ => ChoiceInstruction::RetryMeElse(code_segment.len() + 1)
|
||||
};
|
||||
|
||||
code.push(Line::Choice(choice));
|
||||
code.append(&mut clause_code);
|
||||
}
|
||||
|
||||
code.append(&mut code_segment);
|
||||
}
|
||||
|
||||
code
|
||||
|
||||
@@ -106,6 +106,19 @@ impl fmt::Display for ControlInstruction {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for IndexedChoiceInstruction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&IndexedChoiceInstruction::Try(offset) =>
|
||||
write!(f, "try {}", offset),
|
||||
&IndexedChoiceInstruction::Retry(offset) =>
|
||||
write!(f, "retry {}", offset),
|
||||
&IndexedChoiceInstruction::Trust(offset) =>
|
||||
write!(f, "trust {}", offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ChoiceInstruction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
@@ -119,6 +132,19 @@ impl fmt::Display for ChoiceInstruction {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for IndexingInstruction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
&IndexingInstruction::SwitchOnTerm(v, c, l, s) =>
|
||||
write!(f, "switch_on_term {}, {}, {}, {}", v, c, l, s),
|
||||
&IndexingInstruction::SwitchOnConstant(num_cs, _) =>
|
||||
write!(f, "switch_on_constant {}", num_cs),
|
||||
&IndexingInstruction::SwitchOnStructure(num_ss, _) =>
|
||||
write!(f, "switch_on_structure {}", num_ss)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Level {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
@@ -176,6 +202,10 @@ pub fn print_code(code: &Code) {
|
||||
println!("{}", choice),
|
||||
&Line::Control(ref control) =>
|
||||
println!("{}", control),
|
||||
&Line::IndexedChoice(ref choice) =>
|
||||
println!("{}", choice),
|
||||
&Line::Indexing(ref indexing) =>
|
||||
println!("{}", indexing),
|
||||
&Line::Query(ref query) =>
|
||||
for query_instr in query {
|
||||
println!("{}", query_instr);
|
||||
|
||||
@@ -106,8 +106,8 @@ impl<'a> Iterator for QueryIterator<'a> {
|
||||
},
|
||||
IteratorState::InitialCons(lvl, cell, head, tail) => {
|
||||
self.push_final_cons(lvl, cell, head, tail);
|
||||
self.push_subterm(Level::Deep, head);
|
||||
self.push_subterm(Level::Deep, tail);
|
||||
self.push_subterm(Level::Deep, head);
|
||||
},
|
||||
IteratorState::FinalCons(lvl, cell, head, tail) =>
|
||||
return Some(TermRef::Cons(lvl, cell, head, tail)),
|
||||
|
||||
@@ -110,7 +110,7 @@ impl Machine {
|
||||
self.code_dir.insert((name, arity), p);
|
||||
}
|
||||
|
||||
fn execute_instr<'a>(&mut self, instr_src: LineOrCodeOffset<'a>) -> bool
|
||||
fn execute_instr<'b>(&mut self, instr_src: LineOrCodeOffset<'b>) -> bool
|
||||
{
|
||||
let mut instr = match instr_src {
|
||||
LineOrCodeOffset::Instruction(instr) => instr,
|
||||
@@ -121,6 +121,8 @@ impl Machine {
|
||||
match instr {
|
||||
&Line::Choice(ref choice_instr) =>
|
||||
self.ms.execute_choice_instr(choice_instr),
|
||||
&Line::Control(ref control_instr) =>
|
||||
self.ms.execute_ctrl_instr(&self.code_dir, control_instr),
|
||||
&Line::Fact(ref fact) => {
|
||||
for fact_instr in fact {
|
||||
if self.failed() {
|
||||
@@ -131,6 +133,10 @@ impl Machine {
|
||||
}
|
||||
self.ms.p += 1;
|
||||
},
|
||||
&Line::Indexing(ref indexing_instr) =>
|
||||
self.ms.execute_indexing_instr(&indexing_instr),
|
||||
&Line::IndexedChoice(ref choice_instr) =>
|
||||
self.ms.execute_indexed_choice_instr(choice_instr),
|
||||
&Line::Query(ref query) => {
|
||||
for query_instr in query {
|
||||
if self.failed() {
|
||||
@@ -140,9 +146,7 @@ impl Machine {
|
||||
self.ms.execute_query_instr(&query_instr);
|
||||
}
|
||||
self.ms.p += 1;
|
||||
},
|
||||
&Line::Control(ref control_instr) =>
|
||||
self.ms.execute_ctrl_instr(&self.code_dir, control_instr),
|
||||
}
|
||||
}
|
||||
|
||||
if self.failed() {
|
||||
@@ -556,6 +560,8 @@ impl MachineState {
|
||||
self.h += 1;
|
||||
}
|
||||
};
|
||||
|
||||
self.s += 1;
|
||||
},
|
||||
&FactInstruction::UnifyVariable(reg) => {
|
||||
match self.mode {
|
||||
@@ -640,6 +646,69 @@ impl MachineState {
|
||||
};
|
||||
}
|
||||
|
||||
fn execute_indexing_instr(&mut self, instr: &IndexingInstruction) {
|
||||
match instr {
|
||||
&IndexingInstruction::SwitchOnTerm(v, c, l, s) => {
|
||||
let a1 = self.registers[1].clone();
|
||||
let addr = self.store(self.deref(a1));
|
||||
|
||||
let offset = match addr {
|
||||
Addr::HeapCell(_) | Addr::StackCell(_, _) => v,
|
||||
Addr::Con(_) => c,
|
||||
Addr::Lis(_) => l,
|
||||
Addr::Str(_) => s
|
||||
};
|
||||
|
||||
match offset {
|
||||
0 => self.fail = true,
|
||||
o => self.p += o
|
||||
};
|
||||
},
|
||||
&IndexingInstruction::SwitchOnConstant(_, ref hm) => {
|
||||
let a1 = self.registers[1].clone();
|
||||
let addr = self.store(self.deref(a1));
|
||||
|
||||
let offset = match addr {
|
||||
Addr::Con(constant) => {
|
||||
match hm.get(&constant) {
|
||||
Some(offset) => *offset,
|
||||
_ => 0
|
||||
}
|
||||
},
|
||||
_ => 0
|
||||
};
|
||||
|
||||
match offset {
|
||||
0 => self.fail = true,
|
||||
o => self.p += o,
|
||||
};
|
||||
},
|
||||
&IndexingInstruction::SwitchOnStructure(_, ref hm) => {
|
||||
let a1 = self.registers[1].clone();
|
||||
let addr = self.store(self.deref(a1));
|
||||
|
||||
let offset = match addr {
|
||||
Addr::Str(s) => {
|
||||
if let &HeapCellValue::NamedStr(arity, ref name) = &self.heap[s] {
|
||||
match hm.get(&(name.clone(), arity)) {
|
||||
Some(offset) => *offset,
|
||||
_ => 0
|
||||
}
|
||||
} else {
|
||||
0
|
||||
}
|
||||
},
|
||||
_ => 0
|
||||
};
|
||||
|
||||
match offset {
|
||||
0 => self.fail = true,
|
||||
o => self.p += o
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn execute_query_instr(&mut self, instr: &QueryInstruction) {
|
||||
match instr {
|
||||
&QueryInstruction::PutConstant(_, ref constant, reg) =>
|
||||
@@ -782,6 +851,91 @@ impl MachineState {
|
||||
};
|
||||
}
|
||||
|
||||
fn execute_indexed_choice_instr(&mut self, instr: &IndexedChoiceInstruction)
|
||||
{
|
||||
match instr {
|
||||
&IndexedChoiceInstruction::Try(l) => {
|
||||
let n = self.num_of_args;
|
||||
let num_frames = self.num_frames();
|
||||
|
||||
self.or_stack.push(num_frames + 1,
|
||||
self.e,
|
||||
self.cp,
|
||||
self.b,
|
||||
self.p + 1,
|
||||
self.tr,
|
||||
self.h,
|
||||
self.num_of_args);
|
||||
|
||||
self.b = self.or_stack.len() - 1;
|
||||
let b = self.b;
|
||||
|
||||
for i in 1 .. n + 1 {
|
||||
self.or_stack[b][i] = self.registers[i].clone();
|
||||
}
|
||||
|
||||
self.hb = self.h;
|
||||
self.p += l;
|
||||
},
|
||||
&IndexedChoiceInstruction::Retry(l) => {
|
||||
let b = self.b;
|
||||
let n = self.or_stack[b].num_args();
|
||||
|
||||
for i in 1 .. n + 1 {
|
||||
self.registers[i] = self.or_stack[b][i].clone();
|
||||
}
|
||||
|
||||
self.e = self.or_stack[b].e;
|
||||
self.cp = self.or_stack[b].cp;
|
||||
|
||||
self.or_stack[b].bp = self.p + 1;
|
||||
|
||||
let old_tr = self.or_stack[b].tr;
|
||||
let curr_tr = self.tr;
|
||||
|
||||
self.unwind_trail(old_tr, curr_tr);
|
||||
self.tr = self.or_stack[b].tr;
|
||||
|
||||
self.trail.truncate(self.tr);
|
||||
self.heap.truncate(self.or_stack[b].h);
|
||||
|
||||
self.h = self.or_stack[b].h;
|
||||
self.hb = self.h;
|
||||
|
||||
self.p += l;
|
||||
},
|
||||
&IndexedChoiceInstruction::Trust(l) => {
|
||||
let b = self.b;
|
||||
let n = self.or_stack[b].num_args();
|
||||
|
||||
for i in 1 .. n + 1 {
|
||||
self.registers[i] = self.or_stack[b][i].clone();
|
||||
}
|
||||
|
||||
self.e = self.or_stack[b].e;
|
||||
self.cp = self.or_stack[b].cp;
|
||||
|
||||
let old_tr = self.or_stack[b].tr;
|
||||
let curr_tr = self.tr;
|
||||
|
||||
self.unwind_trail(old_tr, curr_tr);
|
||||
|
||||
self.tr = self.or_stack[b].tr;
|
||||
self.trail.truncate(self.tr);
|
||||
|
||||
self.h = self.or_stack[b].h;
|
||||
self.heap.truncate(self.h);
|
||||
|
||||
self.b = self.or_stack[b].b;
|
||||
|
||||
self.or_stack.pop();
|
||||
|
||||
self.hb = self.h;
|
||||
self.p += l;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn execute_choice_instr(&mut self, instr: &ChoiceInstruction)
|
||||
{
|
||||
match instr {
|
||||
|
||||
@@ -12,7 +12,7 @@ pub TopLevel: TopLevel = {
|
||||
};
|
||||
|
||||
Atom : Atom = {
|
||||
r"[a-z][a-z0-9_]*" => <>.trim().to_string(),
|
||||
r"[a-z][A-Za-z0-9_]*" => <>.trim().to_string(),
|
||||
};
|
||||
|
||||
BoxedTerm : Box<Term> = {
|
||||
@@ -73,5 +73,5 @@ Term : Term = {
|
||||
};
|
||||
|
||||
Var : Var = {
|
||||
r"[A-Z][a-z0-9_]*" => <>.trim().to_string()
|
||||
r"[A-Z][A-Za-z0-9_]*" => <>.trim().to_string()
|
||||
};
|
||||
|
||||
@@ -21,8 +21,8 @@ mod __parse__TopLevel {
|
||||
Term_22_5d_22(&'input str),
|
||||
Term_22___22(&'input str),
|
||||
Term_22_7c_22(&'input str),
|
||||
Termr_23_22_5bA_2dZ_5d_5ba_2dz0_2d9___5d_2a_22_23(&'input str),
|
||||
Termr_23_22_5ba_2dz_5d_5ba_2dz0_2d9___5d_2a_22_23(&'input str),
|
||||
Termr_23_22_5bA_2dZ_5d_5bA_2dZa_2dz0_2d9___5d_2a_22_23(&'input str),
|
||||
Termr_23_22_5ba_2dz_5d_5bA_2dZa_2dz0_2d9___5d_2a_22_23(&'input str),
|
||||
Termerror(__lalrpop_util::ErrorRecovery<usize, (usize, &'input str), ()>),
|
||||
Nt_28_22_2c_22_20_3cTerm_3e_29(Term),
|
||||
Nt_28_22_2c_22_20_3cTerm_3e_29_2a(::std::vec::Vec<Term>),
|
||||
@@ -719,8 +719,8 @@ mod __parse__TopLevel {
|
||||
r###""]""###,
|
||||
r###""_""###,
|
||||
r###""|""###,
|
||||
r###"r#"[A-Z][a-z0-9_]*"#"###,
|
||||
r###"r#"[a-z][a-z0-9_]*"#"###,
|
||||
r###"r#"[A-Z][A-Za-z0-9_]*"#"###,
|
||||
r###"r#"[a-z][A-Za-z0-9_]*"#"###,
|
||||
];
|
||||
__ACTION[(__state * 14)..].iter().zip(__TERMINAL).filter_map(|(&state, terminal)| {
|
||||
if state == 0 {
|
||||
@@ -822,11 +822,11 @@ mod __parse__TopLevel {
|
||||
_ => unreachable!(),
|
||||
},
|
||||
11 => match __lookahead.1 {
|
||||
(11, __tok0) => __Symbol::Termr_23_22_5bA_2dZ_5d_5ba_2dz0_2d9___5d_2a_22_23(__tok0),
|
||||
(11, __tok0) => __Symbol::Termr_23_22_5bA_2dZ_5d_5bA_2dZa_2dz0_2d9___5d_2a_22_23(__tok0),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
12 => match __lookahead.1 {
|
||||
(12, __tok0) => __Symbol::Termr_23_22_5ba_2dz_5d_5ba_2dz0_2d9___5d_2a_22_23(__tok0),
|
||||
(12, __tok0) => __Symbol::Termr_23_22_5ba_2dz_5d_5bA_2dZa_2dz0_2d9___5d_2a_22_23(__tok0),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
_ => unreachable!(),
|
||||
@@ -1028,8 +1028,8 @@ mod __parse__TopLevel {
|
||||
7
|
||||
}
|
||||
14 => {
|
||||
// Atom = r#"[a-z][a-z0-9_]*"# => ActionFn(5);
|
||||
let __sym0 = __pop_Termr_23_22_5ba_2dz_5d_5ba_2dz0_2d9___5d_2a_22_23(__symbols);
|
||||
// Atom = r#"[a-z][A-Za-z0-9_]*"# => ActionFn(5);
|
||||
let __sym0 = __pop_Termr_23_22_5ba_2dz_5d_5bA_2dZa_2dz0_2d9___5d_2a_22_23(__symbols);
|
||||
let __start = __sym0.0.clone();
|
||||
let __end = __sym0.2.clone();
|
||||
let __nt = super::__action5::<>(input, __sym0);
|
||||
@@ -1333,8 +1333,8 @@ mod __parse__TopLevel {
|
||||
17
|
||||
}
|
||||
39 => {
|
||||
// Var = r#"[A-Z][a-z0-9_]*"# => ActionFn(23);
|
||||
let __sym0 = __pop_Termr_23_22_5bA_2dZ_5d_5ba_2dz0_2d9___5d_2a_22_23(__symbols);
|
||||
// Var = r#"[A-Z][A-Za-z0-9_]*"# => ActionFn(23);
|
||||
let __sym0 = __pop_Termr_23_22_5bA_2dZ_5d_5bA_2dZa_2dz0_2d9___5d_2a_22_23(__symbols);
|
||||
let __start = __sym0.0.clone();
|
||||
let __end = __sym0.2.clone();
|
||||
let __nt = super::__action23::<>(input, __sym0);
|
||||
@@ -1468,23 +1468,23 @@ mod __parse__TopLevel {
|
||||
_ => panic!("symbol type mismatch")
|
||||
}
|
||||
}
|
||||
fn __pop_Termr_23_22_5bA_2dZ_5d_5ba_2dz0_2d9___5d_2a_22_23<
|
||||
fn __pop_Termr_23_22_5bA_2dZ_5d_5bA_2dZa_2dz0_2d9___5d_2a_22_23<
|
||||
'input,
|
||||
>(
|
||||
__symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
|
||||
) -> (usize, &'input str, usize) {
|
||||
match __symbols.pop().unwrap() {
|
||||
(__l, __Symbol::Termr_23_22_5bA_2dZ_5d_5ba_2dz0_2d9___5d_2a_22_23(__v), __r) => (__l, __v, __r),
|
||||
(__l, __Symbol::Termr_23_22_5bA_2dZ_5d_5bA_2dZa_2dz0_2d9___5d_2a_22_23(__v), __r) => (__l, __v, __r),
|
||||
_ => panic!("symbol type mismatch")
|
||||
}
|
||||
}
|
||||
fn __pop_Termr_23_22_5ba_2dz_5d_5ba_2dz0_2d9___5d_2a_22_23<
|
||||
fn __pop_Termr_23_22_5ba_2dz_5d_5bA_2dZa_2dz0_2d9___5d_2a_22_23<
|
||||
'input,
|
||||
>(
|
||||
__symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
|
||||
) -> (usize, &'input str, usize) {
|
||||
match __symbols.pop().unwrap() {
|
||||
(__l, __Symbol::Termr_23_22_5ba_2dz_5d_5ba_2dz0_2d9___5d_2a_22_23(__v), __r) => (__l, __v, __r),
|
||||
(__l, __Symbol::Termr_23_22_5ba_2dz_5d_5bA_2dZa_2dz0_2d9___5d_2a_22_23(__v), __r) => (__l, __v, __r),
|
||||
_ => panic!("symbol type mismatch")
|
||||
}
|
||||
}
|
||||
@@ -1845,6 +1845,11 @@ mod __intern_token {
|
||||
__current_state = 16;
|
||||
continue;
|
||||
}
|
||||
65 ... 90 => {
|
||||
__current_match = Some((11, __index + __ch.len_utf8()));
|
||||
__current_state = 16;
|
||||
continue;
|
||||
}
|
||||
95 => /* '_' */ {
|
||||
__current_match = Some((11, __index + 1));
|
||||
__current_state = 16;
|
||||
@@ -1897,6 +1902,11 @@ mod __intern_token {
|
||||
__current_state = 18;
|
||||
continue;
|
||||
}
|
||||
65 ... 90 => {
|
||||
__current_match = Some((12, __index + __ch.len_utf8()));
|
||||
__current_state = 18;
|
||||
continue;
|
||||
}
|
||||
95 => /* '_' */ {
|
||||
__current_match = Some((12, __index + 1));
|
||||
__current_state = 18;
|
||||
@@ -1952,6 +1962,11 @@ mod __intern_token {
|
||||
__current_state = 16;
|
||||
continue;
|
||||
}
|
||||
65 ... 90 => {
|
||||
__current_match = Some((11, __index + __ch.len_utf8()));
|
||||
__current_state = 16;
|
||||
continue;
|
||||
}
|
||||
95 => /* '_' */ {
|
||||
__current_match = Some((11, __index + 1));
|
||||
__current_state = 16;
|
||||
@@ -1983,6 +1998,11 @@ mod __intern_token {
|
||||
__current_state = 18;
|
||||
continue;
|
||||
}
|
||||
65 ... 90 => {
|
||||
__current_match = Some((12, __index + __ch.len_utf8()));
|
||||
__current_state = 18;
|
||||
continue;
|
||||
}
|
||||
95 => /* '_' */ {
|
||||
__current_match = Some((12, __index + 1));
|
||||
__current_state = 18;
|
||||
|
||||
Reference in New Issue
Block a user