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);
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;
}
}
- 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) =>
}
pub enum Declaration {
- Op(usize, Specifier, Rc<Atom>)
+ Op(usize, Specifier, TabledRc<Atom>)
}
pub enum TopLevel {
#[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 {
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>)
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,
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,
DisplayExecute,
DuplicateTermCall,
DuplicateTermExecute,
- Execute(Rc<Atom>, usize),
+ Execute(TabledRc<Atom>, usize),
ExecuteN(usize),
FunctorCall,
FunctorExecute,
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 {
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),
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),
#[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 {
}
}
- 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()),
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 {
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!(),
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)],
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),
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!(),
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),
]
}
-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)
}
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,
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);
// 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 {
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() {
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);
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 {
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 {
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 {
}
}
- 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
{
| &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)) =>
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};
}
pub struct MachineState {
+ pub(super) atom_tbl: TabledData<Atom>,
pub(super) s: usize,
pub(super) p: CodePtr,
pub(super) b: usize,
}
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,
};
}
- 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();
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()),
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())))
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;
}
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.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;
}
}
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.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;
}
}
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;
}
_ => 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;
}
}
_ => 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;
}
}
(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;
}
};
(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;
}
};
(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;
}
};
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;
}
}
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;
}
}
}
}
- 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);
};
}
- 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);
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;
}
},
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;
}
_ => 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)]));
}
}
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, []));
}
},
_ => {
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;
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
}
}
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, _)) =>
}
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) {
+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 {
() => (
)
}
+macro_rules! heap_atom {
+ ($name:expr, $tbl:expr) => (
+ HeapCellValue::Addr(Addr::Con(atom!($name, $tbl)))
+ )
+}
+
macro_rules! functor {
- ($name:expr, $len:expr, [$($args:expr),*]) => {{
+ ($tbl:expr, $name:expr, $len:expr, [$($args:expr),*]) => {{
if $len > 0 {
- vec![ HeapCellValue::NamedStr($len, Rc::new(String::from($name)), None), $($args),* ]
+ vec![ HeapCellValue::NamedStr($len,
+ tabled_rc!($name, $tbl),
+ None),
+ $($args),* ]
} else {
- vec![ atom!($name) ]
+ vec![ heap_atom!($name, $tbl) ]
}
}}
}
-macro_rules! atom {
- ($name:expr) => (
- HeapCellValue::Addr(Addr::Con(Constant::Atom(Rc::new(String::from($name)))))
- )
-}
-
macro_rules! fact {
[$($x:expr),+] => (
Line::Fact(vec![$($x),+])
}
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)
)
}
}
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)
)
}
pub mod or_stack;
pub mod parser;
pub mod targets;
+pub mod tabled_rc;
-Subproject commit dcf51680fb2f030ad2dcdd77237c8faedc8f7107
+Subproject commit 3b1dd579b411a440cc4b475471231fb6f9f2ada9
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> {
}
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);
}
}
}
use prolog::ast::*;
use prolog::iterators::*;
-
-use std::rc::Rc;
+use prolog::tabled_rc::*;
pub trait CompilationTarget<'a> {
type Iterator : Iterator<Item=TermRef<'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;
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)
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)
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;
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;
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(_, _) |
}
}
+#[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) =>
}
}
+#[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) =>
}
}
+#[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)))