optimized up to section 5.11
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rusty-wam"
|
name = "rusty-wam"
|
||||||
version = "0.5.10"
|
version = "0.5.11"
|
||||||
authors = ["Mark Thom"]
|
authors = ["Mark Thom"]
|
||||||
|
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ pure Prolog.
|
|||||||
Pure Prolog is implemented as a simple REPL. "Pure Prolog" is 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
|
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
|
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.
|
two data types currently supported.
|
||||||
|
|
||||||
While proper environment trimming code is emitted by the code
|
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, 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);
|
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() {
|
fn prolog_repl() {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::cmp::Ordering;
|
use std::collections::{HashMap, VecDeque};
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::ops::{Add, AddAssign};
|
use std::ops::{Add, AddAssign};
|
||||||
use std::vec::Vec;
|
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 {
|
pub fn arity(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
&PredicateClause::Fact(ref t) => t.arity(),
|
&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 {
|
pub enum Constant {
|
||||||
Atom(Atom),
|
Atom(Atom),
|
||||||
EmptyList
|
EmptyList
|
||||||
@@ -135,6 +141,54 @@ pub enum TermRef<'a> {
|
|||||||
Var(Level, &'a Cell<VarReg>, &'a Var)
|
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 {
|
pub enum FactInstruction {
|
||||||
GetConstant(Level, Constant, RegType),
|
GetConstant(Level, Constant, RegType),
|
||||||
GetList(Level, RegType),
|
GetList(Level, RegType),
|
||||||
@@ -162,20 +216,6 @@ pub enum QueryInstruction {
|
|||||||
SetVoid(usize)
|
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 CompiledFact = Vec<FactInstruction>;
|
||||||
|
|
||||||
pub type CompiledQuery = Vec<QueryInstruction>;
|
pub type CompiledQuery = Vec<QueryInstruction>;
|
||||||
@@ -184,6 +224,8 @@ pub enum Line {
|
|||||||
Choice(ChoiceInstruction),
|
Choice(ChoiceInstruction),
|
||||||
Control(ControlInstruction),
|
Control(ControlInstruction),
|
||||||
Fact(CompiledFact),
|
Fact(CompiledFact),
|
||||||
|
Indexing(IndexingInstruction),
|
||||||
|
IndexedChoice(IndexedChoiceInstruction),
|
||||||
Query(CompiledQuery)
|
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 Code = Vec<Line>;
|
||||||
|
|
||||||
|
pub type CodeDeque = VecDeque<Line>;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub enum Addr {
|
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)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum CodePtr {
|
pub enum CodePtr {
|
||||||
DirEntry(usize),
|
DirEntry(usize),
|
||||||
@@ -344,6 +369,14 @@ pub type Heap = Vec<HeapCellValue>;
|
|||||||
pub type Registers = Vec<Addr>;
|
pub type Registers = Vec<Addr>;
|
||||||
|
|
||||||
impl Term {
|
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 {
|
pub fn is_clause(&self) -> bool {
|
||||||
if let &Term::Clause(_, _, _) = self {
|
if let &Term::Clause(_, _, _) = self {
|
||||||
true
|
true
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ use prolog::iterators::{FactIterator, QueryIterator};
|
|||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
use std::hash::Hash;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
|
||||||
trait CompilationTarget<'a> {
|
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)]
|
#[derive(Copy, Clone)]
|
||||||
enum VarStatus {
|
enum VarStatus {
|
||||||
New, Old, Permanent(usize)
|
New, Old, Permanent(usize)
|
||||||
@@ -643,7 +877,7 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
Self::add_conditional_call(&mut body, p1, perm_vars);
|
Self::add_conditional_call(&mut body, p1, perm_vars);
|
||||||
|
|
||||||
body = clauses.iter().enumerate()
|
body = clauses.iter().enumerate()
|
||||||
.map(|(i, ref term)| {
|
.map(|(i, term)| {
|
||||||
let num_vars = Self::vars_above_threshold(&vs, i+1);
|
let num_vars = Self::vars_above_threshold(&vs, i+1);
|
||||||
self.compile_internal_query(term, num_vars)
|
self.compile_internal_query(term, num_vars)
|
||||||
})
|
})
|
||||||
@@ -751,9 +985,35 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
code
|
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() {
|
for (i, clause) in clauses.iter().enumerate() {
|
||||||
self.marker.reset();
|
self.marker.reset();
|
||||||
@@ -765,14 +1025,50 @@ impl<'a> CodeGenerator<'a> {
|
|||||||
self.compile_rule(rule)
|
self.compile_rule(rule)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if multi_clause {
|
||||||
let choice = match i {
|
let choice = match i {
|
||||||
0 => ChoiceInstruction::TryMeElse(clause_code.len() + 1),
|
0 => ChoiceInstruction::TryMeElse(clause_code.len() + 1),
|
||||||
_ if i == clauses.len() - 1 => ChoiceInstruction::TrustMe,
|
_ if i == clauses.len() - 1 => ChoiceInstruction::TrustMe,
|
||||||
_ => ChoiceInstruction::RetryMeElse(clause_code.len() + 1)
|
_ => 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.push(Line::Choice(choice));
|
||||||
code.append(&mut clause_code);
|
}
|
||||||
|
|
||||||
|
code.append(&mut code_segment);
|
||||||
}
|
}
|
||||||
|
|
||||||
code
|
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 {
|
impl fmt::Display for ChoiceInstruction {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
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 {
|
impl fmt::Display for Level {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
@@ -176,6 +202,10 @@ pub fn print_code(code: &Code) {
|
|||||||
println!("{}", choice),
|
println!("{}", choice),
|
||||||
&Line::Control(ref control) =>
|
&Line::Control(ref control) =>
|
||||||
println!("{}", control),
|
println!("{}", control),
|
||||||
|
&Line::IndexedChoice(ref choice) =>
|
||||||
|
println!("{}", choice),
|
||||||
|
&Line::Indexing(ref indexing) =>
|
||||||
|
println!("{}", indexing),
|
||||||
&Line::Query(ref query) =>
|
&Line::Query(ref query) =>
|
||||||
for query_instr in query {
|
for query_instr in query {
|
||||||
println!("{}", query_instr);
|
println!("{}", query_instr);
|
||||||
|
|||||||
@@ -106,8 +106,8 @@ impl<'a> Iterator for QueryIterator<'a> {
|
|||||||
},
|
},
|
||||||
IteratorState::InitialCons(lvl, cell, head, tail) => {
|
IteratorState::InitialCons(lvl, cell, head, tail) => {
|
||||||
self.push_final_cons(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, tail);
|
||||||
|
self.push_subterm(Level::Deep, head);
|
||||||
},
|
},
|
||||||
IteratorState::FinalCons(lvl, cell, head, tail) =>
|
IteratorState::FinalCons(lvl, cell, head, tail) =>
|
||||||
return Some(TermRef::Cons(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);
|
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 {
|
let mut instr = match instr_src {
|
||||||
LineOrCodeOffset::Instruction(instr) => instr,
|
LineOrCodeOffset::Instruction(instr) => instr,
|
||||||
@@ -121,6 +121,8 @@ impl Machine {
|
|||||||
match instr {
|
match instr {
|
||||||
&Line::Choice(ref choice_instr) =>
|
&Line::Choice(ref choice_instr) =>
|
||||||
self.ms.execute_choice_instr(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) => {
|
&Line::Fact(ref fact) => {
|
||||||
for fact_instr in fact {
|
for fact_instr in fact {
|
||||||
if self.failed() {
|
if self.failed() {
|
||||||
@@ -131,6 +133,10 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
self.ms.p += 1;
|
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) => {
|
&Line::Query(ref query) => {
|
||||||
for query_instr in query {
|
for query_instr in query {
|
||||||
if self.failed() {
|
if self.failed() {
|
||||||
@@ -140,9 +146,7 @@ impl Machine {
|
|||||||
self.ms.execute_query_instr(&query_instr);
|
self.ms.execute_query_instr(&query_instr);
|
||||||
}
|
}
|
||||||
self.ms.p += 1;
|
self.ms.p += 1;
|
||||||
},
|
}
|
||||||
&Line::Control(ref control_instr) =>
|
|
||||||
self.ms.execute_ctrl_instr(&self.code_dir, control_instr),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.failed() {
|
if self.failed() {
|
||||||
@@ -556,6 +560,8 @@ impl MachineState {
|
|||||||
self.h += 1;
|
self.h += 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.s += 1;
|
||||||
},
|
},
|
||||||
&FactInstruction::UnifyVariable(reg) => {
|
&FactInstruction::UnifyVariable(reg) => {
|
||||||
match self.mode {
|
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) {
|
fn execute_query_instr(&mut self, instr: &QueryInstruction) {
|
||||||
match instr {
|
match instr {
|
||||||
&QueryInstruction::PutConstant(_, ref constant, reg) =>
|
&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)
|
fn execute_choice_instr(&mut self, instr: &ChoiceInstruction)
|
||||||
{
|
{
|
||||||
match instr {
|
match instr {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ pub TopLevel: TopLevel = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Atom : Atom = {
|
Atom : Atom = {
|
||||||
r"[a-z][a-z0-9_]*" => <>.trim().to_string(),
|
r"[a-z][A-Za-z0-9_]*" => <>.trim().to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
BoxedTerm : Box<Term> = {
|
BoxedTerm : Box<Term> = {
|
||||||
@@ -73,5 +73,5 @@ Term : Term = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Var : Var = {
|
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_5d_22(&'input str),
|
||||||
Term_22___22(&'input str),
|
Term_22___22(&'input str),
|
||||||
Term_22_7c_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_2dZa_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),
|
||||||
Termerror(__lalrpop_util::ErrorRecovery<usize, (usize, &'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(Term),
|
||||||
Nt_28_22_2c_22_20_3cTerm_3e_29_2a(::std::vec::Vec<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###""|""###,
|
r###""|""###,
|
||||||
r###"r#"[A-Z][a-z0-9_]*"#"###,
|
r###"r#"[A-Z][A-Za-z0-9_]*"#"###,
|
||||||
r###"r#"[a-z][a-z0-9_]*"#"###,
|
r###"r#"[a-z][A-Za-z0-9_]*"#"###,
|
||||||
];
|
];
|
||||||
__ACTION[(__state * 14)..].iter().zip(__TERMINAL).filter_map(|(&state, terminal)| {
|
__ACTION[(__state * 14)..].iter().zip(__TERMINAL).filter_map(|(&state, terminal)| {
|
||||||
if state == 0 {
|
if state == 0 {
|
||||||
@@ -822,11 +822,11 @@ mod __parse__TopLevel {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
11 => match __lookahead.1 {
|
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!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
12 => match __lookahead.1 {
|
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!(),
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@@ -1028,8 +1028,8 @@ mod __parse__TopLevel {
|
|||||||
7
|
7
|
||||||
}
|
}
|
||||||
14 => {
|
14 => {
|
||||||
// Atom = r#"[a-z][a-z0-9_]*"# => ActionFn(5);
|
// Atom = r#"[a-z][A-Za-z0-9_]*"# => ActionFn(5);
|
||||||
let __sym0 = __pop_Termr_23_22_5ba_2dz_5d_5ba_2dz0_2d9___5d_2a_22_23(__symbols);
|
let __sym0 = __pop_Termr_23_22_5ba_2dz_5d_5bA_2dZa_2dz0_2d9___5d_2a_22_23(__symbols);
|
||||||
let __start = __sym0.0.clone();
|
let __start = __sym0.0.clone();
|
||||||
let __end = __sym0.2.clone();
|
let __end = __sym0.2.clone();
|
||||||
let __nt = super::__action5::<>(input, __sym0);
|
let __nt = super::__action5::<>(input, __sym0);
|
||||||
@@ -1333,8 +1333,8 @@ mod __parse__TopLevel {
|
|||||||
17
|
17
|
||||||
}
|
}
|
||||||
39 => {
|
39 => {
|
||||||
// Var = r#"[A-Z][a-z0-9_]*"# => ActionFn(23);
|
// Var = r#"[A-Z][A-Za-z0-9_]*"# => ActionFn(23);
|
||||||
let __sym0 = __pop_Termr_23_22_5bA_2dZ_5d_5ba_2dz0_2d9___5d_2a_22_23(__symbols);
|
let __sym0 = __pop_Termr_23_22_5bA_2dZ_5d_5bA_2dZa_2dz0_2d9___5d_2a_22_23(__symbols);
|
||||||
let __start = __sym0.0.clone();
|
let __start = __sym0.0.clone();
|
||||||
let __end = __sym0.2.clone();
|
let __end = __sym0.2.clone();
|
||||||
let __nt = super::__action23::<>(input, __sym0);
|
let __nt = super::__action23::<>(input, __sym0);
|
||||||
@@ -1468,23 +1468,23 @@ mod __parse__TopLevel {
|
|||||||
_ => panic!("symbol type mismatch")
|
_ => 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,
|
'input,
|
||||||
>(
|
>(
|
||||||
__symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
|
__symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
|
||||||
) -> (usize, &'input str, usize) {
|
) -> (usize, &'input str, usize) {
|
||||||
match __symbols.pop().unwrap() {
|
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")
|
_ => 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,
|
'input,
|
||||||
>(
|
>(
|
||||||
__symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
|
__symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>
|
||||||
) -> (usize, &'input str, usize) {
|
) -> (usize, &'input str, usize) {
|
||||||
match __symbols.pop().unwrap() {
|
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")
|
_ => panic!("symbol type mismatch")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1845,6 +1845,11 @@ mod __intern_token {
|
|||||||
__current_state = 16;
|
__current_state = 16;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
65 ... 90 => {
|
||||||
|
__current_match = Some((11, __index + __ch.len_utf8()));
|
||||||
|
__current_state = 16;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
95 => /* '_' */ {
|
95 => /* '_' */ {
|
||||||
__current_match = Some((11, __index + 1));
|
__current_match = Some((11, __index + 1));
|
||||||
__current_state = 16;
|
__current_state = 16;
|
||||||
@@ -1897,6 +1902,11 @@ mod __intern_token {
|
|||||||
__current_state = 18;
|
__current_state = 18;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
65 ... 90 => {
|
||||||
|
__current_match = Some((12, __index + __ch.len_utf8()));
|
||||||
|
__current_state = 18;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
95 => /* '_' */ {
|
95 => /* '_' */ {
|
||||||
__current_match = Some((12, __index + 1));
|
__current_match = Some((12, __index + 1));
|
||||||
__current_state = 18;
|
__current_state = 18;
|
||||||
@@ -1952,6 +1962,11 @@ mod __intern_token {
|
|||||||
__current_state = 16;
|
__current_state = 16;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
65 ... 90 => {
|
||||||
|
__current_match = Some((11, __index + __ch.len_utf8()));
|
||||||
|
__current_state = 16;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
95 => /* '_' */ {
|
95 => /* '_' */ {
|
||||||
__current_match = Some((11, __index + 1));
|
__current_match = Some((11, __index + 1));
|
||||||
__current_state = 16;
|
__current_state = 16;
|
||||||
@@ -1983,6 +1998,11 @@ mod __intern_token {
|
|||||||
__current_state = 18;
|
__current_state = 18;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
65 ... 90 => {
|
||||||
|
__current_match = Some((12, __index + __ch.len_utf8()));
|
||||||
|
__current_state = 18;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
95 => /* '_' */ {
|
95 => /* '_' */ {
|
||||||
__current_match = Some((12, __index + 1));
|
__current_match = Some((12, __index + 1));
|
||||||
__current_state = 18;
|
__current_state = 18;
|
||||||
|
|||||||
Reference in New Issue
Block a user