Format code using 'cargo fmt'
This commit is contained in:
@@ -10,7 +10,7 @@ pub struct Frame {
|
||||
pub e: usize,
|
||||
pub cp: LocalCodePtr,
|
||||
pub interrupt_cp: LocalCodePtr,
|
||||
perms: Vec<Addr>
|
||||
perms: Vec<Addr>,
|
||||
}
|
||||
|
||||
impl Frame {
|
||||
@@ -20,7 +20,7 @@ impl Frame {
|
||||
e: e,
|
||||
cp: cp,
|
||||
interrupt_cp: LocalCodePtr::default(),
|
||||
perms: (1 .. n+1).map(|i| Addr::StackCell(fr, i)).collect()
|
||||
perms: (1..n + 1).map(|i| Addr::StackCell(fr, i)).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ impl AndStack {
|
||||
pub(crate) fn take(&mut self) -> Self {
|
||||
AndStack(mem::replace(&mut self.0, vec![]))
|
||||
}
|
||||
|
||||
|
||||
pub fn push(&mut self, global_index: usize, e: usize, cp: LocalCodePtr, n: usize) {
|
||||
let len = self.0.len();
|
||||
self.0.push(Frame::new(global_index, len, e, cp, n));
|
||||
@@ -61,7 +61,7 @@ impl AndStack {
|
||||
if len < n {
|
||||
self[fr].perms.reserve(n - len);
|
||||
|
||||
for i in len .. n {
|
||||
for i in len..n {
|
||||
self[fr].perms.push(Addr::StackCell(fr, i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use indexmap::IndexSet;
|
||||
|
||||
use std::vec::IntoIter;
|
||||
|
||||
pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
|
||||
pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl");
|
||||
pub static PROJECT_ATTRS: &str = include_str!("project_attributes.pl");
|
||||
|
||||
pub(super) type Bindings = Vec<(usize, Addr)>;
|
||||
@@ -26,7 +26,7 @@ impl AttrVarInitializer {
|
||||
bindings: vec![],
|
||||
cp: LocalCodePtr::default(),
|
||||
verify_attrs_loc,
|
||||
project_attrs_loc
|
||||
project_attrs_loc,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,7 @@ impl AttrVarInitializer {
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr)
|
||||
{
|
||||
pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr) {
|
||||
if self.attr_var_init.bindings.is_empty() {
|
||||
self.attr_var_init.cp = self.p.local();
|
||||
self.p = CodePtr::VerifyAttrInterrupt(self.attr_var_init.verify_attrs_loc);
|
||||
@@ -49,17 +48,24 @@ impl MachineState {
|
||||
}
|
||||
|
||||
fn populate_var_and_value_lists(&mut self) -> (Addr, Addr) {
|
||||
let iter = self.attr_var_init.bindings.iter().map(|(ref h, _)| Addr::AttrVar(*h));
|
||||
let iter = self
|
||||
.attr_var_init
|
||||
.bindings
|
||||
.iter()
|
||||
.map(|(ref h, _)| Addr::AttrVar(*h));
|
||||
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||
|
||||
let iter = self.attr_var_init.bindings.iter().map(|(_, ref addr)| addr.clone());
|
||||
let iter = self
|
||||
.attr_var_init
|
||||
.bindings
|
||||
.iter()
|
||||
.map(|(_, ref addr)| addr.clone());
|
||||
let value_list_addr = Addr::HeapCell(self.heap.to_list(iter));
|
||||
|
||||
(var_list_addr, value_list_addr)
|
||||
}
|
||||
|
||||
fn verify_attributes(&mut self)
|
||||
{
|
||||
fn verify_attributes(&mut self) {
|
||||
for (h, _) in &self.attr_var_init.bindings {
|
||||
self.heap[*h] = HeapCellValue::Addr(Addr::AttrVar(*h));
|
||||
}
|
||||
@@ -70,15 +76,14 @@ impl MachineState {
|
||||
self[temp_v!(2)] = value_list_addr;
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter<Addr>
|
||||
{
|
||||
let mut attr_vars: Vec<_> = self.attr_var_init.attr_var_queue[b ..]
|
||||
.iter().filter_map(|h|
|
||||
match self.store(self.deref(Addr::HeapCell(*h))) {
|
||||
Addr::AttrVar(h) => Some(Addr::AttrVar(h)),
|
||||
_ => None
|
||||
}).collect();
|
||||
pub(super) fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter<Addr> {
|
||||
let mut attr_vars: Vec<_> = self.attr_var_init.attr_var_queue[b..]
|
||||
.iter()
|
||||
.filter_map(|h| match self.store(self.deref(Addr::HeapCell(*h))) {
|
||||
Addr::AttrVar(h) => Some(Addr::AttrVar(h)),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
attr_vars.sort_unstable_by(|a1, a2| self.compare_term_test(a1, a2));
|
||||
|
||||
@@ -86,8 +91,7 @@ impl MachineState {
|
||||
attr_vars.into_iter()
|
||||
}
|
||||
|
||||
fn populate_project_attr_lists(&mut self) -> (Addr, Addr)
|
||||
{
|
||||
fn populate_project_attr_lists(&mut self) -> (Addr, Addr) {
|
||||
let mut query_vars = IndexSet::new();
|
||||
let attr_vars = self.gather_attr_vars_created_since(0);
|
||||
|
||||
@@ -98,23 +102,22 @@ impl MachineState {
|
||||
match value {
|
||||
HeapCellValue::Addr(Addr::HeapCell(h)) => {
|
||||
query_vars.insert(Addr::HeapCell(h));
|
||||
},
|
||||
}
|
||||
HeapCellValue::Addr(Addr::StackCell(fr, sc)) => {
|
||||
query_vars.insert(Addr::StackCell(fr, sc));
|
||||
},
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let query_var_list = Addr::HeapCell(self.heap.to_list(query_vars.into_iter()));
|
||||
let attr_var_list = Addr::HeapCell(self.heap.to_list(attr_vars));
|
||||
let attr_var_list = Addr::HeapCell(self.heap.to_list(attr_vars));
|
||||
|
||||
(query_var_list, attr_var_list)
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn verify_attr_interrupt(&mut self, p: usize) {
|
||||
pub(super) fn verify_attr_interrupt(&mut self, p: usize) {
|
||||
let rs = MAX_ARITY;
|
||||
|
||||
// store temp vars in perm vars slots along with self.b0 and
|
||||
@@ -127,7 +130,7 @@ impl MachineState {
|
||||
let e = self.e;
|
||||
self.and_stack[e].interrupt_cp = self.attr_var_init.cp;
|
||||
|
||||
for i in 1 .. rs + 1 {
|
||||
for i in 1..rs + 1 {
|
||||
self.and_stack[e][i] = self[RegType::Temp(i)].clone();
|
||||
}
|
||||
|
||||
@@ -141,8 +144,7 @@ impl MachineState {
|
||||
self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
|
||||
}
|
||||
|
||||
fn print_attribute_goals_string(&mut self, op_dir: &OpDir) -> String
|
||||
{
|
||||
fn print_attribute_goals_string(&mut self, op_dir: &OpDir) -> String {
|
||||
let mut attr_goals = mem::replace(&mut self.attr_var_init.attribute_goals, vec![]);
|
||||
|
||||
if attr_goals.is_empty() {
|
||||
@@ -174,9 +176,7 @@ impl MachineState {
|
||||
}
|
||||
|
||||
impl Machine {
|
||||
pub
|
||||
fn attribute_goals(&mut self) -> String
|
||||
{
|
||||
pub fn attribute_goals(&mut self) -> String {
|
||||
let p = self.machine_st.attr_var_init.project_attrs_loc;
|
||||
let (query_vars, attr_vars) = self.machine_st.populate_project_attr_lists();
|
||||
|
||||
@@ -186,9 +186,14 @@ impl Machine {
|
||||
self.machine_st[temp_v!(2)] = attr_vars;
|
||||
|
||||
self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
|
||||
self.machine_st.query_stepper(&mut self.indices, &mut self.policies, &mut self.code_repo,
|
||||
&mut readline::input_stream());
|
||||
self.machine_st.query_stepper(
|
||||
&mut self.indices,
|
||||
&mut self.policies,
|
||||
&mut self.code_repo,
|
||||
&mut readline::input_stream(),
|
||||
);
|
||||
|
||||
self.machine_st.print_attribute_goals_string(&self.indices.op_dir)
|
||||
self.machine_st
|
||||
.print_attribute_goals_string(&self.indices.op_dir)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ pub struct CodeRepo {
|
||||
pub(super) term_expanders: Code,
|
||||
pub(super) code: Code,
|
||||
pub(super) in_situ_code: Code,
|
||||
pub(super) term_dir: TermDir
|
||||
pub(super) term_dir: TermDir,
|
||||
}
|
||||
|
||||
impl CodeRepo {
|
||||
@@ -29,36 +29,51 @@ impl CodeRepo {
|
||||
term_expanders: Code::new(),
|
||||
code: Code::new(),
|
||||
in_situ_code: Code::new(),
|
||||
term_dir: TermDir::new()
|
||||
term_dir: TermDir::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn term_dir_entry_len(&self, key: PredicateKey) -> (usize, usize) {
|
||||
self.term_dir.get(&key)
|
||||
.map(|entry| ((entry.0).0.len(), entry.1.len()))
|
||||
.unwrap_or((0,0))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn truncate_terms(&mut self, key: PredicateKey, len: usize, queue_len: usize)
|
||||
-> (Predicate, VecDeque<TopLevel>)
|
||||
{
|
||||
self.term_dir.get_mut(&key)
|
||||
.map(|entry| (Predicate((entry.0).0.drain(len ..).collect()),
|
||||
entry.1.drain(queue_len ..).collect()))
|
||||
pub fn term_dir_entry_len(&self, key: PredicateKey) -> (usize, usize) {
|
||||
self.term_dir
|
||||
.get(&key)
|
||||
.map(|entry| ((entry.0).0.len(), entry.1.len()))
|
||||
.unwrap_or((0, 0))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn truncate_terms(
|
||||
&mut self,
|
||||
key: PredicateKey,
|
||||
len: usize,
|
||||
queue_len: usize,
|
||||
) -> (Predicate, VecDeque<TopLevel>) {
|
||||
self.term_dir
|
||||
.get_mut(&key)
|
||||
.map(|entry| {
|
||||
(
|
||||
Predicate((entry.0).0.drain(len..).collect()),
|
||||
entry.1.drain(queue_len..).collect(),
|
||||
)
|
||||
})
|
||||
.unwrap_or((Predicate::new(), VecDeque::from(vec![])))
|
||||
}
|
||||
|
||||
pub fn add_in_situ_result(&mut self, result: &CompiledResult, in_situ_code_dir: &mut InSituCodeDir,
|
||||
flags: MachineFlags)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
pub fn add_in_situ_result(
|
||||
&mut self,
|
||||
result: &CompiledResult,
|
||||
in_situ_code_dir: &mut InSituCodeDir,
|
||||
flags: MachineFlags,
|
||||
) -> Result<(), SessionError> {
|
||||
let (ref decl, ref queue) = result;
|
||||
let (name, arity) = decl.0.first().and_then(|cl| {
|
||||
let arity = cl.arity();
|
||||
cl.name().map(|name| (name, arity))
|
||||
}).ok_or(SessionError::NamelessEntry)?;
|
||||
let (name, arity) = decl
|
||||
.0
|
||||
.first()
|
||||
.and_then(|cl| {
|
||||
let arity = cl.arity();
|
||||
cl.name().map(|name| (name, arity))
|
||||
})
|
||||
.ok_or(SessionError::NamelessEntry)?;
|
||||
|
||||
let p = self.in_situ_code.len();
|
||||
in_situ_code_dir.insert((name, arity), p);
|
||||
@@ -74,53 +89,57 @@ impl CodeRepo {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super)
|
||||
fn size_of_cached_query(&self) -> usize {
|
||||
pub(super) fn size_of_cached_query(&self) -> usize {
|
||||
self.cached_query.len()
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn lookup_instr<'a>(&'a self, last_call: bool, p: &CodePtr) -> Option<RefOrOwned<'a, Line>>
|
||||
{
|
||||
pub(super) fn lookup_instr<'a>(
|
||||
&'a self,
|
||||
last_call: bool,
|
||||
p: &CodePtr,
|
||||
) -> Option<RefOrOwned<'a, Line>> {
|
||||
match p {
|
||||
&CodePtr::Local(LocalCodePtr::UserGoalExpansion(p)) =>
|
||||
&CodePtr::Local(LocalCodePtr::UserGoalExpansion(p)) => {
|
||||
if p < self.goal_expanders.len() {
|
||||
Some(RefOrOwned::Borrowed(&self.goal_expanders[p]))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
&CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) =>
|
||||
}
|
||||
}
|
||||
&CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) => {
|
||||
if p < self.term_expanders.len() {
|
||||
Some(RefOrOwned::Borrowed(&self.term_expanders[p]))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
&CodePtr::Local(LocalCodePtr::TopLevel(_, p)) =>
|
||||
}
|
||||
}
|
||||
&CodePtr::Local(LocalCodePtr::TopLevel(_, p)) => {
|
||||
if p < self.cached_query.len() {
|
||||
Some(RefOrOwned::Borrowed(&self.cached_query[p]))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
&CodePtr::Local(LocalCodePtr::InSituDirEntry(p)) =>
|
||||
Some(RefOrOwned::Borrowed(&self.in_situ_code[p])),
|
||||
&CodePtr::Local(LocalCodePtr::DirEntry(p)) =>
|
||||
Some(RefOrOwned::Borrowed(&self.code[p])),
|
||||
&CodePtr::REPL(..) =>
|
||||
None,
|
||||
}
|
||||
}
|
||||
&CodePtr::Local(LocalCodePtr::InSituDirEntry(p)) => {
|
||||
Some(RefOrOwned::Borrowed(&self.in_situ_code[p]))
|
||||
}
|
||||
&CodePtr::Local(LocalCodePtr::DirEntry(p)) => Some(RefOrOwned::Borrowed(&self.code[p])),
|
||||
&CodePtr::REPL(..) => None,
|
||||
&CodePtr::BuiltInClause(ref built_in, _) => {
|
||||
let call_clause = call_clause!(ClauseType::BuiltIn(built_in.clone()),
|
||||
built_in.arity(),
|
||||
0, last_call);
|
||||
let call_clause = call_clause!(
|
||||
ClauseType::BuiltIn(built_in.clone()),
|
||||
built_in.arity(),
|
||||
0,
|
||||
last_call
|
||||
);
|
||||
Some(RefOrOwned::Owned(call_clause))
|
||||
},
|
||||
}
|
||||
&CodePtr::CallN(arity, _) => {
|
||||
let call_clause = call_clause!(ClauseType::CallN, arity, 0, last_call);
|
||||
Some(RefOrOwned::Owned(call_clause))
|
||||
},
|
||||
&CodePtr::VerifyAttrInterrupt(p) =>
|
||||
Some(RefOrOwned::Borrowed(&self.code[p])),
|
||||
&CodePtr::DynamicTransaction(..) =>
|
||||
None
|
||||
}
|
||||
&CodePtr::VerifyAttrInterrupt(p) => Some(RefOrOwned::Borrowed(&self.code[p])),
|
||||
&CodePtr::DynamicTransaction(..) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,8 +5,7 @@ use std::ops::IndexMut;
|
||||
|
||||
type Trail = Vec<(Ref, HeapCellValue)>;
|
||||
|
||||
pub(crate) trait CopierTarget: IndexMut<usize, Output=HeapCellValue>
|
||||
{
|
||||
pub(crate) trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
|
||||
fn threshold(&self) -> usize;
|
||||
fn push(&mut self, HeapCellValue);
|
||||
fn store(&self, Addr) -> Addr;
|
||||
@@ -14,9 +13,7 @@ pub(crate) trait CopierTarget: IndexMut<usize, Output=HeapCellValue>
|
||||
fn stack(&mut self) -> &mut AndStack;
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn copy_term<T: CopierTarget>(target: T, addr: Addr)
|
||||
{
|
||||
pub(crate) fn copy_term<T: CopierTarget>(target: T, addr: Addr) {
|
||||
let mut copy_term_state = CopyTermState::new(target);
|
||||
copy_term_state.copy_term_impl(addr);
|
||||
}
|
||||
@@ -25,16 +22,16 @@ struct CopyTermState<T: CopierTarget> {
|
||||
trail: Trail,
|
||||
scan: usize,
|
||||
old_h: usize,
|
||||
target: T
|
||||
target: T,
|
||||
}
|
||||
|
||||
impl<T: CopierTarget> CopyTermState<T> {
|
||||
fn new(target: T) -> Self {
|
||||
CopyTermState {
|
||||
trail: vec![],
|
||||
scan: 0,
|
||||
scan: 0,
|
||||
old_h: target.threshold(),
|
||||
target
|
||||
target,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,24 +41,28 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
&mut self.target[scan]
|
||||
}
|
||||
|
||||
fn reinstantiate_var(&mut self, addr: Addr, threshold: usize)
|
||||
{
|
||||
fn reinstantiate_var(&mut self, addr: Addr, threshold: usize) {
|
||||
match addr {
|
||||
Addr::HeapCell(h) => {
|
||||
self.target[threshold] = HeapCellValue::Addr(Addr::HeapCell(threshold));
|
||||
self.target[h] = HeapCellValue::Addr(Addr::HeapCell(threshold));
|
||||
self.trail.push((Ref::HeapCell(h), HeapCellValue::Addr(Addr::HeapCell(h))));
|
||||
},
|
||||
self.trail
|
||||
.push((Ref::HeapCell(h), HeapCellValue::Addr(Addr::HeapCell(h))));
|
||||
}
|
||||
Addr::StackCell(fr, sc) => {
|
||||
self.target[threshold] = HeapCellValue::Addr(Addr::HeapCell(threshold));
|
||||
self.target.stack()[fr][sc] = Addr::HeapCell(threshold);
|
||||
self.trail.push((Ref::StackCell(fr, sc), HeapCellValue::Addr(Addr::StackCell(fr, sc))));
|
||||
},
|
||||
self.trail.push((
|
||||
Ref::StackCell(fr, sc),
|
||||
HeapCellValue::Addr(Addr::StackCell(fr, sc)),
|
||||
));
|
||||
}
|
||||
Addr::AttrVar(h) => {
|
||||
self.target[threshold] = HeapCellValue::Addr(Addr::AttrVar(threshold));
|
||||
self.target[h] = HeapCellValue::Addr(Addr::AttrVar(threshold));
|
||||
self.trail.push((Ref::AttrVar(h), HeapCellValue::Addr(Addr::AttrVar(h))));
|
||||
},
|
||||
self.trail
|
||||
.push((Ref::AttrVar(h), HeapCellValue::Addr(Addr::AttrVar(h))));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -93,16 +94,19 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
let rd = self.target.store(self.target.deref(ra));
|
||||
|
||||
match rd.clone() {
|
||||
Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h =>
|
||||
self.target[threshold] = HeapCellValue::Addr(rd),
|
||||
ra @ Addr::AttrVar(_) | ra @ Addr::HeapCell(..) | ra @ Addr::StackCell(..) =>
|
||||
Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h => {
|
||||
self.target[threshold] = HeapCellValue::Addr(rd)
|
||||
}
|
||||
ra @ Addr::AttrVar(_) | ra @ Addr::HeapCell(..) | ra @ Addr::StackCell(..) => {
|
||||
if ra == rd {
|
||||
self.reinstantiate_var(ra, threshold);
|
||||
} else {
|
||||
self.target[threshold] = HeapCellValue::Addr(ra);
|
||||
},
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.trail.push((Ref::HeapCell(addr), self.target[addr].clone()));
|
||||
self.trail
|
||||
.push((Ref::HeapCell(addr), self.target[addr].clone()));
|
||||
self.target[addr] = HeapCellValue::Addr(Addr::Lis(threshold))
|
||||
}
|
||||
};
|
||||
@@ -120,23 +124,24 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
Addr::AttrVar(h) | Addr::HeapCell(h) if h >= self.old_h => {
|
||||
*self.value_at_scan() = HeapCellValue::Addr(rd);
|
||||
self.scan += 1;
|
||||
},
|
||||
}
|
||||
Addr::AttrVar(h) if addr == rd => {
|
||||
let threshold = self.target.threshold();
|
||||
self.target.push(HeapCellValue::Addr(Addr::AttrVar(threshold)));
|
||||
self.target
|
||||
.push(HeapCellValue::Addr(Addr::AttrVar(threshold)));
|
||||
|
||||
let list_val = self.target[h + 1].clone();
|
||||
self.target.push(list_val);
|
||||
|
||||
self.reinstantiate_var(addr, threshold);
|
||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::AttrVar(threshold));
|
||||
},
|
||||
}
|
||||
_ if addr == rd => {
|
||||
let scan = self.scan;
|
||||
self.reinstantiate_var(addr, scan);
|
||||
self.scan += 1;
|
||||
},
|
||||
_ => *self.value_at_scan() = HeapCellValue::Addr(rd)
|
||||
}
|
||||
_ => *self.value_at_scan() = HeapCellValue::Addr(rd),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,18 +153,22 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::Str(threshold));
|
||||
self.target[addr] = HeapCellValue::Addr(Addr::Str(threshold));
|
||||
|
||||
self.trail.push((Ref::HeapCell(addr),
|
||||
HeapCellValue::NamedStr(arity, name.clone(), fixity.clone())));
|
||||
self.trail.push((
|
||||
Ref::HeapCell(addr),
|
||||
HeapCellValue::NamedStr(arity, name.clone(), fixity.clone()),
|
||||
));
|
||||
|
||||
self.target.push(HeapCellValue::NamedStr(arity, name, fixity));
|
||||
self.target
|
||||
.push(HeapCellValue::NamedStr(arity, name, fixity));
|
||||
|
||||
for i in 0 .. arity {
|
||||
for i in 0..arity {
|
||||
let hcv = self.target[addr + 1 + i].clone();
|
||||
self.target.push(hcv);
|
||||
}
|
||||
},
|
||||
HeapCellValue::Addr(Addr::Str(addr)) =>
|
||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::Str(addr)),
|
||||
}
|
||||
HeapCellValue::Addr(Addr::Str(addr)) => {
|
||||
*self.value_at_scan() = HeapCellValue::Addr(Addr::Str(addr))
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -172,21 +181,15 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
|
||||
while self.scan < self.target.threshold() {
|
||||
match self.value_at_scan().clone() {
|
||||
HeapCellValue::NamedStr(..) =>
|
||||
self.scan += 1,
|
||||
HeapCellValue::Addr(addr) =>
|
||||
match addr {
|
||||
Addr::Lis(addr) =>
|
||||
self.copy_list(addr),
|
||||
addr @ Addr::AttrVar(_)
|
||||
| addr @ Addr::HeapCell(_)
|
||||
| addr @ Addr::StackCell(..) =>
|
||||
self.copy_var(addr),
|
||||
Addr::Str(addr) =>
|
||||
self.copy_structure(addr),
|
||||
Addr::Con(_) | Addr::DBRef(_) =>
|
||||
self.scan += 1
|
||||
}
|
||||
HeapCellValue::NamedStr(..) => self.scan += 1,
|
||||
HeapCellValue::Addr(addr) => match addr {
|
||||
Addr::Lis(addr) => self.copy_list(addr),
|
||||
addr @ Addr::AttrVar(_)
|
||||
| addr @ Addr::HeapCell(_)
|
||||
| addr @ Addr::StackCell(..) => self.copy_var(addr),
|
||||
Addr::Str(addr) => self.copy_structure(addr),
|
||||
Addr::Con(_) | Addr::DBRef(_) => self.scan += 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,12 +197,10 @@ impl<T: CopierTarget> CopyTermState<T> {
|
||||
}
|
||||
|
||||
fn unwind_trail(&mut self) {
|
||||
for (r, value) in self.trail.drain(0 ..) {
|
||||
for (r, value) in self.trail.drain(0..) {
|
||||
match r {
|
||||
Ref::AttrVar(h) | Ref::HeapCell(h) =>
|
||||
self.target[h] = value,
|
||||
Ref::StackCell(fr, sc) =>
|
||||
self.target.stack()[fr][sc] = value.as_addr(0)
|
||||
Ref::AttrVar(h) | Ref::HeapCell(h) => self.target[h] = value,
|
||||
Ref::StackCell(fr, sc) => self.target.stack()[fr][sc] = value.as_addr(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
use prolog_parser::ast::*;
|
||||
|
||||
use prolog::heap_print::*;
|
||||
use prolog::machine::*;
|
||||
use prolog::machine::compile::*;
|
||||
use prolog::machine::machine_errors::*;
|
||||
use prolog::machine::*;
|
||||
|
||||
use std::io::Read;
|
||||
|
||||
impl Machine {
|
||||
pub(super)
|
||||
fn atom_tbl_of(&self, name: &ClauseName) -> TabledData<Atom> {
|
||||
pub(super) fn atom_tbl_of(&self, name: &ClauseName) -> TabledData<Atom> {
|
||||
match name {
|
||||
&ClauseName::User(ref rc) => rc.table.clone(),
|
||||
_ => self.indices.atom_tbl()
|
||||
_ => self.indices.atom_tbl(),
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_into_machine<R: Read>(&mut self, src: ParsingStream<R>, name: ClauseName, arity: usize)
|
||||
-> EvalSession
|
||||
{
|
||||
fn compile_into_machine<R: Read>(
|
||||
&mut self,
|
||||
src: ParsingStream<R>,
|
||||
name: ClauseName,
|
||||
arity: usize,
|
||||
) -> EvalSession {
|
||||
match name.owning_module().as_str() {
|
||||
"user" => match self.indices.code_dir.get(&(name.clone(), arity)).cloned() {
|
||||
Some(idx) => {
|
||||
@@ -26,37 +28,38 @@ impl Machine {
|
||||
|
||||
match module.as_str() {
|
||||
"user" => compile_user_module(self, src),
|
||||
_ => compile_into_module(self, module, src, name)
|
||||
_ => compile_into_module(self, module, src, name),
|
||||
}
|
||||
},
|
||||
None => compile_user_module(self, src)
|
||||
}
|
||||
None => compile_user_module(self, src),
|
||||
},
|
||||
_ => compile_into_module(self, name.owning_module(), src, name)
|
||||
_ => compile_into_module(self, name.owning_module(), src, name),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_predicate_key(&self, name: RegType, arity: RegType) -> PredicateKey
|
||||
{
|
||||
let name = self.machine_st[name].clone();
|
||||
fn get_predicate_key(&self, name: RegType, arity: RegType) -> PredicateKey {
|
||||
let name = self.machine_st[name].clone();
|
||||
let arity = self.machine_st[arity].clone();
|
||||
|
||||
let name = match self.machine_st.store(self.machine_st.deref(name)) {
|
||||
Addr::Con(Constant::Atom(name, _)) => name,
|
||||
_ => unreachable!()
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
|
||||
Addr::Con(Constant::Integer(arity)) =>
|
||||
arity.to_usize().unwrap(),
|
||||
_ => unreachable!()
|
||||
Addr::Con(Constant::Integer(arity)) => arity.to_usize().unwrap(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
(name, arity)
|
||||
}
|
||||
|
||||
fn print_new_dynamic_clause(&self, addrs: VecDeque<Addr>, name: ClauseName, arity: usize)
|
||||
-> String
|
||||
{
|
||||
fn print_new_dynamic_clause(
|
||||
&self,
|
||||
addrs: VecDeque<Addr>,
|
||||
name: ClauseName,
|
||||
arity: usize,
|
||||
) -> String {
|
||||
let mut output = PrinterOutputter::new();
|
||||
output.append(format!(":- dynamic({}/{}). ", name.as_str(), arity).as_str());
|
||||
|
||||
@@ -71,8 +74,7 @@ impl Machine {
|
||||
output.result()
|
||||
}
|
||||
|
||||
fn abolish_dynamic_clause(&mut self, name: RegType, arity: RegType)
|
||||
{
|
||||
fn abolish_dynamic_clause(&mut self, name: RegType, arity: RegType) {
|
||||
let (name, arity) = self.get_predicate_key(name, arity);
|
||||
|
||||
if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) {
|
||||
@@ -80,27 +82,26 @@ impl Machine {
|
||||
}
|
||||
|
||||
self.indices.remove_code_index((name.clone(), arity));
|
||||
self.indices.remove_clause_subsection(name.owning_module(), name, arity);
|
||||
self.indices
|
||||
.remove_clause_subsection(name.owning_module(), name, arity);
|
||||
}
|
||||
|
||||
fn abolish_dynamic_clause_in_module(&mut self, name: RegType, arity: RegType, module: RegType)
|
||||
{
|
||||
fn abolish_dynamic_clause_in_module(&mut self, name: RegType, arity: RegType, module: RegType) {
|
||||
let (name, arity) = self.get_predicate_key(name, arity);
|
||||
let module_addr = self.machine_st[module].clone();
|
||||
|
||||
let module_name = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
||||
Addr::Con(Constant::Atom(module, _)) =>
|
||||
match self.indices.modules.get_mut(&module) {
|
||||
Some(ref mut module) => {
|
||||
module.code_dir.remove(&(name.clone(), arity));
|
||||
module.module_decl.name.clone()
|
||||
},
|
||||
_ => {
|
||||
self.machine_st.fail = true;
|
||||
return;
|
||||
}
|
||||
},
|
||||
_ => unreachable!()
|
||||
Addr::Con(Constant::Atom(module, _)) => match self.indices.modules.get_mut(&module) {
|
||||
Some(ref mut module) => {
|
||||
module.code_dir.remove(&(name.clone(), arity));
|
||||
module.module_decl.name.clone()
|
||||
}
|
||||
_ => {
|
||||
self.machine_st.fail = true;
|
||||
return;
|
||||
}
|
||||
},
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if let Some(idx) = self.indices.code_dir.get(&(name.clone(), arity)) {
|
||||
@@ -110,30 +111,38 @@ impl Machine {
|
||||
}
|
||||
|
||||
self.indices.remove_code_index((name.clone(), arity));
|
||||
self.indices.remove_clause_subsection(module_name, name, arity);
|
||||
self.indices
|
||||
.remove_clause_subsection(module_name, name, arity);
|
||||
}
|
||||
|
||||
fn handle_eval_result_from_dynamic_compile(&mut self, pred_str: String, name: ClauseName,
|
||||
arity: usize, src: ClauseName)
|
||||
{
|
||||
fn handle_eval_result_from_dynamic_compile(
|
||||
&mut self,
|
||||
pred_str: String,
|
||||
name: ClauseName,
|
||||
arity: usize,
|
||||
src: ClauseName,
|
||||
) {
|
||||
let machine_st = mem::replace(&mut self.machine_st, MachineState::new());
|
||||
|
||||
let result = self.compile_into_machine(parsing_stream(pred_str.as_bytes()), name, arity);
|
||||
self.machine_st = machine_st;
|
||||
|
||||
if let EvalSession::Error(err) = result {
|
||||
let h = self.machine_st.heap.h;
|
||||
let h = self.machine_st.heap.h;
|
||||
let stub = MachineError::functor_stub(src, 1);
|
||||
let err = MachineError::session_error(h, err);
|
||||
let err = self.machine_st.error_form(err, stub);
|
||||
let err = MachineError::session_error(h, err);
|
||||
let err = self.machine_st.error_form(err, stub);
|
||||
|
||||
self.machine_st.throw_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
fn recompile_dynamic_predicate_impl(&mut self, place: DynamicAssertPlace, name: ClauseName,
|
||||
arity: usize)
|
||||
{
|
||||
fn recompile_dynamic_predicate_impl(
|
||||
&mut self,
|
||||
place: DynamicAssertPlace,
|
||||
name: ClauseName,
|
||||
arity: usize,
|
||||
) {
|
||||
let stub = MachineError::functor_stub(place.predicate_name(), 1);
|
||||
let pred_str = match self.machine_st.try_from_list(temp_v!(2), stub) {
|
||||
Ok(addrs) => {
|
||||
@@ -142,26 +151,23 @@ impl Machine {
|
||||
|
||||
place.push_to_queue(&mut addrs, added_clause);
|
||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||
},
|
||||
Err(err) =>
|
||||
return self.machine_st.throw_exception(err)
|
||||
}
|
||||
Err(err) => return self.machine_st.throw_exception(err),
|
||||
};
|
||||
|
||||
self.handle_eval_result_from_dynamic_compile(pred_str, name, arity, place.predicate_name());
|
||||
}
|
||||
|
||||
fn set_module_atom_tbl(&mut self, module_addr: Addr, name: &mut ClauseName) -> bool
|
||||
{
|
||||
fn set_module_atom_tbl(&mut self, module_addr: Addr, name: &mut ClauseName) -> bool {
|
||||
let atom_tbl = match self.machine_st.store(self.machine_st.deref(module_addr)) {
|
||||
Addr::Con(Constant::Atom(module, _)) =>
|
||||
match self.indices.modules.get(&module) {
|
||||
Some(ref module) => module.atom_tbl.clone(),
|
||||
None => {
|
||||
self.machine_st.fail = true;
|
||||
return false;
|
||||
}
|
||||
},
|
||||
_ => unreachable!()
|
||||
Addr::Con(Constant::Atom(module, _)) => match self.indices.modules.get(&module) {
|
||||
Some(ref module) => module.atom_tbl.clone(),
|
||||
None => {
|
||||
self.machine_st.fail = true;
|
||||
return false;
|
||||
}
|
||||
},
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if let &mut ClauseName::User(ref mut rc) = name {
|
||||
@@ -171,8 +177,7 @@ impl Machine {
|
||||
true
|
||||
}
|
||||
|
||||
fn recompile_dynamic_predicate_in_module(&mut self, place: DynamicAssertPlace)
|
||||
{
|
||||
fn recompile_dynamic_predicate_in_module(&mut self, place: DynamicAssertPlace) {
|
||||
let (mut name, arity) = self.get_predicate_key(temp_v!(3), temp_v!(4));
|
||||
let module_addr = self.machine_st[temp_v!(5)].clone();
|
||||
|
||||
@@ -181,18 +186,16 @@ impl Machine {
|
||||
}
|
||||
}
|
||||
|
||||
fn recompile_dynamic_predicate(&mut self, place: DynamicAssertPlace)
|
||||
{
|
||||
fn recompile_dynamic_predicate(&mut self, place: DynamicAssertPlace) {
|
||||
let (name, arity) = self.get_predicate_key(temp_v!(3), temp_v!(4));
|
||||
self.recompile_dynamic_predicate_impl(place, name, arity);
|
||||
}
|
||||
|
||||
fn retract_from_dynamic_predicate_in_module(&mut self)
|
||||
{
|
||||
fn retract_from_dynamic_predicate_in_module(&mut self) {
|
||||
let index = self.machine_st[temp_v!(3)].clone();
|
||||
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
||||
Addr::Con(Constant::Integer(n)) => n.to_usize().unwrap(),
|
||||
_ => unreachable!()
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let (mut name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
|
||||
@@ -206,28 +209,29 @@ impl Machine {
|
||||
addrs.remove(index);
|
||||
|
||||
if addrs.is_empty() {
|
||||
self.abolish_dynamic_clause_in_module(temp_v!(1), temp_v!(2),
|
||||
temp_v!(5));
|
||||
self.abolish_dynamic_clause_in_module(temp_v!(1), temp_v!(2), temp_v!(5));
|
||||
return;
|
||||
}
|
||||
|
||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||
},
|
||||
Err(err) =>
|
||||
return self.machine_st.throw_exception(err)
|
||||
}
|
||||
Err(err) => return self.machine_st.throw_exception(err),
|
||||
};
|
||||
|
||||
self.handle_eval_result_from_dynamic_compile(pred_str, name, arity,
|
||||
clause_name!("retract"));
|
||||
self.handle_eval_result_from_dynamic_compile(
|
||||
pred_str,
|
||||
name,
|
||||
arity,
|
||||
clause_name!("retract"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn retract_from_dynamic_predicate(&mut self)
|
||||
{
|
||||
fn retract_from_dynamic_predicate(&mut self) {
|
||||
let index = self.machine_st[temp_v!(3)].clone();
|
||||
let index = match self.machine_st.store(self.machine_st.deref(index)) {
|
||||
Addr::Con(Constant::Integer(n)) => n.to_usize().unwrap(),
|
||||
_ => unreachable!()
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let (name, arity) = self.get_predicate_key(temp_v!(1), temp_v!(2));
|
||||
@@ -244,31 +248,36 @@ impl Machine {
|
||||
}
|
||||
|
||||
self.print_new_dynamic_clause(addrs, name.clone(), arity)
|
||||
},
|
||||
Err(err) =>
|
||||
return self.machine_st.throw_exception(err)
|
||||
}
|
||||
Err(err) => return self.machine_st.throw_exception(err),
|
||||
};
|
||||
|
||||
self.handle_eval_result_from_dynamic_compile(pred_str, name, arity,
|
||||
clause_name!("retract"));
|
||||
self.handle_eval_result_from_dynamic_compile(
|
||||
pred_str,
|
||||
name,
|
||||
arity,
|
||||
clause_name!("retract"),
|
||||
);
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn dynamic_transaction(&mut self, trans_type: DynamicTransactionType, p: LocalCodePtr)
|
||||
{
|
||||
pub(super) fn dynamic_transaction(
|
||||
&mut self,
|
||||
trans_type: DynamicTransactionType,
|
||||
p: LocalCodePtr,
|
||||
) {
|
||||
match trans_type {
|
||||
DynamicTransactionType::Abolish =>
|
||||
self.abolish_dynamic_clause(temp_v!(1), temp_v!(2)),
|
||||
DynamicTransactionType::Assert(place) =>
|
||||
self.recompile_dynamic_predicate(place),
|
||||
DynamicTransactionType::ModuleAbolish =>
|
||||
self.abolish_dynamic_clause_in_module(temp_v!(1), temp_v!(2), temp_v!(3)),
|
||||
DynamicTransactionType::ModuleAssert(place) =>
|
||||
self.recompile_dynamic_predicate_in_module(place),
|
||||
DynamicTransactionType::ModuleRetract =>
|
||||
self.retract_from_dynamic_predicate_in_module(),
|
||||
DynamicTransactionType::Retract =>
|
||||
self.retract_from_dynamic_predicate()
|
||||
DynamicTransactionType::Abolish => self.abolish_dynamic_clause(temp_v!(1), temp_v!(2)),
|
||||
DynamicTransactionType::Assert(place) => self.recompile_dynamic_predicate(place),
|
||||
DynamicTransactionType::ModuleAbolish => {
|
||||
self.abolish_dynamic_clause_in_module(temp_v!(1), temp_v!(2), temp_v!(3))
|
||||
}
|
||||
DynamicTransactionType::ModuleAssert(place) => {
|
||||
self.recompile_dynamic_predicate_in_module(place)
|
||||
}
|
||||
DynamicTransactionType::ModuleRetract => {
|
||||
self.retract_from_dynamic_predicate_in_module()
|
||||
}
|
||||
DynamicTransactionType::Retract => self.retract_from_dynamic_predicate(),
|
||||
}
|
||||
|
||||
self.machine_st.p = CodePtr::Local(p);
|
||||
|
||||
@@ -12,8 +12,10 @@ pub struct Heap {
|
||||
|
||||
impl Heap {
|
||||
pub fn with_capacity(cap: usize) -> Self {
|
||||
Heap { heap: Vec::with_capacity(cap),
|
||||
h: 0 }
|
||||
Heap {
|
||||
heap: Vec::with_capacity(cap),
|
||||
h: 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -29,7 +31,7 @@ impl Heap {
|
||||
|
||||
Heap {
|
||||
heap: mem::replace(&mut self.heap, vec![]),
|
||||
h
|
||||
h,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,13 +63,13 @@ impl Heap {
|
||||
self.h = 0;
|
||||
}
|
||||
|
||||
pub fn to_list<Iter: Iterator<Item=Addr>>(&mut self, values: Iter) -> usize {
|
||||
pub fn to_list<Iter: Iterator<Item = Addr>>(&mut self, values: Iter) -> usize {
|
||||
let head_addr = self.h;
|
||||
|
||||
for value in values {
|
||||
let h = self.h;
|
||||
|
||||
self.push(HeapCellValue::Addr(Addr::Lis(h+1)));
|
||||
self.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
|
||||
self.push(HeapCellValue::Addr(value));
|
||||
}
|
||||
|
||||
@@ -75,7 +77,7 @@ impl Heap {
|
||||
head_addr
|
||||
}
|
||||
|
||||
pub fn extend<Iter: Iterator<Item=HeapCellValue>>(&mut self, iter: Iter) {
|
||||
pub fn extend<Iter: Iterator<Item = HeapCellValue>>(&mut self, iter: Iter) {
|
||||
for hcv in iter {
|
||||
self.push(hcv);
|
||||
}
|
||||
|
||||
@@ -10,63 +10,115 @@ pub(crate) type MachineStub = Vec<HeapCellValue>;
|
||||
#[derive(Clone, Copy)]
|
||||
enum ErrorProvenance {
|
||||
Constructed, // if constructed, offset the addresses.
|
||||
Received // otherwise, preserve the addresses.
|
||||
Received, // otherwise, preserve the addresses.
|
||||
}
|
||||
|
||||
pub(super) struct MachineError {
|
||||
stub: MachineStub,
|
||||
location: Option<(usize, usize)>, // line_num, col_num
|
||||
from: ErrorProvenance
|
||||
from: ErrorProvenance,
|
||||
}
|
||||
|
||||
impl MachineError {
|
||||
pub(super) fn functor_stub(name: ClauseName, arity: usize) -> MachineStub {
|
||||
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
|
||||
functor!("/", 2, [name, heap_integer!(Integer::from(arity))], SharedOpDesc::new(400, YFX))
|
||||
functor!(
|
||||
"/",
|
||||
2,
|
||||
[name, heap_integer!(Integer::from(arity))],
|
||||
SharedOpDesc::new(400, YFX)
|
||||
)
|
||||
}
|
||||
|
||||
pub(super) fn evaluation_error(eval_error: EvalError) -> Self {
|
||||
let stub = functor!("evaluation_error", 1, [heap_atom!(eval_error.as_str())]);
|
||||
MachineError { stub, location: None, from: ErrorProvenance::Received }
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn type_error(valid_type: ValidType, culprit: Addr) -> Self {
|
||||
let stub = functor!("type_error", 2, [heap_atom!(valid_type.as_str()),
|
||||
HeapCellValue::Addr(culprit)]);
|
||||
let stub = functor!(
|
||||
"type_error",
|
||||
2,
|
||||
[
|
||||
heap_atom!(valid_type.as_str()),
|
||||
HeapCellValue::Addr(culprit)
|
||||
]
|
||||
);
|
||||
|
||||
MachineError { stub, location: None, from: ErrorProvenance::Received }
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn module_resolution_error(h: usize, mod_name: ClauseName, name: ClauseName, arity: usize) -> Self
|
||||
{
|
||||
pub(super) fn module_resolution_error(
|
||||
h: usize,
|
||||
mod_name: ClauseName,
|
||||
name: ClauseName,
|
||||
arity: usize,
|
||||
) -> Self {
|
||||
let mod_name = HeapCellValue::Addr(Addr::Con(Constant::Atom(mod_name, None)));
|
||||
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
|
||||
|
||||
let mut stub = functor!("evaluation_error", 1, [HeapCellValue::Addr(Addr::HeapCell(h + 2))]);
|
||||
let mut stub = functor!(
|
||||
"evaluation_error",
|
||||
1,
|
||||
[HeapCellValue::Addr(Addr::HeapCell(h + 2))]
|
||||
);
|
||||
|
||||
stub.append(&mut functor!("/", 2, [HeapCellValue::Addr(Addr::HeapCell(h + 2 + 3)),
|
||||
heap_integer!(Integer::from(arity))],
|
||||
SharedOpDesc::new(400, YFX)));
|
||||
stub.append(&mut functor!(":", 2, [mod_name, name], SharedOpDesc::new(600, XFY)));
|
||||
stub.append(&mut functor!(
|
||||
"/",
|
||||
2,
|
||||
[
|
||||
HeapCellValue::Addr(Addr::HeapCell(h + 2 + 3)),
|
||||
heap_integer!(Integer::from(arity))
|
||||
],
|
||||
SharedOpDesc::new(400, YFX)
|
||||
));
|
||||
stub.append(&mut functor!(
|
||||
":",
|
||||
2,
|
||||
[mod_name, name],
|
||||
SharedOpDesc::new(600, XFY)
|
||||
));
|
||||
|
||||
MachineError { stub, location: None, from: ErrorProvenance::Constructed }
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Constructed,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn existence_error(h: usize, err: ExistenceError) -> Self
|
||||
{
|
||||
pub(super) fn existence_error(h: usize, err: ExistenceError) -> Self {
|
||||
match err {
|
||||
ExistenceError::Procedure(name, arity) => {
|
||||
let mut stub = functor!("existence_error", 2, [heap_atom!("procedure"), heap_str!(3 + h)]);
|
||||
let mut stub = functor!(
|
||||
"existence_error",
|
||||
2,
|
||||
[heap_atom!("procedure"), heap_str!(3 + h)]
|
||||
);
|
||||
stub.append(&mut Self::functor_stub(name, arity));
|
||||
|
||||
MachineError { stub, location: None, from: ErrorProvenance::Constructed }
|
||||
},
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Constructed,
|
||||
}
|
||||
}
|
||||
ExistenceError::Module(name) => {
|
||||
let name = HeapCellValue::Addr(Addr::Con(Constant::Atom(name, None)));
|
||||
let stub = functor!("existence_error", 2, [heap_atom!("module"), name]);
|
||||
|
||||
MachineError { stub, location: None, from: ErrorProvenance::Constructed }
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Constructed,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,31 +127,37 @@ impl MachineError {
|
||||
match err {
|
||||
SessionError::ParserError(err) => Self::syntax_error(h, err),
|
||||
SessionError::CannotOverwriteBuiltIn(pred_str)
|
||||
| SessionError::CannotOverwriteImport(pred_str) =>
|
||||
Self::permission_error(PermissionError::Modify, "private_procedure", pred_str),
|
||||
SessionError::InvalidFileName(filename) =>
|
||||
Self::existence_error(h, ExistenceError::Module(filename)),
|
||||
SessionError::ModuleDoesNotContainExport =>
|
||||
Self::permission_error(PermissionError::Access,
|
||||
"private_procedure",
|
||||
clause_name!("module_does_not_contain_claimed_export")),
|
||||
SessionError::ModuleNotFound =>
|
||||
Self::permission_error(PermissionError::Access,
|
||||
"private_procedure",
|
||||
clause_name!("module_does_not_exist")),
|
||||
SessionError::NoModuleDeclaration(name) =>
|
||||
Self::existence_error(h, ExistenceError::Module(name)),
|
||||
SessionError::OpIsInfixAndPostFix(op) =>
|
||||
Self::permission_error(PermissionError::Create,
|
||||
"operator",
|
||||
op),
|
||||
_ => unreachable!()
|
||||
| SessionError::CannotOverwriteImport(pred_str) => {
|
||||
Self::permission_error(PermissionError::Modify, "private_procedure", pred_str)
|
||||
}
|
||||
SessionError::InvalidFileName(filename) => {
|
||||
Self::existence_error(h, ExistenceError::Module(filename))
|
||||
}
|
||||
SessionError::ModuleDoesNotContainExport => Self::permission_error(
|
||||
PermissionError::Access,
|
||||
"private_procedure",
|
||||
clause_name!("module_does_not_contain_claimed_export"),
|
||||
),
|
||||
SessionError::ModuleNotFound => Self::permission_error(
|
||||
PermissionError::Access,
|
||||
"private_procedure",
|
||||
clause_name!("module_does_not_exist"),
|
||||
),
|
||||
SessionError::NoModuleDeclaration(name) => {
|
||||
Self::existence_error(h, ExistenceError::Module(name))
|
||||
}
|
||||
SessionError::OpIsInfixAndPostFix(op) => {
|
||||
Self::permission_error(PermissionError::Create, "operator", op)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn permission_error(err: PermissionError, index_str: &'static str, pred_str: ClauseName) -> Self
|
||||
{
|
||||
pub(super) fn permission_error(
|
||||
err: PermissionError,
|
||||
index_str: &'static str,
|
||||
pred_str: ClauseName,
|
||||
) -> Self {
|
||||
let pred_str = HeapCellValue::Addr(Addr::Con(Constant::Atom(pred_str, None)));
|
||||
|
||||
let err = vec![heap_atom!(err.as_str()), heap_atom!(index_str), pred_str];
|
||||
@@ -107,22 +165,33 @@ impl MachineError {
|
||||
|
||||
stub.extend(err.into_iter());
|
||||
|
||||
MachineError { stub, location: None, from: ErrorProvenance::Constructed }
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Constructed,
|
||||
}
|
||||
}
|
||||
|
||||
fn arithmetic_error(h: usize, err: ArithmeticError) -> Self {
|
||||
match err {
|
||||
ArithmeticError::UninstantiatedVar =>
|
||||
Self::instantiation_error(),
|
||||
ArithmeticError::UninstantiatedVar => Self::instantiation_error(),
|
||||
ArithmeticError::NonEvaluableFunctor(name, arity) => {
|
||||
let name = HeapCellValue::Addr(Addr::Con(name));
|
||||
let culprit = functor!("/", 2, [name, heap_integer!(Integer::from(arity))],
|
||||
SharedOpDesc::new(400, YFX));
|
||||
let culprit = functor!(
|
||||
"/",
|
||||
2,
|
||||
[name, heap_integer!(Integer::from(arity))],
|
||||
SharedOpDesc::new(400, YFX)
|
||||
);
|
||||
|
||||
let mut stub = Self::type_error(ValidType::Evaluable, Addr::HeapCell(3+h)).stub;
|
||||
let mut stub = Self::type_error(ValidType::Evaluable, Addr::HeapCell(3 + h)).stub;
|
||||
stub.extend(culprit.into_iter());
|
||||
|
||||
MachineError { stub, location: None, from: ErrorProvenance::Constructed }
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Constructed,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,36 +212,53 @@ impl MachineError {
|
||||
|
||||
stub.extend(err.into_iter());
|
||||
|
||||
MachineError { stub, location, from: ErrorProvenance::Constructed }
|
||||
MachineError {
|
||||
stub,
|
||||
location,
|
||||
from: ErrorProvenance::Constructed,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn domain_error(error: DomainError, culprit: Addr) -> Self {
|
||||
let stub = functor!("domain_error", 2, [heap_atom!(error.as_str()),
|
||||
HeapCellValue::Addr(culprit)]);
|
||||
MachineError { stub, location: None, from: ErrorProvenance::Received }
|
||||
let stub = functor!(
|
||||
"domain_error",
|
||||
2,
|
||||
[heap_atom!(error.as_str()), HeapCellValue::Addr(culprit)]
|
||||
);
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn instantiation_error() -> Self {
|
||||
let stub = functor!("instantiation_error");
|
||||
MachineError { stub, location: None, from: ErrorProvenance::Received }
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn representation_error(flag: RepFlag) -> Self {
|
||||
let stub = functor!("representation_error", 1, [heap_atom!(flag.as_str())]);
|
||||
MachineError { stub, location: None, from: ErrorProvenance::Received }
|
||||
MachineError {
|
||||
stub,
|
||||
location: None,
|
||||
from: ErrorProvenance::Received,
|
||||
}
|
||||
}
|
||||
|
||||
fn into_iter(self, offset: usize) -> Box<Iterator<Item=HeapCellValue>> {
|
||||
fn into_iter(self, offset: usize) -> Box<Iterator<Item = HeapCellValue>> {
|
||||
match self.from {
|
||||
ErrorProvenance::Constructed =>
|
||||
Box::new(self.stub.into_iter().map(move |hcv| {
|
||||
match hcv {
|
||||
HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr + offset),
|
||||
hcv => hcv
|
||||
}
|
||||
})),
|
||||
ErrorProvenance::Received =>
|
||||
Box::new(self.stub.into_iter())
|
||||
ErrorProvenance::Constructed => {
|
||||
Box::new(self.stub.into_iter().map(move |hcv| match hcv {
|
||||
HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr + offset),
|
||||
hcv => hcv,
|
||||
}))
|
||||
}
|
||||
ErrorProvenance::Received => Box::new(self.stub.into_iter()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +279,7 @@ impl PermissionError {
|
||||
match self {
|
||||
PermissionError::Access => "access",
|
||||
PermissionError::Create => "create",
|
||||
PermissionError::Modify => "modify"
|
||||
PermissionError::Modify => "modify",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,21 +289,21 @@ impl PermissionError {
|
||||
pub enum ValidType {
|
||||
Atom,
|
||||
Atomic,
|
||||
// Boolean,
|
||||
// Byte,
|
||||
// Boolean,
|
||||
// Byte,
|
||||
Callable,
|
||||
Character,
|
||||
Compound,
|
||||
Evaluable,
|
||||
Float,
|
||||
// InByte,
|
||||
// InCharacter,
|
||||
// InByte,
|
||||
// InCharacter,
|
||||
Integer,
|
||||
List,
|
||||
// Number,
|
||||
// Number,
|
||||
Pair,
|
||||
// PredicateIndicator,
|
||||
// Variable
|
||||
// PredicateIndicator,
|
||||
// Variable
|
||||
}
|
||||
|
||||
impl ValidType {
|
||||
@@ -225,34 +311,34 @@ impl ValidType {
|
||||
match self {
|
||||
ValidType::Atom => "atom",
|
||||
ValidType::Atomic => "atomic",
|
||||
// ValidType::Boolean => "boolean",
|
||||
// ValidType::Byte => "byte",
|
||||
// ValidType::Boolean => "boolean",
|
||||
// ValidType::Byte => "byte",
|
||||
ValidType::Callable => "callable",
|
||||
ValidType::Character => "character",
|
||||
ValidType::Compound => "compound",
|
||||
ValidType::Evaluable => "evaluable",
|
||||
ValidType::Float => "float",
|
||||
// ValidType::InByte => "in_byte",
|
||||
// ValidType::InCharacter => "in_character",
|
||||
// ValidType::InByte => "in_byte",
|
||||
// ValidType::InCharacter => "in_character",
|
||||
ValidType::Integer => "integer",
|
||||
ValidType::List => "list",
|
||||
// ValidType::Number => "number",
|
||||
// ValidType::Number => "number",
|
||||
ValidType::Pair => "pair",
|
||||
// ValidType::PredicateIndicator => "predicate_indicator",
|
||||
// ValidType::Variable => "variable"
|
||||
// ValidType::PredicateIndicator => "predicate_indicator",
|
||||
// ValidType::Variable => "variable"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum DomainError {
|
||||
NotLessThanZero
|
||||
NotLessThanZero,
|
||||
}
|
||||
|
||||
impl DomainError {
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
DomainError::NotLessThanZero => "not_less_than_zero"
|
||||
DomainError::NotLessThanZero => "not_less_than_zero",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -262,10 +348,10 @@ impl DomainError {
|
||||
pub enum RepFlag {
|
||||
Character,
|
||||
CharacterCode,
|
||||
// InCharacterCode,
|
||||
// InCharacterCode,
|
||||
MaxArity,
|
||||
// MaxInteger,
|
||||
// MinInteger
|
||||
// MaxInteger,
|
||||
// MinInteger
|
||||
}
|
||||
|
||||
impl RepFlag {
|
||||
@@ -273,10 +359,10 @@ impl RepFlag {
|
||||
match self {
|
||||
RepFlag::Character => "character",
|
||||
RepFlag::CharacterCode => "character_code",
|
||||
// RepFlag::InCharacterCode => "in_character_code",
|
||||
// RepFlag::InCharacterCode => "in_character_code",
|
||||
RepFlag::MaxArity => "max_arity",
|
||||
// RepFlag::MaxInteger => "max_integer",
|
||||
// RepFlag::MinInteger => "min_integer"
|
||||
// RepFlag::MaxInteger => "max_integer",
|
||||
// RepFlag::MinInteger => "min_integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -286,7 +372,7 @@ impl RepFlag {
|
||||
pub enum EvalError {
|
||||
FloatOverflow,
|
||||
Undefined,
|
||||
// Underflow,
|
||||
// Underflow,
|
||||
ZeroDivisor,
|
||||
}
|
||||
|
||||
@@ -295,7 +381,7 @@ impl EvalError {
|
||||
match self {
|
||||
EvalError::FloatOverflow => "float_overflow",
|
||||
EvalError::Undefined => "undefined",
|
||||
// EvalError::FloatUnderflow => "underflow",
|
||||
// EvalError::FloatUnderflow => "underflow",
|
||||
EvalError::ZeroDivisor => "zero_divisor",
|
||||
}
|
||||
}
|
||||
@@ -306,30 +392,33 @@ pub(super) enum CycleSearchResult {
|
||||
EmptyList,
|
||||
NotList,
|
||||
PartialList(usize, usize), // the list length (up to max), and an offset into the heap.
|
||||
ProperList(usize), // the list length.
|
||||
ProperList(usize), // the list length.
|
||||
String(usize, StringList), // the number of elements iterated, the string tail.
|
||||
UntouchedList(usize) // the address of an uniterated Addr::Lis(address).
|
||||
UntouchedList(usize), // the address of an uniterated Addr::Lis(address).
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
// see 8.4.3 of Draft Technical Corrigendum 2.
|
||||
pub(super) fn check_sort_errors(&self) -> CallResult {
|
||||
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
|
||||
let list = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
let stub = MachineError::functor_stub(clause_name!("sort"), 2);
|
||||
let list = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||
|
||||
match self.detect_cycles(list.clone()) {
|
||||
CycleSearchResult::PartialList(..) =>
|
||||
return Err(self.error_form(MachineError::instantiation_error(), stub)),
|
||||
CycleSearchResult::NotList =>
|
||||
return Err(self.error_form(MachineError::type_error(ValidType::List, list), stub)),
|
||||
CycleSearchResult::PartialList(..) => {
|
||||
return Err(self.error_form(MachineError::instantiation_error(), stub))
|
||||
}
|
||||
CycleSearchResult::NotList => {
|
||||
return Err(self.error_form(MachineError::type_error(ValidType::List, list), stub))
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
match self.detect_cycles(sorted.clone()) {
|
||||
CycleSearchResult::NotList if !sorted.is_ref() =>
|
||||
Err(self.error_form(MachineError::type_error(ValidType::List, sorted), stub)),
|
||||
_ => Ok(())
|
||||
CycleSearchResult::NotList if !sorted.is_ref() => {
|
||||
Err(self.error_form(MachineError::type_error(ValidType::List, sorted), stub))
|
||||
}
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,8 +426,9 @@ impl MachineState {
|
||||
let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
|
||||
|
||||
match self.detect_cycles(list.clone()) {
|
||||
CycleSearchResult::NotList if !list.is_ref() =>
|
||||
Err(self.error_form(MachineError::type_error(ValidType::List, list), stub)),
|
||||
CycleSearchResult::NotList if !list.is_ref() => {
|
||||
Err(self.error_form(MachineError::type_error(ValidType::List, list), stub))
|
||||
}
|
||||
_ => {
|
||||
let mut addr = list;
|
||||
|
||||
@@ -349,12 +439,18 @@ impl MachineState {
|
||||
match self.heap[new_l].clone() {
|
||||
HeapCellValue::Addr(Addr::Str(l)) => new_l = l,
|
||||
HeapCellValue::NamedStr(2, ref name, Some(_))
|
||||
if name.as_str() == "-" => break,
|
||||
if name.as_str() == "-" =>
|
||||
{
|
||||
break
|
||||
}
|
||||
HeapCellValue::Addr(Addr::HeapCell(_)) => break,
|
||||
HeapCellValue::Addr(Addr::StackCell(..)) => break,
|
||||
_ => return Err(self.error_form(MachineError::type_error(ValidType::Pair,
|
||||
Addr::HeapCell(l)),
|
||||
stub))
|
||||
_ => {
|
||||
return Err(self.error_form(
|
||||
MachineError::type_error(ValidType::Pair, Addr::HeapCell(l)),
|
||||
stub,
|
||||
))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -368,16 +464,18 @@ impl MachineState {
|
||||
|
||||
// see 8.4.4 of Draft Technical Corrigendum 2.
|
||||
pub(super) fn check_keysort_errors(&self) -> CallResult {
|
||||
let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
|
||||
let pairs = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
|
||||
let pairs = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
|
||||
|
||||
match self.detect_cycles(pairs.clone()) {
|
||||
CycleSearchResult::PartialList(..) =>
|
||||
Err(self.error_form(MachineError::instantiation_error(), stub)),
|
||||
CycleSearchResult::NotList =>
|
||||
Err(self.error_form(MachineError::type_error(ValidType::List, pairs), stub)),
|
||||
_ => Ok(())
|
||||
CycleSearchResult::PartialList(..) => {
|
||||
Err(self.error_form(MachineError::instantiation_error(), stub))
|
||||
}
|
||||
CycleSearchResult::NotList => {
|
||||
Err(self.error_form(MachineError::type_error(ValidType::List, pairs), stub))
|
||||
}
|
||||
_ => Ok(()),
|
||||
}?;
|
||||
|
||||
self.check_for_list_pairs(sorted)
|
||||
@@ -388,18 +486,25 @@ impl MachineState {
|
||||
let err_len = err.len();
|
||||
|
||||
let h = self.heap.h;
|
||||
let mut stub = vec![HeapCellValue::NamedStr(2, clause_name!("error"), None),
|
||||
HeapCellValue::Addr(Addr::HeapCell(h + 3)),
|
||||
HeapCellValue::Addr(Addr::HeapCell(h + 3 + err_len))];
|
||||
let mut stub = vec![
|
||||
HeapCellValue::NamedStr(2, clause_name!("error"), None),
|
||||
HeapCellValue::Addr(Addr::HeapCell(h + 3)),
|
||||
HeapCellValue::Addr(Addr::HeapCell(h + 3 + err_len)),
|
||||
];
|
||||
|
||||
stub.extend(err.into_iter(3));
|
||||
|
||||
if let Some((line_num, _)) = location {
|
||||
let colon_op_desc = Some(SharedOpDesc::new(600, XFY));
|
||||
|
||||
stub.extend(vec![HeapCellValue::NamedStr(2, clause_name!(":"), colon_op_desc),
|
||||
HeapCellValue::Addr(Addr::HeapCell(h + 6 + err_len)),
|
||||
heap_integer!(Integer::from(line_num))].into_iter());
|
||||
stub.extend(
|
||||
vec![
|
||||
HeapCellValue::NamedStr(2, clause_name!(":"), colon_op_desc),
|
||||
HeapCellValue::Addr(Addr::HeapCell(h + 6 + err_len)),
|
||||
heap_integer!(Integer::from(line_num)),
|
||||
]
|
||||
.into_iter(),
|
||||
);
|
||||
}
|
||||
|
||||
stub.extend(src.into_iter());
|
||||
@@ -423,7 +528,7 @@ impl MachineState {
|
||||
|
||||
pub enum ExistenceError {
|
||||
Module(ClauseName),
|
||||
Procedure(ClauseName, usize)
|
||||
Procedure(ClauseName, usize),
|
||||
}
|
||||
|
||||
pub enum SessionError {
|
||||
@@ -436,7 +541,7 @@ pub enum SessionError {
|
||||
NoModuleDeclaration(ClauseName),
|
||||
OpIsInfixAndPostFix(ClauseName),
|
||||
ParserError(ParserError),
|
||||
UserPrompt
|
||||
UserPrompt,
|
||||
}
|
||||
|
||||
pub enum EvalSession {
|
||||
|
||||
@@ -22,7 +22,13 @@ pub type OssifiedOpDir = BTreeMap<OrderedOpDirKey, (usize, Specifier)>;
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub enum DBRef {
|
||||
NamedPred(ClauseName, usize, Option<SharedOpDesc>),
|
||||
Op(usize, Specifier, ClauseName, Rc<OssifiedOpDir>, SharedOpDesc)
|
||||
Op(
|
||||
usize,
|
||||
Specifier,
|
||||
ClauseName,
|
||||
Rc<OssifiedOpDir>,
|
||||
SharedOpDesc,
|
||||
),
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
@@ -33,22 +39,22 @@ pub enum Addr {
|
||||
Lis(usize),
|
||||
HeapCell(usize),
|
||||
StackCell(usize, usize),
|
||||
Str(usize)
|
||||
Str(usize),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Hash, Eq, PartialEq)]
|
||||
pub enum Ref {
|
||||
AttrVar(usize),
|
||||
HeapCell(usize),
|
||||
StackCell(usize, usize)
|
||||
StackCell(usize, usize),
|
||||
}
|
||||
|
||||
impl Ref {
|
||||
pub fn as_addr(self) -> Addr {
|
||||
match self {
|
||||
Ref::AttrVar(h) => Addr::AttrVar(h),
|
||||
Ref::HeapCell(h) => Addr::HeapCell(h),
|
||||
Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc)
|
||||
Ref::AttrVar(h) => Addr::AttrVar(h),
|
||||
Ref::HeapCell(h) => Addr::HeapCell(h),
|
||||
Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,25 +69,23 @@ impl PartialEq<Ref> for Addr {
|
||||
impl PartialOrd<Ref> for Addr {
|
||||
fn partial_cmp(&self, r: &Ref) -> Option<Ordering> {
|
||||
match self {
|
||||
&Addr::StackCell(fr, sc) =>
|
||||
match *r {
|
||||
Ref::AttrVar(_) | Ref::HeapCell(_) =>
|
||||
Some(Ordering::Greater),
|
||||
Ref::StackCell(fr1, sc1) =>
|
||||
if fr1 < fr || (fr1 == fr && sc1 < sc) {
|
||||
Some(Ordering::Greater)
|
||||
} else if fr1 == fr && sc1 == sc {
|
||||
Some(Ordering::Equal)
|
||||
} else {
|
||||
Some(Ordering::Less)
|
||||
}
|
||||
},
|
||||
&Addr::HeapCell(h) | &Addr::AttrVar(h) =>
|
||||
match r {
|
||||
&Ref::StackCell(..) => Some(Ordering::Less),
|
||||
&Ref::AttrVar(h1) | &Ref::HeapCell(h1) => h.partial_cmp(&h1)
|
||||
},
|
||||
_ => None
|
||||
&Addr::StackCell(fr, sc) => match *r {
|
||||
Ref::AttrVar(_) | Ref::HeapCell(_) => Some(Ordering::Greater),
|
||||
Ref::StackCell(fr1, sc1) => {
|
||||
if fr1 < fr || (fr1 == fr && sc1 < sc) {
|
||||
Some(Ordering::Greater)
|
||||
} else if fr1 == fr && sc1 == sc {
|
||||
Some(Ordering::Equal)
|
||||
} else {
|
||||
Some(Ordering::Less)
|
||||
}
|
||||
}
|
||||
},
|
||||
&Addr::HeapCell(h) | &Addr::AttrVar(h) => match r {
|
||||
&Ref::StackCell(..) => Some(Ordering::Less),
|
||||
&Ref::AttrVar(h1) | &Ref::HeapCell(h1) => h.partial_cmp(&h1),
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,7 +94,7 @@ impl Addr {
|
||||
pub fn is_ref(&self) -> bool {
|
||||
match self {
|
||||
&Addr::AttrVar(_) | &Addr::HeapCell(_) | &Addr::StackCell(_, _) => true,
|
||||
_ => false
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,14 +103,14 @@ impl Addr {
|
||||
&Addr::AttrVar(h) => Some(Ref::AttrVar(h)),
|
||||
&Addr::HeapCell(h) => Some(Ref::HeapCell(h)),
|
||||
&Addr::StackCell(fr, sc) => Some(Ref::StackCell(fr, sc)),
|
||||
_ => None
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_protected(&self, e: usize) -> bool {
|
||||
match self {
|
||||
&Addr::StackCell(addr, _) if addr >= e => false,
|
||||
_ => true
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,7 +124,7 @@ impl Add<usize> for Addr {
|
||||
Addr::AttrVar(h) => Addr::AttrVar(h + rhs),
|
||||
Addr::HeapCell(h) => Addr::HeapCell(h + rhs),
|
||||
Addr::Str(s) => Addr::Str(s + rhs),
|
||||
_ => self
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,7 +139,7 @@ impl Sub<i64> for Addr {
|
||||
Addr::AttrVar(h) => Addr::AttrVar(h + rhs.abs() as usize),
|
||||
Addr::HeapCell(h) => Addr::HeapCell(h + rhs.abs() as usize),
|
||||
Addr::Str(s) => Addr::Str(s + rhs.abs() as usize),
|
||||
_ => self
|
||||
_ => self,
|
||||
}
|
||||
} else {
|
||||
self.sub(rhs as usize)
|
||||
@@ -152,7 +156,7 @@ impl Sub<usize> for Addr {
|
||||
Addr::AttrVar(h) => Addr::AttrVar(h - rhs),
|
||||
Addr::HeapCell(h) => Addr::HeapCell(h - rhs),
|
||||
Addr::Str(s) => Addr::Str(s - rhs),
|
||||
_ => self
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,9 +170,9 @@ impl SubAssign<usize> for Addr {
|
||||
impl From<Ref> for Addr {
|
||||
fn from(r: Ref) -> Self {
|
||||
match r {
|
||||
Ref::AttrVar(h) => Addr::AttrVar(h),
|
||||
Ref::HeapCell(h) => Addr::HeapCell(h),
|
||||
Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc)
|
||||
Ref::AttrVar(h) => Addr::AttrVar(h),
|
||||
Ref::HeapCell(h) => Addr::HeapCell(h),
|
||||
Ref::StackCell(fr, sc) => Addr::StackCell(fr, sc),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,7 +180,7 @@ impl From<Ref> for Addr {
|
||||
#[derive(Clone)]
|
||||
pub enum TrailRef {
|
||||
Ref(Ref),
|
||||
AttrVarLink(usize, Addr)
|
||||
AttrVarLink(usize, Addr),
|
||||
}
|
||||
|
||||
impl From<Ref> for TrailRef {
|
||||
@@ -195,7 +199,7 @@ impl HeapCellValue {
|
||||
pub fn as_addr(&self, focus: usize) -> Addr {
|
||||
match self {
|
||||
&HeapCellValue::Addr(ref a) => a.clone(),
|
||||
&HeapCellValue::NamedStr(_, _, _) => Addr::Str(focus)
|
||||
&HeapCellValue::NamedStr(_, _, _) => Addr::Str(focus),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -229,14 +233,17 @@ impl CodeIndex {
|
||||
pub fn local(&self) -> Option<usize> {
|
||||
match self.0.borrow().0 {
|
||||
IndexPtr::Index(i) => Some(i),
|
||||
_ => None
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CodeIndex {
|
||||
fn default() -> Self {
|
||||
CodeIndex(Rc::new(RefCell::new((IndexPtr::Undefined, clause_name!("")))))
|
||||
CodeIndex(Rc::new(RefCell::new((
|
||||
IndexPtr::Undefined,
|
||||
clause_name!(""),
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,23 +255,24 @@ impl From<(usize, ClauseName)> for CodeIndex {
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum DynamicAssertPlace {
|
||||
Back, Front
|
||||
Back,
|
||||
Front,
|
||||
}
|
||||
|
||||
impl DynamicAssertPlace {
|
||||
#[inline]
|
||||
pub fn predicate_name(self) -> ClauseName {
|
||||
match self {
|
||||
DynamicAssertPlace::Back => clause_name!("assertz"),
|
||||
DynamicAssertPlace::Front => clause_name!("asserta")
|
||||
DynamicAssertPlace::Back => clause_name!("assertz"),
|
||||
DynamicAssertPlace::Front => clause_name!("asserta"),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn push_to_queue(self, addrs: &mut VecDeque<Addr>, new_addr: Addr) {
|
||||
match self {
|
||||
DynamicAssertPlace::Back => addrs.push_back(new_addr),
|
||||
DynamicAssertPlace::Front => addrs.push_front(new_addr)
|
||||
DynamicAssertPlace::Back => addrs.push_back(new_addr),
|
||||
DynamicAssertPlace::Front => addrs.push_front(new_addr),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -276,34 +284,33 @@ pub enum DynamicTransactionType {
|
||||
ModuleAbolish,
|
||||
ModuleAssert(DynamicAssertPlace),
|
||||
ModuleRetract,
|
||||
Retract // dynamic index of the clause to remove.
|
||||
Retract, // dynamic index of the clause to remove.
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
|
||||
pub enum REPLCodePtr {
|
||||
CompileBatch,
|
||||
SubmitQueryAndPrintResults
|
||||
SubmitQueryAndPrintResults,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum CodePtr {
|
||||
BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
|
||||
CallN(usize, LocalCodePtr), // arity, local.
|
||||
CallN(usize, LocalCodePtr), // arity, local.
|
||||
Local(LocalCodePtr),
|
||||
DynamicTransaction(DynamicTransactionType, LocalCodePtr), // the type of transaction, the return pointer.
|
||||
REPL(REPLCodePtr, LocalCodePtr), // the REPL code, the return pointer.
|
||||
VerifyAttrInterrupt(usize) // location of the verify attribute interrupt code in the CodeDir.
|
||||
REPL(REPLCodePtr, LocalCodePtr), // the REPL code, the return pointer.
|
||||
VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir.
|
||||
}
|
||||
|
||||
impl CodePtr {
|
||||
pub fn local(&self) -> LocalCodePtr {
|
||||
match self {
|
||||
&CodePtr::BuiltInClause(_, ref local)
|
||||
| &CodePtr::CallN(_, ref local)
|
||||
| &CodePtr::Local(ref local) => local.clone(),
|
||||
| &CodePtr::CallN(_, ref local)
|
||||
| &CodePtr::Local(ref local) => local.clone(),
|
||||
&CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p),
|
||||
&CodePtr::REPL(_, p)
|
||||
| &CodePtr::DynamicTransaction(_, p) => p
|
||||
&CodePtr::REPL(_, p) | &CodePtr::DynamicTransaction(_, p) => p,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -314,7 +321,7 @@ pub enum LocalCodePtr {
|
||||
InSituDirEntry(usize),
|
||||
TopLevel(usize, usize), // chunk_num, offset.
|
||||
UserGoalExpansion(usize),
|
||||
UserTermExpansion(usize)
|
||||
UserTermExpansion(usize),
|
||||
}
|
||||
|
||||
impl LocalCodePtr {
|
||||
@@ -330,7 +337,7 @@ impl PartialOrd<CodePtr> for CodePtr {
|
||||
fn partial_cmp(&self, other: &CodePtr) -> Option<Ordering> {
|
||||
match (self, other) {
|
||||
(&CodePtr::Local(ref l1), &CodePtr::Local(ref l2)) => l1.partial_cmp(l2),
|
||||
_ => Some(Ordering::Greater)
|
||||
_ => Some(Ordering::Greater),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -339,14 +346,14 @@ impl PartialOrd<LocalCodePtr> for LocalCodePtr {
|
||||
fn partial_cmp(&self, other: &LocalCodePtr) -> Option<Ordering> {
|
||||
match (self, other) {
|
||||
(&LocalCodePtr::InSituDirEntry(p1), &LocalCodePtr::InSituDirEntry(ref p2))
|
||||
| (&LocalCodePtr::DirEntry(p1), &LocalCodePtr::DirEntry(ref p2))
|
||||
| (&LocalCodePtr::UserTermExpansion(p1), &LocalCodePtr::UserTermExpansion(ref p2))
|
||||
| (&LocalCodePtr::UserGoalExpansion(p1), &LocalCodePtr::UserGoalExpansion(ref p2))
|
||||
| (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) =>
|
||||
p1.partial_cmp(p2),
|
||||
(_, &LocalCodePtr::TopLevel(_, _)) =>
|
||||
Some(Ordering::Less),
|
||||
_ => Some(Ordering::Greater)
|
||||
| (&LocalCodePtr::DirEntry(p1), &LocalCodePtr::DirEntry(ref p2))
|
||||
| (&LocalCodePtr::UserTermExpansion(p1), &LocalCodePtr::UserTermExpansion(ref p2))
|
||||
| (&LocalCodePtr::UserGoalExpansion(p1), &LocalCodePtr::UserGoalExpansion(ref p2))
|
||||
| (&LocalCodePtr::TopLevel(_, p1), &LocalCodePtr::TopLevel(_, ref p2)) => {
|
||||
p1.partial_cmp(p2)
|
||||
}
|
||||
(_, &LocalCodePtr::TopLevel(_, _)) => Some(Ordering::Less),
|
||||
_ => Some(Ordering::Greater),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -381,10 +388,10 @@ impl AddAssign<usize> for LocalCodePtr {
|
||||
fn add_assign(&mut self, rhs: usize) {
|
||||
match self {
|
||||
&mut LocalCodePtr::InSituDirEntry(ref mut p)
|
||||
| &mut LocalCodePtr::UserGoalExpansion(ref mut p)
|
||||
| &mut LocalCodePtr::UserTermExpansion(ref mut p)
|
||||
| &mut LocalCodePtr::DirEntry(ref mut p)
|
||||
| &mut LocalCodePtr::TopLevel(_, ref mut p) => *p += rhs
|
||||
| &mut LocalCodePtr::UserGoalExpansion(ref mut p)
|
||||
| &mut LocalCodePtr::UserTermExpansion(ref mut p)
|
||||
| &mut LocalCodePtr::DirEntry(ref mut p)
|
||||
| &mut LocalCodePtr::TopLevel(_, ref mut p) => *p += rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -395,10 +402,12 @@ impl Add<usize> for CodePtr {
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
match self {
|
||||
p @ CodePtr::REPL(..)
|
||||
| p @ CodePtr::VerifyAttrInterrupt(_)
|
||||
| p @ CodePtr::DynamicTransaction(..) => p,
|
||||
| p @ CodePtr::VerifyAttrInterrupt(_)
|
||||
| p @ CodePtr::DynamicTransaction(..) => p,
|
||||
CodePtr::Local(local) => CodePtr::Local(local + rhs),
|
||||
CodePtr::CallN(_, local) | CodePtr::BuiltInClause(_, local) => CodePtr::Local(local + rhs)
|
||||
CodePtr::CallN(_, local) | CodePtr::BuiltInClause(_, local) => {
|
||||
CodePtr::Local(local + rhs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -406,14 +415,14 @@ impl Add<usize> for CodePtr {
|
||||
impl AddAssign<usize> for CodePtr {
|
||||
fn add_assign(&mut self, rhs: usize) {
|
||||
match self {
|
||||
&mut CodePtr::VerifyAttrInterrupt(_) => {},
|
||||
&mut CodePtr::VerifyAttrInterrupt(_) => {}
|
||||
&mut CodePtr::Local(ref mut local) => *local += rhs,
|
||||
_ => *self = CodePtr::Local(self.local() + rhs)
|
||||
_ => *self = CodePtr::Local(self.local() + rhs),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type HeapVarDict = IndexMap<Rc<Var>, Addr>;
|
||||
pub type HeapVarDict = IndexMap<Rc<Var>, Addr>;
|
||||
pub type AllocVarDict = IndexMap<Rc<Var>, VarData>;
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -423,11 +432,13 @@ pub struct DynamicPredicateInfo {
|
||||
|
||||
impl Default for DynamicPredicateInfo {
|
||||
fn default() -> Self {
|
||||
DynamicPredicateInfo { clauses_subsection_p: 0 }
|
||||
DynamicPredicateInfo {
|
||||
clauses_subsection_p: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type InSituCodeDir = IndexMap<PredicateKey, usize>;
|
||||
pub type InSituCodeDir = IndexMap<PredicateKey, usize>;
|
||||
// key type: module name, predicate indicator.
|
||||
pub type DynamicCodeDir = IndexMap<(ClauseName, ClauseName, usize), DynamicPredicateInfo>;
|
||||
|
||||
@@ -444,42 +455,41 @@ pub struct IndexStore {
|
||||
}
|
||||
|
||||
impl IndexStore {
|
||||
pub fn predicate_exists(&self, name: ClauseName, module: ClauseName, arity: usize,
|
||||
op_spec: Option<SharedOpDesc>)
|
||||
-> bool
|
||||
{
|
||||
pub fn predicate_exists(
|
||||
&self,
|
||||
name: ClauseName,
|
||||
module: ClauseName,
|
||||
arity: usize,
|
||||
op_spec: Option<SharedOpDesc>,
|
||||
) -> bool {
|
||||
match self.modules.get(&module) {
|
||||
Some(module) =>
|
||||
match ClauseType::from(name, arity, op_spec) {
|
||||
ClauseType::Named(name, arity, _) =>
|
||||
module.code_dir.contains_key(&(name, arity)),
|
||||
ClauseType::Op(name, spec, ..) =>
|
||||
module.code_dir.contains_key(&(name, spec.arity())),
|
||||
_ =>
|
||||
true
|
||||
},
|
||||
None =>
|
||||
match ClauseType::from(name, arity, op_spec) {
|
||||
ClauseType::Named(name, arity, _) =>
|
||||
self.code_dir.contains_key(&(name, arity)),
|
||||
ClauseType::Op(name, spec, ..) =>
|
||||
self.code_dir.contains_key(&(name, spec.arity())),
|
||||
_ =>
|
||||
true
|
||||
Some(module) => match ClauseType::from(name, arity, op_spec) {
|
||||
ClauseType::Named(name, arity, _) => module.code_dir.contains_key(&(name, arity)),
|
||||
ClauseType::Op(name, spec, ..) => {
|
||||
module.code_dir.contains_key(&(name, spec.arity()))
|
||||
}
|
||||
_ => true,
|
||||
},
|
||||
None => match ClauseType::from(name, arity, op_spec) {
|
||||
ClauseType::Named(name, arity, _) => self.code_dir.contains_key(&(name, arity)),
|
||||
ClauseType::Op(name, spec, ..) => self.code_dir.contains_key(&(name, spec.arity())),
|
||||
_ => true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn remove_clause_subsection(&mut self, module: ClauseName, name: ClauseName, arity: usize)
|
||||
{
|
||||
pub fn remove_clause_subsection(&mut self, module: ClauseName, name: ClauseName, arity: usize) {
|
||||
self.dynamic_code_dir.remove(&(module, name, arity));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_clause_subsection(&self, module: ClauseName, name: ClauseName, arity: usize)
|
||||
-> Option<DynamicPredicateInfo>
|
||||
{
|
||||
pub fn get_clause_subsection(
|
||||
&self,
|
||||
module: ClauseName,
|
||||
name: ClauseName,
|
||||
arity: usize,
|
||||
) -> Option<DynamicPredicateInfo> {
|
||||
self.dynamic_code_dir.get(&(module, name, arity)).cloned()
|
||||
}
|
||||
|
||||
@@ -503,7 +513,7 @@ impl IndexStore {
|
||||
in_situ_code_dir: InSituCodeDir::new(),
|
||||
op_dir: default_op_dir(),
|
||||
modules: ModuleDir::new(),
|
||||
// parsing_stream: readline::parsing_stream(String::new())
|
||||
// parsing_stream: readline::parsing_stream(String::new())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,21 +528,30 @@ impl IndexStore {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_internal(&self, name: ClauseName, arity: usize, in_mod: ClauseName) -> Option<CodeIndex>
|
||||
{
|
||||
self.modules.get(&in_mod)
|
||||
fn get_internal(
|
||||
&self,
|
||||
name: ClauseName,
|
||||
arity: usize,
|
||||
in_mod: ClauseName,
|
||||
) -> Option<CodeIndex> {
|
||||
self.modules
|
||||
.get(&in_mod)
|
||||
.and_then(|ref module| module.code_dir.get(&(name, arity)))
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub(super) fn get_cleaner_sites(&self) -> (usize, usize) {
|
||||
let r_w_h = clause_name!("run_cleaners_with_handling");
|
||||
let r_w_h = clause_name!("run_cleaners_with_handling");
|
||||
let r_wo_h = clause_name!("run_cleaners_without_handling");
|
||||
|
||||
let non_iso = clause_name!("non_iso");
|
||||
|
||||
let r_w_h = self.get_internal(r_w_h, 0, non_iso.clone()).and_then(|item| item.local());
|
||||
let r_wo_h = self.get_internal(r_wo_h, 1, non_iso).and_then(|item| item.local());
|
||||
let r_w_h = self
|
||||
.get_internal(r_w_h, 0, non_iso.clone())
|
||||
.and_then(|item| item.local());
|
||||
let r_wo_h = self
|
||||
.get_internal(r_wo_h, 1, non_iso)
|
||||
.and_then(|item| item.local());
|
||||
|
||||
if let Some(r_w_h) = r_w_h {
|
||||
if let Some(r_wo_h) = r_wo_h {
|
||||
@@ -552,36 +571,38 @@ pub enum CompileTimeHook {
|
||||
GoalExpansion,
|
||||
TermExpansion,
|
||||
UserGoalExpansion,
|
||||
UserTermExpansion
|
||||
UserTermExpansion,
|
||||
}
|
||||
|
||||
impl CompileTimeHook {
|
||||
pub fn name(self) -> ClauseName {
|
||||
match self {
|
||||
CompileTimeHook::UserGoalExpansion
|
||||
| CompileTimeHook::GoalExpansion => clause_name!("goal_expansion"),
|
||||
CompileTimeHook::UserTermExpansion
|
||||
| CompileTimeHook::TermExpansion => clause_name!("term_expansion")
|
||||
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
|
||||
clause_name!("goal_expansion")
|
||||
}
|
||||
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
|
||||
clause_name!("term_expansion")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn arity(self) -> usize {
|
||||
match self {
|
||||
CompileTimeHook::UserGoalExpansion
|
||||
| CompileTimeHook::GoalExpansion => 2,
|
||||
CompileTimeHook::UserTermExpansion
|
||||
| CompileTimeHook::TermExpansion => 2
|
||||
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => 2,
|
||||
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => 2,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn user_scope(self) -> Self {
|
||||
match self {
|
||||
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion =>
|
||||
CompileTimeHook::UserGoalExpansion,
|
||||
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion =>
|
||||
CompileTimeHook::UserTermExpansion,
|
||||
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
|
||||
CompileTimeHook::UserGoalExpansion
|
||||
}
|
||||
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
|
||||
CompileTimeHook::UserTermExpansion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -589,30 +610,31 @@ impl CompileTimeHook {
|
||||
pub fn has_module_scope(self) -> bool {
|
||||
match self {
|
||||
CompileTimeHook::UserTermExpansion | CompileTimeHook::UserGoalExpansion => false,
|
||||
_ => true
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum RefOrOwned<'a, T: 'a> {
|
||||
Borrowed(&'a T),
|
||||
Owned(T)
|
||||
Owned(T),
|
||||
}
|
||||
|
||||
impl<'a, T> RefOrOwned<'a, T> {
|
||||
pub fn as_ref(&'a self) -> &'a T {
|
||||
match self {
|
||||
&RefOrOwned::Borrowed(r) => r,
|
||||
&RefOrOwned::Owned(ref r) => r
|
||||
&RefOrOwned::Owned(ref r) => r,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_owned(self) -> T
|
||||
where T: Clone
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
match self {
|
||||
RefOrOwned::Borrowed(item) => item.clone(),
|
||||
RefOrOwned::Owned(item) => item
|
||||
RefOrOwned::Owned(item) => item,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ use prolog::rug::Integer;
|
||||
use downcast::Any;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::io::{Write, stdout};
|
||||
use std::io::{stdout, Write};
|
||||
use std::mem;
|
||||
use std::ops::{Index, IndexMut};
|
||||
|
||||
@@ -28,7 +28,10 @@ pub(super) struct Ball {
|
||||
|
||||
impl Ball {
|
||||
pub(super) fn new() -> Self {
|
||||
Ball { boundary: 0, stub: MachineStub::new() }
|
||||
Ball {
|
||||
boundary: 0,
|
||||
stub: MachineStub::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn reset(&mut self) {
|
||||
@@ -42,13 +45,13 @@ impl Ball {
|
||||
|
||||
Ball {
|
||||
boundary,
|
||||
stub: mem::replace(&mut self.stub, vec![])
|
||||
stub: mem::replace(&mut self.stub, vec![]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct CopyTerm<'a> {
|
||||
state: &'a mut MachineState
|
||||
state: &'a mut MachineState,
|
||||
}
|
||||
|
||||
impl<'a> CopyTerm<'a> {
|
||||
@@ -102,10 +105,18 @@ pub(super) struct CopyBallTerm<'a> {
|
||||
}
|
||||
|
||||
impl<'a> CopyBallTerm<'a> {
|
||||
pub(super) fn new(and_stack: &'a mut AndStack, heap: &'a mut Heap, stub: &'a mut MachineStub) -> Self
|
||||
{
|
||||
pub(super) fn new(
|
||||
and_stack: &'a mut AndStack,
|
||||
heap: &'a mut Heap,
|
||||
stub: &'a mut MachineStub,
|
||||
) -> Self {
|
||||
let hb = heap.len();
|
||||
CopyBallTerm { and_stack, heap, heap_boundary: hb, stub }
|
||||
CopyBallTerm {
|
||||
and_stack,
|
||||
heap,
|
||||
heap_boundary: hb,
|
||||
stub,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,15 +156,15 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
|
||||
|
||||
fn store(&self, addr: Addr) -> Addr {
|
||||
match addr {
|
||||
Addr::HeapCell(h) | Addr::AttrVar(h) if h < self.heap_boundary =>
|
||||
self.heap[h].as_addr(h),
|
||||
Addr::HeapCell(h) | Addr::AttrVar(h) if h < self.heap_boundary => {
|
||||
self.heap[h].as_addr(h)
|
||||
}
|
||||
Addr::HeapCell(h) | Addr::AttrVar(h) => {
|
||||
let index = h - self.heap_boundary;
|
||||
self.stub[index].as_addr(h)
|
||||
},
|
||||
Addr::StackCell(fr, sc) =>
|
||||
self.and_stack[fr][sc].clone(),
|
||||
addr => addr
|
||||
}
|
||||
Addr::StackCell(fr, sc) => self.and_stack[fr][sc].clone(),
|
||||
addr => addr,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +178,7 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
|
||||
}
|
||||
|
||||
return addr;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn stack(&mut self) -> &mut AndStack {
|
||||
@@ -206,7 +217,7 @@ pub type Registers = Vec<Addr>;
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) enum MachineMode {
|
||||
Read,
|
||||
Write
|
||||
Write,
|
||||
}
|
||||
|
||||
pub struct MachineState {
|
||||
@@ -235,97 +246,85 @@ pub struct MachineState {
|
||||
pub(super) interms: Vec<Number>, // intermediate numbers.
|
||||
pub(super) last_call: bool,
|
||||
pub(crate) heap_locs: HeapVarDict,
|
||||
pub(crate) flags: MachineFlags
|
||||
pub(crate) flags: MachineFlags,
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
pub(super)
|
||||
fn try_char_list(&self, addrs: Vec<Addr>) -> Result<String, MachineError>
|
||||
{
|
||||
pub(super) fn try_char_list(&self, addrs: Vec<Addr>) -> Result<String, MachineError> {
|
||||
let mut chars = String::new();
|
||||
let mut iter = addrs.iter();
|
||||
|
||||
while let Some(addr) = iter.next() {
|
||||
match addr {
|
||||
&Addr::Con(Constant::String(ref s))
|
||||
if self.flags.double_quotes.is_chars() => {
|
||||
chars += s.borrow().as_str();
|
||||
&Addr::Con(Constant::String(ref s)) if self.flags.double_quotes.is_chars() => {
|
||||
chars += s.borrow().as_str();
|
||||
|
||||
if iter.next().is_some() {
|
||||
return Err(MachineError::type_error(ValidType::Character, addr.clone()));
|
||||
}
|
||||
},
|
||||
&Addr::Con(Constant::Char(c)) =>
|
||||
chars.push(c),
|
||||
&Addr::Con(Constant::Atom(ref name, _))
|
||||
if name.as_str().len() == 1 => {
|
||||
chars += name.as_str();
|
||||
},
|
||||
_ =>
|
||||
return Err(MachineError::type_error(ValidType::Character, addr.clone()))
|
||||
if iter.next().is_some() {
|
||||
return Err(MachineError::type_error(ValidType::Character, addr.clone()));
|
||||
}
|
||||
}
|
||||
&Addr::Con(Constant::Char(c)) => chars.push(c),
|
||||
&Addr::Con(Constant::Atom(ref name, _)) if name.as_str().len() == 1 => {
|
||||
chars += name.as_str();
|
||||
}
|
||||
_ => return Err(MachineError::type_error(ValidType::Character, addr.clone())),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(chars)
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn try_code_list(&self, addrs: Vec<Addr>) -> Result<Vec<u8>, MachineError>
|
||||
{
|
||||
pub(super) fn try_code_list(&self, addrs: Vec<Addr>) -> Result<Vec<u8>, MachineError> {
|
||||
let mut codes = vec![];
|
||||
let mut iter = addrs.iter();
|
||||
let mut iter = addrs.iter();
|
||||
|
||||
while let Some(addr) = iter.next() {
|
||||
match addr {
|
||||
&Addr::Con(Constant::String(ref s))
|
||||
if self.flags.double_quotes.is_codes() => {
|
||||
codes.extend(s.borrow().chars().map(|c| c as u8));
|
||||
&Addr::Con(Constant::String(ref s)) if self.flags.double_quotes.is_codes() => {
|
||||
codes.extend(s.borrow().chars().map(|c| c as u8));
|
||||
|
||||
if iter.next().is_some() {
|
||||
return Err(MachineError::representation_error(RepFlag::CharacterCode));
|
||||
}
|
||||
},
|
||||
&Addr::Con(Constant::CharCode(c)) =>
|
||||
codes.push(c),
|
||||
&Addr::Con(Constant::Integer(ref n)) =>
|
||||
if iter.next().is_some() {
|
||||
return Err(MachineError::representation_error(RepFlag::CharacterCode));
|
||||
}
|
||||
}
|
||||
&Addr::Con(Constant::CharCode(c)) => codes.push(c),
|
||||
&Addr::Con(Constant::Integer(ref n)) => {
|
||||
if let Some(c) = n.to_u8() {
|
||||
codes.push(c);
|
||||
} else {
|
||||
return Err(MachineError::representation_error(RepFlag::CharacterCode));
|
||||
},
|
||||
_ =>
|
||||
return Err(MachineError::representation_error(RepFlag::CharacterCode))
|
||||
}
|
||||
}
|
||||
_ => return Err(MachineError::representation_error(RepFlag::CharacterCode)),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(codes)
|
||||
}
|
||||
|
||||
fn call_at_index(&mut self, arity: usize, p: usize)
|
||||
{
|
||||
|
||||
fn call_at_index(&mut self, arity: usize, p: usize) {
|
||||
self.cp.assign_if_local(self.p.clone() + 1);
|
||||
self.num_of_args = arity;
|
||||
self.b0 = self.b;
|
||||
self.p = dir_entry!(p);
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn execute_at_index(&mut self, arity: usize, p: usize)
|
||||
{
|
||||
pub(super) fn execute_at_index(&mut self, arity: usize, p: usize) {
|
||||
self.num_of_args = arity;
|
||||
self.b0 = self.b;
|
||||
self.p = dir_entry!(p);
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn module_lookup(&mut self, indices: &IndexStore, key: PredicateKey, module_name: ClauseName,
|
||||
last_call: bool)
|
||||
-> CallResult
|
||||
{
|
||||
pub(super) fn module_lookup(
|
||||
&mut self,
|
||||
indices: &IndexStore,
|
||||
key: PredicateKey,
|
||||
module_name: ClauseName,
|
||||
last_call: bool,
|
||||
) -> CallResult {
|
||||
let (name, arity) = key;
|
||||
|
||||
if let Some(ref idx) = indices.get_code_index((name.clone(), arity), module_name.clone())
|
||||
{
|
||||
if let Some(ref idx) = indices.get_code_index((name.clone(), arity), module_name.clone()) {
|
||||
if let IndexPtr::Index(compiled_tl_index) = idx.0.borrow().0 {
|
||||
if last_call {
|
||||
self.execute_at_index(arity, compiled_tl_index);
|
||||
@@ -345,25 +344,29 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_in_situ_lookup(name: ClauseName, arity: usize, indices: &IndexStore) -> Option<usize>
|
||||
{
|
||||
fn try_in_situ_lookup(name: ClauseName, arity: usize, indices: &IndexStore) -> Option<usize> {
|
||||
match indices.in_situ_code_dir.get(&(name.clone(), arity)) {
|
||||
Some(p) => Some(*p),
|
||||
None => match indices.code_dir.get(&(name, arity)) {
|
||||
Some(ref idx) => if let &IndexPtr::Index(p) = &idx.0.borrow().0 {
|
||||
Some(p)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
Some(ref idx) => {
|
||||
if let &IndexPtr::Index(p) = &idx.0.borrow().0 {
|
||||
Some(p)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn try_in_situ(machine_st: &mut MachineState, name: ClauseName, arity: usize,
|
||||
indices: &IndexStore, last_call: bool)
|
||||
-> CallResult
|
||||
{
|
||||
fn try_in_situ(
|
||||
machine_st: &mut MachineState,
|
||||
name: ClauseName,
|
||||
arity: usize,
|
||||
indices: &IndexStore,
|
||||
last_call: bool,
|
||||
) -> CallResult {
|
||||
if let Some(p) = try_in_situ_lookup(name.clone(), arity, indices) {
|
||||
if last_call {
|
||||
machine_st.execute_at_index(arity, p);
|
||||
@@ -385,21 +388,20 @@ fn try_in_situ(machine_st: &mut MachineState, name: ClauseName, arity: usize,
|
||||
pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
|
||||
|
||||
pub(crate) trait CallPolicy: Any {
|
||||
fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult
|
||||
{
|
||||
fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult {
|
||||
let b = machine_st.b - 1;
|
||||
let n = machine_st.or_stack[b].num_args();
|
||||
|
||||
for i in 1 .. n + 1 {
|
||||
for i in 1..n + 1 {
|
||||
machine_st.registers[i] = machine_st.or_stack[b][i].clone();
|
||||
}
|
||||
|
||||
machine_st.e = machine_st.or_stack[b].e;
|
||||
machine_st.e = machine_st.or_stack[b].e;
|
||||
machine_st.cp = machine_st.or_stack[b].cp.clone();
|
||||
|
||||
machine_st.or_stack[b].bp = machine_st.p.clone() + offset;
|
||||
|
||||
let old_tr = machine_st.or_stack[b].tr;
|
||||
let old_tr = machine_st.or_stack[b].tr;
|
||||
let curr_tr = machine_st.tr;
|
||||
|
||||
machine_st.unwind_trail(old_tr, curr_tr);
|
||||
@@ -407,7 +409,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
|
||||
machine_st.trail.truncate(machine_st.tr);
|
||||
|
||||
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||
let curr_pstr_tr = machine_st.pstr_tr;
|
||||
|
||||
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
||||
@@ -418,7 +420,10 @@ pub(crate) trait CallPolicy: Any {
|
||||
machine_st.heap.truncate(machine_st.or_stack[b].h);
|
||||
|
||||
let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b;
|
||||
machine_st.attr_var_init.attr_var_queue.truncate(attr_var_init_b);
|
||||
machine_st
|
||||
.attr_var_init
|
||||
.attr_var_queue
|
||||
.truncate(attr_var_init_b);
|
||||
|
||||
machine_st.hb = machine_st.heap.h;
|
||||
machine_st.p += 1;
|
||||
@@ -426,21 +431,20 @@ pub(crate) trait CallPolicy: Any {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult
|
||||
{
|
||||
fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult {
|
||||
let b = machine_st.b - 1;
|
||||
let n = machine_st.or_stack[b].num_args();
|
||||
|
||||
for i in 1 .. n + 1 {
|
||||
for i in 1..n + 1 {
|
||||
machine_st.registers[i] = machine_st.or_stack[b][i].clone();
|
||||
}
|
||||
|
||||
machine_st.e = machine_st.or_stack[b].e;
|
||||
machine_st.e = machine_st.or_stack[b].e;
|
||||
machine_st.cp = machine_st.or_stack[b].cp.clone();
|
||||
|
||||
machine_st.or_stack[b].bp = machine_st.p.clone() + 1;
|
||||
|
||||
let old_tr = machine_st.or_stack[b].tr;
|
||||
let old_tr = machine_st.or_stack[b].tr;
|
||||
let curr_tr = machine_st.tr;
|
||||
|
||||
machine_st.unwind_trail(old_tr, curr_tr);
|
||||
@@ -448,7 +452,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
|
||||
machine_st.trail.truncate(machine_st.tr);
|
||||
|
||||
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||
let curr_pstr_tr = machine_st.pstr_tr;
|
||||
|
||||
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
||||
@@ -459,7 +463,10 @@ pub(crate) trait CallPolicy: Any {
|
||||
machine_st.heap.truncate(machine_st.or_stack[b].h);
|
||||
|
||||
let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b;
|
||||
machine_st.attr_var_init.attr_var_queue.truncate(attr_var_init_b);
|
||||
machine_st
|
||||
.attr_var_init
|
||||
.attr_var_queue
|
||||
.truncate(attr_var_init_b);
|
||||
|
||||
machine_st.hb = machine_st.heap.h;
|
||||
machine_st.p += offset;
|
||||
@@ -467,19 +474,18 @@ pub(crate) trait CallPolicy: Any {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult
|
||||
{
|
||||
fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult {
|
||||
let b = machine_st.b - 1;
|
||||
let n = machine_st.or_stack[b].num_args();
|
||||
|
||||
for i in 1 .. n + 1 {
|
||||
for i in 1..n + 1 {
|
||||
machine_st.registers[i] = machine_st.or_stack[b][i].clone();
|
||||
}
|
||||
|
||||
machine_st.e = machine_st.or_stack[b].e;
|
||||
machine_st.e = machine_st.or_stack[b].e;
|
||||
machine_st.cp = machine_st.or_stack[b].cp.clone();
|
||||
|
||||
let old_tr = machine_st.or_stack[b].tr;
|
||||
let old_tr = machine_st.or_stack[b].tr;
|
||||
let curr_tr = machine_st.tr;
|
||||
|
||||
machine_st.unwind_trail(old_tr, curr_tr);
|
||||
@@ -487,7 +493,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
|
||||
machine_st.trail.truncate(machine_st.tr);
|
||||
|
||||
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||
let curr_pstr_tr = machine_st.pstr_tr;
|
||||
|
||||
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
||||
@@ -498,7 +504,10 @@ pub(crate) trait CallPolicy: Any {
|
||||
machine_st.heap.truncate(machine_st.or_stack[b].h);
|
||||
|
||||
let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b;
|
||||
machine_st.attr_var_init.attr_var_queue.truncate(attr_var_init_b);
|
||||
machine_st
|
||||
.attr_var_init
|
||||
.attr_var_queue
|
||||
.truncate(attr_var_init_b);
|
||||
|
||||
machine_st.b = machine_st.or_stack[b].b;
|
||||
machine_st.or_stack.truncate(machine_st.b);
|
||||
@@ -509,19 +518,18 @@ pub(crate) trait CallPolicy: Any {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult
|
||||
{
|
||||
fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult {
|
||||
let b = machine_st.b - 1;
|
||||
let n = machine_st.or_stack[b].num_args();
|
||||
|
||||
for i in 1 .. n + 1 {
|
||||
for i in 1..n + 1 {
|
||||
machine_st.registers[i] = machine_st.or_stack[b][i].clone();
|
||||
}
|
||||
|
||||
machine_st.e = machine_st.or_stack[b].e;
|
||||
machine_st.e = machine_st.or_stack[b].e;
|
||||
machine_st.cp = machine_st.or_stack[b].cp.clone();
|
||||
|
||||
let old_tr = machine_st.or_stack[b].tr;
|
||||
let old_tr = machine_st.or_stack[b].tr;
|
||||
let curr_tr = machine_st.tr;
|
||||
|
||||
machine_st.unwind_trail(old_tr, curr_tr);
|
||||
@@ -529,7 +537,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
|
||||
machine_st.trail.truncate(machine_st.tr);
|
||||
|
||||
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||
let old_pstr_tr = machine_st.or_stack[b].pstr_tr;
|
||||
let curr_pstr_tr = machine_st.pstr_tr;
|
||||
|
||||
machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr);
|
||||
@@ -540,7 +548,10 @@ pub(crate) trait CallPolicy: Any {
|
||||
machine_st.heap.truncate(machine_st.or_stack[b].h);
|
||||
|
||||
let attr_var_init_b = machine_st.or_stack[b].attr_var_init_b;
|
||||
machine_st.attr_var_init.attr_var_queue.truncate(attr_var_init_b);
|
||||
machine_st
|
||||
.attr_var_init
|
||||
.attr_var_queue
|
||||
.truncate(attr_var_init_b);
|
||||
|
||||
machine_st.b = machine_st.or_stack[b].b;
|
||||
machine_st.or_stack.truncate(machine_st.b);
|
||||
@@ -551,10 +562,14 @@ pub(crate) trait CallPolicy: Any {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName,
|
||||
arity: usize, idx: CodeIndex, indices: &mut IndexStore)
|
||||
-> CallResult
|
||||
{
|
||||
fn context_call(
|
||||
&mut self,
|
||||
machine_st: &mut MachineState,
|
||||
name: ClauseName,
|
||||
arity: usize,
|
||||
idx: CodeIndex,
|
||||
indices: &mut IndexStore,
|
||||
) -> CallResult {
|
||||
if machine_st.last_call {
|
||||
self.try_execute(machine_st, name, arity, idx, indices)
|
||||
} else {
|
||||
@@ -562,48 +577,59 @@ pub(crate) trait CallPolicy: Any {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_call(&mut self, machine_st: &mut MachineState, name: ClauseName, arity: usize,
|
||||
idx: CodeIndex, indices: &IndexStore)
|
||||
-> CallResult
|
||||
{
|
||||
fn try_call(
|
||||
&mut self,
|
||||
machine_st: &mut MachineState,
|
||||
name: ClauseName,
|
||||
arity: usize,
|
||||
idx: CodeIndex,
|
||||
indices: &IndexStore,
|
||||
) -> CallResult {
|
||||
match idx.0.borrow().0 {
|
||||
IndexPtr::Undefined =>
|
||||
return try_in_situ(machine_st, name, arity, indices, false),
|
||||
IndexPtr::Index(compiled_tl_index) =>
|
||||
IndexPtr::Undefined => return try_in_situ(machine_st, name, arity, indices, false),
|
||||
IndexPtr::Index(compiled_tl_index) => {
|
||||
machine_st.call_at_index(arity, compiled_tl_index)
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn try_execute(&mut self, machine_st: &mut MachineState, name: ClauseName,
|
||||
arity: usize, idx: CodeIndex, indices: &IndexStore)
|
||||
-> CallResult
|
||||
{
|
||||
fn try_execute(
|
||||
&mut self,
|
||||
machine_st: &mut MachineState,
|
||||
name: ClauseName,
|
||||
arity: usize,
|
||||
idx: CodeIndex,
|
||||
indices: &IndexStore,
|
||||
) -> CallResult {
|
||||
match idx.0.borrow().0 {
|
||||
IndexPtr::Undefined =>
|
||||
return try_in_situ(machine_st, name, arity, indices, true),
|
||||
IndexPtr::Index(compiled_tl_index) =>
|
||||
IndexPtr::Undefined => return try_in_situ(machine_st, name, arity, indices, true),
|
||||
IndexPtr::Index(compiled_tl_index) => {
|
||||
machine_st.execute_at_index(arity, compiled_tl_index)
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn call_builtin(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType,
|
||||
indices: &mut IndexStore, parsing_stream: &mut PrologStream)
|
||||
-> CallResult
|
||||
{
|
||||
fn call_builtin(
|
||||
&mut self,
|
||||
machine_st: &mut MachineState,
|
||||
ct: &BuiltInClauseType,
|
||||
indices: &mut IndexStore,
|
||||
parsing_stream: &mut PrologStream,
|
||||
) -> CallResult {
|
||||
match ct {
|
||||
&BuiltInClauseType::AcyclicTerm => {
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
machine_st.fail = machine_st.is_cyclic_term(addr);
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::Arg => {
|
||||
machine_st.try_arg()?;
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::Compare => {
|
||||
let a1 = machine_st[temp_v!(1)].clone();
|
||||
let a2 = machine_st[temp_v!(2)].clone();
|
||||
@@ -613,11 +639,11 @@ pub(crate) trait CallPolicy: Any {
|
||||
Ordering::Greater => {
|
||||
let spec = fetch_atom_op_spec(clause_name!(">"), None, &indices.op_dir);
|
||||
Addr::Con(Constant::Atom(clause_name!(">"), spec))
|
||||
},
|
||||
}
|
||||
Ordering::Equal => {
|
||||
let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir);
|
||||
Addr::Con(Constant::Atom(clause_name!("="), spec))
|
||||
},
|
||||
}
|
||||
Ordering::Less => {
|
||||
let spec = fetch_atom_op_spec(clause_name!("<"), None, &indices.op_dir);
|
||||
Addr::Con(Constant::Atom(clause_name!("<"), spec))
|
||||
@@ -626,57 +652,57 @@ pub(crate) trait CallPolicy: Any {
|
||||
|
||||
machine_st.unify(a1, c);
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::CompareTerm(qt) => {
|
||||
machine_st.compare_term(qt);
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::CyclicTerm => {
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
machine_st.fail = !machine_st.is_cyclic_term(addr);
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::Nl => {
|
||||
let mut stdout = stdout();
|
||||
|
||||
write!(stdout, "\n\r").unwrap();
|
||||
stdout.flush().unwrap();
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::Read => {
|
||||
match machine_st.read(parsing_stream, indices.atom_tbl.clone(), &indices.op_dir) {
|
||||
Ok(offset) => {
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
machine_st.unify(addr, Addr::HeapCell(offset.heap_loc));
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
let h = machine_st.heap.h;
|
||||
let h = machine_st.heap.h;
|
||||
let stub = MachineError::functor_stub(clause_name!("read"), 1);
|
||||
let err = MachineError::syntax_error(h, e);
|
||||
let err = machine_st.error_form(err, stub);
|
||||
let err = MachineError::syntax_error(h, e);
|
||||
let err = machine_st.error_form(err, stub);
|
||||
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::CopyTerm => {
|
||||
machine_st.copy_term();
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::Eq => {
|
||||
machine_st.fail = machine_st.eq_test();
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::Ground => {
|
||||
machine_st.fail = machine_st.ground_test();
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::Functor => {
|
||||
machine_st.try_functor(&indices)?;
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::NotEq => {
|
||||
let a1 = machine_st[temp_v!(1)].clone();
|
||||
let a2 = machine_st[temp_v!(2)].clone();
|
||||
@@ -688,7 +714,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
};
|
||||
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::PartialString => {
|
||||
let s = machine_st.try_string_list(temp_v!(1))?;
|
||||
let a2 = machine_st[temp_v!(2)].clone();
|
||||
@@ -697,7 +723,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
machine_st.write_constant_to_var(a2, Constant::String(s));
|
||||
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::Sort => {
|
||||
machine_st.check_sort_errors()?;
|
||||
|
||||
@@ -713,7 +739,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
machine_st.unify(r2, heap_addr);
|
||||
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::KeySort => {
|
||||
machine_st.check_keysort_errors()?;
|
||||
|
||||
@@ -735,38 +761,46 @@ pub(crate) trait CallPolicy: Any {
|
||||
machine_st.unify(r2, heap_addr);
|
||||
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
&BuiltInClauseType::Is(r, ref at) => {
|
||||
let a1 = machine_st[r].clone();
|
||||
let a2 = machine_st.get_number(at)?;
|
||||
|
||||
machine_st.unify(a1, Addr::Con(a2.to_constant()));
|
||||
return_from_clause!(machine_st.last_call, machine_st)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_hook(&mut self, machine_st: &mut MachineState, hook: &CompileTimeHook) -> CallResult
|
||||
{
|
||||
fn compile_hook(
|
||||
&mut self,
|
||||
machine_st: &mut MachineState,
|
||||
hook: &CompileTimeHook,
|
||||
) -> CallResult {
|
||||
machine_st.cp = LocalCodePtr::TopLevel(0, 0);
|
||||
|
||||
machine_st.num_of_args = hook.arity();
|
||||
machine_st.b0 = machine_st.b;
|
||||
|
||||
machine_st.p = match hook {
|
||||
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion =>
|
||||
CodePtr::Local(LocalCodePtr::UserTermExpansion(0)),
|
||||
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion =>
|
||||
CompileTimeHook::UserTermExpansion | CompileTimeHook::TermExpansion => {
|
||||
CodePtr::Local(LocalCodePtr::UserTermExpansion(0))
|
||||
}
|
||||
CompileTimeHook::UserGoalExpansion | CompileTimeHook::GoalExpansion => {
|
||||
CodePtr::Local(LocalCodePtr::UserGoalExpansion(0))
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn call_n(&mut self, machine_st: &mut MachineState, arity: usize, indices: &mut IndexStore,
|
||||
parsing_stream: &mut PrologStream)
|
||||
-> CallResult
|
||||
{
|
||||
fn call_n(
|
||||
&mut self,
|
||||
machine_st: &mut MachineState,
|
||||
arity: usize,
|
||||
indices: &mut IndexStore,
|
||||
parsing_stream: &mut PrologStream,
|
||||
) -> CallResult {
|
||||
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
|
||||
match ClauseType::from(name.clone(), arity, None) {
|
||||
ClauseType::CallN => {
|
||||
@@ -777,18 +811,18 @@ pub(crate) trait CallPolicy: Any {
|
||||
}
|
||||
|
||||
machine_st.p = CodePtr::CallN(arity, machine_st.p.local());
|
||||
},
|
||||
}
|
||||
ClauseType::BuiltIn(built_in) => {
|
||||
machine_st.setup_built_in_call(built_in.clone());
|
||||
self.call_builtin(machine_st, &built_in, indices, parsing_stream)?;
|
||||
},
|
||||
}
|
||||
ClauseType::Inlined(inlined) => {
|
||||
machine_st.execute_inlined(&inlined);
|
||||
|
||||
if machine_st.last_call {
|
||||
machine_st.p = CodePtr::Local(machine_st.cp);
|
||||
}
|
||||
},
|
||||
}
|
||||
ClauseType::Op(..) | ClauseType::Named(..) => {
|
||||
let module = name.owning_module();
|
||||
|
||||
@@ -799,17 +833,17 @@ pub(crate) trait CallPolicy: Any {
|
||||
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
|
||||
let key = ExistenceError::Procedure(name, arity);
|
||||
|
||||
return Err(machine_st.error_form(MachineError::existence_error(h, key),
|
||||
stub));
|
||||
return Err(
|
||||
machine_st.error_form(MachineError::existence_error(h, key), stub)
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
ClauseType::Hook(_) | ClauseType::System(_) => {
|
||||
let name = Addr::Con(Constant::Atom(name, None));
|
||||
let stub = MachineError::functor_stub(clause_name!("call"), arity + 1);
|
||||
|
||||
return Err(machine_st.error_form(MachineError::type_error(ValidType::Callable,
|
||||
name),
|
||||
stub));
|
||||
return Err(machine_st
|
||||
.error_form(MachineError::type_error(ValidType::Callable, name), stub));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -819,51 +853,60 @@ pub(crate) trait CallPolicy: Any {
|
||||
}
|
||||
|
||||
impl CallPolicy for CWILCallPolicy {
|
||||
fn context_call(&mut self, machine_st: &mut MachineState, name: ClauseName,
|
||||
arity: usize, idx: CodeIndex, indices: &mut IndexStore)
|
||||
-> CallResult
|
||||
{
|
||||
self.prev_policy.context_call(machine_st, name, arity, idx, indices)?;
|
||||
fn context_call(
|
||||
&mut self,
|
||||
machine_st: &mut MachineState,
|
||||
name: ClauseName,
|
||||
arity: usize,
|
||||
idx: CodeIndex,
|
||||
indices: &mut IndexStore,
|
||||
) -> CallResult {
|
||||
self.prev_policy
|
||||
.context_call(machine_st, name, arity, idx, indices)?;
|
||||
self.increment(machine_st)
|
||||
}
|
||||
|
||||
fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult
|
||||
{
|
||||
fn retry_me_else(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult {
|
||||
self.prev_policy.retry_me_else(machine_st, offset)?;
|
||||
self.increment(machine_st)
|
||||
}
|
||||
|
||||
fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult
|
||||
{
|
||||
fn retry(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult {
|
||||
self.prev_policy.retry(machine_st, offset)?;
|
||||
self.increment(machine_st)
|
||||
}
|
||||
|
||||
fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult
|
||||
{
|
||||
fn trust_me(&mut self, machine_st: &mut MachineState) -> CallResult {
|
||||
self.prev_policy.trust_me(machine_st)?;
|
||||
self.increment(machine_st)
|
||||
}
|
||||
|
||||
fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult
|
||||
{
|
||||
fn trust(&mut self, machine_st: &mut MachineState, offset: usize) -> CallResult {
|
||||
self.prev_policy.trust(machine_st, offset)?;
|
||||
self.increment(machine_st)
|
||||
}
|
||||
|
||||
fn call_builtin(&mut self, machine_st: &mut MachineState, ct: &BuiltInClauseType,
|
||||
indices: &mut IndexStore, parsing_stream: &mut PrologStream)
|
||||
-> CallResult
|
||||
{
|
||||
self.prev_policy.call_builtin(machine_st, ct, indices, parsing_stream)?;
|
||||
fn call_builtin(
|
||||
&mut self,
|
||||
machine_st: &mut MachineState,
|
||||
ct: &BuiltInClauseType,
|
||||
indices: &mut IndexStore,
|
||||
parsing_stream: &mut PrologStream,
|
||||
) -> CallResult {
|
||||
self.prev_policy
|
||||
.call_builtin(machine_st, ct, indices, parsing_stream)?;
|
||||
self.increment(machine_st)
|
||||
}
|
||||
|
||||
fn call_n(&mut self, machine_st: &mut MachineState, arity: usize, indices: &mut IndexStore,
|
||||
parsing_stream: &mut PrologStream)
|
||||
-> CallResult
|
||||
{
|
||||
self.prev_policy.call_n(machine_st, arity, indices, parsing_stream)?;
|
||||
fn call_n(
|
||||
&mut self,
|
||||
machine_st: &mut MachineState,
|
||||
arity: usize,
|
||||
indices: &mut IndexStore,
|
||||
parsing_stream: &mut PrologStream,
|
||||
) -> CallResult {
|
||||
self.prev_policy
|
||||
.call_n(machine_st, arity, indices, parsing_stream)?;
|
||||
self.increment(machine_st)
|
||||
}
|
||||
}
|
||||
@@ -876,21 +919,22 @@ impl CallPolicy for DefaultCallPolicy {}
|
||||
|
||||
pub(crate) struct CWILCallPolicy {
|
||||
pub(crate) prev_policy: Box<CallPolicy>,
|
||||
count: Integer,
|
||||
count: Integer,
|
||||
limits: Vec<(Integer, usize)>,
|
||||
inference_limit_exceeded: bool
|
||||
inference_limit_exceeded: bool,
|
||||
}
|
||||
|
||||
impl CWILCallPolicy {
|
||||
pub(crate) fn new_in_place(policy: &mut Box<CallPolicy>)
|
||||
{
|
||||
pub(crate) fn new_in_place(policy: &mut Box<CallPolicy>) {
|
||||
let mut prev_policy: Box<CallPolicy> = Box::new(DefaultCallPolicy {});
|
||||
mem::swap(&mut prev_policy, policy);
|
||||
|
||||
let new_policy = CWILCallPolicy { prev_policy,
|
||||
count: Integer::from(0),
|
||||
limits: vec![],
|
||||
inference_limit_exceeded: false };
|
||||
let new_policy = CWILCallPolicy {
|
||||
prev_policy,
|
||||
count: Integer::from(0),
|
||||
limits: vec![],
|
||||
inference_limit_exceeded: false,
|
||||
};
|
||||
*policy = Box::new(new_policy);
|
||||
}
|
||||
|
||||
@@ -902,8 +946,11 @@ impl CWILCallPolicy {
|
||||
if let Some(&(ref limit, bp)) = self.limits.last() {
|
||||
if self.count == *limit {
|
||||
self.inference_limit_exceeded = true;
|
||||
return Err(functor!("inference_limit_exceeded", 1,
|
||||
[HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))]));
|
||||
return Err(functor!(
|
||||
"inference_limit_exceeded",
|
||||
1,
|
||||
[HeapCellValue::Addr(Addr::Con(Constant::Usize(bp)))]
|
||||
));
|
||||
} else {
|
||||
self.count += 1;
|
||||
}
|
||||
@@ -916,8 +963,8 @@ impl CWILCallPolicy {
|
||||
limit += &self.count;
|
||||
|
||||
match self.limits.last().cloned() {
|
||||
Some((ref inner_limit, _)) if *inner_limit <= limit => {},
|
||||
_ => self.limits.push((limit, b))
|
||||
Some((ref inner_limit, _)) if *inner_limit <= limit => {}
|
||||
_ => self.limits.push((limit, b)),
|
||||
};
|
||||
|
||||
&self.count
|
||||
@@ -986,13 +1033,17 @@ impl CutPolicy for DefaultCutPolicy {
|
||||
pub(crate) struct SCCCutPolicy {
|
||||
// locations of cleaners, cut points, the previous block
|
||||
cont_pts: Vec<(Addr, usize, usize)>,
|
||||
r_c_w_h: usize,
|
||||
r_c_wo_h: usize
|
||||
r_c_w_h: usize,
|
||||
r_c_wo_h: usize,
|
||||
}
|
||||
|
||||
impl SCCCutPolicy {
|
||||
pub(crate) fn new(r_c_w_h: usize, r_c_wo_h: usize) -> Self {
|
||||
SCCCutPolicy { cont_pts: vec![], r_c_w_h, r_c_wo_h }
|
||||
SCCCutPolicy {
|
||||
cont_pts: vec![],
|
||||
r_c_w_h,
|
||||
r_c_wo_h,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn out_of_cont_pts(&self) -> bool {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,29 +7,30 @@ use prolog::forms::*;
|
||||
use prolog::heap_print::*;
|
||||
use prolog::instructions::*;
|
||||
use prolog::read::*;
|
||||
use prolog::write::{ContinueResult, next_keypress};
|
||||
use prolog::write::{next_keypress, ContinueResult};
|
||||
|
||||
pub mod machine_indices;
|
||||
pub mod heap;
|
||||
mod and_stack;
|
||||
mod or_stack;
|
||||
mod attributed_variables;
|
||||
pub(super) mod code_repo;
|
||||
pub mod compile;
|
||||
mod copier;
|
||||
mod dynamic_database;
|
||||
pub mod heap;
|
||||
pub mod machine_errors;
|
||||
pub mod toplevel;
|
||||
pub mod compile;
|
||||
pub(super) mod code_repo;
|
||||
pub mod modules;
|
||||
pub mod machine_indices;
|
||||
pub(super) mod machine_state;
|
||||
pub mod modules;
|
||||
mod or_stack;
|
||||
pub(super) mod term_expansion;
|
||||
pub mod toplevel;
|
||||
|
||||
#[macro_use] mod machine_state_impl;
|
||||
#[macro_use]
|
||||
mod machine_state_impl;
|
||||
mod system_calls;
|
||||
|
||||
use prolog::machine::attributed_variables::*;
|
||||
use prolog::machine::compile::*;
|
||||
use prolog::machine::code_repo::*;
|
||||
use prolog::machine::compile::*;
|
||||
use prolog::machine::machine_errors::*;
|
||||
use prolog::machine::machine_indices::*;
|
||||
use prolog::machine::machine_state::*;
|
||||
@@ -40,13 +41,13 @@ use prolog::read::PrologStream;
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::io::{Read, Write, stdout};
|
||||
use std::fs::File;
|
||||
use std::io::{stdout, Read, Write};
|
||||
use std::mem;
|
||||
use std::ops::Index;
|
||||
use std::rc::Rc;
|
||||
|
||||
use termion::raw::{IntoRawMode};
|
||||
use termion::raw::IntoRawMode;
|
||||
|
||||
pub struct MachinePolicies {
|
||||
call_policy: Box<CallPolicy>,
|
||||
@@ -69,7 +70,7 @@ pub struct Machine {
|
||||
pub(super) indices: IndexStore,
|
||||
pub(super) code_repo: CodeRepo,
|
||||
pub(super) toplevel_idx: usize,
|
||||
pub(super) prolog_stream: ParsingStream<Box<Read>>
|
||||
pub(super) prolog_stream: ParsingStream<Box<Read>>,
|
||||
}
|
||||
|
||||
impl Index<LocalCodePtr> for CodeRepo {
|
||||
@@ -103,23 +104,21 @@ impl SubModuleUser for IndexStore {
|
||||
&mut self.op_dir
|
||||
}
|
||||
|
||||
fn get_code_index(&self, key: PredicateKey, module: ClauseName) -> Option<CodeIndex>
|
||||
{
|
||||
fn get_code_index(&self, key: PredicateKey, module: ClauseName) -> Option<CodeIndex> {
|
||||
match module.as_str() {
|
||||
"user" | "builtin" => self.code_dir.get(&key).cloned(),
|
||||
_ => self.modules.get(&module).and_then(|ref module| {
|
||||
module.code_dir.get(&key).cloned().map(CodeIndex::from)
|
||||
})
|
||||
_ => self
|
||||
.modules
|
||||
.get(&module)
|
||||
.and_then(|ref module| module.code_dir.get(&key).cloned().map(CodeIndex::from)),
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_code_index(&mut self, key: PredicateKey)
|
||||
{
|
||||
fn remove_code_index(&mut self, key: PredicateKey) {
|
||||
self.code_dir.remove(&key);
|
||||
}
|
||||
|
||||
fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: CodeIndex)
|
||||
{
|
||||
fn insert_dir_entry(&mut self, name: ClauseName, arity: usize, idx: CodeIndex) {
|
||||
if let Some(ref code_idx) = self.code_dir.get(&(name.clone(), arity)) {
|
||||
if !code_idx.is_undefined() {
|
||||
println!("warning: overwriting {}/{}", &name, arity);
|
||||
@@ -133,21 +132,31 @@ impl SubModuleUser for IndexStore {
|
||||
self.code_dir.insert((name, arity), idx);
|
||||
}
|
||||
|
||||
fn use_qualified_module(&mut self, code_repo: &mut CodeRepo, flags: MachineFlags,
|
||||
submodule: &Module, exports: &Vec<PredicateKey>)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
fn use_qualified_module(
|
||||
&mut self,
|
||||
code_repo: &mut CodeRepo,
|
||||
flags: MachineFlags,
|
||||
submodule: &Module,
|
||||
exports: &Vec<PredicateKey>,
|
||||
) -> Result<(), SessionError> {
|
||||
use_qualified_module(self, submodule, exports)?;
|
||||
submodule.dump_expansions(code_repo, flags).map_err(SessionError::from)
|
||||
submodule
|
||||
.dump_expansions(code_repo, flags)
|
||||
.map_err(SessionError::from)
|
||||
}
|
||||
|
||||
fn use_module(&mut self, code_repo: &mut CodeRepo, flags: MachineFlags, submodule: &Module)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
fn use_module(
|
||||
&mut self,
|
||||
code_repo: &mut CodeRepo,
|
||||
flags: MachineFlags,
|
||||
submodule: &Module,
|
||||
) -> Result<(), SessionError> {
|
||||
use_module(self, submodule)?;
|
||||
|
||||
if !submodule.inserted_expansions {
|
||||
submodule.dump_expansions(code_repo, flags).map_err(SessionError::from)
|
||||
submodule
|
||||
.dump_expansions(code_repo, flags)
|
||||
.map_err(SessionError::from)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@@ -155,9 +164,9 @@ impl SubModuleUser for IndexStore {
|
||||
}
|
||||
|
||||
static BUILTINS: &str = include_str!("../lib/builtins.pl");
|
||||
static ERROR: &str = include_str!("../lib/error.pl");
|
||||
static LISTS: &str = include_str!("../lib/lists.pl");
|
||||
static NON_ISO: &str = include_str!("../lib/non_iso.pl");
|
||||
static ERROR: &str = include_str!("../lib/error.pl");
|
||||
static LISTS: &str = include_str!("../lib/lists.pl");
|
||||
static NON_ISO: &str = include_str!("../lib/non_iso.pl");
|
||||
static TOPLEVEL: &str = include_str!("../toplevel.pl");
|
||||
|
||||
impl Machine {
|
||||
@@ -166,16 +175,16 @@ impl Machine {
|
||||
Ok(code) => {
|
||||
self.machine_st.attr_var_init.verify_attrs_loc = self.code_repo.code.len();
|
||||
self.code_repo.code.extend(code.into_iter());
|
||||
},
|
||||
Err(_) => panic!("Machine::compile_special_forms() failed at VERIFY_ATTRS")
|
||||
}
|
||||
Err(_) => panic!("Machine::compile_special_forms() failed at VERIFY_ATTRS"),
|
||||
}
|
||||
|
||||
match compile_special_form(self, parsing_stream(PROJECT_ATTRS.as_bytes())) {
|
||||
Ok(code) => {
|
||||
self.machine_st.attr_var_init.project_attrs_loc = self.code_repo.code.len();
|
||||
self.code_repo.code.extend(code.into_iter());
|
||||
},
|
||||
Err(_) => panic!("Machine::compile_special_forms() failed at PROJECT_ATTRS")
|
||||
}
|
||||
Err(_) => panic!("Machine::compile_special_forms() failed at PROJECT_ATTRS"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,15 +196,15 @@ impl Machine {
|
||||
fn compile_scryerrc(&mut self) {
|
||||
let mut path = match dirs::home_dir() {
|
||||
Some(path) => path,
|
||||
None => return
|
||||
None => return,
|
||||
};
|
||||
|
||||
|
||||
path.push(".scryerrc");
|
||||
|
||||
if path.is_file() {
|
||||
let file_src = match File::open(&path) {
|
||||
Ok(file_handle) => parsing_stream(file_handle),
|
||||
Err(_) => return
|
||||
Err(_) => return,
|
||||
};
|
||||
|
||||
compile_user_module(self, file_src);
|
||||
@@ -221,13 +230,16 @@ impl Machine {
|
||||
indices: IndexStore::new(),
|
||||
code_repo: CodeRepo::new(),
|
||||
toplevel_idx: 0,
|
||||
prolog_stream
|
||||
prolog_stream,
|
||||
};
|
||||
|
||||
let atom_tbl = wam.indices.atom_tbl.clone();
|
||||
|
||||
compile_listing(&mut wam, parsing_stream(BUILTINS.as_bytes()),
|
||||
default_index_store!(atom_tbl.clone()));
|
||||
compile_listing(
|
||||
&mut wam,
|
||||
parsing_stream(BUILTINS.as_bytes()),
|
||||
default_index_store!(atom_tbl.clone()),
|
||||
);
|
||||
|
||||
wam.compile_special_forms();
|
||||
wam.compile_top_level();
|
||||
@@ -246,11 +258,10 @@ impl Machine {
|
||||
self.machine_st.flags
|
||||
}
|
||||
|
||||
pub fn check_toplevel_code(&self, indices: &IndexStore) -> Result<(), SessionError>
|
||||
{
|
||||
pub fn check_toplevel_code(&self, indices: &IndexStore) -> Result<(), SessionError> {
|
||||
for (key, idx) in &indices.code_dir {
|
||||
match ClauseType::from(key.0.clone(), key.1, None) {
|
||||
ClauseType::Named(..) | ClauseType::Op(..) => {},
|
||||
ClauseType::Named(..) | ClauseType::Op(..) => {}
|
||||
_ => {
|
||||
// ensure we don't try to overwrite the name/arity of a builtin.
|
||||
let err_str = format!("{}/{}", key.0, key.1);
|
||||
@@ -269,8 +280,12 @@ impl Machine {
|
||||
}
|
||||
|
||||
if existing_idx.module_name() != idx.module_name() {
|
||||
let err_str = format!("{}/{} from module {}", key.0, key.1,
|
||||
existing_idx.module_name().as_str());
|
||||
let err_str = format!(
|
||||
"{}/{} from module {}",
|
||||
key.0,
|
||||
key.1,
|
||||
existing_idx.module_name().as_str()
|
||||
);
|
||||
let err_str = clause_name!(err_str, self.indices.atom_tbl());
|
||||
|
||||
return Err(SessionError::CannotOverwriteImport(err_str));
|
||||
@@ -282,8 +297,7 @@ impl Machine {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_batched_code(&mut self, code: Code, code_dir: CodeDir)
|
||||
{
|
||||
pub fn add_batched_code(&mut self, code: Code, code_dir: CodeDir) {
|
||||
// error detection has finished, so update the master index of keys.
|
||||
for (key, idx) in code_dir {
|
||||
if let Some(ref mut master_idx) = self.indices.code_dir.get_mut(&key) {
|
||||
@@ -309,12 +323,13 @@ impl Machine {
|
||||
|
||||
#[inline]
|
||||
pub fn add_module(&mut self, module: Module, code: Code) {
|
||||
self.indices.modules.insert(module.module_decl.name.clone(), module);
|
||||
self.indices
|
||||
.modules
|
||||
.insert(module.module_decl.name.clone(), module);
|
||||
self.code_repo.code.extend(code.into_iter());
|
||||
}
|
||||
|
||||
pub fn submit_query(&mut self, code: Code, alloc_locs: AllocVarDict) -> EvalSession
|
||||
{
|
||||
pub fn submit_query(&mut self, code: Code, alloc_locs: AllocVarDict) -> EvalSession {
|
||||
self.code_repo.cached_query = code;
|
||||
self.run_query(&alloc_locs);
|
||||
|
||||
@@ -328,16 +343,15 @@ impl Machine {
|
||||
pub fn throw_session_error(&mut self, err: SessionError, key: PredicateKey) {
|
||||
let h = self.machine_st.heap.h;
|
||||
|
||||
let err = MachineError::session_error(h, err);
|
||||
let err = MachineError::session_error(h, err);
|
||||
let stub = MachineError::functor_stub(key.0, key.1);
|
||||
let err = self.machine_st.error_form(err, stub);
|
||||
let err = self.machine_st.error_form(err, stub);
|
||||
|
||||
self.machine_st.throw_exception(err);
|
||||
return;
|
||||
}
|
||||
|
||||
fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr)
|
||||
{
|
||||
fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) {
|
||||
match code_ptr {
|
||||
REPLCodePtr::CompileBatch => {
|
||||
#[cfg(feature = "readline_rs_compat")]
|
||||
@@ -352,7 +366,7 @@ impl Machine {
|
||||
EvalSession::Error(e) => self.throw_session_error(e, (clause_name!("repl"), 0)),
|
||||
_ => {}
|
||||
};
|
||||
},
|
||||
}
|
||||
REPLCodePtr::SubmitQueryAndPrintResults => {
|
||||
let term = self.machine_st[temp_v!(1)].clone();
|
||||
let stub = MachineError::functor_stub(clause_name!("repl"), 0);
|
||||
@@ -364,16 +378,18 @@ impl Machine {
|
||||
for addr in addrs {
|
||||
match addr {
|
||||
Addr::Str(s) => {
|
||||
let var_atom = match self.machine_st.heap[s+1].as_addr(s+1) {
|
||||
Addr::Con(Constant::Atom(var_atom, _)) =>
|
||||
Rc::new(var_atom.to_string()),
|
||||
_ => unreachable!()
|
||||
let var_atom = match self.machine_st.heap[s + 1].as_addr(s + 1)
|
||||
{
|
||||
Addr::Con(Constant::Atom(var_atom, _)) => {
|
||||
Rc::new(var_atom.to_string())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let var_addr = self.machine_st.heap[s+2].as_addr(s+2);
|
||||
let var_addr = self.machine_st.heap[s + 2].as_addr(s + 2);
|
||||
var_dict.insert(var_atom, var_addr);
|
||||
},
|
||||
_ => unreachable!()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -381,7 +397,7 @@ impl Machine {
|
||||
let term_output = self.machine_st.print_query(term, &self.indices.op_dir);
|
||||
|
||||
term_output.result()
|
||||
},
|
||||
}
|
||||
Err(err_stub) => {
|
||||
self.machine_st.throw_exception(err_stub);
|
||||
return;
|
||||
@@ -395,7 +411,7 @@ impl Machine {
|
||||
|
||||
let result = match stream_to_toplevel(stream, self) {
|
||||
Ok(packet) => compile_term(self, packet),
|
||||
Err(e) => EvalSession::from(e)
|
||||
Err(e) => EvalSession::from(e),
|
||||
};
|
||||
|
||||
self.handle_eval_session(result, snapshot);
|
||||
@@ -419,117 +435,128 @@ impl Machine {
|
||||
|
||||
fn handle_eval_session(&mut self, result: EvalSession, snapshot: MachineState) {
|
||||
match result {
|
||||
EvalSession::InitialQuerySuccess(alloc_locs) =>
|
||||
loop {
|
||||
let bindings = {
|
||||
let output = PrinterOutputter::new();
|
||||
self.toplevel_heap_view(output).result()
|
||||
};
|
||||
EvalSession::InitialQuerySuccess(alloc_locs) => loop {
|
||||
let bindings = {
|
||||
let output = PrinterOutputter::new();
|
||||
self.toplevel_heap_view(output).result()
|
||||
};
|
||||
|
||||
let attr_goals = self.attribute_goals();
|
||||
let attr_goals = self.attribute_goals();
|
||||
|
||||
if !(self.machine_st.b > 0) {
|
||||
if bindings.is_empty() {
|
||||
let space = if requires_space(&attr_goals, ".") { " " } else { "" };
|
||||
if !(self.machine_st.b > 0) {
|
||||
if bindings.is_empty() {
|
||||
let space = if requires_space(&attr_goals, ".") {
|
||||
" "
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
if !attr_goals.is_empty() {
|
||||
println!("{}{}.", attr_goals, space);
|
||||
} else {
|
||||
println!("true.");
|
||||
}
|
||||
if !attr_goals.is_empty() {
|
||||
println!("{}{}.", attr_goals, space);
|
||||
} else {
|
||||
println!("true.");
|
||||
}
|
||||
|
||||
self.machine_st.absorb_snapshot(snapshot);
|
||||
return;
|
||||
}
|
||||
} else if bindings.is_empty() && attr_goals.is_empty() {
|
||||
print!("true");
|
||||
stdout().flush().unwrap();
|
||||
}
|
||||
|
||||
let mut raw_stdout = stdout().into_raw_mode().unwrap();
|
||||
|
||||
if !attr_goals.is_empty() {
|
||||
if bindings.is_empty() {
|
||||
write!(raw_stdout, "{}", attr_goals).unwrap();
|
||||
} else {
|
||||
write!(raw_stdout, "{}, {}", bindings, attr_goals).unwrap();
|
||||
}
|
||||
} else if !bindings.is_empty() {
|
||||
write!(raw_stdout, "{}", bindings).unwrap();
|
||||
}
|
||||
|
||||
if self.machine_st.b > 0 {
|
||||
raw_stdout.flush().unwrap();
|
||||
|
||||
let result = match next_keypress() {
|
||||
ContinueResult::ContinueQuery => {
|
||||
write!(raw_stdout, " ;\r\n").unwrap();
|
||||
self.continue_query(&alloc_locs)
|
||||
}
|
||||
ContinueResult::Conclude => {
|
||||
write!(raw_stdout, " ...\r\n").unwrap();
|
||||
self.machine_st.absorb_snapshot(snapshot);
|
||||
return;
|
||||
}
|
||||
} else if bindings.is_empty() && attr_goals.is_empty() {
|
||||
print!("true");
|
||||
stdout().flush().unwrap();
|
||||
}
|
||||
};
|
||||
|
||||
let mut raw_stdout = stdout().into_raw_mode().unwrap();
|
||||
|
||||
if !attr_goals.is_empty() {
|
||||
if bindings.is_empty() {
|
||||
write!(raw_stdout, "{}", attr_goals).unwrap();
|
||||
} else {
|
||||
write!(raw_stdout, "{}, {}", bindings, attr_goals).unwrap();
|
||||
}
|
||||
} else if !bindings.is_empty() {
|
||||
write!(raw_stdout, "{}", bindings).unwrap();
|
||||
}
|
||||
match result {
|
||||
EvalSession::QueryFailure => {
|
||||
if self.machine_st.ball.stub.len() > 0 {
|
||||
self.propagate_exception_to_toplevel(snapshot);
|
||||
return;
|
||||
} else {
|
||||
write!(raw_stdout, "false.\r\n").unwrap();
|
||||
raw_stdout.flush().unwrap();
|
||||
|
||||
if self.machine_st.b > 0 {
|
||||
raw_stdout.flush().unwrap();
|
||||
|
||||
let result = match next_keypress() {
|
||||
ContinueResult::ContinueQuery => {
|
||||
write!(raw_stdout, " ;\r\n").unwrap();
|
||||
self.continue_query(&alloc_locs)
|
||||
},
|
||||
ContinueResult::Conclude => {
|
||||
write!(raw_stdout, " ...\r\n").unwrap();
|
||||
self.machine_st.absorb_snapshot(snapshot);
|
||||
return;
|
||||
}
|
||||
}
|
||||
EvalSession::Error(err) => {
|
||||
self.machine_st.absorb_snapshot(snapshot);
|
||||
self.throw_session_error(err, (clause_name!("repl"), 0));
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
if bindings.is_empty() && attr_goals.is_empty() {
|
||||
write!(raw_stdout, "true.\r\n").unwrap();
|
||||
} else {
|
||||
let space = if !attr_goals.is_empty() {
|
||||
if requires_space(&attr_goals, ".") {
|
||||
" "
|
||||
} else {
|
||||
""
|
||||
}
|
||||
} else {
|
||||
if requires_space(&bindings, ".") {
|
||||
" "
|
||||
} else {
|
||||
""
|
||||
}
|
||||
};
|
||||
|
||||
let mut raw_stdout = stdout().into_raw_mode().unwrap();
|
||||
|
||||
match result {
|
||||
EvalSession::QueryFailure =>
|
||||
if self.machine_st.ball.stub.len() > 0 {
|
||||
self.propagate_exception_to_toplevel(snapshot);
|
||||
return;
|
||||
} else {
|
||||
write!(raw_stdout, "false.\r\n").unwrap();
|
||||
raw_stdout.flush().unwrap();
|
||||
|
||||
self.machine_st.absorb_snapshot(snapshot);
|
||||
return;
|
||||
},
|
||||
EvalSession::Error(err) => {
|
||||
self.machine_st.absorb_snapshot(snapshot);
|
||||
self.throw_session_error(err, (clause_name!("repl"), 0));
|
||||
return;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
if bindings.is_empty() && attr_goals.is_empty() {
|
||||
write!(raw_stdout, "true.\r\n").unwrap();
|
||||
} else {
|
||||
let space = if !attr_goals.is_empty() {
|
||||
if requires_space(&attr_goals, ".") { " " } else { "" }
|
||||
} else {
|
||||
if requires_space(&bindings, ".") { " " } else { "" }
|
||||
};
|
||||
|
||||
write!(raw_stdout, "{}.\r\n", space).unwrap();
|
||||
}
|
||||
|
||||
break;
|
||||
write!(raw_stdout, "{}.\r\n", space).unwrap();
|
||||
}
|
||||
},
|
||||
|
||||
break;
|
||||
}
|
||||
},
|
||||
EvalSession::Error(err) => {
|
||||
self.machine_st.absorb_snapshot(snapshot);
|
||||
self.throw_session_error(err, (clause_name!("repl"), 0));
|
||||
return;
|
||||
},
|
||||
EvalSession::QueryFailure =>
|
||||
}
|
||||
EvalSession::QueryFailure => {
|
||||
if self.machine_st.ball.stub.len() > 0 {
|
||||
return self.propagate_exception_to_toplevel(snapshot);
|
||||
} else {
|
||||
println!("false.");
|
||||
},
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.machine_st.absorb_snapshot(snapshot);
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn run_query(&mut self, alloc_locs: &AllocVarDict)
|
||||
{
|
||||
pub(super) fn run_query(&mut self, alloc_locs: &AllocVarDict) {
|
||||
let end_ptr = top_level_code_ptr!(0, self.code_repo.size_of_cached_query());
|
||||
|
||||
while self.machine_st.p < end_ptr {
|
||||
@@ -538,20 +565,23 @@ impl Machine {
|
||||
&Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {
|
||||
self.machine_st.record_var_places(cn, alloc_locs);
|
||||
cn += 1;
|
||||
},
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.machine_st.p = top_level_code_ptr!(cn, p);
|
||||
}
|
||||
|
||||
self.machine_st.query_stepper(&mut self.indices, &mut self.policies, &mut self.code_repo,
|
||||
&mut self.prolog_stream);
|
||||
self.machine_st.query_stepper(
|
||||
&mut self.indices,
|
||||
&mut self.policies,
|
||||
&mut self.code_repo,
|
||||
&mut self.prolog_stream,
|
||||
);
|
||||
|
||||
match self.machine_st.p {
|
||||
CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {},
|
||||
CodePtr::REPL(code_ptr, p) =>
|
||||
self.handle_toplevel_command(code_ptr, p),
|
||||
CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {}
|
||||
CodePtr::REPL(code_ptr, p) => self.handle_toplevel_command(code_ptr, p),
|
||||
CodePtr::DynamicTransaction(trans_type, p) => {
|
||||
// self.code_repo.cached_query is about to be overwritten by the term expander,
|
||||
// so hold onto it locally and restore it after the compiler has finished.
|
||||
@@ -569,7 +599,7 @@ impl Machine {
|
||||
}
|
||||
|
||||
self.code_repo.cached_query = cached_query;
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
if self.machine_st.heap_locs.is_empty() {
|
||||
self.machine_st.record_var_places(0, alloc_locs);
|
||||
@@ -581,8 +611,7 @@ impl Machine {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn continue_query(&mut self, alloc_locs: &AllocVarDict) -> EvalSession
|
||||
{
|
||||
pub fn continue_query(&mut self, alloc_locs: &AllocVarDict) -> EvalSession {
|
||||
if !self.or_stack_is_empty() {
|
||||
let b = self.machine_st.b - 1;
|
||||
self.machine_st.p = self.machine_st.or_stack[b].bp.clone();
|
||||
@@ -605,15 +634,17 @@ impl Machine {
|
||||
}
|
||||
|
||||
pub fn toplevel_heap_view<Outputter>(&self, mut output: Outputter) -> Outputter
|
||||
where Outputter: HCValueOutputter
|
||||
where
|
||||
Outputter: HCValueOutputter,
|
||||
{
|
||||
let mut sorted_vars: Vec<_> = self.machine_st.heap_locs.iter().collect();
|
||||
sorted_vars.sort_by_key(|ref v| v.0);
|
||||
|
||||
for (var, addr) in sorted_vars {
|
||||
let addr = self.machine_st.store(self.machine_st.deref(addr.clone()));
|
||||
output = self.machine_st.print_var_eq(var.clone(), addr, &self.indices.op_dir,
|
||||
output);
|
||||
output = self
|
||||
.machine_st
|
||||
.print_var_eq(var.clone(), addr, &self.indices.op_dir, output);
|
||||
}
|
||||
|
||||
output
|
||||
@@ -621,14 +652,19 @@ impl Machine {
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn test_heap_view<Outputter>(&self, mut output: Outputter) -> Outputter
|
||||
where Outputter: HCValueOutputter
|
||||
where
|
||||
Outputter: HCValueOutputter,
|
||||
{
|
||||
let mut sorted_vars: Vec<(&Rc<Var>, &Addr)> = self.machine_st.heap_locs.iter().collect();
|
||||
sorted_vars.sort_by_key(|ref v| v.0);
|
||||
|
||||
for (var, addr) in sorted_vars {
|
||||
output = self.machine_st.print_var_eq(var.clone(), addr.clone(), &self.indices.op_dir,
|
||||
output);
|
||||
output = self.machine_st.print_var_eq(
|
||||
var.clone(),
|
||||
addr.clone(),
|
||||
&self.indices.op_dir,
|
||||
output,
|
||||
);
|
||||
}
|
||||
|
||||
output
|
||||
@@ -640,18 +676,18 @@ impl Machine {
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
fn record_var_places(&mut self, chunk_num: usize, alloc_locs: &AllocVarDict)
|
||||
{
|
||||
fn record_var_places(&mut self, chunk_num: usize, alloc_locs: &AllocVarDict) {
|
||||
for (var, var_data) in alloc_locs {
|
||||
match var_data {
|
||||
&VarData::Perm(p) if p > 0 =>
|
||||
&VarData::Perm(p) if p > 0 => {
|
||||
if !self.heap_locs.contains_key(var) {
|
||||
let e = self.e;
|
||||
let r = var_data.as_reg_type().reg_num();
|
||||
let addr = self.and_stack[e][r].clone();
|
||||
|
||||
self.heap_locs.insert(var.clone(), addr);
|
||||
},
|
||||
}
|
||||
}
|
||||
&VarData::Temp(cn, _, _) if cn == chunk_num => {
|
||||
let r = var_data.as_reg_type();
|
||||
|
||||
@@ -659,18 +695,19 @@ impl MachineState {
|
||||
let addr = self[r].clone();
|
||||
self.heap_locs.insert(var.clone(), addr);
|
||||
}
|
||||
},
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_query(&mut self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter
|
||||
{
|
||||
fn print_query(&mut self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter {
|
||||
let flags = self.flags;
|
||||
|
||||
let mut output = {
|
||||
self.flags = MachineFlags { double_quotes: DoubleQuotes::Atom };
|
||||
self.flags = MachineFlags {
|
||||
double_quotes: DoubleQuotes::Atom,
|
||||
};
|
||||
|
||||
let output = PrinterOutputter::new();
|
||||
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
|
||||
@@ -689,28 +726,38 @@ impl MachineState {
|
||||
output
|
||||
}
|
||||
|
||||
fn dispatch_instr(&mut self, instr: &Line, indices: &mut IndexStore, policies: &mut MachinePolicies,
|
||||
code_repo: &CodeRepo, prolog_stream: &mut PrologStream)
|
||||
{
|
||||
fn dispatch_instr(
|
||||
&mut self,
|
||||
instr: &Line,
|
||||
indices: &mut IndexStore,
|
||||
policies: &mut MachinePolicies,
|
||||
code_repo: &CodeRepo,
|
||||
prolog_stream: &mut PrologStream,
|
||||
) {
|
||||
match instr {
|
||||
&Line::Arithmetic(ref arith_instr) =>
|
||||
self.execute_arith_instr(arith_instr),
|
||||
&Line::Choice(ref choice_instr) =>
|
||||
self.execute_choice_instr(choice_instr, &mut policies.call_policy),
|
||||
&Line::Cut(ref cut_instr) =>
|
||||
self.execute_cut_instr(cut_instr, &mut policies.cut_policy),
|
||||
&Line::Control(ref control_instr) =>
|
||||
self.execute_ctrl_instr(indices, code_repo, &mut policies.call_policy,
|
||||
&mut policies.cut_policy, prolog_stream,
|
||||
control_instr),
|
||||
&Line::Arithmetic(ref arith_instr) => self.execute_arith_instr(arith_instr),
|
||||
&Line::Choice(ref choice_instr) => {
|
||||
self.execute_choice_instr(choice_instr, &mut policies.call_policy)
|
||||
}
|
||||
&Line::Cut(ref cut_instr) => {
|
||||
self.execute_cut_instr(cut_instr, &mut policies.cut_policy)
|
||||
}
|
||||
&Line::Control(ref control_instr) => self.execute_ctrl_instr(
|
||||
indices,
|
||||
code_repo,
|
||||
&mut policies.call_policy,
|
||||
&mut policies.cut_policy,
|
||||
prolog_stream,
|
||||
control_instr,
|
||||
),
|
||||
&Line::Fact(ref fact_instr) => {
|
||||
self.execute_fact_instr(&fact_instr);
|
||||
self.p += 1;
|
||||
},
|
||||
&Line::Indexing(ref indexing_instr) =>
|
||||
self.execute_indexing_instr(&indexing_instr),
|
||||
&Line::IndexedChoice(ref choice_instr) =>
|
||||
self.execute_indexed_choice_instr(choice_instr, &mut policies.call_policy),
|
||||
}
|
||||
&Line::Indexing(ref indexing_instr) => self.execute_indexing_instr(&indexing_instr),
|
||||
&Line::IndexedChoice(ref choice_instr) => {
|
||||
self.execute_indexed_choice_instr(choice_instr, &mut policies.call_policy)
|
||||
}
|
||||
&Line::Query(ref query_instr) => {
|
||||
self.execute_query_instr(&query_instr);
|
||||
self.p += 1;
|
||||
@@ -718,24 +765,27 @@ impl MachineState {
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_instr(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies,
|
||||
code_repo: &CodeRepo, prolog_stream: &mut PrologStream)
|
||||
{
|
||||
fn execute_instr(
|
||||
&mut self,
|
||||
indices: &mut IndexStore,
|
||||
policies: &mut MachinePolicies,
|
||||
code_repo: &CodeRepo,
|
||||
prolog_stream: &mut PrologStream,
|
||||
) {
|
||||
let instr = match code_repo.lookup_instr(self.last_call, &self.p) {
|
||||
Some(instr) => instr,
|
||||
None => return
|
||||
None => return,
|
||||
};
|
||||
|
||||
self.dispatch_instr(instr.as_ref(), indices, policies, code_repo, prolog_stream);
|
||||
}
|
||||
|
||||
fn backtrack(&mut self)
|
||||
{
|
||||
fn backtrack(&mut self) {
|
||||
if self.b > 0 {
|
||||
let b = self.b - 1;
|
||||
|
||||
self.b0 = self.or_stack[b].b0;
|
||||
self.p = self.or_stack[b].bp.clone();
|
||||
self.p = self.or_stack[b].bp.clone();
|
||||
|
||||
if let CodePtr::Local(LocalCodePtr::TopLevel(_, p)) = self.p {
|
||||
self.fail = p == 0;
|
||||
@@ -749,27 +799,23 @@ impl MachineState {
|
||||
|
||||
fn check_machine_index(&mut self, code_repo: &CodeRepo) -> bool {
|
||||
match self.p {
|
||||
CodePtr::Local(LocalCodePtr::DirEntry(p))
|
||||
if p < code_repo.code.len() => {},
|
||||
CodePtr::Local(LocalCodePtr::DirEntry(p)) if p < code_repo.code.len() => {}
|
||||
CodePtr::Local(LocalCodePtr::UserTermExpansion(p))
|
||||
if p < code_repo.term_expanders.len() => {},
|
||||
CodePtr::Local(LocalCodePtr::UserTermExpansion(_)) =>
|
||||
self.fail = true,
|
||||
if p < code_repo.term_expanders.len() => {}
|
||||
CodePtr::Local(LocalCodePtr::UserTermExpansion(_)) => self.fail = true,
|
||||
CodePtr::Local(LocalCodePtr::UserGoalExpansion(p))
|
||||
if p < code_repo.goal_expanders.len() => {},
|
||||
CodePtr::Local(LocalCodePtr::UserGoalExpansion(_)) =>
|
||||
self.fail = true,
|
||||
CodePtr::Local(LocalCodePtr::InSituDirEntry(p))
|
||||
if p < code_repo.in_situ_code.len() => {},
|
||||
CodePtr::Local(_) | CodePtr::REPL(..) =>
|
||||
return false,
|
||||
if p < code_repo.goal_expanders.len() => {}
|
||||
CodePtr::Local(LocalCodePtr::UserGoalExpansion(_)) => self.fail = true,
|
||||
CodePtr::Local(LocalCodePtr::InSituDirEntry(p)) if p < code_repo.in_situ_code.len() => {
|
||||
}
|
||||
CodePtr::Local(_) | CodePtr::REPL(..) => return false,
|
||||
CodePtr::DynamicTransaction(..) => {
|
||||
// prevent use of dynamic transactions from
|
||||
// succeeding in expansions. self.fail will be toggled
|
||||
// back to false later.
|
||||
self.fail = true;
|
||||
return false;
|
||||
},
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -777,10 +823,13 @@ impl MachineState {
|
||||
}
|
||||
|
||||
// return true iff verify_attr_interrupt is called.
|
||||
fn verify_attr_stepper(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies,
|
||||
code_repo: &mut CodeRepo, prolog_stream: &mut PrologStream)
|
||||
-> bool
|
||||
{
|
||||
fn verify_attr_stepper(
|
||||
&mut self,
|
||||
indices: &mut IndexStore,
|
||||
policies: &mut MachinePolicies,
|
||||
code_repo: &mut CodeRepo,
|
||||
prolog_stream: &mut PrologStream,
|
||||
) -> bool {
|
||||
loop {
|
||||
let instr = match code_repo.lookup_instr(self.last_call, &self.p) {
|
||||
Some(instr) => {
|
||||
@@ -791,8 +840,8 @@ impl MachineState {
|
||||
self.run_verify_attr_interrupt(cp);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
None => return false
|
||||
}
|
||||
None => return false,
|
||||
};
|
||||
|
||||
self.dispatch_instr(instr.as_ref(), indices, policies, code_repo, prolog_stream);
|
||||
@@ -814,9 +863,13 @@ impl MachineState {
|
||||
self.verify_attr_interrupt(p);
|
||||
}
|
||||
|
||||
fn query_stepper(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies,
|
||||
code_repo: &mut CodeRepo, prolog_stream: &mut PrologStream)
|
||||
{
|
||||
fn query_stepper(
|
||||
&mut self,
|
||||
indices: &mut IndexStore,
|
||||
policies: &mut MachinePolicies,
|
||||
code_repo: &mut CodeRepo,
|
||||
prolog_stream: &mut PrologStream,
|
||||
) {
|
||||
loop {
|
||||
self.execute_instr(indices, policies, code_repo, prolog_stream);
|
||||
|
||||
@@ -825,7 +878,7 @@ impl MachineState {
|
||||
}
|
||||
|
||||
match self.p {
|
||||
CodePtr::VerifyAttrInterrupt(_) => {
|
||||
CodePtr::VerifyAttrInterrupt(_) => {
|
||||
self.p = CodePtr::Local(self.attr_var_init.cp + 1);
|
||||
|
||||
if !self.verify_attr_stepper(indices, policies, code_repo, prolog_stream) {
|
||||
@@ -836,11 +889,12 @@ impl MachineState {
|
||||
let cp = self.p.local();
|
||||
self.run_verify_attr_interrupt(cp);
|
||||
}
|
||||
},
|
||||
_ =>
|
||||
}
|
||||
_ => {
|
||||
if !self.check_machine_index(code_repo) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,37 +6,50 @@ use prolog::machine::code_repo::*;
|
||||
use prolog::machine::machine_errors::*;
|
||||
use prolog::machine::machine_indices::*;
|
||||
|
||||
use std::collections::{VecDeque};
|
||||
use std::collections::VecDeque;
|
||||
|
||||
// Module's and related types are defined in forms.
|
||||
impl Module {
|
||||
pub fn new(module_decl: ModuleDecl, atom_tbl: TabledData<Atom>) -> Self {
|
||||
Module { module_decl, atom_tbl,
|
||||
user_term_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||
user_goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||
term_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||
goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||
code_dir: CodeDir::new(),
|
||||
op_dir: default_op_dir(),
|
||||
inserted_expansions: false }
|
||||
Module {
|
||||
module_decl,
|
||||
atom_tbl,
|
||||
user_term_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||
user_goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||
term_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||
goal_expansions: (Predicate::new(), VecDeque::from(vec![])),
|
||||
code_dir: CodeDir::new(),
|
||||
op_dir: default_op_dir(),
|
||||
inserted_expansions: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dump_expansions(&self, code_repo: &mut CodeRepo, flags: MachineFlags)
|
||||
-> Result<(), ParserError>
|
||||
{
|
||||
pub fn dump_expansions(
|
||||
&self,
|
||||
code_repo: &mut CodeRepo,
|
||||
flags: MachineFlags,
|
||||
) -> Result<(), ParserError> {
|
||||
{
|
||||
let te = code_repo.term_dir.entry((clause_name!("term_expansion"), 2))
|
||||
let te = code_repo
|
||||
.term_dir
|
||||
.entry((clause_name!("term_expansion"), 2))
|
||||
.or_insert((Predicate::new(), VecDeque::from(vec![])));
|
||||
|
||||
(te.0).0.extend((self.user_term_expansions.0).0.iter().cloned());
|
||||
(te.0)
|
||||
.0
|
||||
.extend((self.user_term_expansions.0).0.iter().cloned());
|
||||
te.1.extend(self.user_term_expansions.1.iter().cloned());
|
||||
}
|
||||
|
||||
{
|
||||
let ge = code_repo.term_dir.entry((clause_name!("goal_expansion"), 2))
|
||||
let ge = code_repo
|
||||
.term_dir
|
||||
.entry((clause_name!("goal_expansion"), 2))
|
||||
.or_insert((Predicate::new(), VecDeque::from(vec![])));
|
||||
|
||||
(ge.0).0.extend((self.user_goal_expansions.0).0.iter().cloned());
|
||||
(ge.0)
|
||||
.0
|
||||
.extend((self.user_goal_expansions.0).0.iter().cloned());
|
||||
ge.1.extend(self.user_goal_expansions.1.iter().cloned());
|
||||
}
|
||||
|
||||
@@ -46,14 +59,17 @@ impl Module {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_module_expansion_record(&mut self, hook: CompileTimeHook, clause: PredicateClause,
|
||||
queue: VecDeque<TopLevel>)
|
||||
{
|
||||
pub fn add_module_expansion_record(
|
||||
&mut self,
|
||||
hook: CompileTimeHook,
|
||||
clause: PredicateClause,
|
||||
queue: VecDeque<TopLevel>,
|
||||
) {
|
||||
match hook {
|
||||
CompileTimeHook::TermExpansion | CompileTimeHook::UserTermExpansion => {
|
||||
(self.term_expansions.0).0.push(clause);
|
||||
self.term_expansions.1.extend(queue.into_iter());
|
||||
},
|
||||
}
|
||||
CompileTimeHook::GoalExpansion | CompileTimeHook::UserGoalExpansion => {
|
||||
(self.goal_expansions.0).0.push(clause);
|
||||
self.goal_expansions.1.extend(queue.into_iter());
|
||||
@@ -62,8 +78,7 @@ impl Module {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SubModuleUser
|
||||
{
|
||||
pub trait SubModuleUser {
|
||||
fn atom_tbl(&self) -> TabledData<Atom>;
|
||||
fn op_dir(&mut self) -> &mut OpDir;
|
||||
fn remove_code_index(&mut self, PredicateKey);
|
||||
@@ -71,18 +86,18 @@ pub trait SubModuleUser
|
||||
|
||||
fn insert_dir_entry(&mut self, ClauseName, usize, CodeIndex);
|
||||
|
||||
fn get_op_module_name(&mut self, name: ClauseName, fixity: Fixity) -> Option<ClauseName>
|
||||
{
|
||||
self.op_dir().get(&(name, fixity)).map(|op_val| op_val.owning_module())
|
||||
fn get_op_module_name(&mut self, name: ClauseName, fixity: Fixity) -> Option<ClauseName> {
|
||||
self.op_dir()
|
||||
.get(&(name, fixity))
|
||||
.map(|op_val| op_val.owning_module())
|
||||
}
|
||||
|
||||
fn remove_module(&mut self, mod_name: ClauseName, module: &Module)
|
||||
{
|
||||
fn remove_module(&mut self, mod_name: ClauseName, module: &Module) {
|
||||
for (name, arity) in module.module_decl.exports.iter().cloned() {
|
||||
let name = name.defrock_brackets();
|
||||
|
||||
match self.get_code_index((name.clone(), arity), mod_name.clone()) {
|
||||
Some(CodeIndex (ref code_idx)) => {
|
||||
Some(CodeIndex(ref code_idx)) => {
|
||||
if &code_idx.borrow().1 != &module.module_decl.name {
|
||||
continue;
|
||||
}
|
||||
@@ -91,15 +106,13 @@ pub trait SubModuleUser
|
||||
|
||||
// remove or respecify ops.
|
||||
if arity == 2 {
|
||||
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::In)
|
||||
{
|
||||
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::In) {
|
||||
if mod_name == module.module_decl.name {
|
||||
self.op_dir().remove(&(name.clone(), Fixity::In));
|
||||
}
|
||||
}
|
||||
} else if arity == 1 {
|
||||
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::Pre)
|
||||
{
|
||||
if let Some(mod_name) = self.get_op_module_name(name.clone(), Fixity::Pre) {
|
||||
if mod_name == module.module_decl.name {
|
||||
self.op_dir().remove(&(name.clone(), Fixity::Pre));
|
||||
}
|
||||
@@ -112,15 +125,14 @@ pub trait SubModuleUser
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// returns true on successful import.
|
||||
fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool
|
||||
{
|
||||
fn import_decl(&mut self, name: ClauseName, arity: usize, submodule: &Module) -> bool {
|
||||
let name = name.defrock_brackets();
|
||||
let mut found_op = false;
|
||||
|
||||
@@ -153,17 +165,30 @@ pub trait SubModuleUser
|
||||
}
|
||||
}
|
||||
|
||||
fn use_qualified_module(&mut self, &mut CodeRepo, MachineFlags, &Module, &Vec<PredicateKey>)
|
||||
-> Result<(), SessionError>;
|
||||
fn use_qualified_module(
|
||||
&mut self,
|
||||
&mut CodeRepo,
|
||||
MachineFlags,
|
||||
&Module,
|
||||
&Vec<PredicateKey>,
|
||||
) -> Result<(), SessionError>;
|
||||
fn use_module(&mut self, &mut CodeRepo, MachineFlags, &Module) -> Result<(), SessionError>;
|
||||
}
|
||||
|
||||
pub fn use_qualified_module<User>(user: &mut User, submodule: &Module, exports: &Vec<PredicateKey>)
|
||||
-> Result<(), SessionError>
|
||||
where User: SubModuleUser
|
||||
pub fn use_qualified_module<User>(
|
||||
user: &mut User,
|
||||
submodule: &Module,
|
||||
exports: &Vec<PredicateKey>,
|
||||
) -> Result<(), SessionError>
|
||||
where
|
||||
User: SubModuleUser,
|
||||
{
|
||||
for (name, arity) in exports.iter().cloned() {
|
||||
if !submodule.module_decl.exports.contains(&(name.clone(), arity)) {
|
||||
if !submodule
|
||||
.module_decl
|
||||
.exports
|
||||
.contains(&(name.clone(), arity))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -175,9 +200,10 @@ pub fn use_qualified_module<User>(user: &mut User, submodule: &Module, exports:
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn use_module<User: SubModuleUser>(user: &mut User, submodule: &Module)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
pub fn use_module<User: SubModuleUser>(
|
||||
user: &mut User,
|
||||
submodule: &Module,
|
||||
) -> Result<(), SessionError> {
|
||||
for (name, arity) in submodule.module_decl.exports.iter().cloned() {
|
||||
if !user.import_decl(name, arity, submodule) {
|
||||
return Err(SessionError::ModuleDoesNotContainExport);
|
||||
@@ -208,31 +234,53 @@ impl SubModuleUser for Module {
|
||||
self.code_dir.insert((name, arity), idx);
|
||||
}
|
||||
|
||||
fn use_qualified_module(&mut self, _: &mut CodeRepo, _: MachineFlags, submodule: &Module,
|
||||
exports: &Vec<PredicateKey>)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
fn use_qualified_module(
|
||||
&mut self,
|
||||
_: &mut CodeRepo,
|
||||
_: MachineFlags,
|
||||
submodule: &Module,
|
||||
exports: &Vec<PredicateKey>,
|
||||
) -> Result<(), SessionError> {
|
||||
use_qualified_module(self, submodule, exports)?;
|
||||
|
||||
(self.user_term_expansions.0).0.extend((submodule.term_expansions.0).0.iter().cloned());
|
||||
self.user_term_expansions.1.extend(submodule.term_expansions.1.iter().cloned());
|
||||
(self.user_term_expansions.0)
|
||||
.0
|
||||
.extend((submodule.term_expansions.0).0.iter().cloned());
|
||||
self.user_term_expansions
|
||||
.1
|
||||
.extend(submodule.term_expansions.1.iter().cloned());
|
||||
|
||||
(self.user_goal_expansions.0).0.extend((submodule.goal_expansions.0).0.iter().cloned());
|
||||
self.user_goal_expansions.1.extend(submodule.goal_expansions.1.iter().cloned());
|
||||
(self.user_goal_expansions.0)
|
||||
.0
|
||||
.extend((submodule.goal_expansions.0).0.iter().cloned());
|
||||
self.user_goal_expansions
|
||||
.1
|
||||
.extend(submodule.goal_expansions.1.iter().cloned());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn use_module(&mut self, _: &mut CodeRepo, _: MachineFlags, submodule: &Module)
|
||||
-> Result<(), SessionError>
|
||||
{
|
||||
fn use_module(
|
||||
&mut self,
|
||||
_: &mut CodeRepo,
|
||||
_: MachineFlags,
|
||||
submodule: &Module,
|
||||
) -> Result<(), SessionError> {
|
||||
use_module(self, submodule)?;
|
||||
|
||||
(self.user_term_expansions.0).0.extend((submodule.term_expansions.0).0.iter().cloned());
|
||||
self.user_term_expansions.1.extend(submodule.term_expansions.1.iter().cloned());
|
||||
(self.user_term_expansions.0)
|
||||
.0
|
||||
.extend((submodule.term_expansions.0).0.iter().cloned());
|
||||
self.user_term_expansions
|
||||
.1
|
||||
.extend(submodule.term_expansions.1.iter().cloned());
|
||||
|
||||
(self.user_goal_expansions.0).0.extend((submodule.goal_expansions.0).0.iter().cloned());
|
||||
self.user_goal_expansions.1.extend(submodule.goal_expansions.1.iter().cloned());
|
||||
(self.user_goal_expansions.0)
|
||||
.0
|
||||
.extend((submodule.goal_expansions.0).0.iter().cloned());
|
||||
self.user_goal_expansions
|
||||
.1
|
||||
.extend(submodule.goal_expansions.1.iter().cloned());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -9,29 +9,29 @@ pub struct Frame {
|
||||
pub e: usize,
|
||||
pub cp: LocalCodePtr,
|
||||
pub attr_var_init_b: usize,
|
||||
pub b: usize,
|
||||
pub b: usize,
|
||||
pub bp: CodePtr,
|
||||
pub tr: usize,
|
||||
pub pstr_tr: usize,
|
||||
pub h: usize,
|
||||
pub b0: usize,
|
||||
args: Vec<Addr>
|
||||
args: Vec<Addr>,
|
||||
}
|
||||
|
||||
impl Frame {
|
||||
fn new(global_index: usize,
|
||||
e: usize,
|
||||
cp: LocalCodePtr,
|
||||
attr_var_init_b: usize,
|
||||
b: usize,
|
||||
bp: CodePtr,
|
||||
tr: usize,
|
||||
pstr_tr: usize,
|
||||
h: usize,
|
||||
b0: usize,
|
||||
n: usize)
|
||||
-> Self
|
||||
{
|
||||
fn new(
|
||||
global_index: usize,
|
||||
e: usize,
|
||||
cp: LocalCodePtr,
|
||||
attr_var_init_b: usize,
|
||||
b: usize,
|
||||
bp: CodePtr,
|
||||
tr: usize,
|
||||
pstr_tr: usize,
|
||||
h: usize,
|
||||
b0: usize,
|
||||
n: usize,
|
||||
) -> Self {
|
||||
Frame {
|
||||
global_index,
|
||||
e,
|
||||
@@ -43,7 +43,7 @@ impl Frame {
|
||||
pstr_tr,
|
||||
h,
|
||||
b0,
|
||||
args: vec![Addr::HeapCell(0); n]
|
||||
args: vec![Addr::HeapCell(0); n],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,20 +59,33 @@ impl OrStack {
|
||||
OrStack(Vec::new())
|
||||
}
|
||||
|
||||
pub fn push(&mut self,
|
||||
global_index: usize,
|
||||
e: usize,
|
||||
cp: LocalCodePtr,
|
||||
attr_var_init_b: usize,
|
||||
b: usize,
|
||||
bp: CodePtr,
|
||||
tr: usize,
|
||||
pstr_tr: usize,
|
||||
h: usize,
|
||||
b0: usize,
|
||||
n: usize)
|
||||
{
|
||||
self.0.push(Frame::new(global_index, e, cp, attr_var_init_b, b, bp, tr, pstr_tr, h, b0, n));
|
||||
pub fn push(
|
||||
&mut self,
|
||||
global_index: usize,
|
||||
e: usize,
|
||||
cp: LocalCodePtr,
|
||||
attr_var_init_b: usize,
|
||||
b: usize,
|
||||
bp: CodePtr,
|
||||
tr: usize,
|
||||
pstr_tr: usize,
|
||||
h: usize,
|
||||
b0: usize,
|
||||
n: usize,
|
||||
) {
|
||||
self.0.push(Frame::new(
|
||||
global_index,
|
||||
e,
|
||||
cp,
|
||||
attr_var_init_b,
|
||||
b,
|
||||
bp,
|
||||
tr,
|
||||
pstr_tr,
|
||||
h,
|
||||
b0,
|
||||
n,
|
||||
));
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -87,7 +100,7 @@ impl OrStack {
|
||||
pub fn clear(&mut self) {
|
||||
self.0.clear()
|
||||
}
|
||||
|
||||
|
||||
pub fn top(&self) -> Option<&Frame> {
|
||||
self.0.last()
|
||||
}
|
||||
@@ -97,7 +110,7 @@ impl OrStack {
|
||||
pub fn truncate(&mut self, new_b: usize) {
|
||||
self.0.truncate(new_b);
|
||||
}
|
||||
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
use prolog_parser::ast::*;
|
||||
use prolog_parser::parser::*;
|
||||
|
||||
use prolog::machine::*;
|
||||
use prolog::machine::machine_indices::HeapCellValue;
|
||||
use prolog::rug::Integer;
|
||||
use prolog::machine::*;
|
||||
use prolog::rug::ops::Pow;
|
||||
use prolog::rug::Integer;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::collections::VecDeque;
|
||||
@@ -12,8 +12,7 @@ use std::io::Read;
|
||||
use std::iter::Rev;
|
||||
use std::vec::IntoIter;
|
||||
|
||||
fn unfold_by_str_once(term: &mut Term, s: &str) -> Option<(Term, Term)>
|
||||
{
|
||||
fn unfold_by_str_once(term: &mut Term, s: &str) -> Option<(Term, Term)> {
|
||||
if let &mut Term::Clause(_, ref name, ref mut subterms, _) = term {
|
||||
if name.as_str() == s && subterms.len() == 2 {
|
||||
let snd = *subterms.pop().unwrap();
|
||||
@@ -26,8 +25,7 @@ fn unfold_by_str_once(term: &mut Term, s: &str) -> Option<(Term, Term)>
|
||||
None
|
||||
}
|
||||
|
||||
pub fn unfold_by_str(mut term: Term, s: &str) -> Vec<Term>
|
||||
{
|
||||
pub fn unfold_by_str(mut term: Term, s: &str) -> Vec<Term> {
|
||||
let mut terms = vec![];
|
||||
|
||||
while let Some((fst, snd)) = unfold_by_str_once(&mut term, s) {
|
||||
@@ -40,22 +38,24 @@ pub fn unfold_by_str(mut term: Term, s: &str) -> Vec<Term>
|
||||
}
|
||||
|
||||
pub fn fold_by_str<I>(terms: I, mut term: Term, sym: ClauseName) -> Term
|
||||
where I: DoubleEndedIterator<Item=Term>
|
||||
where
|
||||
I: DoubleEndedIterator<Item = Term>,
|
||||
{
|
||||
for prec in terms.rev() {
|
||||
term = Term::Clause(Cell::default(), sym.clone(),
|
||||
vec![Box::new(prec), Box::new(term)],
|
||||
None);
|
||||
term = Term::Clause(
|
||||
Cell::default(),
|
||||
sym.clone(),
|
||||
vec![Box::new(prec), Box::new(term)],
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
term
|
||||
}
|
||||
|
||||
fn extract_from_list(head: Box<Term>, tail: Box<Term>)
|
||||
-> Result<Rev<IntoIter<Term>>, ParserError>
|
||||
{
|
||||
fn extract_from_list(head: Box<Term>, tail: Box<Term>) -> Result<Rev<IntoIter<Term>>, ParserError> {
|
||||
let mut terms = vec![*head];
|
||||
let mut tail = *tail;
|
||||
let mut tail = *tail;
|
||||
|
||||
while let Term::Cons(_, head, next_tail) = tail {
|
||||
terms.push(*head);
|
||||
@@ -81,19 +81,19 @@ pub struct TermStream<'a, R: Read> {
|
||||
|
||||
pub struct ExpansionAdditionResult {
|
||||
term_expansion_additions: (Predicate, VecDeque<TopLevel>),
|
||||
goal_expansion_additions: (Predicate, VecDeque<TopLevel>)
|
||||
goal_expansion_additions: (Predicate, VecDeque<TopLevel>),
|
||||
}
|
||||
|
||||
impl ExpansionAdditionResult {
|
||||
pub fn take_term_expansions(&mut self) -> (Predicate, VecDeque<TopLevel>) {
|
||||
let tes = mem::replace(&mut self.term_expansion_additions.0, Predicate::new());
|
||||
let tes = mem::replace(&mut self.term_expansion_additions.0, Predicate::new());
|
||||
let teqs = mem::replace(&mut self.term_expansion_additions.1, VecDeque::from(vec![]));
|
||||
|
||||
(tes, teqs)
|
||||
}
|
||||
|
||||
pub fn take_goal_expansions(&mut self) -> (Predicate, VecDeque<TopLevel>) {
|
||||
let ges = mem::replace(&mut self.goal_expansion_additions.0, Predicate::new());
|
||||
let ges = mem::replace(&mut self.goal_expansion_additions.0, Predicate::new());
|
||||
let geqs = mem::replace(&mut self.goal_expansion_additions.1, VecDeque::from(vec![]));
|
||||
|
||||
(ges, geqs)
|
||||
@@ -109,17 +109,24 @@ impl<'a, R: Read> Drop for TermStream<'a, R> {
|
||||
}
|
||||
|
||||
impl<'a, R: Read> TermStream<'a, R> {
|
||||
pub fn new(src: &'a mut ParsingStream<R>, atom_tbl: TabledData<Atom>, flags: MachineFlags, wam: &'a mut Machine)
|
||||
-> Self
|
||||
{
|
||||
pub fn new(
|
||||
src: &'a mut ParsingStream<R>,
|
||||
atom_tbl: TabledData<Atom>,
|
||||
flags: MachineFlags,
|
||||
wam: &'a mut Machine,
|
||||
) -> Self {
|
||||
TermStream {
|
||||
stack: Vec::new(),
|
||||
term_expansion_lens: wam.code_repo.term_dir_entry_len((clause_name!("term_expansion"), 2)),
|
||||
goal_expansion_lens: wam.code_repo.term_dir_entry_len((clause_name!("goal_expansion"), 2)),
|
||||
term_expansion_lens: wam
|
||||
.code_repo
|
||||
.term_dir_entry_len((clause_name!("term_expansion"), 2)),
|
||||
goal_expansion_lens: wam
|
||||
.code_repo
|
||||
.term_dir_entry_len((clause_name!("goal_expansion"), 2)),
|
||||
wam,
|
||||
parser: Parser::new(src, atom_tbl, flags),
|
||||
in_module: false,
|
||||
flags
|
||||
flags,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,11 +141,11 @@ impl<'a, R: Read> TermStream<'a, R> {
|
||||
CompileTimeHook::UserTermExpansion => {
|
||||
self.term_expansion_lens.0 += len;
|
||||
self.term_expansion_lens.1 += queue_len;
|
||||
},
|
||||
}
|
||||
CompileTimeHook::UserGoalExpansion => {
|
||||
self.goal_expansion_lens.0 += len;
|
||||
self.goal_expansion_lens.1 += queue_len;
|
||||
},
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -169,27 +176,34 @@ impl<'a, R: Read> TermStream<'a, R> {
|
||||
Ok(self.stack.is_empty() && self.parser.eof()?)
|
||||
}
|
||||
|
||||
pub fn rollback_expansion_code(&mut self) -> Result<ExpansionAdditionResult, ParserError>
|
||||
{
|
||||
pub fn rollback_expansion_code(&mut self) -> Result<ExpansionAdditionResult, ParserError> {
|
||||
let te_len = self.term_expansion_lens.0;
|
||||
let te_queue_len = self.term_expansion_lens.1;
|
||||
|
||||
let ge_len = self.goal_expansion_lens.0;
|
||||
let ge_queue_len = self.goal_expansion_lens.1;
|
||||
|
||||
let term_expansion_additions =
|
||||
self.wam.code_repo.truncate_terms((clause_name!("term_expansion"), 2),
|
||||
te_len, te_queue_len);
|
||||
let goal_expansion_additions =
|
||||
self.wam.code_repo.truncate_terms((clause_name!("goal_expansion"), 2),
|
||||
ge_len, ge_queue_len);
|
||||
let term_expansion_additions = self.wam.code_repo.truncate_terms(
|
||||
(clause_name!("term_expansion"), 2),
|
||||
te_len,
|
||||
te_queue_len,
|
||||
);
|
||||
let goal_expansion_additions = self.wam.code_repo.truncate_terms(
|
||||
(clause_name!("goal_expansion"), 2),
|
||||
ge_len,
|
||||
ge_queue_len,
|
||||
);
|
||||
|
||||
self.wam.code_repo.compile_hook(CompileTimeHook::TermExpansion, self.flags)?;
|
||||
self.wam.code_repo.compile_hook(CompileTimeHook::GoalExpansion, self.flags)?;
|
||||
self.wam
|
||||
.code_repo
|
||||
.compile_hook(CompileTimeHook::TermExpansion, self.flags)?;
|
||||
self.wam
|
||||
.code_repo
|
||||
.compile_hook(CompileTimeHook::GoalExpansion, self.flags)?;
|
||||
|
||||
Ok(ExpansionAdditionResult {
|
||||
term_expansion_additions,
|
||||
goal_expansion_additions
|
||||
goal_expansion_additions,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -198,34 +212,37 @@ impl<'a, R: Read> TermStream<'a, R> {
|
||||
Term::Cons(_, head, tail) => {
|
||||
let iter = extract_from_list(head, tail)?;
|
||||
Ok(self.stack.extend(iter))
|
||||
},
|
||||
Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) =>
|
||||
Ok(self.stack.push(term)),
|
||||
_ =>
|
||||
Err(ParserError::ExpectedTopLevelTerm)
|
||||
}
|
||||
Term::Clause(..) | Term::Constant(_, Constant::Atom(..)) => Ok(self.stack.push(term)),
|
||||
_ => Err(ParserError::ExpectedTopLevelTerm),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_expansion_output(&self, term_string: &str, op_dir: &OpDir) -> Result<Term, ParserError>
|
||||
{
|
||||
fn parse_expansion_output(
|
||||
&self,
|
||||
term_string: &str,
|
||||
op_dir: &OpDir,
|
||||
) -> Result<Term, ParserError> {
|
||||
let mut stream = parsing_stream(term_string.trim().as_bytes());
|
||||
let mut parser = Parser::new(&mut stream, self.parser.get_atom_tbl(), self.flags);
|
||||
|
||||
parser.read_term(composite_op!(self.in_module, &self.wam.indices.op_dir, op_dir))
|
||||
parser.read_term(composite_op!(
|
||||
self.in_module,
|
||||
&self.wam.indices.op_dir,
|
||||
op_dir
|
||||
))
|
||||
}
|
||||
|
||||
pub fn read_term(&mut self, op_dir: &OpDir) -> Result<Term, ParserError>
|
||||
{
|
||||
pub fn read_term(&mut self, op_dir: &OpDir) -> Result<Term, ParserError> {
|
||||
let mut machine_st = MachineState::new();
|
||||
|
||||
loop {
|
||||
while let Some(term) = self.stack.pop() {
|
||||
match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::TermExpansion)
|
||||
{
|
||||
match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::TermExpansion) {
|
||||
Some(term_string) => {
|
||||
let term = self.parse_expansion_output(term_string.as_str(), op_dir)?;
|
||||
self.enqueue_term(term)?
|
||||
},
|
||||
}
|
||||
None => {
|
||||
let term = self.run_goal_expanders(&mut machine_st, op_dir, term)?;
|
||||
return Ok(term);
|
||||
@@ -234,16 +251,21 @@ impl<'a, R: Read> TermStream<'a, R> {
|
||||
}
|
||||
|
||||
self.parser.reset();
|
||||
let term = self.parser.read_term(composite_op!(self.in_module, &self.wam.indices.op_dir,
|
||||
op_dir))?;
|
||||
let term = self.parser.read_term(composite_op!(
|
||||
self.in_module,
|
||||
&self.wam.indices.op_dir,
|
||||
op_dir
|
||||
))?;
|
||||
self.stack.push(term);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate)
|
||||
fn run_goal_expanders(&mut self, machine_st: &mut MachineState, op_dir: &OpDir, term: Term)
|
||||
-> Result<Term, ParserError>
|
||||
{
|
||||
pub(crate) fn run_goal_expanders(
|
||||
&mut self,
|
||||
machine_st: &mut MachineState,
|
||||
op_dir: &OpDir,
|
||||
term: Term,
|
||||
) -> Result<Term, ParserError> {
|
||||
match term {
|
||||
Term::Clause(cell, name, mut terms, arity) => {
|
||||
let mut new_terms = {
|
||||
@@ -251,45 +273,50 @@ impl<'a, R: Read> TermStream<'a, R> {
|
||||
(":-", 2) => {
|
||||
let comma_term = *terms.pop().unwrap();
|
||||
unfold_by_str(comma_term, ",")
|
||||
},
|
||||
}
|
||||
("?-", 1) => unfold_by_str(*terms.pop().unwrap(), ","),
|
||||
_ => return Ok(Term::Clause(cell, name, terms, arity))
|
||||
_ => return Ok(Term::Clause(cell, name, terms, arity)),
|
||||
};
|
||||
|
||||
self.expand_goals(machine_st, op_dir, VecDeque::from(old_terms))?
|
||||
};
|
||||
|
||||
let initial_term = new_terms.pop().unwrap();
|
||||
terms.push(Box::new(fold_by_str(new_terms.into_iter(), initial_term,
|
||||
clause_name!(","))));
|
||||
terms.push(Box::new(fold_by_str(
|
||||
new_terms.into_iter(),
|
||||
initial_term,
|
||||
clause_name!(","),
|
||||
)));
|
||||
Ok(Term::Clause(cell, name, terms, arity))
|
||||
},
|
||||
_ =>
|
||||
Ok(term)
|
||||
}
|
||||
_ => Ok(term),
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_goals(&mut self, machine_st: &mut MachineState, op_dir: &OpDir, mut terms: VecDeque<Term>)
|
||||
-> Result<Vec<Term>, ParserError>
|
||||
{
|
||||
fn expand_goals(
|
||||
&mut self,
|
||||
machine_st: &mut MachineState,
|
||||
op_dir: &OpDir,
|
||||
mut terms: VecDeque<Term>,
|
||||
) -> Result<Vec<Term>, ParserError> {
|
||||
let mut results = vec![];
|
||||
|
||||
while let Some(term) = terms.pop_front() {
|
||||
match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::GoalExpansion)
|
||||
{
|
||||
match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::GoalExpansion) {
|
||||
Some(term_string) => {
|
||||
println!("trying to goal expand {}", term_string);
|
||||
let term = self.parse_expansion_output(term_string.as_str(), op_dir)?;
|
||||
|
||||
match term {
|
||||
Term::Cons(_, head, tail) =>
|
||||
Term::Cons(_, head, tail) => {
|
||||
for term in extract_from_list(head, tail)? {
|
||||
terms.push_front(term);
|
||||
},
|
||||
term => terms.push_front(term)
|
||||
}
|
||||
}
|
||||
term => terms.push_front(term),
|
||||
};
|
||||
},
|
||||
None => results.push(term)
|
||||
}
|
||||
None => results.push(term),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,9 +325,7 @@ impl<'a, R: Read> TermStream<'a, R> {
|
||||
}
|
||||
|
||||
impl MachineState {
|
||||
pub(super)
|
||||
fn print_with_locs(&self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter
|
||||
{
|
||||
pub(super) fn print_with_locs(&self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter {
|
||||
let output = PrinterOutputter::new();
|
||||
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
|
||||
let mut max_var_length = 0;
|
||||
@@ -327,9 +352,12 @@ impl MachineState {
|
||||
output
|
||||
}
|
||||
|
||||
fn try_expand_term(&mut self, wam: &mut Machine, term: &Term, hook: CompileTimeHook)
|
||||
-> Option<String>
|
||||
{
|
||||
fn try_expand_term(
|
||||
&mut self,
|
||||
wam: &mut Machine,
|
||||
term: &Term,
|
||||
hook: CompileTimeHook,
|
||||
) -> Option<String> {
|
||||
let term_write_result = write_term_to_heap(term, self);
|
||||
let h = self.heap.h;
|
||||
|
||||
@@ -340,7 +368,12 @@ impl MachineState {
|
||||
let code = vec![call_clause!(ClauseType::Hook(hook), 2, 0, true)];
|
||||
|
||||
wam.code_repo.cached_query = code;
|
||||
self.query_stepper(&mut wam.indices, &mut wam.policies, &mut wam.code_repo, &mut readline::input_stream());
|
||||
self.query_stepper(
|
||||
&mut wam.indices,
|
||||
&mut wam.policies,
|
||||
&mut wam.code_repo,
|
||||
&mut readline::input_stream(),
|
||||
);
|
||||
|
||||
if self.fail {
|
||||
self.reset();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user