* `member/2`
* `memberchk/2`
* `must_be/2`
+* `nl/0`
* `nonvar/1`
* `numbervars/2`
* `once/1`
let mut code = try!(cg.compile_query(&terms));
compile_appendix(&mut code, &queue, false, flags)?;
-
Ok((code, cg.take_vars()))
}
pub fn print(mut self, addr: Addr) -> Outputter {
let mut iter = self.machine_st.pre_order_iter(addr);
-
+
loop {
if let Some(loc_data) = self.state_stack.pop() {
match loc_data {
#[derive(Copy, Clone, PartialEq)]
pub enum SystemClauseType {
CheckCutPoint,
+ Deallocate,
DeleteAttribute,
DeleteHeadAttribute,
DynamicModuleResolution,
pub fn name(&self) -> ClauseName {
match self {
&SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
+ &SystemClauseType::Deallocate => clause_name!("$deallocate"),
&SystemClauseType::DeleteAttribute => clause_name!("$del_attr_non_head"),
&SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
&SystemClauseType::DynamicModuleResolution => clause_name!("$module_call"),
pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
match (name, arity) {
("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
+ ("$deallocate", 0) => Some(SystemClauseType::Deallocate),
("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute),
("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute),
("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution),
Ground,
Is(RegType, ArithmeticTerm),
KeySort,
+ Nl,
NotEq,
PartialString,
Read,
&BuiltInClauseType::Ground => clause_name!("ground"),
&BuiltInClauseType::Is(..) => clause_name!("is"),
&BuiltInClauseType::KeySort => clause_name!("keysort"),
+ &BuiltInClauseType::Nl => clause_name!("nl"),
&BuiltInClauseType::NotEq => clause_name!("\\=="),
&BuiltInClauseType::Read => clause_name!("read"),
&BuiltInClauseType::Sort => clause_name!("sort"),
&BuiltInClauseType::Is(..) => 2,
&BuiltInClauseType::KeySort => 2,
&BuiltInClauseType::NotEq => 2,
+ &BuiltInClauseType::Nl => 0,
&BuiltInClauseType::Read => 1,
&BuiltInClauseType::Sort => 2,
&BuiltInClauseType::PartialString => 1,
("ground", 1) => Some(BuiltInClauseType::Ground),
("is", 2) => Some(BuiltInClauseType::Is(temp_v!(1), ArithmeticTerm::Reg(temp_v!(2)))),
("keysort", 2) => Some(BuiltInClauseType::KeySort),
+ ("nl", 0) => Some(BuiltInClauseType::Nl),
("\\==", 2) => Some(BuiltInClauseType::NotEq),
("sort", 2) => Some(BuiltInClauseType::Sort),
("read", 1) => Some(BuiltInClauseType::Read),
BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
CallN(usize, LocalCodePtr), // arity, local.
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 {
&CodePtr::BuiltInClause(_, ref local)
| &CodePtr::CallN(_, ref local)
| &CodePtr::Local(ref local) => local.clone(),
- &CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p)
+ &CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p),
}
}
}
% suggestions for improvement.
dif(X, Y) :- ( X \= Y -> true
- ; term_variables(X, XVars), term_variables(Y, YVars),
- ( XVars == [], YVars == [] -> false
+ ; term_variables(X, XVars), term_variables(Y, YVars),
+ ( XVars == [], YVars == [] -> true
; dif_set_variables(XVars, X, Y),
dif_set_variables(YVars, X, Y)
)
).
-gather_dif_goals(Attrs, Goal, Goal) :-
+gather_dif_goals(Attrs, _) :-
var(Attrs), !.
-gather_dif_goals([dif(X, Y)|Attrs], OldGoal, Goal) :-
- ( var(OldGoal), !, gather_dif_goals(Attrs, dif(X, Y), Goal)
- ; !, gather_dif_goals(Attrs, (dif(X, Y), OldGoal), Goal)
- ).
-gather_dif_goals([_|Attrs], OldGoal, Goal) :-
- gather_dif_goals(Attrs, OldGoal, Goal).
+gather_dif_goals([dif(X, Y) | Attrs], Goal) :-
+ gather_dif_goals(Attrs, OldGoal),
+ ( var(OldGoal), !, Goal = dif(X, Y)
+ ; !, Goal = (dif(X, Y), OldGoal)
+ ).
+gather_dif_goals([_ | Attrs], Goal) :-
+ gather_dif_goals(Attrs, Goal).
attribute_goals(X, Goal) :-
'$get_attr_list'(X, Attrs),
- gather_dif_goals(Attrs, _, Goal).
+ gather_dif_goals(Attrs, Goal).
+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,
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;
count
}
-
+
pub(super)
fn verify_attributes(&mut self)
{
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);
+ }
}
use downcast::Any;
use std::cmp::Ordering;
-use std::io::stdin;
+use std::io::{Write, stdin, stdout};
use std::mem::swap;
use std::ops::{Index, IndexMut};
use std::rc::Rc;
pub(super) struct Ball {
- pub(super) boundary: usize, // ball.0
+ pub(super) boundary: usize, // ball.0
pub(super) stub: MachineStub, // ball.1
}
machine_st.pstr_trail.truncate(machine_st.pstr_tr);
machine_st.heap.truncate(machine_st.or_stack[b].h);
-
+
machine_st.hb = machine_st.heap.h;
machine_st.p += offset;
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(stdin(), indices.atom_tbl.clone(), &indices.op_dir) {
Ok(offset) => {
fn print_var_eq<Outputter>(&self, var: Rc<Var>, addr: Addr, var_dir: &HeapVarDict,
mut output: Outputter)
-> Outputter
- where Outputter: HCValueOutputter
+ where Outputter: HCValueOutputter
{
let orig_len = output.len();
pub(super)
fn print_exception<Outputter>(&self, addr: Addr, var_dir: &HeapVarDict, output: Outputter)
-> Outputter
- where Outputter: HCValueOutputter
+ where Outputter: HCValueOutputter
{
let printer = HCPrinter::from_heap_locs(&self, output, var_dir);
printer.print(addr)
| (HeapCellValue::Addr(Addr::HeapCell(hc1)),
HeapCellValue::Addr(Addr::AttrVar(hc2)))
| (HeapCellValue::Addr(Addr::AttrVar(hc1)),
- HeapCellValue::Addr(Addr::AttrVar(hc2))) =>
+ HeapCellValue::Addr(Addr::AttrVar(hc2))) =>
if hc1 != hc2 {
return hc1.cmp(&hc2);
},
self.tr,
self.pstr_tr,
self.heap.h,
- self.b0,
+ self.b0,
self.num_of_args);
self.b = self.or_stack.len();
for (var, addr) in sorted_vars {
output = self.machine_st.print_var_eq(var.clone(), addr.clone(), var_dir, output);
}
-
+
output
}
_ => {}
};
}
- }
-
- 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,
heap_locs: &mut HeapVarDict)
-:- use_module(library(dcgs)).
-
driver(QueryVars, AttrVars) :-
- phrase(gather_modules(AttrVars), Modules0),
+ gather_modules(AttrVars, Modules0, _),
sort(Modules0, Modules),
call_project_attributes(Modules, QueryVars, AttrVars),
- call_attribute_goals(QueryVars),
- call_attribute_goals(AttrVars).
+ call_attribute_goals(Modules, QueryVars),
+ call_attribute_goals(Modules, AttrVars),
+ '$deallocate'.
call_project_attributes([], _, _).
call_project_attributes([Module|Modules], 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
),
call_project_attributes(Modules, QueryVars, AttrVars).
-call_attribute_goals([]).
-call_attribute_goals([AttrVar | AttrVars]) :-
- ( '$get_attr_list'(AttrVar, Ls) -> call_goals(Ls, AttrVar)
- ; true
- ),
- call_attribute_goals(AttrVars).
+call_attribute_goals([], _).
+call_attribute_goals([Module | Modules], AttrVars) :-
+ call_goals(AttrVars, Module),
+ call_attribute_goals(Modules, AttrVars).
-call_goals(Ls, _) :- var(Ls), !.
-call_goals([Attr|Attrs], X) :-
- '$module_of'(Module, Attr),
- ( catch(Module:attribute_goals(X, Goal),
- error(evaluation_error((Module:attribute_goals/2), attribute_goals/2)),
- writeq(Goal)) -> true
+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
),
- call_goals(Attrs, X).
+ call_goals(AttrVars, Module).
-gather_modules([]) --> [].
-gather_modules([AttrVar|AttrVars]) -->
- { '$get_attr_list'(AttrVar, Attrs) },
- gather_modules_for_attrs(Attrs),
- gather_modules(AttrVars).
+gather_modules([], [], _).
+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) --> { var(Attrs), ! }.
-gather_modules_for_attrs([Attr|Attrs]) -->
- { '$module_of'(Module, Attr) },
- [Module],
- gather_modules_for_attrs(Attrs).
+gather_modules_for_attrs(Attrs, Modules, Modules) :-
+ var(Attrs), !.
+gather_modules_for_attrs([Attr|Attrs], [Module|Modules], Modules0) :-
+ '$module_of'(Module, Attr),
+ gather_modules_for_attrs(Attrs, Modules, Modules0).
// a step in Brent's algorithm.
fn brents_alg_step(&self, brent_st: &mut BrentAlgState) -> Option<CycleSearchResult>
{
- 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
- },
+ match self.heap[brent_st.hare].clone() {
HeapCellValue::NamedStr(..) =>
Some(CycleSearchResult::NotList),
HeapCellValue::Addr(addr) =>
Some(CycleSearchResult::ProperList(brent_st.steps)),
Addr::HeapCell(_) | Addr::StackCell(..) =>
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)
}
_ => self.fail = true
};
},
+ &SystemClauseType::Deallocate => {
+ self.deallocate();
+ return Ok(());
+ },
&SystemClauseType::DeleteAttribute => {
let ls0 = self.store(self.deref(self[temp_v!(1)].clone()));
let e = self.e;
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();
- }
-
+ }
+
if let &Addr::Con(Constant::Usize(b0)) = &self.and_stack[e][frame_len - 1] {
self.b0 = b0;
}
self.p = CodePtr::Local(self.and_stack[e].special_form_cp);
self.deallocate();
-
+
return Ok(());
},
&SystemClauseType::RestoreCutPolicy => {
}
let mut output = printer.print(addr);
- println!("{}", output.result());
+ print!("{}", output.result());
}
};
write!(stdout, "{}", bindings).unwrap();
stdout.flush().unwrap();
+ wam.attribute_goals(&heap_locs);
+
if !wam.or_stack_is_empty() {
stdout.flush().unwrap();
for c in stdin.keys() {
match c.unwrap() {
Key::Char(' ') | Key::Char(';') => {
- write!(stdout, " ;\n\r").unwrap();
+ write!(stdout, " ;\r\n").unwrap();
result = wam.continue_query(&alloc_locs, &mut heap_locs);
break;
},
Key::Char('.') => {
- write!(stdout, " .\n\r").unwrap();
+ write!(stdout, " .\r\n").unwrap();
return;
},
_ => {}
if let &EvalSession::Error(SessionError::QueryFailure) = &result
{
- write!(stdout, "false.\n\r").unwrap();
+ write!(stdout, "false.\r\n").unwrap();
stdout.flush().unwrap();
return;
}
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();
return;
}