[[package]]
name = "rusty-wam"
-version = "0.7.16"
+version = "0.7.17"
dependencies = [
"downcast 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
pub fn clear(&mut self) {
self.0.clear()
}
-
- pub fn resize(&mut self, fr: usize, n: usize) {
- let len = self[fr].perms.len();
-
+
+ pub fn resize(&mut self, fr: usize, n: usize) {
+ let len = self[fr].perms.len();
+
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));
}
}
- }
+ }
}
impl Index<usize> for AndStack {
fn perm_var_offset(&self) -> usize {
self.has_deep_cut as usize
}
+
+ fn mark_unsafe_vars(&self, mut unsafe_var_marker: UnsafeVarMarker, code: &mut Code) {
+ // target the last goal of the rule for handling unsafe variables.
+ // we use this weird logic to find the last goal.
+ let index = if let &Line::Control(_) = code.last().unwrap() {
+ code.len() - 2
+ } else {
+ code.len() - 1
+ };
+
+ if let Line::Query(_) = &code[index] {
+ unsafe_var_marker.record_unsafe_vars(&self.perm_vs);
+
+ for line in code.iter_mut() {
+ if let &mut Line::Query(ref mut query) = line {
+ unsafe_var_marker.mark_safe_vars(query);
+ }
+ }
+ }
+
+ if let &mut Line::Query(ref mut query) = &mut code[index] {
+ unsafe_var_marker.mark_unsafe_vars(query);
+ }
+ }
}
impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
self.compile_seq_prelude(&conjunct_info, &mut code);
let iter = FactIterator::from_rule_head_clause(args);
- let fact = self.compile_target(iter, GenContext::Head, false);
+ let mut fact = self.compile_target(iter, GenContext::Head, false);
+
+ let mut unsafe_var_marker = UnsafeVarMarker::new();
if !fact.is_empty() {
+ unsafe_var_marker = self.mark_unsafe_fact_vars(&mut fact);
code.push(Line::Fact(fact));
}
try!(self.compile_seq(iter, &conjunct_info, &mut code, false));
if conjunct_info.allocates() {
- let index = if let &Line::Control(_) = code.last().unwrap() {
- code.len() - 2
- } else {
- code.len() - 1
- };
-
- if let &mut Line::Query(ref mut query) = &mut code[index] {
- let head_iter = FactIterator::from_rule_head_clause(args);
- conjunct_info.perm_vs.mark_unsafe_vars_in_rule(head_iter, query);
- }
+ conjunct_info.mark_unsafe_vars(unsafe_var_marker, &mut code);
}
Self::compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1));
Ok(code)
}
- fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact)
+ fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact) -> UnsafeVarMarker
{
let mut unsafe_vars = HashMap::new();
*fact_instr = FactInstruction::UnifyLocalValue(reg);
}
},
- &mut FactInstruction::UnifyVariable(reg) => {
+ &mut FactInstruction::UnifyVariable(reg) =>
if let Some(found) = unsafe_vars.get_mut(®) {
*found = true;
- }
- },
+ },
_ => {}
};
}
+
+ UnsafeVarMarker { unsafe_vars }
}
pub fn compile_fact<'b: 'a>(&mut self, term: &'b Term) -> Code
try!(self.compile_seq(iter, &conjunct_info, &mut code, true));
if conjunct_info.allocates() {
- let index = if let &Line::Control(_) = code.last().unwrap() {
- code.len() - 2
- } else {
- code.len() - 1
- };
-
- if let &mut Line::Query(ref mut query) = &mut code[index] {
- conjunct_info.perm_vs.mark_unsafe_vars_in_query(query);
- }
+ conjunct_info.mark_unsafe_vars(UnsafeVarMarker::new(), &mut code);
}
if let Some(query_term) = query.last() {
let mut code = try!(cg.compile_query(&terms));
compile_appendix(&mut code, &queue, false, flags)?;
-
+
Ok((code, cg.take_vars()))
}
}
}
}
+}
+
+pub struct UnsafeVarMarker {
+ pub unsafe_vars: HashMap<RegType, bool>
+}
+
+impl UnsafeVarMarker {
+ pub fn new() -> Self {
+ UnsafeVarMarker {
+ unsafe_vars: HashMap::new()
+ }
+ }
+
+ pub fn record_unsafe_vars(&mut self, fixtures: &VariableFixtures) {
+ for &(_, ref cb) in fixtures.values() {
+ if let Some(index) = cb.first() {
+ if !self.unsafe_vars.contains_key(&index.get().norm()) {
+ self.unsafe_vars.insert(index.get().norm(), false);
+ }
+ }
+ }
+ }
+
+ pub fn mark_safe_vars(&mut self, query: &mut CompiledQuery) {
+ for query_instr in query.iter_mut() {
+ match query_instr {
+ &mut QueryInstruction::PutVariable(RegType::Temp(r), _) =>
+ if let Some(found) = self.unsafe_vars.get_mut(&RegType::Temp(r)) {
+ *found = true;
+ },
+ &mut QueryInstruction::SetVariable(reg) =>
+ if let Some(found) = self.unsafe_vars.get_mut(®) {
+ *found = true;
+ },
+ _ => {}
+ }
+ }
+ }
- fn mark_unsafe_vars(&self, unsafe_vars: &mut HashMap<RegType, bool>, query: &mut CompiledQuery)
+ pub fn mark_unsafe_vars(&mut self, query: &mut CompiledQuery)
{
for query_instr in query.iter_mut() {
match query_instr {
&mut QueryInstruction::PutValue(RegType::Perm(i), arg) =>
- if let Some(found) = unsafe_vars.get_mut(&RegType::Perm(i)) {
+ if let Some(found) = self.unsafe_vars.get_mut(&RegType::Perm(i)) {
if !*found {
*found = true;
*query_instr = QueryInstruction::PutUnsafeValue(i, arg);
}
},
- &mut QueryInstruction::SetVariable(reg)
- | &mut QueryInstruction::PutVariable(reg, _) =>
- if let Some(found) = unsafe_vars.get_mut(®) {
- *found = true;
- },
&mut QueryInstruction::SetValue(reg) =>
- if let Some(found) = unsafe_vars.get_mut(®) {
+ if let Some(found) = self.unsafe_vars.get_mut(®) {
if !*found {
*found = true;
*query_instr = QueryInstruction::SetLocalValue(reg);
};
}
}
-
- fn record_unsafe_vars(&self, unsafe_vars: &mut HashMap<RegType, bool>) {
- for &(_, ref cb) in self.values() {
- match cb.first() {
- Some(index) => {
- unsafe_vars.insert(index.get().norm(), false);
- },
- None => {}
- };
- }
- }
-
- fn mark_head_vars_as_safe(&self, head_iter: FactIterator<'a>, unsafe_vars: &mut HashMap<RegType, bool>)
- {
- for term_ref in head_iter {
- match term_ref {
- TermRef::Var(Level::Shallow, cell, _) => {
- unsafe_vars.remove(&cell.get().norm());
- },
- _ => {}
- };
- }
- }
-
- pub fn mark_unsafe_vars_in_query(&self, query: &mut CompiledQuery) {
- let mut unsafe_vars = HashMap::new();
-
- self.record_unsafe_vars(&mut unsafe_vars);
- self.mark_unsafe_vars(&mut unsafe_vars, query);
- }
-
- pub fn mark_unsafe_vars_in_rule(&self, head_iter: FactIterator<'a>, query: &mut CompiledQuery)
- {
- let mut unsafe_vars = HashMap::new();
-
- self.record_unsafe_vars(&mut unsafe_vars);
- self.mark_head_vars_as_safe(head_iter, &mut unsafe_vars);
- self.mark_unsafe_vars(&mut unsafe_vars, query);
- }
}
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 {
use std::cell::{Cell, RefCell};
use std::collections::{BTreeSet, HashMap, VecDeque};
use std::cmp::Ordering;
-use std::fmt;
use std::ops::{Add, AddAssign, Index, IndexMut, Sub};
use std::rc::Rc;
impl ClauseType {
pub fn spec(&self) -> Option<(usize, Specifier)> {
- match self {
+ match self {
&ClauseType::Op(ref op_decl, _) =>
Some((op_decl.0, op_decl.1)),
&ClauseType::Inlined(InlinedClauseType::CompareNumber(..))
| &ClauseType::BuiltIn(BuiltInClauseType::Is(..))
- | &ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(_))
+ | &ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(_))
| &ClauseType::BuiltIn(BuiltInClauseType::NotEq)
| &ClauseType::BuiltIn(BuiltInClauseType::Eq) =>
Some((700, XFX)),
Str(usize)
}
-impl fmt::Display for Addr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- &Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
- &Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
- &Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
- &Addr::StackCell(fr, sc)=> write!(f, "Addr::StackCell({}, {})", fr, sc),
- &Addr::Str(s) => write!(f, "Addr::Str({})", s)
- }
- }
-}
-
impl PartialEq<Ref> for Addr {
fn eq(&self, r: &Ref) -> bool {
self.as_var() == Some(*r)
pub fn name(&self) -> ClauseName {
self.2.clone()
}
-
+
pub fn submit(&self, module: ClauseName, op_dir: &mut OpDir) -> Result<(), SessionError>
{
let (prec, spec, name) = (self.0, self.1, self.2.clone());
% write, write_canonical, writeq, write_term.
is_write_option(Functor) :-
- Functor =.. [Name, Arg | Args],
- ( Args == [], Arg == true -> true
- ; Args == [], Arg == false -> true
+ Functor =.. [Name, Arg],
+ ( Arg == true -> true
+ ; Arg == false -> true
; throw(error(domain_error(write_option, Functor), write_term/2)) ), % 8.14.2.3 e)
( Name == ignore_ops -> true
; Name == quoted -> true
}
}
+ #[allow(dead_code)]
+ pub fn print_heap(&self) {
+ for h in 0 .. self.heap.h {
+ println!("{} : {}", h, self.heap[h]);
+ }
+ }
+
#[inline]
pub fn machine_flags(&self) -> MachineFlags {
self.flags
if let Addr::HeapCell(hc) = addr {
if hc < h {
- self.heap.push(HeapCellValue::Addr(addr));
+ let heap_val = self.heap[hc].clone();
+ self.heap.push(heap_val);
return;
}
}
.unwrap_or(0);
if and_gi > or_gi {
- let index = self.e + 1;
+ let new_e = self.e + 1;
- self.and_stack[index].e = self.e;
- self.and_stack[index].cp = self.cp.clone();
- self.and_stack[index].global_index = gi;
+ self.and_stack[new_e].e = self.e;
+ self.and_stack[new_e].cp = self.cp.clone();
+ self.and_stack[new_e].global_index = gi;
- self.and_stack.resize(index, num_cells);
- self.e = index;
+ self.and_stack.resize(new_e, num_cells);
+ self.e = new_e;
return;
}
}
self.query_stepper(indices, policies, code_repo);
-
+
match self.p {
CodePtr::Local(LocalCodePtr::TopLevel(_, p)) if p > 0 => {},
_ => {
&SystemClauseType::WriteTerm => {
let addr = self[temp_v!(1)].clone();
- let ignore_ops = self[temp_v!(2)].clone();
- let numbervars = self[temp_v!(3)].clone();
- let quoted = self[temp_v!(4)].clone();
+ let ignore_ops = self.store(self.deref(self[temp_v!(2)].clone()));
+ let numbervars = self.store(self.deref(self[temp_v!(3)].clone()));
+ let quoted = self.store(self.deref(self[temp_v!(4)].clone()));
let mut printer = HCPrinter::new(&self, PrinterOutputter::new());
}
}
+impl fmt::Display for HeapCellValue {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ &HeapCellValue::Addr(ref addr) =>
+ write!(f, "{}", addr),
+ &HeapCellValue::NamedStr(arity, ref name, Some((priority, spec))) =>
+ write!(f, "{}/{} (op, priority: {}, spec: {})", name.as_str(), arity,
+ priority, spec),
+ &HeapCellValue::NamedStr(arity, ref name, None) =>
+ write!(f, "{}/{}", name.as_str(), arity)
+ }
+ }
+}
+
+impl fmt::Display for Addr {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ &Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
+ &Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
+ &Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
+ &Addr::StackCell(fr, sc)=> write!(f, "Addr::StackCell({}, {})", fr, sc),
+ &Addr::Str(s) => write!(f, "Addr::Str({})", s)
+ }
+ }
+}
+
impl fmt::Display for ControlInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
["N = 5", "Xs = [_4, _8, _12, _16, _20]"]],
6);
- assert_prolog_success!(&mut wam, "?- length(Xs, 3).", [["Xs = [_4, _8, _12]"]]);
+ assert_prolog_success!(&mut wam, "?- length(Xs, 3).", [["Xs = [_5, _9, _13]"]]);
assert_prolog_success!(&mut wam, "?- length([], N).", [["N = 0"]]);
assert_prolog_success!(&mut wam, "?- length(Xs, 0).", [["Xs = []"]]);
assert_prolog_success!(&mut wam, "?- length([a,b,[a,b,c]], 3).");
assert_prolog_failure!(&mut wam, "?- Pairs = [a-a|Pairs], keysort(Pairs, _).");
assert_prolog_success!(&mut wam, "?- Pairs = [a-a|Pairs], catch(keysort(Pairs, _), error(E, _), true).",
- [["E = type_error(list, [a-a | _22])", "Pairs = [a-a | Pairs]"]]);
+ [["E = type_error(list, [a-a | _25])", "Pairs = [a-a | Pairs]"]]);
assert_prolog_success!(&mut wam, "?- keysort([], L).",
[["L = []"]]);
assert_prolog_success!(&mut wam, "?- catch(keysort([],[a|a]),error(Pat, _),true).",
[["Pat = type_error(list, [a | a])"]]);
assert_prolog_success!(&mut wam, "?- catch(keysort(_, _), error(E, _), true).",
- [["E = type_error(list, _13)"]]);
+ [["E = type_error(list, _16)"]]);
assert_prolog_success!(&mut wam, "?- catch(keysort([a-1], [_|b]), error(E, _), true).",
- [["E = type_error(list, [_24 | b])"]]);
+ [["E = type_error(list, [_27 | b])"]]);
assert_prolog_success!(&mut wam, "?- catch(keysort([a-1], [a-b,c-d,a]), error(E, _), true).",
[["E = type_error(pair, a)"]]);
assert_prolog_success!(&mut wam, "?- catch(keysort([a], [a-b]), error(E, _), true).",
assert_prolog_success!(&mut wam, "?- sort([], L).",
[["L = []"]]);
assert_prolog_success!(&mut wam, "?- catch(sort(_, []), error(E, _), true).",
- [["E = type_error(list, _13)"]]);
+ [["E = type_error(list, _16)"]]);
assert_prolog_success!(&mut wam, "?- catch(sort([a,b,c], not_a_list), error(E, _), true).",
[["E = type_error(list, not_a_list)"]]);