fix attribute_goals/2 display bugs, cycle detection bug
This commit is contained in:
@@ -163,6 +163,7 @@ The following predicates are built-in to rusty-wam.
|
|||||||
* `member/2`
|
* `member/2`
|
||||||
* `memberchk/2`
|
* `memberchk/2`
|
||||||
* `must_be/2`
|
* `must_be/2`
|
||||||
|
* `nl/0`
|
||||||
* `nonvar/1`
|
* `nonvar/1`
|
||||||
* `numbervars/2`
|
* `numbervars/2`
|
||||||
* `once/1`
|
* `once/1`
|
||||||
|
|||||||
@@ -118,7 +118,6 @@ fn compile_query(terms: Vec<QueryTerm>, queue: VecDeque<TopLevel>, flags: Machin
|
|||||||
let mut code = try!(cg.compile_query(&terms));
|
let mut code = try!(cg.compile_query(&terms));
|
||||||
|
|
||||||
compile_appendix(&mut code, &queue, false, flags)?;
|
compile_appendix(&mut code, &queue, false, flags)?;
|
||||||
|
|
||||||
Ok((code, cg.take_vars()))
|
Ok((code, cg.take_vars()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -630,7 +630,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
|
|||||||
|
|
||||||
pub fn print(mut self, addr: Addr) -> Outputter {
|
pub fn print(mut self, addr: Addr) -> Outputter {
|
||||||
let mut iter = self.machine_st.pre_order_iter(addr);
|
let mut iter = self.machine_st.pre_order_iter(addr);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if let Some(loc_data) = self.state_stack.pop() {
|
if let Some(loc_data) = self.state_stack.pop() {
|
||||||
match loc_data {
|
match loc_data {
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ pub struct Module {
|
|||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub enum SystemClauseType {
|
pub enum SystemClauseType {
|
||||||
CheckCutPoint,
|
CheckCutPoint,
|
||||||
|
Deallocate,
|
||||||
DeleteAttribute,
|
DeleteAttribute,
|
||||||
DeleteHeadAttribute,
|
DeleteHeadAttribute,
|
||||||
DynamicModuleResolution,
|
DynamicModuleResolution,
|
||||||
@@ -279,6 +280,7 @@ impl SystemClauseType {
|
|||||||
pub fn name(&self) -> ClauseName {
|
pub fn name(&self) -> ClauseName {
|
||||||
match self {
|
match self {
|
||||||
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
|
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
|
||||||
|
&SystemClauseType::Deallocate => clause_name!("$deallocate"),
|
||||||
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
|
||||||
&SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
|
&SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
|
||||||
&SystemClauseType::DynamicModuleResolution => clause_name!("$module_call"),
|
&SystemClauseType::DynamicModuleResolution => clause_name!("$module_call"),
|
||||||
@@ -320,6 +322,7 @@ impl SystemClauseType {
|
|||||||
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
|
||||||
match (name, arity) {
|
match (name, arity) {
|
||||||
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
|
||||||
|
("$deallocate", 0) => Some(SystemClauseType::Deallocate),
|
||||||
("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute),
|
("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute),
|
||||||
("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute),
|
("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute),
|
||||||
("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution),
|
("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution),
|
||||||
@@ -372,6 +375,7 @@ pub enum BuiltInClauseType {
|
|||||||
Ground,
|
Ground,
|
||||||
Is(RegType, ArithmeticTerm),
|
Is(RegType, ArithmeticTerm),
|
||||||
KeySort,
|
KeySort,
|
||||||
|
Nl,
|
||||||
NotEq,
|
NotEq,
|
||||||
PartialString,
|
PartialString,
|
||||||
Read,
|
Read,
|
||||||
@@ -450,6 +454,7 @@ impl BuiltInClauseType {
|
|||||||
&BuiltInClauseType::Ground => clause_name!("ground"),
|
&BuiltInClauseType::Ground => clause_name!("ground"),
|
||||||
&BuiltInClauseType::Is(..) => clause_name!("is"),
|
&BuiltInClauseType::Is(..) => clause_name!("is"),
|
||||||
&BuiltInClauseType::KeySort => clause_name!("keysort"),
|
&BuiltInClauseType::KeySort => clause_name!("keysort"),
|
||||||
|
&BuiltInClauseType::Nl => clause_name!("nl"),
|
||||||
&BuiltInClauseType::NotEq => clause_name!("\\=="),
|
&BuiltInClauseType::NotEq => clause_name!("\\=="),
|
||||||
&BuiltInClauseType::Read => clause_name!("read"),
|
&BuiltInClauseType::Read => clause_name!("read"),
|
||||||
&BuiltInClauseType::Sort => clause_name!("sort"),
|
&BuiltInClauseType::Sort => clause_name!("sort"),
|
||||||
@@ -471,6 +476,7 @@ impl BuiltInClauseType {
|
|||||||
&BuiltInClauseType::Is(..) => 2,
|
&BuiltInClauseType::Is(..) => 2,
|
||||||
&BuiltInClauseType::KeySort => 2,
|
&BuiltInClauseType::KeySort => 2,
|
||||||
&BuiltInClauseType::NotEq => 2,
|
&BuiltInClauseType::NotEq => 2,
|
||||||
|
&BuiltInClauseType::Nl => 0,
|
||||||
&BuiltInClauseType::Read => 1,
|
&BuiltInClauseType::Read => 1,
|
||||||
&BuiltInClauseType::Sort => 2,
|
&BuiltInClauseType::Sort => 2,
|
||||||
&BuiltInClauseType::PartialString => 1,
|
&BuiltInClauseType::PartialString => 1,
|
||||||
@@ -495,6 +501,7 @@ impl BuiltInClauseType {
|
|||||||
("ground", 1) => Some(BuiltInClauseType::Ground),
|
("ground", 1) => Some(BuiltInClauseType::Ground),
|
||||||
("is", 2) => Some(BuiltInClauseType::Is(temp_v!(1), ArithmeticTerm::Reg(temp_v!(2)))),
|
("is", 2) => Some(BuiltInClauseType::Is(temp_v!(1), ArithmeticTerm::Reg(temp_v!(2)))),
|
||||||
("keysort", 2) => Some(BuiltInClauseType::KeySort),
|
("keysort", 2) => Some(BuiltInClauseType::KeySort),
|
||||||
|
("nl", 0) => Some(BuiltInClauseType::Nl),
|
||||||
("\\==", 2) => Some(BuiltInClauseType::NotEq),
|
("\\==", 2) => Some(BuiltInClauseType::NotEq),
|
||||||
("sort", 2) => Some(BuiltInClauseType::Sort),
|
("sort", 2) => Some(BuiltInClauseType::Sort),
|
||||||
("read", 1) => Some(BuiltInClauseType::Read),
|
("read", 1) => Some(BuiltInClauseType::Read),
|
||||||
@@ -927,7 +934,7 @@ pub enum CodePtr {
|
|||||||
BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
|
BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
|
||||||
CallN(usize, LocalCodePtr), // arity, local.
|
CallN(usize, LocalCodePtr), // arity, local.
|
||||||
Local(LocalCodePtr),
|
Local(LocalCodePtr),
|
||||||
VerifyAttrInterrupt(usize) // location of the verify attribute interrupt code in the CodeDir.
|
VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir.
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CodePtr {
|
impl CodePtr {
|
||||||
@@ -936,7 +943,7 @@ impl CodePtr {
|
|||||||
&CodePtr::BuiltInClause(_, ref local)
|
&CodePtr::BuiltInClause(_, ref local)
|
||||||
| &CodePtr::CallN(_, ref local)
|
| &CodePtr::CallN(_, ref local)
|
||||||
| &CodePtr::Local(ref local) => local.clone(),
|
| &CodePtr::Local(ref local) => local.clone(),
|
||||||
&CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p)
|
&CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,22 +36,23 @@ verify_attributes(Var, Value, Goals) :-
|
|||||||
% suggestions for improvement.
|
% suggestions for improvement.
|
||||||
|
|
||||||
dif(X, Y) :- ( X \= Y -> true
|
dif(X, Y) :- ( X \= Y -> true
|
||||||
; term_variables(X, XVars), term_variables(Y, YVars),
|
; term_variables(X, XVars), term_variables(Y, YVars),
|
||||||
( XVars == [], YVars == [] -> false
|
( XVars == [], YVars == [] -> true
|
||||||
; dif_set_variables(XVars, X, Y),
|
; dif_set_variables(XVars, X, Y),
|
||||||
dif_set_variables(YVars, X, Y)
|
dif_set_variables(YVars, X, Y)
|
||||||
)
|
)
|
||||||
).
|
).
|
||||||
|
|
||||||
gather_dif_goals(Attrs, Goal, Goal) :-
|
gather_dif_goals(Attrs, _) :-
|
||||||
var(Attrs), !.
|
var(Attrs), !.
|
||||||
gather_dif_goals([dif(X, Y)|Attrs], OldGoal, Goal) :-
|
gather_dif_goals([dif(X, Y) | Attrs], Goal) :-
|
||||||
( var(OldGoal), !, gather_dif_goals(Attrs, dif(X, Y), Goal)
|
gather_dif_goals(Attrs, OldGoal),
|
||||||
; !, gather_dif_goals(Attrs, (dif(X, Y), OldGoal), Goal)
|
( var(OldGoal), !, Goal = dif(X, Y)
|
||||||
).
|
; !, Goal = (dif(X, Y), OldGoal)
|
||||||
gather_dif_goals([_|Attrs], OldGoal, Goal) :-
|
).
|
||||||
gather_dif_goals(Attrs, OldGoal, Goal).
|
gather_dif_goals([_ | Attrs], Goal) :-
|
||||||
|
gather_dif_goals(Attrs, Goal).
|
||||||
|
|
||||||
attribute_goals(X, Goal) :-
|
attribute_goals(X, Goal) :-
|
||||||
'$get_attr_list'(X, Attrs),
|
'$get_attr_list'(X, Attrs),
|
||||||
gather_dif_goals(Attrs, _, Goal).
|
gather_dif_goals(Attrs, Goal).
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
|
use prolog::heap_iter::*;
|
||||||
use prolog::machine::*;
|
use prolog::machine::*;
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
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 static PROJECT_ATTRS: &str = include_str!("project_attributes.pl");
|
||||||
|
|
||||||
pub(super) type Bindings = Vec<(usize, Addr)>;
|
pub(super) type Bindings = Vec<(usize, Addr)>;
|
||||||
|
|
||||||
pub(super) struct AttrVarInitializer {
|
pub(super) struct AttrVarInitializer {
|
||||||
pub(super) bindings: Bindings,
|
pub(super) bindings: Bindings,
|
||||||
pub(super) cp: LocalCodePtr,
|
pub(super) cp: LocalCodePtr,
|
||||||
pub(super) verify_attrs_loc: usize,
|
pub(super) verify_attrs_loc: usize,
|
||||||
@@ -52,7 +55,7 @@ impl MachineState {
|
|||||||
pub(super)
|
pub(super)
|
||||||
fn calculate_register_threshold(&self) -> usize {
|
fn calculate_register_threshold(&self) -> usize {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
||||||
for r in 1 .. MAX_ARITY + 1 {
|
for r in 1 .. MAX_ARITY + 1 {
|
||||||
if let &Addr::HeapCell(0) = &self[RegType::Temp(r)] {
|
if let &Addr::HeapCell(0) = &self[RegType::Temp(r)] {
|
||||||
break;
|
break;
|
||||||
@@ -63,7 +66,7 @@ impl MachineState {
|
|||||||
|
|
||||||
count
|
count
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn verify_attributes(&mut self)
|
fn verify_attributes(&mut self)
|
||||||
{
|
{
|
||||||
@@ -89,4 +92,79 @@ impl MachineState {
|
|||||||
self[temp_v!(1)] = var_list_addr;
|
self[temp_v!(1)] = var_list_addr;
|
||||||
self[temp_v!(2)] = value_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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ use prolog::or_stack::*;
|
|||||||
use downcast::Any;
|
use downcast::Any;
|
||||||
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::io::stdin;
|
use std::io::{Write, stdin, stdout};
|
||||||
use std::mem::swap;
|
use std::mem::swap;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub(super) struct Ball {
|
pub(super) struct Ball {
|
||||||
pub(super) boundary: usize, // ball.0
|
pub(super) boundary: usize, // ball.0
|
||||||
pub(super) stub: MachineStub, // ball.1
|
pub(super) stub: MachineStub, // ball.1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,7 +378,7 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
machine_st.pstr_trail.truncate(machine_st.pstr_tr);
|
machine_st.pstr_trail.truncate(machine_st.pstr_tr);
|
||||||
|
|
||||||
machine_st.heap.truncate(machine_st.or_stack[b].h);
|
machine_st.heap.truncate(machine_st.or_stack[b].h);
|
||||||
|
|
||||||
machine_st.hb = machine_st.heap.h;
|
machine_st.hb = machine_st.heap.h;
|
||||||
machine_st.p += offset;
|
machine_st.p += offset;
|
||||||
|
|
||||||
@@ -547,6 +547,13 @@ pub(crate) trait CallPolicy: Any {
|
|||||||
machine_st.fail = !machine_st.is_cyclic_term(addr);
|
machine_st.fail = !machine_st.is_cyclic_term(addr);
|
||||||
return_from_clause!(machine_st.last_call, machine_st)
|
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 => {
|
&BuiltInClauseType::Read => {
|
||||||
match machine_st.read(stdin(), indices.atom_tbl.clone(), &indices.op_dir) {
|
match machine_st.read(stdin(), indices.atom_tbl.clone(), &indices.op_dir) {
|
||||||
Ok(offset) => {
|
Ok(offset) => {
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ impl MachineState {
|
|||||||
fn print_var_eq<Outputter>(&self, var: Rc<Var>, addr: Addr, var_dir: &HeapVarDict,
|
fn print_var_eq<Outputter>(&self, var: Rc<Var>, addr: Addr, var_dir: &HeapVarDict,
|
||||||
mut output: Outputter)
|
mut output: Outputter)
|
||||||
-> Outputter
|
-> Outputter
|
||||||
where Outputter: HCValueOutputter
|
where Outputter: HCValueOutputter
|
||||||
{
|
{
|
||||||
let orig_len = output.len();
|
let orig_len = output.len();
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ impl MachineState {
|
|||||||
pub(super)
|
pub(super)
|
||||||
fn print_exception<Outputter>(&self, addr: Addr, var_dir: &HeapVarDict, output: Outputter)
|
fn print_exception<Outputter>(&self, addr: Addr, var_dir: &HeapVarDict, output: Outputter)
|
||||||
-> Outputter
|
-> Outputter
|
||||||
where Outputter: HCValueOutputter
|
where Outputter: HCValueOutputter
|
||||||
{
|
{
|
||||||
let printer = HCPrinter::from_heap_locs(&self, output, var_dir);
|
let printer = HCPrinter::from_heap_locs(&self, output, var_dir);
|
||||||
printer.print(addr)
|
printer.print(addr)
|
||||||
@@ -1626,7 +1626,7 @@ impl MachineState {
|
|||||||
| (HeapCellValue::Addr(Addr::HeapCell(hc1)),
|
| (HeapCellValue::Addr(Addr::HeapCell(hc1)),
|
||||||
HeapCellValue::Addr(Addr::AttrVar(hc2)))
|
HeapCellValue::Addr(Addr::AttrVar(hc2)))
|
||||||
| (HeapCellValue::Addr(Addr::AttrVar(hc1)),
|
| (HeapCellValue::Addr(Addr::AttrVar(hc1)),
|
||||||
HeapCellValue::Addr(Addr::AttrVar(hc2))) =>
|
HeapCellValue::Addr(Addr::AttrVar(hc2))) =>
|
||||||
if hc1 != hc2 {
|
if hc1 != hc2 {
|
||||||
return hc1.cmp(&hc2);
|
return hc1.cmp(&hc2);
|
||||||
},
|
},
|
||||||
@@ -2260,7 +2260,7 @@ impl MachineState {
|
|||||||
self.tr,
|
self.tr,
|
||||||
self.pstr_tr,
|
self.pstr_tr,
|
||||||
self.heap.h,
|
self.heap.h,
|
||||||
self.b0,
|
self.b0,
|
||||||
self.num_of_args);
|
self.num_of_args);
|
||||||
|
|
||||||
self.b = self.or_stack.len();
|
self.b = self.or_stack.len();
|
||||||
|
|||||||
@@ -502,7 +502,7 @@ impl Machine {
|
|||||||
for (var, addr) in sorted_vars {
|
for (var, addr) in sorted_vars {
|
||||||
output = self.machine_st.print_var_eq(var.clone(), addr.clone(), var_dir, output);
|
output = self.machine_st.print_var_eq(var.clone(), addr.clone(), var_dir, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,34 +604,7 @@ impl MachineState {
|
|||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn record_var_places(&self, chunk_num: usize, alloc_locs: &AllocVarDict,
|
fn record_var_places(&self, chunk_num: usize, alloc_locs: &AllocVarDict,
|
||||||
heap_locs: &mut HeapVarDict)
|
heap_locs: &mut HeapVarDict)
|
||||||
|
|||||||
@@ -1,46 +1,43 @@
|
|||||||
:- use_module(library(dcgs)).
|
|
||||||
|
|
||||||
driver(QueryVars, AttrVars) :-
|
driver(QueryVars, AttrVars) :-
|
||||||
phrase(gather_modules(AttrVars), Modules0),
|
gather_modules(AttrVars, Modules0, _),
|
||||||
sort(Modules0, Modules),
|
sort(Modules0, Modules),
|
||||||
call_project_attributes(Modules, QueryVars, AttrVars),
|
call_project_attributes(Modules, QueryVars, AttrVars),
|
||||||
call_attribute_goals(QueryVars),
|
call_attribute_goals(Modules, QueryVars),
|
||||||
call_attribute_goals(AttrVars).
|
call_attribute_goals(Modules, AttrVars),
|
||||||
|
'$deallocate'.
|
||||||
|
|
||||||
call_project_attributes([], _, _).
|
call_project_attributes([], _, _).
|
||||||
call_project_attributes([Module|Modules], QueryVars, AttrVars) :-
|
call_project_attributes([Module|Modules], QueryVars, AttrVars) :-
|
||||||
( catch(Module:project_attributes(QueryVars, AttrVars),
|
( catch(Module:project_attributes(QueryVars, AttrVars),
|
||||||
error(evaluation_error((Module:project_attributes/2), project_attributes/2)),
|
error(evaluation_error((Module:project_attributes)/2), project_attributes/2),
|
||||||
true) -> true
|
true) -> true
|
||||||
; true
|
; true
|
||||||
),
|
),
|
||||||
call_project_attributes(Modules, QueryVars, AttrVars).
|
call_project_attributes(Modules, QueryVars, AttrVars).
|
||||||
|
|
||||||
call_attribute_goals([]).
|
call_attribute_goals([], _).
|
||||||
call_attribute_goals([AttrVar | AttrVars]) :-
|
call_attribute_goals([Module | Modules], AttrVars) :-
|
||||||
( '$get_attr_list'(AttrVar, Ls) -> call_goals(Ls, AttrVar)
|
call_goals(AttrVars, Module),
|
||||||
|
call_attribute_goals(Modules, AttrVars).
|
||||||
|
|
||||||
|
call_goals([], _).
|
||||||
|
call_goals([AttrVar|AttrVars], Module) :-
|
||||||
|
( catch(Module:attribute_goals(AttrVar, Goal),
|
||||||
|
error(evaluation_error((Module:attribute_goals)/2), attribute_goals/2),
|
||||||
|
true),
|
||||||
|
nonvar(Goal) -> nl, writeq(Goal)
|
||||||
; true
|
; true
|
||||||
),
|
),
|
||||||
call_attribute_goals(AttrVars).
|
call_goals(AttrVars, Module).
|
||||||
|
|
||||||
call_goals(Ls, _) :- var(Ls), !.
|
gather_modules([], [], _).
|
||||||
call_goals([Attr|Attrs], X) :-
|
gather_modules([AttrVar|AttrVars], Modules, Modules0) :-
|
||||||
|
'$get_attr_list'(AttrVar, Attrs),
|
||||||
|
gather_modules_for_attrs(Attrs, Modules, Modules0),
|
||||||
|
gather_modules(AttrVars, Modules0, _).
|
||||||
|
|
||||||
|
gather_modules_for_attrs(Attrs, Modules, Modules) :-
|
||||||
|
var(Attrs), !.
|
||||||
|
gather_modules_for_attrs([Attr|Attrs], [Module|Modules], Modules0) :-
|
||||||
'$module_of'(Module, Attr),
|
'$module_of'(Module, Attr),
|
||||||
( catch(Module:attribute_goals(X, Goal),
|
gather_modules_for_attrs(Attrs, Modules, Modules0).
|
||||||
error(evaluation_error((Module:attribute_goals/2), attribute_goals/2)),
|
|
||||||
writeq(Goal)) -> true
|
|
||||||
; true
|
|
||||||
),
|
|
||||||
call_goals(Attrs, X).
|
|
||||||
|
|
||||||
gather_modules([]) --> [].
|
|
||||||
gather_modules([AttrVar|AttrVars]) -->
|
|
||||||
{ '$get_attr_list'(AttrVar, Attrs) },
|
|
||||||
gather_modules_for_attrs(Attrs),
|
|
||||||
gather_modules(AttrVars).
|
|
||||||
|
|
||||||
gather_modules_for_attrs(Attrs) --> { var(Attrs), ! }.
|
|
||||||
gather_modules_for_attrs([Attr|Attrs]) -->
|
|
||||||
{ '$module_of'(Module, Attr) },
|
|
||||||
[Module],
|
|
||||||
gather_modules_for_attrs(Attrs).
|
|
||||||
|
|||||||
@@ -30,20 +30,7 @@ impl MachineState {
|
|||||||
// a step in Brent's algorithm.
|
// a step in Brent's algorithm.
|
||||||
fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option<CycleSearchResult>
|
fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option<CycleSearchResult>
|
||||||
{
|
{
|
||||||
match self.heap[brent_st.hare].clone() {
|
match self.heap[brent_st.hare].clone() {
|
||||||
HeapCellValue::Addr(Addr::Lis(l)) => {
|
|
||||||
brent_st.hare = l + 1;
|
|
||||||
brent_st.steps += 1;
|
|
||||||
|
|
||||||
if brent_st.tortoise == brent_st.hare {
|
|
||||||
return Some(CycleSearchResult::NotList);
|
|
||||||
} else if brent_st.steps == brent_st.power {
|
|
||||||
brent_st.tortoise = brent_st.hare;
|
|
||||||
brent_st.power <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
},
|
|
||||||
HeapCellValue::NamedStr(..) =>
|
HeapCellValue::NamedStr(..) =>
|
||||||
Some(CycleSearchResult::NotList),
|
Some(CycleSearchResult::NotList),
|
||||||
HeapCellValue::Addr(addr) =>
|
HeapCellValue::Addr(addr) =>
|
||||||
@@ -52,6 +39,19 @@ impl MachineState {
|
|||||||
Some(CycleSearchResult::ProperList(brent_st.steps)),
|
Some(CycleSearchResult::ProperList(brent_st.steps)),
|
||||||
Addr::HeapCell(_) | Addr::StackCell(..) =>
|
Addr::HeapCell(_) | Addr::StackCell(..) =>
|
||||||
Some(CycleSearchResult::PartialList(brent_st.steps, brent_st.hare)),
|
Some(CycleSearchResult::PartialList(brent_st.steps, brent_st.hare)),
|
||||||
|
Addr::Lis(l) => {
|
||||||
|
brent_st.hare = l + 1;
|
||||||
|
brent_st.steps += 1;
|
||||||
|
|
||||||
|
if brent_st.tortoise == brent_st.hare {
|
||||||
|
return Some(CycleSearchResult::NotList);
|
||||||
|
} else if brent_st.steps == brent_st.power {
|
||||||
|
brent_st.tortoise = brent_st.hare;
|
||||||
|
brent_st.power <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
},
|
||||||
_ =>
|
_ =>
|
||||||
Some(CycleSearchResult::NotList)
|
Some(CycleSearchResult::NotList)
|
||||||
}
|
}
|
||||||
@@ -204,6 +204,10 @@ impl MachineState {
|
|||||||
_ => self.fail = true
|
_ => self.fail = true
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
&SystemClauseType::Deallocate => {
|
||||||
|
self.deallocate();
|
||||||
|
return Ok(());
|
||||||
|
},
|
||||||
&SystemClauseType::DeleteAttribute => {
|
&SystemClauseType::DeleteAttribute => {
|
||||||
let ls0 = self.store(self.deref(self[temp_v!(1)].clone()));
|
let ls0 = self.store(self.deref(self[temp_v!(1)].clone()));
|
||||||
|
|
||||||
@@ -453,11 +457,11 @@ impl MachineState {
|
|||||||
let e = self.e;
|
let e = self.e;
|
||||||
|
|
||||||
let frame_len = self.and_stack[e].len();
|
let frame_len = self.and_stack[e].len();
|
||||||
|
|
||||||
for i in 1 .. frame_len - 1 {
|
for i in 1 .. frame_len - 1 {
|
||||||
self[RegType::Temp(i)] = self.and_stack[e][i].clone();
|
self[RegType::Temp(i)] = self.and_stack[e][i].clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let &Addr::Con(Constant::Usize(b0)) = &self.and_stack[e][frame_len - 1] {
|
if let &Addr::Con(Constant::Usize(b0)) = &self.and_stack[e][frame_len - 1] {
|
||||||
self.b0 = b0;
|
self.b0 = b0;
|
||||||
}
|
}
|
||||||
@@ -468,7 +472,7 @@ impl MachineState {
|
|||||||
|
|
||||||
self.p = CodePtr::Local(self.and_stack[e].special_form_cp);
|
self.p = CodePtr::Local(self.and_stack[e].special_form_cp);
|
||||||
self.deallocate();
|
self.deallocate();
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
},
|
},
|
||||||
&SystemClauseType::RestoreCutPolicy => {
|
&SystemClauseType::RestoreCutPolicy => {
|
||||||
@@ -643,7 +647,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut output = printer.print(addr);
|
let mut output = printer.print(addr);
|
||||||
println!("{}", output.result());
|
print!("{}", output.result());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -360,18 +360,20 @@ pub fn print(wam: &mut Machine, result: EvalSession) {
|
|||||||
write!(stdout, "{}", bindings).unwrap();
|
write!(stdout, "{}", bindings).unwrap();
|
||||||
stdout.flush().unwrap();
|
stdout.flush().unwrap();
|
||||||
|
|
||||||
|
wam.attribute_goals(&heap_locs);
|
||||||
|
|
||||||
if !wam.or_stack_is_empty() {
|
if !wam.or_stack_is_empty() {
|
||||||
stdout.flush().unwrap();
|
stdout.flush().unwrap();
|
||||||
|
|
||||||
for c in stdin.keys() {
|
for c in stdin.keys() {
|
||||||
match c.unwrap() {
|
match c.unwrap() {
|
||||||
Key::Char(' ') | Key::Char(';') => {
|
Key::Char(' ') | Key::Char(';') => {
|
||||||
write!(stdout, " ;\n\r").unwrap();
|
write!(stdout, " ;\r\n").unwrap();
|
||||||
result = wam.continue_query(&alloc_locs, &mut heap_locs);
|
result = wam.continue_query(&alloc_locs, &mut heap_locs);
|
||||||
break;
|
break;
|
||||||
},
|
},
|
||||||
Key::Char('.') => {
|
Key::Char('.') => {
|
||||||
write!(stdout, " .\n\r").unwrap();
|
write!(stdout, " .\r\n").unwrap();
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -380,14 +382,14 @@ pub fn print(wam: &mut Machine, result: EvalSession) {
|
|||||||
|
|
||||||
if let &EvalSession::Error(SessionError::QueryFailure) = &result
|
if let &EvalSession::Error(SessionError::QueryFailure) = &result
|
||||||
{
|
{
|
||||||
write!(stdout, "false.\n\r").unwrap();
|
write!(stdout, "false.\r\n").unwrap();
|
||||||
stdout.flush().unwrap();
|
stdout.flush().unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let &EvalSession::Error(SessionError::QueryFailureWithException(ref e)) = &result
|
if let &EvalSession::Error(SessionError::QueryFailureWithException(ref e)) = &result
|
||||||
{
|
{
|
||||||
write!(stdout, "{}\n\r", error_string(e)).unwrap();
|
write!(stdout, "{}\r\n", error_string(e)).unwrap();
|
||||||
stdout.flush().unwrap();
|
stdout.flush().unwrap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user