fix attribute_goals/2 display bugs, cycle detection bug
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
use prolog::heap_iter::*;
|
||||
use prolog::machine::*;
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
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)>;
|
||||
|
||||
pub(super) struct AttrVarInitializer {
|
||||
pub(super) struct AttrVarInitializer {
|
||||
pub(super) bindings: Bindings,
|
||||
pub(super) cp: LocalCodePtr,
|
||||
pub(super) verify_attrs_loc: usize,
|
||||
@@ -52,7 +55,7 @@ impl MachineState {
|
||||
pub(super)
|
||||
fn calculate_register_threshold(&self) -> usize {
|
||||
let mut count = 0;
|
||||
|
||||
|
||||
for r in 1 .. MAX_ARITY + 1 {
|
||||
if let &Addr::HeapCell(0) = &self[RegType::Temp(r)] {
|
||||
break;
|
||||
@@ -63,7 +66,7 @@ impl MachineState {
|
||||
|
||||
count
|
||||
}
|
||||
|
||||
|
||||
pub(super)
|
||||
fn verify_attributes(&mut self)
|
||||
{
|
||||
@@ -89,4 +92,79 @@ impl MachineState {
|
||||
self[temp_v!(1)] = var_list_addr;
|
||||
self[temp_v!(2)] = value_list_addr;
|
||||
}
|
||||
|
||||
fn populate_project_attr_lists(&mut self, var_dict: &HeapVarDict) -> (Addr, Addr)
|
||||
{
|
||||
let mut query_vars = HashSet::new();
|
||||
let mut attr_vars = HashSet::new();
|
||||
|
||||
for (_, addr) in var_dict {
|
||||
let iter = HCPreOrderIterator::new(&self, addr.clone());
|
||||
|
||||
for value in iter {
|
||||
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));
|
||||
},
|
||||
HeapCellValue::Addr(Addr::AttrVar(h)) => {
|
||||
attr_vars.insert(Addr::AttrVar(h));
|
||||
},
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
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.into_iter()));
|
||||
|
||||
(query_var_list, attr_var_list)
|
||||
}
|
||||
|
||||
pub(super)
|
||||
fn verify_attr_interrupt(&mut self, p: usize) {
|
||||
let rs = self.calculate_register_threshold();
|
||||
|
||||
// store temp vars in perm vars slots along with
|
||||
// self.b0 and self.num_of_args. why self.bo? if we return to a
|
||||
// NeckCut after finishing the interrupt, it won't
|
||||
// work correctly if self.b == self.b0. we must
|
||||
// change it back when we return, as if nothing happened.
|
||||
self.allocate(rs + 2);
|
||||
|
||||
let e = self.e;
|
||||
self.and_stack[e].special_form_cp = self.attr_var_init.cp;
|
||||
|
||||
for i in 1 .. rs + 1 {
|
||||
self.and_stack[e][i] = self[RegType::Temp(i)].clone();
|
||||
}
|
||||
|
||||
self.and_stack[e][rs + 1] = Addr::Con(Constant::Usize(self.b0));
|
||||
self.and_stack[e][rs + 2] = Addr::Con(Constant::Usize(self.num_of_args));
|
||||
|
||||
self.verify_attributes();
|
||||
|
||||
self.num_of_args = 2;
|
||||
self.b0 = self.b;
|
||||
self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
|
||||
}
|
||||
}
|
||||
|
||||
impl Machine {
|
||||
pub
|
||||
fn attribute_goals(&mut self, var_dict: &HeapVarDict)
|
||||
{
|
||||
let p = self.machine_st.attr_var_init.project_attrs_loc;
|
||||
let (query_vars, attr_vars) = self.machine_st.populate_project_attr_lists(var_dict);
|
||||
|
||||
self.machine_st.allocate(0);
|
||||
|
||||
self.machine_st[temp_v!(1)] = query_vars;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user