add an atom table.
This commit is contained in:
@@ -13,7 +13,7 @@ mod tests;
|
||||
|
||||
fn process_buffer(wam: &mut Machine, buffer: &str)
|
||||
{
|
||||
match parse_code(buffer, wam.op_dir()) {
|
||||
match parse_code(buffer, wam.atom_tbl(), wam.op_dir()) {
|
||||
Ok(tl) => {
|
||||
let result = eval(wam, &tl);
|
||||
print(wam, result);
|
||||
|
||||
@@ -2,6 +2,7 @@ use prolog::num::bigint::BigInt;
|
||||
use prolog::num::{Float, ToPrimitive, Zero};
|
||||
use prolog::num::rational::Ratio;
|
||||
use prolog::ordered_float::*;
|
||||
use prolog::tabled_rc::*;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::cmp::Ordering;
|
||||
@@ -59,7 +60,7 @@ impl PredicateClause {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<Rc<Atom>> {
|
||||
pub fn name(&self) -> Option<TabledRc<Atom>> {
|
||||
match self {
|
||||
&PredicateClause::Fact(ref term) => term.name(),
|
||||
&PredicateClause::Rule(ref rule) =>
|
||||
@@ -73,7 +74,7 @@ impl PredicateClause {
|
||||
}
|
||||
|
||||
pub enum Declaration {
|
||||
Op(usize, Specifier, Rc<Atom>)
|
||||
Op(usize, Specifier, TabledRc<Atom>)
|
||||
}
|
||||
|
||||
pub enum TopLevel {
|
||||
@@ -266,19 +267,13 @@ pub enum Fixity {
|
||||
|
||||
#[derive(Clone, Eq, Hash, PartialEq)]
|
||||
pub enum Constant {
|
||||
Atom(Rc<Atom>),
|
||||
Atom(TabledRc<Atom>),
|
||||
Number(Number),
|
||||
String(Rc<String>),
|
||||
Usize(usize),
|
||||
EmptyList
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for Constant {
|
||||
fn from(input: &str) -> Constant {
|
||||
Constant::Atom(Rc::new(String::from(input)))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Constant {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
@@ -298,7 +293,7 @@ impl fmt::Display for Constant {
|
||||
|
||||
pub enum Term {
|
||||
AnonVar,
|
||||
Clause(Cell<RegType>, Rc<Atom>, Vec<Box<Term>>, Option<Fixity>),
|
||||
Clause(Cell<RegType>, TabledRc<Atom>, Vec<Box<Term>>, Option<Fixity>),
|
||||
Cons(Cell<RegType>, Box<Term>, Box<Term>),
|
||||
Constant(Cell<RegType>, Constant),
|
||||
Var(Cell<VarReg>, Rc<Var>)
|
||||
@@ -373,7 +368,7 @@ pub struct Rule {
|
||||
pub enum ClauseType<'a> {
|
||||
CallN,
|
||||
Catch,
|
||||
Deep(Level, &'a Cell<RegType>, &'a Rc<Atom>, Option<Fixity>),
|
||||
Deep(Level, &'a Cell<RegType>, &'a TabledRc<Atom>, Option<Fixity>),
|
||||
Is,
|
||||
Root,
|
||||
Throw,
|
||||
@@ -745,7 +740,7 @@ pub enum ControlInstruction {
|
||||
Allocate(usize), // num_frames.
|
||||
ArgCall,
|
||||
ArgExecute,
|
||||
Call(Rc<Atom>, usize, usize), // name, arity, perm_vars after threshold.
|
||||
Call(TabledRc<Atom>, usize, usize), // name, arity, perm_vars after threshold.
|
||||
CallN(usize), // arity.
|
||||
CatchCall,
|
||||
CatchExecute,
|
||||
@@ -754,7 +749,7 @@ pub enum ControlInstruction {
|
||||
DisplayExecute,
|
||||
DuplicateTermCall,
|
||||
DuplicateTermExecute,
|
||||
Execute(Rc<Atom>, usize),
|
||||
Execute(TabledRc<Atom>, usize),
|
||||
ExecuteN(usize),
|
||||
FunctorCall,
|
||||
FunctorExecute,
|
||||
@@ -797,7 +792,7 @@ impl ControlInstruction {
|
||||
pub enum IndexingInstruction {
|
||||
SwitchOnTerm(usize, usize, usize, usize),
|
||||
SwitchOnConstant(usize, HashMap<Constant, usize>),
|
||||
SwitchOnStructure(usize, HashMap<(Rc<Atom>, usize), usize>)
|
||||
SwitchOnStructure(usize, HashMap<(TabledRc<Atom>, usize), usize>)
|
||||
}
|
||||
|
||||
impl From<IndexingInstruction> for Line {
|
||||
@@ -809,7 +804,7 @@ impl From<IndexingInstruction> for Line {
|
||||
pub enum FactInstruction {
|
||||
GetConstant(Level, Constant, RegType),
|
||||
GetList(Level, RegType),
|
||||
GetStructure(Level, Rc<Atom>, usize, RegType, Option<Fixity>),
|
||||
GetStructure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>),
|
||||
GetValue(RegType, usize),
|
||||
GetVariable(RegType, usize),
|
||||
UnifyConstant(Constant),
|
||||
@@ -823,7 +818,7 @@ pub enum QueryInstruction {
|
||||
GetVariable(RegType, usize),
|
||||
PutConstant(Level, Constant, RegType),
|
||||
PutList(Level, RegType),
|
||||
PutStructure(Level, Rc<Atom>, usize, RegType, Option<Fixity>),
|
||||
PutStructure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>),
|
||||
PutUnsafeValue(usize, usize),
|
||||
PutValue(RegType, usize),
|
||||
PutVariable(RegType, usize),
|
||||
@@ -907,7 +902,7 @@ pub enum Ref {
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum HeapCellValue {
|
||||
Addr(Addr),
|
||||
NamedStr(usize, Rc<Atom>, Option<Fixity>), // arity, name.
|
||||
NamedStr(usize, TabledRc<Atom>, Option<Fixity>), // arity, name, fixity if it has one.
|
||||
}
|
||||
|
||||
impl HeapCellValue {
|
||||
@@ -1035,7 +1030,7 @@ impl Term {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<Rc<Atom>> {
|
||||
pub fn name(&self) -> Option<TabledRc<Atom>> {
|
||||
match self {
|
||||
&Term::Constant(_, Constant::Atom(ref atom))
|
||||
| &Term::Clause(_, ref atom, ..) => Some(atom.clone()),
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use prolog::ast::*;
|
||||
use prolog::num::bigint::{BigInt};
|
||||
use prolog::tabled_rc::*;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type PredicateKey = (Rc<Atom>, usize); // name, arity, type.
|
||||
pub type PredicateKey = (TabledRc<Atom>, usize); // name, arity, type.
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum PredicateKeyType {
|
||||
@@ -12,13 +13,13 @@ pub enum PredicateKeyType {
|
||||
User
|
||||
}
|
||||
|
||||
pub type OpDirKey = (Rc<Atom>, Fixity);
|
||||
pub type OpDirKey = (TabledRc<Atom>, Fixity);
|
||||
// name and fixity -> operator type and precedence.
|
||||
pub type OpDir = HashMap<OpDirKey, (Specifier, usize)>;
|
||||
|
||||
pub type CodeDir = HashMap<PredicateKey, (PredicateKeyType, usize)>;
|
||||
|
||||
fn get_builtins() -> Code {
|
||||
fn get_builtins(atom_tbl: TabledData<Atom>) -> Code {
|
||||
vec![internal_call_n!(), // callN/N, 0.
|
||||
is_atomic!(temp_v!(1)), // atomic/1, 1.
|
||||
proceed!(),
|
||||
@@ -114,25 +115,25 @@ fn get_builtins() -> Code {
|
||||
retry!(7),
|
||||
trust!(10),
|
||||
try_me_else!(4),
|
||||
fact![get_constant!(Constant::from("!"), temp_v!(1)),
|
||||
get_structure!(String::from(","), 2, temp_v!(2), Some(infix!())),
|
||||
fact![get_constant!(atom!("!", atom_tbl), temp_v!(1)),
|
||||
get_structure!(atom_tbl, ",", 2, temp_v!(2), Some(infix!())),
|
||||
unify_variable!(temp_v!(1)),
|
||||
unify_variable!(temp_v!(2))],
|
||||
set_cp!(temp_v!(3)),
|
||||
goto!(83, 3),
|
||||
retry_me_else!(4),
|
||||
fact![get_constant!(Constant::from("!"), temp_v!(1)),
|
||||
get_constant!(Constant::from("!"), temp_v!(2))],
|
||||
fact![get_constant!(atom!("!", atom_tbl), temp_v!(1)),
|
||||
get_constant!(atom!("!", atom_tbl), temp_v!(2))],
|
||||
set_cp!(temp_v!(3)),
|
||||
proceed!(),
|
||||
trust_me!(),
|
||||
fact![get_constant!(Constant::from("!"), temp_v!(1))],
|
||||
fact![get_constant!(atom!("!", atom_tbl), temp_v!(1))],
|
||||
set_cp!(temp_v!(3)),
|
||||
query![put_value!(temp_v!(2), 1)],
|
||||
execute_n!(1),
|
||||
retry_me_else!(8),
|
||||
allocate!(3),
|
||||
fact![get_structure!(String::from(","), 2, temp_v!(2), Some(infix!())),
|
||||
fact![get_structure!(atom_tbl, ",", 2, temp_v!(2), Some(infix!())),
|
||||
unify_variable!(perm_v!(2)),
|
||||
unify_variable!(perm_v!(1)),
|
||||
get_var_in_fact!(perm_v!(3), 3)],
|
||||
@@ -146,7 +147,7 @@ fn get_builtins() -> Code {
|
||||
retry_me_else!(10),
|
||||
allocate!(1),
|
||||
get_level!(),
|
||||
fact![get_constant!(Constant::from("!"), temp_v!(2)),
|
||||
fact![get_constant!(atom!("!", atom_tbl), temp_v!(2)),
|
||||
get_var_in_fact!(perm_v!(1), 3)],
|
||||
neck_cut!(),
|
||||
call_n!(1),
|
||||
@@ -167,12 +168,12 @@ fn get_builtins() -> Code {
|
||||
indexed_try!(3),
|
||||
trust!(5),
|
||||
try_me_else!(3),
|
||||
fact![get_structure!(String::from("->"), 2, temp_v!(1), Some(infix!())),
|
||||
fact![get_structure!(atom_tbl, "->", 2, temp_v!(1), Some(infix!())),
|
||||
unify_variable!(temp_v!(1)),
|
||||
unify_variable!(temp_v!(2))],
|
||||
goto!(139, 3),
|
||||
trust_me!(),
|
||||
fact![get_structure!(String::from("->"), 2, temp_v!(1), Some(infix!())),
|
||||
fact![get_structure!(atom_tbl, "->", 2, temp_v!(1), Some(infix!())),
|
||||
unify_void!(2)],
|
||||
query![put_value!(temp_v!(2), 1)],
|
||||
neck_cut!(),
|
||||
@@ -231,12 +232,13 @@ fn get_builtins() -> Code {
|
||||
goto!(149, 3), // goto get_arg/3.
|
||||
trust_me!(),
|
||||
query![get_var_in_query!(temp_v!(4), 1),
|
||||
put_structure!(Level::Shallow,
|
||||
put_structure!(atom_tbl,
|
||||
Level::Shallow,
|
||||
String::from("type_error"),
|
||||
1,
|
||||
temp_v!(1),
|
||||
None),
|
||||
set_constant!(Constant::Atom(rc_atom!("integer_expected")))],
|
||||
set_constant!(atom!("integer_expected", atom_tbl))],
|
||||
goto!(59, 1), // goto throw/1.
|
||||
try_me_else!(5), // arg_/3, 173.
|
||||
fact![get_value!(temp_v!(1), 2),
|
||||
@@ -277,76 +279,76 @@ fn get_builtins() -> Code {
|
||||
]
|
||||
}
|
||||
|
||||
pub fn build_code_dir() -> (Code, CodeDir, OpDir)
|
||||
pub fn build_code_dir(atom_tbl: TabledData<Atom>) -> (Code, CodeDir, OpDir)
|
||||
{
|
||||
let mut code_dir = HashMap::new();
|
||||
let mut op_dir = HashMap::new();
|
||||
|
||||
let builtin_code = get_builtins();
|
||||
let builtin_code = get_builtins(atom_tbl.clone());
|
||||
|
||||
op_dir.insert((rc_atom!(":-"), Fixity::In), (XFX, 1200));
|
||||
op_dir.insert((rc_atom!(":-"), Fixity::Pre), (FX, 1200));
|
||||
op_dir.insert((rc_atom!("?-"), Fixity::Pre), (FX, 1200));
|
||||
op_dir.insert((tabled_rc!(":-", atom_tbl), Fixity::In), (XFX, 1200));
|
||||
op_dir.insert((tabled_rc!(":-", atom_tbl), Fixity::Pre), (FX, 1200));
|
||||
op_dir.insert((tabled_rc!("?-", atom_tbl), Fixity::Pre), (FX, 1200));
|
||||
|
||||
// control operators.
|
||||
op_dir.insert((rc_atom!("\\+"), Fixity::Pre), (FY, 900));
|
||||
op_dir.insert((rc_atom!("="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("\\+", atom_tbl), Fixity::Pre), (FY, 900));
|
||||
op_dir.insert((tabled_rc!("=", atom_tbl), Fixity::In), (XFX, 700));
|
||||
|
||||
// arithmetic operators.
|
||||
op_dir.insert((rc_atom!("is"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((rc_atom!("+"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((rc_atom!("-"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((rc_atom!("/\\"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((rc_atom!("\\/"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((rc_atom!("xor"), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((rc_atom!("//"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((rc_atom!("/"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((rc_atom!("div"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((rc_atom!("*"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((rc_atom!("-"), Fixity::Pre), (FY, 200));
|
||||
op_dir.insert((rc_atom!("rdiv"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((rc_atom!("<<"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((rc_atom!(">>"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((rc_atom!("mod"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((rc_atom!("rem"), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("is", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("+", atom_tbl), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((tabled_rc!("-", atom_tbl), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((tabled_rc!("/\\", atom_tbl), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((tabled_rc!("\\/", atom_tbl), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((tabled_rc!("xor", atom_tbl), Fixity::In), (YFX, 500));
|
||||
op_dir.insert((tabled_rc!("//", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("/", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("div", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("*", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("-", atom_tbl), Fixity::Pre), (FY, 200));
|
||||
op_dir.insert((tabled_rc!("rdiv", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("<<", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!(">>", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("mod", atom_tbl), Fixity::In), (YFX, 400));
|
||||
op_dir.insert((tabled_rc!("rem", atom_tbl), Fixity::In), (YFX, 400));
|
||||
|
||||
// arithmetic comparison operators.
|
||||
op_dir.insert((rc_atom!(">"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((rc_atom!("<"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((rc_atom!("=\\="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((rc_atom!("=:="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((rc_atom!(">="), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((rc_atom!("=<"), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!(">", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("<", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("=\\=", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("=:=", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!(">=", atom_tbl), Fixity::In), (XFX, 700));
|
||||
op_dir.insert((tabled_rc!("=<", atom_tbl), Fixity::In), (XFX, 700));
|
||||
|
||||
// control operators.
|
||||
op_dir.insert((rc_atom!(";"), Fixity::In), (XFY, 1100));
|
||||
op_dir.insert((rc_atom!("->"), Fixity::In), (XFY, 1050));
|
||||
op_dir.insert((tabled_rc!(";", atom_tbl), Fixity::In), (XFY, 1100));
|
||||
op_dir.insert((tabled_rc!("->", atom_tbl), Fixity::In), (XFY, 1050));
|
||||
|
||||
// there are 63 registers in the VM, so call/N is defined for all 0 <= N <= 62
|
||||
// (an extra register is needed for the predicate name)
|
||||
for arity in 0 .. 63 {
|
||||
code_dir.insert((rc_atom!("call"), arity), (PredicateKeyType::BuiltIn, 0));
|
||||
code_dir.insert((tabled_rc!("call", atom_tbl), arity), (PredicateKeyType::BuiltIn, 0));
|
||||
}
|
||||
|
||||
code_dir.insert((rc_atom!("atomic"), 1), (PredicateKeyType::BuiltIn, 1));
|
||||
code_dir.insert((rc_atom!("var"), 1), (PredicateKeyType::BuiltIn, 3));
|
||||
code_dir.insert((rc_atom!("false"), 0), (PredicateKeyType::BuiltIn, 61));
|
||||
code_dir.insert((rc_atom!("\\+"), 1), (PredicateKeyType::BuiltIn, 62));
|
||||
code_dir.insert((rc_atom!("duplicate_term"), 2), (PredicateKeyType::BuiltIn, 71));
|
||||
code_dir.insert((rc_atom!("catch"), 3), (PredicateKeyType::BuiltIn, 5));
|
||||
code_dir.insert((rc_atom!("throw"), 1), (PredicateKeyType::BuiltIn, 59));
|
||||
code_dir.insert((rc_atom!("="), 2), (PredicateKeyType::BuiltIn, 73));
|
||||
code_dir.insert((rc_atom!("true"), 0), (PredicateKeyType::BuiltIn, 75));
|
||||
code_dir.insert((tabled_rc!("atomic", atom_tbl), 1), (PredicateKeyType::BuiltIn, 1));
|
||||
code_dir.insert((tabled_rc!("var", atom_tbl), 1), (PredicateKeyType::BuiltIn, 3));
|
||||
code_dir.insert((tabled_rc!("false", atom_tbl), 0), (PredicateKeyType::BuiltIn, 61));
|
||||
code_dir.insert((tabled_rc!("\\+", atom_tbl), 1), (PredicateKeyType::BuiltIn, 62));
|
||||
code_dir.insert((tabled_rc!("duplicate_term", atom_tbl), 2), (PredicateKeyType::BuiltIn, 71));
|
||||
code_dir.insert((tabled_rc!("catch", atom_tbl), 3), (PredicateKeyType::BuiltIn, 5));
|
||||
code_dir.insert((tabled_rc!("throw", atom_tbl), 1), (PredicateKeyType::BuiltIn, 59));
|
||||
code_dir.insert((tabled_rc!("=", atom_tbl), 2), (PredicateKeyType::BuiltIn, 73));
|
||||
code_dir.insert((tabled_rc!("true", atom_tbl), 0), (PredicateKeyType::BuiltIn, 75));
|
||||
|
||||
code_dir.insert((rc_atom!(","), 2), (PredicateKeyType::BuiltIn, 76));
|
||||
code_dir.insert((rc_atom!(";"), 2), (PredicateKeyType::BuiltIn, 120));
|
||||
code_dir.insert((rc_atom!("->"), 2), (PredicateKeyType::BuiltIn, 138));
|
||||
code_dir.insert((tabled_rc!(",", atom_tbl), 2), (PredicateKeyType::BuiltIn, 76));
|
||||
code_dir.insert((tabled_rc!(";", atom_tbl), 2), (PredicateKeyType::BuiltIn, 120));
|
||||
code_dir.insert((tabled_rc!("->", atom_tbl), 2), (PredicateKeyType::BuiltIn, 138));
|
||||
|
||||
code_dir.insert((rc_atom!("functor"), 3), (PredicateKeyType::BuiltIn, 146));
|
||||
code_dir.insert((rc_atom!("arg"), 3), (PredicateKeyType::BuiltIn, 150));
|
||||
code_dir.insert((rc_atom!("integer"), 1), (PredicateKeyType::BuiltIn, 147));
|
||||
code_dir.insert((tabled_rc!("functor", atom_tbl), 3), (PredicateKeyType::BuiltIn, 146));
|
||||
code_dir.insert((tabled_rc!("arg", atom_tbl), 3), (PredicateKeyType::BuiltIn, 150));
|
||||
code_dir.insert((tabled_rc!("integer", atom_tbl), 1), (PredicateKeyType::BuiltIn, 147));
|
||||
|
||||
code_dir.insert((rc_atom!("display"), 1), (PredicateKeyType::BuiltIn, 192));
|
||||
code_dir.insert((tabled_rc!("display", atom_tbl), 1), (PredicateKeyType::BuiltIn, 192));
|
||||
|
||||
(builtin_code, code_dir, op_dir)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use prolog::ast::*;
|
||||
use prolog::heap_iter::*;
|
||||
use prolog::tabled_rc::*;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum TokenOrRedirect {
|
||||
Atom(Rc<Atom>),
|
||||
Atom(TabledRc<Atom>),
|
||||
Redirect,
|
||||
Open,
|
||||
Close,
|
||||
@@ -20,7 +21,7 @@ pub enum TokenOrRedirect {
|
||||
pub trait HeapCellValueFormatter {
|
||||
// this function belongs to the display predicate formatter, which it uses
|
||||
// to format all clauses.
|
||||
fn format_struct(&self, arity: usize, name: Rc<Atom>, state_stack: &mut Vec<TokenOrRedirect>)
|
||||
fn format_struct(&self, arity: usize, name: TabledRc<Atom>, state_stack: &mut Vec<TokenOrRedirect>)
|
||||
{
|
||||
state_stack.push(TokenOrRedirect::Close);
|
||||
|
||||
@@ -37,7 +38,7 @@ pub trait HeapCellValueFormatter {
|
||||
|
||||
// this can be overloaded to handle special cases, falling back on the default of
|
||||
// format_struct when convenient.
|
||||
fn format_clause(&self, usize, Rc<Atom>, Option<Fixity>, &mut Vec<TokenOrRedirect>);
|
||||
fn format_clause(&self, usize, TabledRc<Atom>, Option<Fixity>, &mut Vec<TokenOrRedirect>);
|
||||
}
|
||||
|
||||
pub trait HeapCellValueOutputter {
|
||||
@@ -94,7 +95,7 @@ impl HeapCellValueOutputter for PrinterOutputter {
|
||||
pub struct DisplayFormatter {}
|
||||
|
||||
impl HeapCellValueFormatter for DisplayFormatter {
|
||||
fn format_clause(&self, arity: usize, name: Rc<Atom>, fixity: Option<Fixity>,
|
||||
fn format_clause(&self, arity: usize, name: TabledRc<Atom>, fixity: Option<Fixity>,
|
||||
state_stack: &mut Vec<TokenOrRedirect>)
|
||||
{
|
||||
if fixity.is_some() {
|
||||
@@ -102,7 +103,7 @@ impl HeapCellValueFormatter for DisplayFormatter {
|
||||
new_name += name.as_ref();
|
||||
new_name += "'";
|
||||
|
||||
let name = Rc::new(new_name);
|
||||
let name = TabledRc::new(new_name, name.table());
|
||||
self.format_struct(arity, name, state_stack);
|
||||
} else {
|
||||
self.format_struct(arity, name, state_stack);
|
||||
@@ -113,7 +114,7 @@ impl HeapCellValueFormatter for DisplayFormatter {
|
||||
pub struct TermFormatter {}
|
||||
|
||||
impl HeapCellValueFormatter for TermFormatter {
|
||||
fn format_clause(&self, arity: usize, name: Rc<Atom>, fixity: Option<Fixity>,
|
||||
fn format_clause(&self, arity: usize, name: TabledRc<Atom>, fixity: Option<Fixity>,
|
||||
state_stack: &mut Vec<TokenOrRedirect>)
|
||||
{
|
||||
if let Some(fixity) = fixity {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use prolog::ast::*;
|
||||
use prolog::tabled_rc::*;
|
||||
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::hash::Hash;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum IntIndex {
|
||||
@@ -12,7 +12,7 @@ enum IntIndex {
|
||||
pub struct CodeOffsets {
|
||||
pub constants: HashMap<Constant, ThirdLevelIndex>,
|
||||
pub lists: ThirdLevelIndex,
|
||||
pub structures: HashMap<(Rc<Atom>, usize), ThirdLevelIndex>
|
||||
pub structures: HashMap<(TabledRc<Atom>, usize), ThirdLevelIndex>
|
||||
}
|
||||
|
||||
impl CodeOffsets {
|
||||
@@ -145,7 +145,7 @@ impl CodeOffsets {
|
||||
}
|
||||
}
|
||||
|
||||
fn switch_on_structure(str_ind: HashMap<(Rc<Atom>, usize), ThirdLevelIndex>,
|
||||
fn switch_on_structure(str_ind: HashMap<(TabledRc<Atom>, usize), ThirdLevelIndex>,
|
||||
prelude: &mut CodeDeque)
|
||||
-> IntIndex
|
||||
{
|
||||
|
||||
@@ -54,7 +54,7 @@ impl<'a> QueryIterator<'a> {
|
||||
| &QueryTerm::Is(ref terms) => {
|
||||
let state = TermIterState::Clause(0, ClauseType::Is, terms);
|
||||
QueryIterator { state_stack: vec![state] }
|
||||
},
|
||||
},
|
||||
&QueryTerm::Inlined(InlinedQueryTerm::IsAtomic(ref terms))
|
||||
| &QueryTerm::Inlined(InlinedQueryTerm::IsInteger(ref terms))
|
||||
| &QueryTerm::Inlined(InlinedQueryTerm::IsVar(ref terms)) =>
|
||||
|
||||
@@ -8,6 +8,7 @@ use prolog::num::{Integer, ToPrimitive, Zero};
|
||||
use prolog::num::bigint::{BigInt, BigUint};
|
||||
use prolog::num::rational::Ratio;
|
||||
use prolog::or_stack::*;
|
||||
use prolog::tabled_rc::*;
|
||||
|
||||
use std::cmp::max;
|
||||
use std::ops::{Index, IndexMut};
|
||||
@@ -172,6 +173,7 @@ pub(super) enum MachineMode {
|
||||
}
|
||||
|
||||
pub struct MachineState {
|
||||
pub(super) atom_tbl: TabledData<Atom>,
|
||||
pub(super) s: usize,
|
||||
pub(super) p: CodePtr,
|
||||
pub(super) b: usize,
|
||||
@@ -194,8 +196,9 @@ pub struct MachineState {
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
pub(super) fn new() -> MachineState {
|
||||
MachineState { s: 0,
|
||||
pub(super) fn new(atom_tbl: TabledData<Atom>) -> MachineState {
|
||||
MachineState { atom_tbl,
|
||||
s: 0,
|
||||
p: CodePtr::default(),
|
||||
b: 0,
|
||||
b0: 0,
|
||||
@@ -440,7 +443,8 @@ impl MachineState {
|
||||
};
|
||||
}
|
||||
|
||||
fn get_number(&self, at: &ArithmeticTerm) -> Result<Number, Vec<HeapCellValue>> {
|
||||
fn get_number(&self, at: &ArithmeticTerm) -> Result<Number, Vec<HeapCellValue>> {
|
||||
|
||||
match at {
|
||||
&ArithmeticTerm::Reg(r) => {
|
||||
let addr = self[r].clone();
|
||||
@@ -448,7 +452,13 @@ impl MachineState {
|
||||
|
||||
match item {
|
||||
Addr::Con(Constant::Number(n)) => Ok(n),
|
||||
_ => Err(functor!("instantiation_error", 1, [atom!("(is)/2")]))
|
||||
_ => {
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
Err(functor!(self.atom_tbl,
|
||||
"instantiation_error",
|
||||
1,
|
||||
[heap_atom!("(is)/2", atom_tbl)]))
|
||||
}
|
||||
}
|
||||
},
|
||||
&ArithmeticTerm::Interm(i) => Ok(self.interms[i-1].clone()),
|
||||
@@ -465,7 +475,10 @@ impl MachineState {
|
||||
if let Some(r) = Ratio::from_float(fl.into_inner()) {
|
||||
Ok(Rc::new(r))
|
||||
} else {
|
||||
Err(functor!("instantiation_error", 1, [atom!("(is)/2")]))
|
||||
Err(functor!(self.atom_tbl,
|
||||
"instantiation_error",
|
||||
1,
|
||||
[heap_atom!("(is)/2", self.atom_tbl)]))
|
||||
},
|
||||
Number::Integer(bi) =>
|
||||
Ok(Rc::new(Ratio::from_integer((*bi).clone())))
|
||||
@@ -514,9 +527,11 @@ impl MachineState {
|
||||
let r2 = try_or_fail!(self, self.get_rational(a2));
|
||||
|
||||
if *r2 == Ratio::zero() {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("zero_divisor")]));
|
||||
[heap_atom!("zero_divisor", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -530,9 +545,11 @@ impl MachineState {
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
if *n2 == BigInt::zero() {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("zero_divisor")]));
|
||||
[heap_atom!("zero_divisor", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -540,9 +557,11 @@ impl MachineState {
|
||||
self.p += 1;
|
||||
},
|
||||
_ => {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("expected_integer_args")]));
|
||||
[heap_atom!("expected_integer_args", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -554,9 +573,11 @@ impl MachineState {
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
if *n2 == BigInt::zero() {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("zero_divisor")]));
|
||||
[heap_atom!("zero_divisor", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -564,9 +585,11 @@ impl MachineState {
|
||||
self.p += 1;
|
||||
},
|
||||
_ => {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("expected_integer_args")]));
|
||||
[heap_atom!("expected_integer_args", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -582,9 +605,11 @@ impl MachineState {
|
||||
let n2 = try_or_fail!(self, self.get_number(a2));
|
||||
|
||||
if n2.is_zero() {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("zero_divisor")]));
|
||||
[heap_atom!("zero_divisor", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -602,9 +627,11 @@ impl MachineState {
|
||||
_ => self.interms[t - 1] = Number::Integer(Rc::new(&*n1 >> usize::max_value()))
|
||||
},
|
||||
_ => {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("expected_integer_args")]));
|
||||
[heap_atom!("expected_integer_args", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -622,9 +649,11 @@ impl MachineState {
|
||||
_ => self.interms[t - 1] = Number::Integer(Rc::new(&*n1 << usize::max_value()))
|
||||
},
|
||||
_ => {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("expected_integer_args")]));
|
||||
[heap_atom!("expected_integer_args", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -639,9 +668,11 @@ impl MachineState {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
self.signed_bitwise_op(&*n1, &*n2, t, |u_n1, u_n2| u_n1 ^ u_n2),
|
||||
_ => {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("expected_integer_args")]));
|
||||
[heap_atom!("expected_integer_args", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -656,9 +687,11 @@ impl MachineState {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
self.signed_bitwise_op(&*n1, &*n2, t, |u_n1, u_n2| u_n1 & u_n2),
|
||||
_ => {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("expected_integer_args")]));
|
||||
[heap_atom!("expected_integer_args", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -673,9 +706,11 @@ impl MachineState {
|
||||
(Number::Integer(n1), Number::Integer(n2)) =>
|
||||
self.signed_bitwise_op(&*n1, &*n2, t, |u_n1, u_n2| u_n1 | u_n2),
|
||||
_ => {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("expected_integer_args")]));
|
||||
[heap_atom!("expected_integer_args", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -689,18 +724,22 @@ impl MachineState {
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
if *n2 == BigInt::zero() {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("zero_divisor")]));
|
||||
[heap_atom!("zero_divisor", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
|
||||
self.interms[t - 1] = Number::Integer(Rc::new(n1.mod_floor(&n2)));
|
||||
},
|
||||
_ => {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("expected_integer_args")]));
|
||||
[heap_atom!("expected_integer_args", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -714,18 +753,22 @@ impl MachineState {
|
||||
match (n1, n2) {
|
||||
(Number::Integer(n1), Number::Integer(n2)) => {
|
||||
if *n2 == BigInt::zero() {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("zero_divisor")]));
|
||||
[heap_atom!("zero_divisor", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
|
||||
self.interms[t - 1] = Number::Integer(Rc::new(&*n1 % &*n2));
|
||||
},
|
||||
_ => {
|
||||
self.throw_exception(functor!("evaluation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"evaluation_error",
|
||||
1,
|
||||
[atom!("expected_integer_args")]));
|
||||
[heap_atom!("expected_integer_args", atom_tbl)]));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1041,7 +1084,7 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_call_predicate(&mut self, code_dir: &CodeDir, name: Rc<Atom>, arity: usize)
|
||||
fn try_call_predicate(&mut self, code_dir: &CodeDir, name: TabledRc<Atom>, arity: usize)
|
||||
{
|
||||
let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1);
|
||||
|
||||
@@ -1056,7 +1099,7 @@ impl MachineState {
|
||||
};
|
||||
}
|
||||
|
||||
fn try_execute_predicate(&mut self, code_dir: &CodeDir, name: Rc<Atom>, arity: usize)
|
||||
fn try_execute_predicate(&mut self, code_dir: &CodeDir, name: TabledRc<Atom>, arity: usize)
|
||||
{
|
||||
let compiled_tl_index = code_dir.get(&(name, arity)).map(|index| index.1);
|
||||
|
||||
@@ -1116,9 +1159,11 @@ impl MachineState {
|
||||
|
||||
if let HeapCellValue::NamedStr(narity, name, _) = result {
|
||||
if narity + arity > 63 {
|
||||
self.throw_exception(functor!("representation_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"representation_error",
|
||||
1,
|
||||
[atom!("exceeds_max_arity")]));
|
||||
[heap_atom!("exceeds_max_arity", atom_tbl)]));
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -1138,13 +1183,16 @@ impl MachineState {
|
||||
},
|
||||
Addr::Con(Constant::Atom(name)) => (name, 0),
|
||||
Addr::HeapCell(_) | Addr::StackCell(_, _) => {
|
||||
self.throw_exception(functor!("instantiation_error", 0, []));
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl, "instantiation_error", 0, []));
|
||||
return None;
|
||||
},
|
||||
_ => {
|
||||
self.throw_exception(functor!("type_error",
|
||||
let atom_tbl = self.atom_tbl.clone();
|
||||
self.throw_exception(functor!(atom_tbl,
|
||||
"type_error",
|
||||
2,
|
||||
[atom!("callable"),
|
||||
[heap_atom!("callable", atom_tbl),
|
||||
HeapCellValue::Addr(addr)]));
|
||||
return None;
|
||||
}
|
||||
@@ -1193,7 +1241,10 @@ impl MachineState {
|
||||
_ => self.fail = true
|
||||
};
|
||||
} else {
|
||||
return Err(functor!("type_error", 1, [atom!("compound_expected")]));
|
||||
return Err(functor!(self.atom_tbl,
|
||||
"type_error",
|
||||
1,
|
||||
[heap_atom!("compound_expected", self.atom_tbl)]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1419,10 +1470,10 @@ impl MachineState {
|
||||
|
||||
self.unify(a1, f_a);
|
||||
} else {
|
||||
return Err(functor!("instantiation_error", 0, []));
|
||||
return Err(functor!(self.atom_tbl, "instantiation_error", 0, []));
|
||||
}
|
||||
} else {
|
||||
return Err(functor!("instantiation_error", 0, []));
|
||||
return Err(functor!(self.atom_tbl, "instantiation_error", 0, []));
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
|
||||
@@ -3,10 +3,13 @@ use prolog::builtins::*;
|
||||
use prolog::codegen::*;
|
||||
use prolog::heap_print::*;
|
||||
use prolog::fixtures::*;
|
||||
use prolog::tabled_rc::*;
|
||||
|
||||
pub(crate) mod machine_state;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::mem::swap;
|
||||
use std::ops::Index;
|
||||
use std::rc::Rc;
|
||||
use std::vec::Vec;
|
||||
@@ -37,13 +40,14 @@ impl Index<CodePtr> for Machine {
|
||||
|
||||
impl Machine {
|
||||
pub fn new() -> Self {
|
||||
let (code, code_dir, op_dir) = build_code_dir();
|
||||
let atom_tbl = Rc::new(RefCell::new(HashSet::new()));
|
||||
let (code, code_dir, op_dir) = build_code_dir(atom_tbl.clone());
|
||||
|
||||
Machine {
|
||||
ms: machine_state::MachineState::new(),
|
||||
code: code,
|
||||
code_dir: code_dir,
|
||||
op_dir: op_dir,
|
||||
ms: machine_state::MachineState::new(atom_tbl),
|
||||
code,
|
||||
code_dir,
|
||||
op_dir,
|
||||
cached_query: None
|
||||
}
|
||||
}
|
||||
@@ -52,7 +56,13 @@ impl Machine {
|
||||
self.ms.fail
|
||||
}
|
||||
|
||||
fn add_user_code<'a>(&mut self, name: Rc<Atom>, arity: usize, offset: usize) -> EvalSession<'a>
|
||||
pub fn atom_tbl(&self) -> TabledData<Atom> {
|
||||
self.ms.atom_tbl.clone()
|
||||
}
|
||||
|
||||
fn add_user_code<'a>(&mut self, name: TabledRc<Atom>,
|
||||
arity: usize, offset: usize)
|
||||
-> EvalSession<'a>
|
||||
{
|
||||
match self.code_dir.get(&(name.clone(), arity)) {
|
||||
Some(&(PredicateKeyType::BuiltIn, _)) =>
|
||||
@@ -369,9 +379,8 @@ impl Machine {
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.reset();
|
||||
self.code.clear();
|
||||
self.code_dir.clear();
|
||||
let mut machine = Machine::new();
|
||||
swap(self, &mut machine);
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
macro_rules! tabled_rc {
|
||||
($e:expr, $tbl:expr) => (
|
||||
TabledRc::new(String::from($e), $tbl.clone())
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! atom {
|
||||
($e:expr, $tbl:expr) => (
|
||||
Constant::Atom(tabled_rc!($e, $tbl))
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! internal_call_n {
|
||||
() => (
|
||||
@@ -41,20 +52,23 @@ macro_rules! query {
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! functor {
|
||||
($name:expr, $len:expr, [$($args:expr),*]) => {{
|
||||
if $len > 0 {
|
||||
vec![ HeapCellValue::NamedStr($len, Rc::new(String::from($name)), None), $($args),* ]
|
||||
} else {
|
||||
vec![ atom!($name) ]
|
||||
}
|
||||
}}
|
||||
macro_rules! heap_atom {
|
||||
($name:expr, $tbl:expr) => (
|
||||
HeapCellValue::Addr(Addr::Con(atom!($name, $tbl)))
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! atom {
|
||||
($name:expr) => (
|
||||
HeapCellValue::Addr(Addr::Con(Constant::Atom(Rc::new(String::from($name)))))
|
||||
)
|
||||
macro_rules! functor {
|
||||
($tbl:expr, $name:expr, $len:expr, [$($args:expr),*]) => {{
|
||||
if $len > 0 {
|
||||
vec![ HeapCellValue::NamedStr($len,
|
||||
tabled_rc!($name, $tbl),
|
||||
None),
|
||||
$($args),* ]
|
||||
} else {
|
||||
vec![ heap_atom!($name, $tbl) ]
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! fact {
|
||||
@@ -101,8 +115,8 @@ macro_rules! put_var {
|
||||
}
|
||||
|
||||
macro_rules! put_structure {
|
||||
($lvl:expr, $name:expr, $arity:expr, $r:expr, $fix:expr) => (
|
||||
QueryInstruction::PutStructure($lvl, Rc::new($name), $arity, $r, $fix)
|
||||
($tbl:expr, $lvl:expr, $name:expr, $arity:expr, $r:expr, $fix:expr) => (
|
||||
QueryInstruction::PutStructure($lvl, tabled_rc!($name, $tbl), $arity, $r, $fix)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -317,8 +331,12 @@ macro_rules! get_constant {
|
||||
}
|
||||
|
||||
macro_rules! get_structure {
|
||||
($atom:expr, $arity:expr, $r:expr, $fix:expr) => (
|
||||
FactInstruction::GetStructure(Level::Shallow, Rc::new($atom), $arity, $r, $fix)
|
||||
($tbl:expr, $atom:expr, $arity:expr, $r:expr, $fix:expr) => (
|
||||
FactInstruction::GetStructure(Level::Shallow,
|
||||
tabled_rc!($atom, $tbl),
|
||||
$arity,
|
||||
$r,
|
||||
$fix)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,3 +22,4 @@ pub mod machine;
|
||||
pub mod or_stack;
|
||||
pub mod parser;
|
||||
pub mod targets;
|
||||
pub mod tabled_rc;
|
||||
|
||||
Submodule src/prolog/parser updated: dcf51680fb...3b1dd579b4
@@ -2,15 +2,15 @@ use std::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type TabledData<T> = HashSet<Rc<T>>;
|
||||
pub type TabledData<T> = Rc<RefCell<HashSet<Rc<T>>>>;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct TabledRc<T: Hash + Eq> {
|
||||
atom: Rc<T>,
|
||||
table: Rc<RefCell<TabledData<T>>>
|
||||
table: TabledData<T>
|
||||
}
|
||||
|
||||
impl<T: Hash + Eq> Hash for TabledRc<T> {
|
||||
@@ -21,16 +21,26 @@ impl<T: Hash + Eq> Hash for TabledRc<T> {
|
||||
}
|
||||
|
||||
impl<T: Hash + Eq> TabledRc<T> {
|
||||
pub fn new(atom: T, table: Rc<RefCell<TabledData<T>>>) -> Self {
|
||||
TabledRc { atom: Rc::new(atom), table }
|
||||
pub fn new(atom: T, table: TabledData<T>) -> Self {
|
||||
let atom = match table.borrow_mut().take(&atom) {
|
||||
Some(atom) => atom.clone(),
|
||||
None => Rc::new(atom)
|
||||
};
|
||||
|
||||
table.borrow_mut().insert(atom.clone());
|
||||
|
||||
TabledRc { atom, table }
|
||||
}
|
||||
|
||||
pub fn table(&self) -> TabledData<T> {
|
||||
self.table.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Hash + Eq> Drop for TabledRc<T> {
|
||||
fn drop(&mut self) {
|
||||
if Rc::strong_count(&self.atom) == 2 {
|
||||
let mut table = self.table.borrow_mut();
|
||||
table.deref_mut().remove(&self.atom);
|
||||
self.table.borrow_mut().remove(&self.atom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use prolog::ast::*;
|
||||
use prolog::iterators::*;
|
||||
|
||||
use std::rc::Rc;
|
||||
use prolog::tabled_rc::*;
|
||||
|
||||
pub trait CompilationTarget<'a> {
|
||||
type Iterator : Iterator<Item=TermRef<'a>>;
|
||||
@@ -10,7 +9,7 @@ pub trait CompilationTarget<'a> {
|
||||
|
||||
fn to_constant(Level, Constant, RegType) -> Self;
|
||||
fn to_list(Level, RegType) -> Self;
|
||||
fn to_structure(Level, Rc<Atom>, usize, RegType, Option<Fixity>) -> Self;
|
||||
fn to_structure(Level, TabledRc<Atom>, usize, RegType, Option<Fixity>) -> Self;
|
||||
|
||||
fn to_void(usize) -> Self;
|
||||
fn is_void_instr(&self) -> bool;
|
||||
@@ -41,7 +40,8 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
|
||||
FactInstruction::GetConstant(lvl, constant, reg)
|
||||
}
|
||||
|
||||
fn to_structure(lvl: Level, atom: Rc<Atom>, arity: usize, reg: RegType, fixity: Option<Fixity>)
|
||||
fn to_structure(lvl: Level, atom: TabledRc<Atom>, arity: usize,
|
||||
reg: RegType, fixity: Option<Fixity>)
|
||||
-> Self
|
||||
{
|
||||
FactInstruction::GetStructure(lvl, atom, arity, reg, fixity)
|
||||
@@ -105,7 +105,8 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
|
||||
term.post_order_iter()
|
||||
}
|
||||
|
||||
fn to_structure(lvl: Level, atom: Rc<Atom>, arity: usize, reg: RegType, fixity: Option<Fixity>)
|
||||
fn to_structure(lvl: Level, atom: TabledRc<Atom>, arity: usize,
|
||||
reg: RegType, fixity: Option<Fixity>)
|
||||
-> Self
|
||||
{
|
||||
QueryInstruction::PutStructure(lvl, atom, arity, reg, fixity)
|
||||
|
||||
@@ -74,7 +74,7 @@ pub fn collect_test_output_with_limit<'a>(wam: &mut Machine, alloc_locs: AllocVa
|
||||
mut heap_locs: HeapVarDict<'a>, limit: usize)
|
||||
-> HashSet<String>
|
||||
{
|
||||
let mut output = TestOutputter::new();
|
||||
let mut output = TestOutputter::new();
|
||||
output = wam.heap_view(&heap_locs, output);
|
||||
|
||||
let mut count = 1;
|
||||
@@ -82,9 +82,9 @@ pub fn collect_test_output_with_limit<'a>(wam: &mut Machine, alloc_locs: AllocVa
|
||||
if count == limit {
|
||||
return output.result();
|
||||
}
|
||||
|
||||
|
||||
while let EvalSession::SubsequentQuerySuccess = wam.continue_query(&alloc_locs, &mut heap_locs)
|
||||
{
|
||||
{
|
||||
output = wam.heap_view(&heap_locs, output);
|
||||
|
||||
count += 1;
|
||||
@@ -97,11 +97,12 @@ pub fn collect_test_output_with_limit<'a>(wam: &mut Machine, alloc_locs: AllocVa
|
||||
output.result()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn submit(wam: &mut Machine, buffer: &str) -> bool
|
||||
{
|
||||
wam.reset();
|
||||
|
||||
match parse_code(buffer.trim(), wam.op_dir()) {
|
||||
match parse_code(buffer.trim(), wam.atom_tbl(), wam.op_dir()) {
|
||||
Ok(tl) =>
|
||||
match eval(wam, &tl) {
|
||||
EvalSession::InitialQuerySuccess(_, _) |
|
||||
@@ -114,11 +115,12 @@ pub fn submit(wam: &mut Machine, buffer: &str) -> bool
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn submit_query(wam: &mut Machine, buffer: &str, result: HashSet<String>) -> bool
|
||||
{
|
||||
wam.reset();
|
||||
|
||||
match parse_code(buffer.trim(), wam.op_dir()) {
|
||||
match parse_code(buffer.trim(), wam.atom_tbl(), wam.op_dir()) {
|
||||
Ok(tl) =>
|
||||
match eval(wam, &tl) {
|
||||
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
|
||||
@@ -130,13 +132,14 @@ pub fn submit_query(wam: &mut Machine, buffer: &str, result: HashSet<String>) ->
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str,
|
||||
result: HashSet<String>, limit: usize)
|
||||
-> bool
|
||||
{
|
||||
wam.reset();
|
||||
|
||||
match parse_code(buffer.trim(), wam.op_dir()) {
|
||||
match parse_code(buffer.trim(), wam.atom_tbl(), wam.op_dir()) {
|
||||
Ok(tl) =>
|
||||
match eval(wam, &tl) {
|
||||
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
|
||||
@@ -149,24 +152,28 @@ pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! expand_strs {
|
||||
($arr:expr) => (
|
||||
$arr.into_iter().map(|s| String::from(*s)).collect()
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_prolog_success_with_limit {
|
||||
($wam:expr, $buf:expr, $res:expr, $limit:expr) => (
|
||||
assert!(submit_query_with_limit($wam, $buf, expand_strs!($res), $limit))
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_prolog_failure {
|
||||
($wam: expr, $buf: expr) => (
|
||||
assert_eq!(submit($wam, $buf), false)
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! assert_prolog_success {
|
||||
($wam:expr, $query:expr, $res:expr) => (
|
||||
assert!(submit_query($wam, $query, expand_strs!($res)))
|
||||
|
||||
Reference in New Issue
Block a user