add db refs
This commit is contained in:
@@ -184,7 +184,7 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
self.copy_var(addr),
|
||||
Addr::Str(addr) =>
|
||||
self.copy_structure(addr),
|
||||
Addr::Con(_) =>
|
||||
Addr::Con(_) | Addr::DBRef(_) =>
|
||||
self.scan += 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,15 +7,22 @@ use prolog::forms::*;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::collections::{BTreeMap, HashMap, VecDeque};
|
||||
use std::mem;
|
||||
use std::ops::{Add, AddAssign, Sub, SubAssign};
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub enum DBRef {
|
||||
BuiltInPred(ClauseName, usize),
|
||||
NamedPred(ClauseName, usize)
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Addr {
|
||||
AttrVar(usize),
|
||||
Con(Constant),
|
||||
DBRef(DBRef),
|
||||
Lis(usize),
|
||||
HeapCell(usize),
|
||||
StackCell(usize, usize),
|
||||
@@ -502,7 +509,7 @@ impl IndexStore {
|
||||
}
|
||||
}
|
||||
|
||||
pub type CodeDir = HashMap<PredicateKey, CodeIndex>;
|
||||
pub type CodeDir = BTreeMap<PredicateKey, CodeIndex>;
|
||||
pub type TermDir = HashMap<PredicateKey, (Predicate, VecDeque<TopLevel>)>;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
|
||||
|
||||
@@ -628,7 +628,7 @@ impl MachineState {
|
||||
"+" => interms.push(a1 + a2),
|
||||
"-" => interms.push(a1 - a2),
|
||||
"*" => interms.push(a1 * a2),
|
||||
"/" => interms.push(self.div(a1, a2)?),
|
||||
"/" => interms.push(self.div(a1, a2)?),
|
||||
"**" => interms.push(self.pow(a1, a2)?),
|
||||
"max" => interms.push(self.max(a1, a2)?),
|
||||
"rdiv" => {
|
||||
@@ -850,10 +850,10 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
fn max(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
|
||||
fn max(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
|
||||
Ok(max(n1, n2))
|
||||
}
|
||||
|
||||
|
||||
fn remainder(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineStub>
|
||||
{
|
||||
let stub = MachineError::functor_stub(clause_name!("(rem)"), 2);
|
||||
@@ -923,7 +923,7 @@ impl MachineState {
|
||||
let n2 = try_or_fail!(self, self.get_number(a2));
|
||||
|
||||
self.interms[t - 1] = try_or_fail!(self, self.max(n1, n2));
|
||||
self.p += 1;
|
||||
self.p += 1;
|
||||
},
|
||||
&ArithmeticInstruction::Pow(ref a1, ref a2, t) => {
|
||||
let n1 = try_or_fail!(self, self.get_number(a1));
|
||||
@@ -1208,6 +1208,10 @@ impl MachineState {
|
||||
Addr::Con(_) => c,
|
||||
Addr::Lis(_) => l,
|
||||
Addr::Str(_) => s,
|
||||
Addr::DBRef(_) => {
|
||||
self.fail = true;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
match offset {
|
||||
@@ -1885,6 +1889,8 @@ impl MachineState {
|
||||
let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
|
||||
match a1.clone() {
|
||||
Addr::DBRef(_) =>
|
||||
self.fail = true,
|
||||
Addr::Con(_) =>
|
||||
self.try_functor_unify_components(a1, Addr::Con(integer!(0))),
|
||||
Addr::Str(o) =>
|
||||
@@ -2223,7 +2229,7 @@ impl MachineState {
|
||||
try_or_fail!(self, call_policy.compile_hook(self, hook)),
|
||||
&ClauseType::Inlined(ref ct) => {
|
||||
self.execute_inlined(ct);
|
||||
|
||||
|
||||
if lco {
|
||||
self.p = CodePtr::Local(self.cp);
|
||||
}
|
||||
|
||||
@@ -7,9 +7,11 @@ use prolog::machine::copier::*;
|
||||
use prolog::machine::machine_errors::*;
|
||||
use prolog::machine::machine_indices::*;
|
||||
use prolog::machine::machine_state::*;
|
||||
use prolog::num::{ToPrimitive, Zero};
|
||||
use prolog::num::{FromPrimitive, ToPrimitive, Zero};
|
||||
use prolog::num::bigint::{BigInt};
|
||||
|
||||
use ref_thread_local::RefThreadLocal;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::io::{stdout, Write};
|
||||
use std::mem;
|
||||
@@ -213,6 +215,57 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_next_db_ref(&mut self, db_ref: &DBRef, code_dir: &CodeDir) {
|
||||
match db_ref {
|
||||
&DBRef::BuiltInPred(ref name, arity) => {
|
||||
let key = (name.as_str(), arity);
|
||||
|
||||
match CLAUSE_TYPE_FORMS.borrow().range(&key ..).skip(1).next() {
|
||||
Some(((_, arity), ct)) => {
|
||||
let a2 = self[temp_v!(2)].clone();
|
||||
|
||||
if let Some(r) = a2.as_var() {
|
||||
self.bind(r, Addr::DBRef(DBRef::BuiltInPred(ct.name(), *arity)));
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
},
|
||||
None =>
|
||||
match code_dir.iter().next() {
|
||||
Some(((ref name, arity), _)) => {
|
||||
let a2 = self[temp_v!(2)].clone();
|
||||
|
||||
if let Some(r) = a2.as_var() {
|
||||
self.bind(r, Addr::DBRef(DBRef::NamedPred(name.clone(), *arity)));
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
},
|
||||
None => {
|
||||
self.fail = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
&DBRef::NamedPred(ref name, arity) => {
|
||||
let key = (name.clone(), arity);
|
||||
|
||||
match code_dir.range(key ..).skip(1).next() {
|
||||
Some(((name, arity), _)) => {
|
||||
let a2 = self[temp_v!(2)].clone();
|
||||
|
||||
if let Some(r) = a2.as_var() {
|
||||
self.bind(r, Addr::DBRef(DBRef::NamedPred(name.clone(), *arity)));
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
},
|
||||
None => self.fail = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn system_call(&mut self,
|
||||
ct: &SystemClauseType,
|
||||
indices: &mut IndexStore,
|
||||
@@ -462,27 +515,53 @@ impl MachineState {
|
||||
self.p = CodePtr::Local(LocalCodePtr::UserTermExpansion(0));
|
||||
return Ok(());
|
||||
},
|
||||
&SystemClauseType::GetCurrentPredicateList => {
|
||||
let mut addrs = vec![];
|
||||
&SystemClauseType::GetNextDBRef => {
|
||||
let a1 = self[temp_v!(1)].clone();
|
||||
|
||||
for ((name, arity), idx) in indices.code_dir.iter() {
|
||||
if idx.is_undefined() {
|
||||
continue;
|
||||
match self.store(self.deref(a1)) {
|
||||
addr @ Addr::HeapCell(_)
|
||||
| addr @ Addr::StackCell(..)
|
||||
| addr @ Addr::AttrVar(_) =>
|
||||
match CLAUSE_TYPE_FORMS.borrow().iter().next() {
|
||||
Some(((_, arity), ct)) => {
|
||||
let db_ref = DBRef::BuiltInPred(ct.name(), *arity);
|
||||
let r = addr.as_var().unwrap();
|
||||
|
||||
self.bind(r, Addr::DBRef(db_ref));
|
||||
},
|
||||
None => {
|
||||
self.fail = true;
|
||||
return Ok(());
|
||||
}
|
||||
},
|
||||
Addr::DBRef(ref db_ref) =>
|
||||
self.get_next_db_ref(db_ref, &indices.code_dir),
|
||||
_ => {
|
||||
self.fail = true;
|
||||
}
|
||||
};
|
||||
},
|
||||
&SystemClauseType::LookupDBRef => {
|
||||
let a1 = self[temp_v!(1)].clone();
|
||||
|
||||
let h = self.heap.h;
|
||||
match self.store(self.deref(a1)) {
|
||||
Addr::DBRef(db_ref) =>
|
||||
match db_ref {
|
||||
DBRef::BuiltInPred(name, arity) | DBRef::NamedPred(name, arity) => {
|
||||
let a2 = self[temp_v!(2)].clone();
|
||||
let a3 = self[temp_v!(3)].clone();
|
||||
|
||||
self.heap.push(HeapCellValue::NamedStr(2, clause_name!("/"), Some((400, YFX))));
|
||||
self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::Atom(name.clone(), None))));
|
||||
self.heap.push(heap_integer!(*arity));
|
||||
let arity = Number::Integer(Rc::new(BigInt::from_usize(arity).unwrap()));
|
||||
|
||||
addrs.push(Addr::Str(h));
|
||||
self.unify(a2, Addr::Con(Constant::Atom(name, None)));
|
||||
|
||||
if !self.fail {
|
||||
self.unify(a3, Addr::Con(Constant::Number(arity)));
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => self.fail = true
|
||||
}
|
||||
|
||||
let list_addr = Addr::HeapCell(self.heap.to_list(addrs.into_iter()));
|
||||
let target_addr = self[temp_v!(1)].clone();
|
||||
|
||||
self.unify(list_addr, target_addr);
|
||||
},
|
||||
&SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff =>
|
||||
self.truncate_if_no_lifted_heap_diff(|h| Addr::HeapCell(h)),
|
||||
|
||||
Reference in New Issue
Block a user