add an atom table.

This commit is contained in:
Mark Thom
2018-01-16 23:26:59 -07:00
parent 38cd9e5db7
commit d8be7b5b49
14 changed files with 276 additions and 181 deletions

View File

@@ -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, []));
}
},
_ => {

View File

@@ -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) {