add variable_names as a write option

This commit is contained in:
Mark Thom
2019-05-05 00:58:56 -04:00
parent b05cff3044
commit bf8a2ab6a6
11 changed files with 182 additions and 113 deletions

View File

@@ -410,7 +410,7 @@ impl SystemClauseType {
("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack), ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
("$unify_with_occurs_check", 2) => Some(SystemClauseType::UnifyWithOccursCheck), ("$unify_with_occurs_check", 2) => Some(SystemClauseType::UnifyWithOccursCheck),
("$variant", 2) => Some(SystemClauseType::Variant), ("$variant", 2) => Some(SystemClauseType::Variant),
("$write_term", 4) => Some(SystemClauseType::WriteTerm), ("$write_term", 5) => Some(SystemClauseType::WriteTerm),
_ => None _ => None
} }
} }

View File

@@ -299,6 +299,7 @@ pub struct HCPrinter<'a, Outputter> {
printed_vars: HashSet<Addr>, printed_vars: HashSet<Addr>,
last_item_idx: usize, last_item_idx: usize,
cyclic_terms: HashMap<Addr, usize>, cyclic_terms: HashMap<Addr, usize>,
pub(crate) var_names: HashMap<Addr, String>,
pub(crate) numbervars_offset: BigInt, pub(crate) numbervars_offset: BigInt,
pub(crate) numbervars: bool, pub(crate) numbervars: bool,
pub(crate) quoted: bool, pub(crate) quoted: bool,
@@ -341,10 +342,9 @@ pub fn requires_space(atom: &str, op: &str) -> bool {
} }
} }
fn reverse_heap_locs<'a>(machine_st: &'a MachineState, heap_locs: &'a HeapVarDict) fn reverse_heap_locs<'a>(machine_st: &'a MachineState) -> ReverseHeapVarDict
-> ReverseHeapVarDict
{ {
heap_locs.iter().map(|(var, var_addr)| { machine_st.heap_locs.iter().map(|(var, var_addr)| {
(machine_st.store(machine_st.deref(var_addr.clone())), var.clone()) (machine_st.store(machine_st.deref(var_addr.clone())), var.clone())
}).collect() }).collect()
} }
@@ -414,17 +414,17 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
numbervars_offset: BigInt::zero(), numbervars_offset: BigInt::zero(),
quoted: false, quoted: false,
ignore_ops: false, ignore_ops: false,
cyclic_terms: HashMap::new() } cyclic_terms: HashMap::new(),
var_names: HashMap::new() }
} }
pub fn from_heap_locs(machine_st: &'a MachineState, op_dir: &'a OpDir, output: Outputter, pub fn from_heap_locs(machine_st: &'a MachineState, op_dir: &'a OpDir, output: Outputter)
heap_locs: &'a HeapVarDict)
-> Self -> Self
{ {
let mut printer = Self::new(machine_st, op_dir, output); let mut printer = Self::new(machine_st, op_dir, output);
printer.toplevel_spec = Some(DirectedOp::Right(clause_name!("="), SharedOpDesc::new(700, XFX))); printer.toplevel_spec = Some(DirectedOp::Right(clause_name!("="), SharedOpDesc::new(700, XFX)));
printer.heap_locs = reverse_heap_locs(machine_st, heap_locs); printer.heap_locs = reverse_heap_locs(machine_st);
printer printer
} }
@@ -578,7 +578,17 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
self.outputter.append(s); self.outputter.append(s);
} }
fn offset_as_string(&self, addr: Addr) -> Option<String> { fn offset_as_string(&self, iter: &mut HCPreOrderIterator, addr: Addr) -> Option<String>
{
if let Some(var) = self.var_names.get(&addr) {
if addr.as_var().is_some() {
return Some(format!("{}", var));
} else {
iter.stack().push(addr);
return None;
}
}
match addr { match addr {
Addr::AttrVar(h) => Addr::AttrVar(h) =>
Some(format!("_{}", h + 1)), Some(format!("_{}", h + 1)),
@@ -894,7 +904,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
self.push_list(); self.push_list();
}, },
HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr) =>
if let Some(offset_str) = self.offset_as_string(addr) { if let Some(offset_str) = self.offset_as_string(iter, addr) {
push_space_if_amb!(self, &offset_str, { push_space_if_amb!(self, &offset_str, {
self.append_str(offset_str.as_str()); self.append_str(offset_str.as_str());
}) })

View File

@@ -220,22 +220,41 @@ is_write_option(Functor) :-
Functor =.. [Name, Arg], Functor =.. [Name, Arg],
( Arg == true -> true ( Arg == true -> true
; Arg == false -> true ; Arg == false -> true
; Name == variable_names -> must_be_var_names_list(Arg)
; var(Arg) -> throw(error(instantiation_error, write_term/2)) ; var(Arg) -> throw(error(instantiation_error, write_term/2))
; throw(error(domain_error(write_option, Functor), write_term/2)) ; throw(error(domain_error(write_option, Functor), write_term/2))
), % 8.14.2.3 e) ), % 8.14.2.3 e)
( Name == ignore_ops -> true ( Name == ignore_ops -> true
; Name == quoted -> true ; Name == quoted -> true
; Name == numbervars -> true ; Name == numbervars -> true
; Name == variable_names -> true
; throw(error(domain_error(write_option, Functor), write_term/2)) ; throw(error(domain_error(write_option, Functor), write_term/2))
). % 8.14.2.3 e) ). % 8.14.2.3 e)
inst_member_or([X|Xs], Y, _) :- inst_member_or([X|Xs], Y, Z) :-
( var(X) -> throw(error(instantiation_error, write_term/2)) ( var(X) -> throw(error(instantiation_error, write_term/2))
; is_write_option(X) -> ( Y = X, ! ; inst_member_or(Xs, Y, _) ) ; is_write_option(X) -> ( Y = X, ! ; inst_member_or(Xs, Y, Z) )
; throw(error(domain_error(write_option, X), write_term/2)) ; throw(error(domain_error(write_option, X), write_term/2))
). ).
inst_member_or([], Y, Y). inst_member_or([], Y, Y).
must_be_var_names_list(VarNames) :-
'$skip_max_list'(_, -1, VarNames, Tail),
( Tail == [] -> must_be_var_names_list_(VarNames)
; var(Tail) -> throw(error(instantiation_error, write_term/2))
; throw(error(domain_error(write_options, variable_names(VarNames)), write_term/2))
).
must_be_var_names_list_([]).
must_be_var_names_list_([VarName | VarNames]) :-
( nonvar(VarName), VarName = (Atom = _) ->
( atom(Atom) -> must_be_var_names_list_(VarNames)
; var(Atom) -> throw(error(instantiation_error, write_term/2))
; throw(error(domain_error(write_options, variable_names(VarName)), write_term/2))
)
; throw(error(instantiation_error, write_term/2))
).
write_term(_, Options) :- write_term(_, Options) :-
var(Options), throw(error(instantiation_error, write_term/2)). var(Options), throw(error(instantiation_error, write_term/2)).
write_term(Term, Options) :- write_term(Term, Options) :-
@@ -247,7 +266,8 @@ write_term(Term, Options) :-
inst_member_or(Options, ignore_ops(IgnoreOps), ignore_ops(false)), inst_member_or(Options, ignore_ops(IgnoreOps), ignore_ops(false)),
inst_member_or(Options, numbervars(NumberVars), numbervars(false)), inst_member_or(Options, numbervars(NumberVars), numbervars(false)),
inst_member_or(Options, quoted(Quoted), quoted(false)), inst_member_or(Options, quoted(Quoted), quoted(false)),
'$write_term'(Term, IgnoreOps, NumberVars, Quoted). inst_member_or(Options, variable_names(VarNames), variable_names([])),
'$write_term'(Term, IgnoreOps, NumberVars, Quoted, VarNames).
write(Term) :- write_term(Term, [numbervars(true)]). write(Term) :- write_term(Term, [numbervars(true)]).
@@ -605,8 +625,8 @@ module_abolish(Pred, Module) :-
( var(Name) -> throw(error(instantiation_error, abolish/1)) ( var(Name) -> throw(error(instantiation_error, abolish/1))
; integer(Arity) -> ; integer(Arity) ->
( \+ atom(Name) -> throw(error(type_error(atom, Name), abolish/1)) ( \+ atom(Name) -> throw(error(type_error(atom, Name), abolish/1))
; Arity < 0 -> throw(domain_error(not_less_than_zero, Arity), abolish/1) ; Arity < 0 -> throw(error(domain_error(not_less_than_zero, Arity), abolish/1))
; max_arity(N), Arity > N -> throw(representation_error(max_arity), abolish/1) ; max_arity(N), Arity > N -> throw(error(representation_error(max_arity), abolish/1))
; functor(Head, Name, Arity) -> ; functor(Head, Name, Arity) ->
( '$module_head_is_dynamic'(Head, Module) -> ( '$module_head_is_dynamic'(Head, Module) ->
'$abolish_module_clause'(Name, Arity, Module) '$abolish_module_clause'(Name, Arity, Module)
@@ -626,8 +646,8 @@ abolish(Pred) :-
; var(Arity) -> throw(error(instantiation_error, abolish/1)) ; var(Arity) -> throw(error(instantiation_error, abolish/1))
; integer(Arity) -> ; integer(Arity) ->
( \+ atom(Name) -> throw(error(type_error(atom, Name), abolish/1)) ( \+ atom(Name) -> throw(error(type_error(atom, Name), abolish/1))
; Arity < 0 -> throw(domain_error(not_less_than_zero, Arity), abolish/1) ; Arity < 0 -> throw(error(domain_error(not_less_than_zero, Arity), abolish/1))
; max_arity(N), Arity > N -> throw(representation_error(max_arity), abolish/1) ; max_arity(N), Arity > N -> throw(error(representation_error(max_arity), abolish/1))
; functor(Head, Name, Arity) -> ; functor(Head, Name, Arity) ->
( '$no_such_predicate'(Head) -> true ( '$no_such_predicate'(Head) -> true
; '$head_is_dynamic'(Head) -> '$abolish_clause'(Name, Arity) ; '$head_is_dynamic'(Head) -> '$abolish_clause'(Name, Arity)

View File

@@ -85,12 +85,12 @@ impl MachineState {
attr_vars.into_iter() attr_vars.into_iter()
} }
fn populate_project_attr_lists(&mut self, var_dict: &HeapVarDict) -> (Addr, Addr) fn populate_project_attr_lists(&mut self) -> (Addr, Addr)
{ {
let mut query_vars = HashSet::new(); let mut query_vars = HashSet::new();
let attr_vars = self.gather_attr_vars_created_since(0); let attr_vars = self.gather_attr_vars_created_since(0);
for (_, addr) in var_dict { for (_, addr) in self.heap_locs.iter() {
let iter = self.acyclic_pre_order_iter(addr.clone()); let iter = self.acyclic_pre_order_iter(addr.clone());
for value in iter { for value in iter {
@@ -140,7 +140,7 @@ impl MachineState {
self.p = CodePtr::Local(LocalCodePtr::DirEntry(p)); self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
} }
fn print_attribute_goals_string(&mut self, op_dir: &OpDir, var_dict: &HeapVarDict) -> 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![]); let mut attr_goals = mem::replace(&mut self.attr_var_init.attribute_goals, vec![]);
@@ -154,7 +154,7 @@ impl MachineState {
let mut output = PrinterOutputter::new(); let mut output = PrinterOutputter::new();
for goal_addr in attr_goals { for goal_addr in attr_goals {
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output, var_dict); let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
printer.see_all_locs(); printer.see_all_locs();
printer.numbervars = false; printer.numbervars = false;
@@ -174,10 +174,10 @@ impl MachineState {
impl Machine { impl Machine {
pub pub
fn attribute_goals(&mut self, var_dict: &HeapVarDict) -> String fn attribute_goals(&mut self) -> String
{ {
let p = self.machine_st.attr_var_init.project_attrs_loc; 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); let (query_vars, attr_vars) = self.machine_st.populate_project_attr_lists();
self.machine_st.allocate(0); self.machine_st.allocate(0);
@@ -188,6 +188,6 @@ impl Machine {
self.machine_st.query_stepper(&mut self.indices, &mut self.policies, &mut self.code_repo, self.machine_st.query_stepper(&mut self.indices, &mut self.policies, &mut self.code_repo,
&mut readline::input_stream()); &mut readline::input_stream());
self.machine_st.print_attribute_goals_string(&self.indices.op_dir, var_dict) self.machine_st.print_attribute_goals_string(&self.indices.op_dir)
} }
} }

View File

@@ -391,7 +391,7 @@ pub enum SessionError {
pub enum EvalSession { pub enum EvalSession {
EntrySuccess, EntrySuccess,
Error(SessionError), Error(SessionError),
InitialQuerySuccess(AllocVarDict, HeapVarDict), InitialQuerySuccess(AllocVarDict),
QueryFailure, QueryFailure,
SubsequentQuerySuccess, SubsequentQuerySuccess,
} }

View File

@@ -235,6 +235,7 @@ pub struct MachineState {
pub(super) lifted_heap: Vec<HeapCellValue>, pub(super) lifted_heap: Vec<HeapCellValue>,
pub(super) interms: Vec<Number>, // intermediate numbers. pub(super) interms: Vec<Number>, // intermediate numbers.
pub(super) last_call: bool, pub(super) last_call: bool,
pub(crate) heap_locs: HeapVarDict,
pub(crate) flags: MachineFlags pub(crate) flags: MachineFlags
} }

View File

@@ -64,6 +64,7 @@ impl MachineState {
lifted_heap: Vec::with_capacity(1024), lifted_heap: Vec::with_capacity(1024),
interms: vec![Number::default(); 256], interms: vec![Number::default(); 256],
last_call: false, last_call: false,
heap_locs: HeapVarDict::new(),
flags: MachineFlags::default() flags: MachineFlags::default()
} }
} }
@@ -94,6 +95,7 @@ impl MachineState {
lifted_heap: Vec::with_capacity(capacity), lifted_heap: Vec::with_capacity(capacity),
interms: vec![Number::default(); 0], interms: vec![Number::default(); 0],
last_call: false, last_call: false,
heap_locs: HeapVarDict::new(),
flags: MachineFlags::default() flags: MachineFlags::default()
} }
} }
@@ -187,8 +189,7 @@ impl MachineState {
} }
pub(super) pub(super)
fn print_var_eq<Outputter>(&self, var: Rc<Var>, addr: Addr, op_dir: &OpDir, var_dict: &HeapVarDict, fn print_var_eq<Outputter>(&self, var: Rc<Var>, addr: Addr, op_dir: &OpDir, mut output: Outputter)
mut output: Outputter)
-> Outputter -> Outputter
where Outputter: HCValueOutputter where Outputter: HCValueOutputter
{ {
@@ -199,7 +200,7 @@ impl MachineState {
output.append(var.as_str()); output.append(var.as_str());
output.append(" = "); output.append(" = ");
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output, var_dict); let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
printer.numbervars = false; printer.numbervars = false;
printer.quoted = true; printer.quoted = true;
@@ -2816,6 +2817,7 @@ impl MachineState {
self.block = 0; self.block = 0;
self.ball.reset(); self.ball.reset();
self.heap_locs.clear();
self.lifted_heap.clear(); self.lifted_heap.clear();
} }

View File

@@ -217,7 +217,7 @@ impl Machine {
pub fn run_toplevel(&mut self) { pub fn run_toplevel(&mut self) {
self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(self.toplevel_idx)); self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(self.toplevel_idx));
self.run_query(&AllocVarDict::new(), &mut HeapVarDict::new()); self.run_query(&AllocVarDict::new());
} }
pub fn new(prolog_stream: PrologStream) -> Self { pub fn new(prolog_stream: PrologStream) -> Self {
@@ -316,41 +316,13 @@ impl Machine {
pub fn submit_query(&mut self, code: Code, alloc_locs: AllocVarDict) -> EvalSession pub fn submit_query(&mut self, code: Code, alloc_locs: AllocVarDict) -> EvalSession
{ {
let mut heap_locs = HeapVarDict::new();
self.code_repo.cached_query = code; self.code_repo.cached_query = code;
self.run_query(&alloc_locs, &mut heap_locs); self.run_query(&alloc_locs);
if self.machine_st.fail { if self.machine_st.fail {
EvalSession::QueryFailure EvalSession::QueryFailure
} else { } else {
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) EvalSession::InitialQuerySuccess(alloc_locs)
}
}
fn record_var_places(&self, chunk_num: usize, alloc_locs: &AllocVarDict,
heap_locs: &mut HeapVarDict)
{
for (var, var_data) in alloc_locs {
match var_data {
&VarData::Perm(p) if p > 0 =>
if !heap_locs.contains_key(var) {
let e = self.machine_st.e;
let r = var_data.as_reg_type().reg_num();
let addr = self.machine_st.and_stack[e][r].clone();
heap_locs.insert(var.clone(), addr);
},
&VarData::Temp(cn, _, _) if cn == chunk_num => {
let r = var_data.as_reg_type();
if r.reg_num() != 0 {
let addr = self.machine_st[r].clone();
heap_locs.insert(var.clone(), addr);
}
},
_ => {}
}
} }
} }
@@ -413,8 +385,9 @@ impl Machine {
}; };
} }
let term_output = self.machine_st.print_query(term, &self.indices.op_dir, self.machine_st.heap_locs = var_dict;
&var_dict); let term_output = self.machine_st.print_query(term, &self.indices.op_dir);
term_output.result() term_output.result()
}, },
Err(err_stub) => { Err(err_stub) => {
@@ -454,14 +427,14 @@ impl Machine {
fn handle_eval_session(&mut self, result: EvalSession, snapshot: MachineState) { fn handle_eval_session(&mut self, result: EvalSession, snapshot: MachineState) {
match result { match result {
EvalSession::InitialQuerySuccess(alloc_locs, mut heap_locs) => EvalSession::InitialQuerySuccess(alloc_locs) =>
loop { loop {
let bindings = { let bindings = {
let mut output = PrinterOutputter::new(); let mut output = PrinterOutputter::new();
self.toplevel_heap_view(&heap_locs, output).result() self.toplevel_heap_view(output).result()
}; };
let attr_goals = self.attribute_goals(&heap_locs); let attr_goals = self.attribute_goals();
if !(self.machine_st.b > 0) { if !(self.machine_st.b > 0) {
if bindings.is_empty() { if bindings.is_empty() {
@@ -499,7 +472,7 @@ impl Machine {
let result = match next_keypress() { let result = match next_keypress() {
ContinueResult::ContinueQuery => { ContinueResult::ContinueQuery => {
write!(raw_stdout, " ;\r\n").unwrap(); write!(raw_stdout, " ;\r\n").unwrap();
self.continue_query(&alloc_locs, &mut heap_locs) self.continue_query(&alloc_locs)
}, },
ContinueResult::Conclude => { ContinueResult::Conclude => {
write!(raw_stdout, " ...\r\n").unwrap(); write!(raw_stdout, " ...\r\n").unwrap();
@@ -563,7 +536,7 @@ impl Machine {
} }
pub(super) pub(super)
fn run_query(&mut self, alloc_locs: &AllocVarDict, heap_locs: &mut HeapVarDict) fn run_query(&mut self, alloc_locs: &AllocVarDict)
{ {
let end_ptr = top_level_code_ptr!(0, self.code_repo.size_of_cached_query()); let end_ptr = top_level_code_ptr!(0, self.code_repo.size_of_cached_query());
@@ -571,7 +544,7 @@ impl Machine {
if let CodePtr::Local(LocalCodePtr::TopLevel(mut cn, p)) = self.machine_st.p { if let CodePtr::Local(LocalCodePtr::TopLevel(mut cn, p)) = self.machine_st.p {
match &self.code_repo[LocalCodePtr::TopLevel(cn, p)] { match &self.code_repo[LocalCodePtr::TopLevel(cn, p)] {
&Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => { &Line::Control(ref ctrl_instr) if ctrl_instr.is_jump_instr() => {
self.record_var_places(cn, alloc_locs, heap_locs); self.machine_st.record_var_places(cn, alloc_locs);
cn += 1; cn += 1;
}, },
_ => {} _ => {}
@@ -595,8 +568,8 @@ impl Machine {
self.dynamic_transaction(trans_type, p); self.dynamic_transaction(trans_type, p);
if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.machine_st.p { if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.machine_st.p {
if heap_locs.is_empty() { if self.machine_st.heap_locs.is_empty() {
self.record_var_places(0, alloc_locs, heap_locs); self.machine_st.record_var_places(0, alloc_locs);
} }
self.code_repo.cached_query = cached_query; self.code_repo.cached_query = cached_query;
@@ -606,8 +579,8 @@ impl Machine {
self.code_repo.cached_query = cached_query; self.code_repo.cached_query = cached_query;
}, },
_ => { _ => {
if heap_locs.is_empty() { if self.machine_st.heap_locs.is_empty() {
self.record_var_places(0, alloc_locs, heap_locs); self.machine_st.record_var_places(0, alloc_locs);
} }
break; break;
@@ -616,7 +589,7 @@ impl Machine {
} }
} }
pub fn continue_query(&mut self, alloc_l: &AllocVarDict, heap_l: &mut HeapVarDict) -> EvalSession pub fn continue_query(&mut self, alloc_locs: &AllocVarDict) -> EvalSession
{ {
if !self.or_stack_is_empty() { if !self.or_stack_is_empty() {
let b = self.machine_st.b - 1; let b = self.machine_st.b - 1;
@@ -627,7 +600,7 @@ impl Machine {
return EvalSession::QueryFailure; return EvalSession::QueryFailure;
} }
self.run_query(alloc_l, heap_l); self.run_query(alloc_locs);
if self.machine_st.fail { if self.machine_st.fail {
EvalSession::QueryFailure EvalSession::QueryFailure
@@ -639,15 +612,15 @@ impl Machine {
} }
} }
pub fn toplevel_heap_view<Outputter>(&self, var_dir: &HeapVarDict, mut output: Outputter) -> Outputter pub fn toplevel_heap_view<Outputter>(&self, mut output: Outputter) -> Outputter
where Outputter: HCValueOutputter where Outputter: HCValueOutputter
{ {
let mut sorted_vars: Vec<_> = var_dir.iter().collect(); let mut sorted_vars: Vec<_> = self.machine_st.heap_locs.iter().collect();
sorted_vars.sort_by_key(|ref v| v.0); sorted_vars.sort_by_key(|ref v| v.0);
for (var, addr) in sorted_vars { for (var, addr) in sorted_vars {
let addr = self.machine_st.store(self.machine_st.deref(addr.clone())); 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, var_dir, output = self.machine_st.print_var_eq(var.clone(), addr, &self.indices.op_dir,
output); output);
} }
@@ -655,16 +628,15 @@ impl Machine {
} }
#[cfg(test)] #[cfg(test)]
pub fn test_heap_view<Outputter>(&self, var_dir: &HeapVarDict, mut output: Outputter) pub fn test_heap_view<Outputter>(&self, mut output: Outputter) -> Outputter
-> Outputter
where Outputter: HCValueOutputter where Outputter: HCValueOutputter
{ {
let mut sorted_vars: Vec<(&Rc<Var>, &Addr)> = var_dir.iter().collect(); let mut sorted_vars: Vec<(&Rc<Var>, &Addr)> = self.machine_st.heap_locs.iter().collect();
sorted_vars.sort_by_key(|ref v| v.0); sorted_vars.sort_by_key(|ref v| v.0);
for (var, addr) in sorted_vars { for (var, addr) in sorted_vars {
output = self.machine_st.print_var_eq(var.clone(), addr.clone(), &self.indices.op_dir, output = self.machine_st.print_var_eq(var.clone(), addr.clone(), &self.indices.op_dir,
var_dir, output); output);
} }
output output
@@ -677,7 +649,32 @@ impl Machine {
impl MachineState { impl MachineState {
fn print_query(&mut self, addr: Addr, op_dir: &OpDir, var_dict: &HeapVarDict) -> PrinterOutputter 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 =>
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();
if r.reg_num() != 0 {
let addr = self[r].clone();
self.heap_locs.insert(var.clone(), addr);
}
},
_ => {}
}
}
}
fn print_query(&mut self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter
{ {
let flags = self.flags; let flags = self.flags;
@@ -685,7 +682,7 @@ impl MachineState {
self.flags = MachineFlags { double_quotes: DoubleQuotes::Atom }; self.flags = MachineFlags { double_quotes: DoubleQuotes::Atom };
let output = PrinterOutputter::new(); let output = PrinterOutputter::new();
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output, var_dict); let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
printer.quoted = true; printer.quoted = true;
printer.numbervars = false; printer.numbervars = false;

View File

@@ -18,7 +18,7 @@ use prolog::read::{PrologStream, readline};
use ref_thread_local::RefThreadLocal; use ref_thread_local::RefThreadLocal;
use std::collections::HashSet; use std::collections::{HashMap, HashSet};
use std::io::{stdout, Write}; use std::io::{stdout, Write};
use std::iter::once; use std::iter::once;
use std::mem; use std::mem;
@@ -1666,6 +1666,47 @@ impl MachineState {
printer.quoted = name.as_str() == "true"; printer.quoted = name.as_str() == "true";
} }
let stub = MachineError::functor_stub(clause_name!("write_term"), 2);
match self.try_from_list(temp_v!(5), stub.clone()) {
Ok(addrs) => {
let mut var_names: HashMap<Addr, String> = HashMap::new();
for addr in addrs {
match addr {
Addr::Str(s) =>
match &self.heap[s] {
&HeapCellValue::NamedStr(2, ref name, _)
if name.as_str() == "=" => {
let atom = self.heap[s+1].as_addr(s+1);
let var = self.heap[s+2].as_addr(s+2);
let atom = match self.store(self.deref(atom)) {
Addr::Con(Constant::Atom(atom, _)) => atom.to_string(),
Addr::Con(Constant::Char(c)) => c.to_string(),
_ => unreachable!()
};
let var = self.store(self.deref(var));
if var_names.contains_key(&var) {
continue;
}
var_names.insert(var, atom);
},
_ => unreachable!()
},
_ => unreachable!()
}
}
printer.var_names = var_names;
},
Err(err) =>
return Err(err)
}
let mut output = printer.print(addr); let mut output = printer.print(addr);
print!("{}", output.result()); print!("{}", output.result());
stdout().flush().unwrap(); stdout().flush().unwrap();

View File

@@ -289,13 +289,13 @@ impl<'a, R: Read> TermStream<'a, R> {
impl MachineState { impl MachineState {
pub(super) pub(super)
fn print_with_locs(&self, addr: Addr, op_dir: &OpDir, var_dict: &HeapVarDict) -> PrinterOutputter fn print_with_locs(&self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter
{ {
let output = PrinterOutputter::new(); let output = PrinterOutputter::new();
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output, var_dict); let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
let mut max_var_length = 0; let mut max_var_length = 0;
for var in var_dict.keys() { for var in self.heap_locs.keys() {
max_var_length = std::cmp::max(var.len(), max_var_length); max_var_length = std::cmp::max(var.len(), max_var_length);
} }
@@ -337,8 +337,10 @@ impl MachineState {
self.reset(); self.reset();
None None
} else { } else {
let &TermWriteResult { heap_loc: _, ref var_dict } = &term_write_result; let TermWriteResult { var_dict, .. } = term_write_result;
let output = self.print_with_locs(Addr::HeapCell(h), &indices.op_dir, var_dict);
self.heap_locs = var_dict;
let output = self.print_with_locs(Addr::HeapCell(h), &indices.op_dir);
self.reset(); self.reset();
Some(output.result()) Some(output.result())

View File

@@ -84,30 +84,27 @@ impl HCValueOutputter for TestOutputter {
} }
} }
pub fn collect_test_output(wam: &mut Machine, alloc_locs: AllocVarDict, mut heap_locs: HeapVarDict) pub fn collect_test_output(wam: &mut Machine, alloc_locs: AllocVarDict) -> Vec<HashSet<String>>
-> Vec<HashSet<String>>
{ {
let mut output = TestOutputter::new(); let mut output = TestOutputter::new();
output = wam.test_heap_view(&heap_locs, output); output = wam.test_heap_view(output);
output.cache(); output.cache();
while let EvalSession::SubsequentQuerySuccess = wam.continue_query(&alloc_locs, &mut heap_locs) while let EvalSession::SubsequentQuerySuccess = wam.continue_query(&alloc_locs) {
{ output = wam.test_heap_view(output);
output = wam.test_heap_view(&heap_locs, output);
output.cache(); output.cache();
} }
output.result() output.result()
} }
pub fn collect_test_output_with_limit(wam: &mut Machine, alloc_locs: AllocVarDict, pub fn collect_test_output_with_limit(wam: &mut Machine, alloc_locs: AllocVarDict, limit: usize)
mut heap_locs: HeapVarDict, limit: usize)
-> Vec<HashSet<String>> -> Vec<HashSet<String>>
{ {
let mut output = TestOutputter::new(); let mut output = TestOutputter::new();
output = wam.test_heap_view(&heap_locs, output); output = wam.test_heap_view(output);
output.cache(); output.cache();
let mut count = 1; let mut count = 1;
@@ -116,9 +113,9 @@ pub fn collect_test_output_with_limit(wam: &mut Machine, alloc_locs: AllocVarDic
return output.result(); return output.result();
} }
while let EvalSession::SubsequentQuerySuccess = wam.continue_query(&alloc_locs, &mut heap_locs) while let EvalSession::SubsequentQuerySuccess = wam.continue_query(&alloc_locs)
{ {
output = wam.test_heap_view(&heap_locs, output); output = wam.test_heap_view(output);
output.cache(); output.cache();
count += 1; count += 1;
@@ -137,7 +134,7 @@ pub fn submit(wam: &mut Machine, buffer: &str) -> bool
wam.reset(); wam.reset();
match submit_code(wam, buffer) { match submit_code(wam, buffer) {
EvalSession::InitialQuerySuccess(_, _) | EvalSession::InitialQuerySuccess(_) |
EvalSession::EntrySuccess | EvalSession::EntrySuccess |
EvalSession::SubsequentQuerySuccess => EvalSession::SubsequentQuerySuccess =>
true, true,
@@ -153,8 +150,8 @@ pub fn submit_query(wam: &mut Machine, buffer: &str, result: Vec<HashSet<String>
match stream_to_toplevel(parsing_stream(buffer.as_bytes()), wam) { match stream_to_toplevel(parsing_stream(buffer.as_bytes()), wam) {
Ok(term) => Ok(term) =>
match compile_term(wam, term) { match compile_term(wam, term) {
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) => EvalSession::InitialQuerySuccess(alloc_locs) =>
result == collect_test_output(wam, alloc_locs, heap_locs), result == collect_test_output(wam, alloc_locs),
EvalSession::EntrySuccess => true, EvalSession::EntrySuccess => true,
_ => false _ => false
}, },
@@ -188,9 +185,8 @@ pub fn submit_query_with_limit(wam: &mut Machine, buffer: &str,
match stream_to_toplevel(parsing_stream(buffer.as_bytes()), wam) { match stream_to_toplevel(parsing_stream(buffer.as_bytes()), wam) {
Ok(term) => Ok(term) =>
match compile_term(wam, term) { match compile_term(wam, term) {
EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) => EvalSession::InitialQuerySuccess(alloc_locs) =>
result == collect_test_output_with_limit(wam, alloc_locs, result == collect_test_output_with_limit(wam, alloc_locs, limit),
heap_locs, limit),
EvalSession::EntrySuccess => true, EvalSession::EntrySuccess => true,
_ => false _ => false
}, },
@@ -1673,7 +1669,7 @@ fn test_queries_on_builtins()
submit(&mut wam, ":- use_module(library(non_iso))."); submit(&mut wam, ":- use_module(library(non_iso)).");
assert_prolog_success!(&mut wam, "call_with_inference_limit((setup_call_cleanup(S=1,(G=2;fail),writeq(S+G>B)),B=3,!),100,R).", assert_prolog_success!(&mut wam, "call_with_inference_limit((setup_call_cleanup(S=1,(G=2;fail),writeq(S+G>B)),B=3,!),135,R).",
[["G = 2","B = 3","R = !","S = 1"]]); [["G = 2","B = 3","R = !","S = 1"]]);
assert_prolog_success!(&mut wam, "call_with_inference_limit((setup_call_cleanup(S=1,(G=2;fail),writeq(S+G>B)),B=3,!),10,R).", assert_prolog_success!(&mut wam, "call_with_inference_limit((setup_call_cleanup(S=1,(G=2;fail),writeq(S+G>B)),B=3,!),10,R).",
[["S = _1","G = _4","B = _14","R = inference_limit_exceeded"]]); [["S = _1","G = _4","B = _14","R = inference_limit_exceeded"]]);