]> Repositorios git - scryer-prolog.git/commitdiff
add variable_names as a write option
authorMark Thom <[email protected]>
Sun, 5 May 2019 04:58:56 +0000 (00:58 -0400)
committerMark Thom <[email protected]>
Sun, 5 May 2019 04:58:56 +0000 (00:58 -0400)
src/prolog/clause_types.rs
src/prolog/heap_print.rs
src/prolog/lib/builtins.pl
src/prolog/machine/attributed_variables.rs
src/prolog/machine/machine_errors.rs
src/prolog/machine/machine_state.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/mod.rs
src/prolog/machine/system_calls.rs
src/prolog/machine/term_expansion.rs
src/tests.rs

index f5c504df1279d37f210daa189f928367ae6060e8..5a5c67b29d483949d830177bb9710580fed79408 100644 (file)
@@ -410,7 +410,7 @@ impl SystemClauseType {
             ("$unwind_stack", 0) => Some(SystemClauseType::UnwindStack),
             ("$unify_with_occurs_check", 2) => Some(SystemClauseType::UnifyWithOccursCheck),
             ("$variant", 2) => Some(SystemClauseType::Variant),
-            ("$write_term", 4) => Some(SystemClauseType::WriteTerm),
+            ("$write_term", 5) => Some(SystemClauseType::WriteTerm),
             _ => None
         }
     }
index 286631e615595c180b28bfd3260f655d79a425a1..0f1229a6eb52ccd51a824e46aa516bbaa57caa68 100644 (file)
@@ -290,15 +290,16 @@ impl MachineState {
 type ReverseHeapVarDict = HashMap<Addr, Rc<Var>>;
 
 pub struct HCPrinter<'a, Outputter> {
-    outputter:    Outputter,
-    machine_st:   &'a MachineState,
+    outputter: Outputter,
+    machine_st: &'a MachineState,
     op_dir: &'a OpDir,
-    state_stack:  Vec<TokenOrRedirect>,
+    state_stack: Vec<TokenOrRedirect>,
     toplevel_spec: Option<DirectedOp>,
-    heap_locs:    ReverseHeapVarDict,
+    heap_locs: ReverseHeapVarDict,
     printed_vars: HashSet<Addr>,
     last_item_idx: usize,
     cyclic_terms: HashMap<Addr, usize>,
+    pub(crate) var_names: HashMap<Addr, String>,
     pub(crate) numbervars_offset: BigInt,
     pub(crate) numbervars:   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)
-                         -> ReverseHeapVarDict
+fn reverse_heap_locs<'a>(machine_st: &'a MachineState) -> 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())
     }).collect()
 }
@@ -414,17 +414,17 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
                     numbervars_offset: BigInt::zero(),
                     quoted: 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,
-                          heap_locs: &'a HeapVarDict)
+    pub fn from_heap_locs(machine_st: &'a MachineState, op_dir: &'a OpDir, output: Outputter)
                           -> Self
     {
         let mut printer = Self::new(machine_st, op_dir, output);
 
         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
     }
@@ -577,8 +577,18 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
         self.last_item_idx = self.outputter.len();
         self.outputter.append(s);
     }
+    
+    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;
+            }
+        }
 
-    fn offset_as_string(&self, addr: Addr) -> Option<String> {
         match addr {
             Addr::AttrVar(h) =>
                 Some(format!("_{}", h + 1)),
@@ -894,7 +904,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
                     self.push_list();
                 },
             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, {
                         self.append_str(offset_str.as_str());
                     })
index f1f986bf6bc54339a238b08309d3912d6877d7ba..d573e3ea028735dc0e97c7898bcaa081bd92aa37 100644 (file)
@@ -220,22 +220,41 @@ is_write_option(Functor) :-
     Functor =.. [Name, Arg],
     ( Arg == true -> true
     ; Arg == false -> true
+    ; Name == variable_names -> must_be_var_names_list(Arg)             
     ; var(Arg) -> throw(error(instantiation_error, write_term/2))
     ; throw(error(domain_error(write_option, Functor), write_term/2))
     ), % 8.14.2.3 e)
     ( Name == ignore_ops -> true
     ; Name == quoted -> true
     ; Name == numbervars -> true
+    ; Name == variable_names -> true
     ; throw(error(domain_error(write_option, Functor), write_term/2))
     ). % 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))
-    ;  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))
     ).
 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) :-
     var(Options), throw(error(instantiation_error, write_term/2)).
 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, numbervars(NumberVars), numbervars(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)]).
 
@@ -605,8 +625,8 @@ module_abolish(Pred, Module) :-
        (  var(Name)  -> throw(error(instantiation_error, abolish/1))
        ;  integer(Arity) ->
          ( \+ atom(Name) -> throw(error(type_error(atom, Name), abolish/1))
-         ; Arity < 0 -> throw(domain_error(not_less_than_zero, Arity), abolish/1)
-         ; max_arity(N), Arity > N -> throw(representation_error(max_arity), abolish/1)
+         ; Arity < 0 -> throw(error(domain_error(not_less_than_zero, Arity), abolish/1))
+         ; max_arity(N), Arity > N -> throw(error(representation_error(max_arity), abolish/1))
          ; functor(Head, Name, Arity) ->
            (  '$module_head_is_dynamic'(Head, Module) ->
               '$abolish_module_clause'(Name, Arity, Module)
@@ -626,8 +646,8 @@ abolish(Pred) :-
        ;  var(Arity) -> throw(error(instantiation_error, abolish/1))
        ;  integer(Arity) ->
          ( \+ atom(Name) -> throw(error(type_error(atom, Name), abolish/1))
-         ; Arity < 0 -> throw(domain_error(not_less_than_zero, Arity), abolish/1)
-         ; max_arity(N), Arity > N -> throw(representation_error(max_arity), abolish/1)
+         ; Arity < 0 -> throw(error(domain_error(not_less_than_zero, Arity), abolish/1))
+         ; max_arity(N), Arity > N -> throw(error(representation_error(max_arity), abolish/1))
          ; functor(Head, Name, Arity) ->
            (  '$no_such_predicate'(Head) -> true
            ;  '$head_is_dynamic'(Head) -> '$abolish_clause'(Name, Arity)
index ba21dd4323ef966479e59af38709dcb527b3bf48..600d2173bc79901642001e3051556be5e8e776da 100644 (file)
@@ -85,12 +85,12 @@ impl MachineState {
         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 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());
 
             for value in iter {
@@ -140,7 +140,7 @@ impl MachineState {
         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![]);
 
@@ -154,7 +154,7 @@ impl MachineState {
         let mut output = PrinterOutputter::new();
 
         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.numbervars = false;
@@ -174,10 +174,10 @@ impl MachineState {
 
 impl Machine {
     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 (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);
 
@@ -188,6 +188,6 @@ impl Machine {
         self.machine_st.query_stepper(&mut self.indices, &mut self.policies, &mut self.code_repo,
                                       &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)
     }
 }
index e9eb56f3e59994c4aca9d98f841fbb10235e69d1..c2a7e336521055cd5f11fe68b8183f0c9f54586d 100644 (file)
@@ -391,7 +391,7 @@ pub enum SessionError {
 pub enum EvalSession {
     EntrySuccess,
     Error(SessionError),
-    InitialQuerySuccess(AllocVarDict, HeapVarDict),
+    InitialQuerySuccess(AllocVarDict),
     QueryFailure,
     SubsequentQuerySuccess,
 }
index 50eb4c11f6481a999718c94c637c3e5abb3144a2..82f8126fc7dbe38c91f8f65f0b055e2d4da3d3db 100644 (file)
@@ -235,6 +235,7 @@ pub struct MachineState {
     pub(super) lifted_heap: Vec<HeapCellValue>,
     pub(super) interms: Vec<Number>, // intermediate numbers.
     pub(super) last_call: bool,
+    pub(crate) heap_locs: HeapVarDict,
     pub(crate) flags: MachineFlags
 }
 
index 8bcfde78928a8d05032ca464aa4fb549922b1d5f..f790b980c513631d71a43d68332c3515b52bc14f 100644 (file)
@@ -64,6 +64,7 @@ impl MachineState {
             lifted_heap: Vec::with_capacity(1024),
             interms: vec![Number::default(); 256],
             last_call: false,
+            heap_locs: HeapVarDict::new(),
             flags: MachineFlags::default()
         }
     }
@@ -94,6 +95,7 @@ impl MachineState {
             lifted_heap: Vec::with_capacity(capacity),
             interms: vec![Number::default(); 0],
             last_call: false,
+            heap_locs: HeapVarDict::new(),
             flags: MachineFlags::default()
         }
     }
@@ -187,8 +189,7 @@ impl MachineState {
     }
 
     pub(super)
-    fn print_var_eq<Outputter>(&self, var: Rc<Var>, addr: Addr, op_dir: &OpDir, var_dict: &HeapVarDict,
-                               mut output: Outputter)
+    fn print_var_eq<Outputter>(&self, var: Rc<Var>, addr: Addr, op_dir: &OpDir, mut output: Outputter)
                                -> Outputter
       where Outputter: HCValueOutputter
     {
@@ -199,7 +200,7 @@ impl MachineState {
         output.append(var.as_str());
         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.quoted = true;
@@ -2816,6 +2817,7 @@ impl MachineState {
         self.block = 0;
 
         self.ball.reset();
+        self.heap_locs.clear();
         self.lifted_heap.clear();
     }
 
index d076ea8bd0c014bf54a98d1babad19af708e7562..4b2a4e63971821f22c7749fef30beea144928f12 100644 (file)
@@ -217,7 +217,7 @@ impl Machine {
 
     pub fn run_toplevel(&mut self) {
         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 {
@@ -316,41 +316,13 @@ impl Machine {
 
     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.run_query(&alloc_locs, &mut heap_locs);
+        self.run_query(&alloc_locs);
 
         if self.machine_st.fail {
             EvalSession::QueryFailure
         } else {
-            EvalSession::InitialQuerySuccess(alloc_locs, heap_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);
-                    }
-                },
-                _ => {}
-            }
+            EvalSession::InitialQuerySuccess(alloc_locs)
         }
     }
 
@@ -413,8 +385,9 @@ impl Machine {
                             };
                         }
 
-                        let term_output = self.machine_st.print_query(term, &self.indices.op_dir,
-                                                                      &var_dict);
+                        self.machine_st.heap_locs = var_dict;
+                        let term_output = self.machine_st.print_query(term, &self.indices.op_dir);
+                        
                         term_output.result()
                     },
                     Err(err_stub) => {
@@ -454,14 +427,14 @@ impl Machine {
 
     fn handle_eval_session(&mut self, result: EvalSession, snapshot: MachineState) {
         match result {
-            EvalSession::InitialQuerySuccess(alloc_locs, mut heap_locs) =>
+            EvalSession::InitialQuerySuccess(alloc_locs) =>
                 loop {
                     let bindings = {
                         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 bindings.is_empty() {
@@ -499,7 +472,7 @@ impl Machine {
                         let result = match next_keypress() {
                             ContinueResult::ContinueQuery => {
                                 write!(raw_stdout, " ;\r\n").unwrap();
-                                self.continue_query(&alloc_locs, &mut heap_locs)
+                                self.continue_query(&alloc_locs)
                             },
                             ContinueResult::Conclude => {
                                 write!(raw_stdout, " ...\r\n").unwrap();
@@ -563,7 +536,7 @@ impl Machine {
     }
 
     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());
 
@@ -571,7 +544,7 @@ impl Machine {
             if let CodePtr::Local(LocalCodePtr::TopLevel(mut cn, p)) = self.machine_st.p {
                 match &self.code_repo[LocalCodePtr::TopLevel(cn, p)] {
                     &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;
                     },
                     _ => {}
@@ -595,8 +568,8 @@ impl Machine {
                     self.dynamic_transaction(trans_type, p);
 
                     if let CodePtr::Local(LocalCodePtr::TopLevel(_, 0)) = self.machine_st.p {
-                        if heap_locs.is_empty() {
-                            self.record_var_places(0, alloc_locs, heap_locs);
+                        if self.machine_st.heap_locs.is_empty() {
+                            self.machine_st.record_var_places(0, alloc_locs);
                         }
 
                         self.code_repo.cached_query = cached_query;
@@ -606,8 +579,8 @@ impl Machine {
                     self.code_repo.cached_query = cached_query;
                 },
                 _ => {
-                    if heap_locs.is_empty() {
-                        self.record_var_places(0, alloc_locs, heap_locs);
+                    if self.machine_st.heap_locs.is_empty() {
+                        self.machine_st.record_var_places(0, alloc_locs);
                     }
 
                     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() {
             let b = self.machine_st.b - 1;
@@ -627,7 +600,7 @@ impl Machine {
                 return EvalSession::QueryFailure;
             }
 
-            self.run_query(alloc_l, heap_l);
+            self.run_query(alloc_locs);
 
             if self.machine_st.fail {
                 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
     {
-        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);
 
         for (var, addr) in sorted_vars {
             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);
         }
 
@@ -655,16 +628,15 @@ impl Machine {
     }
 
     #[cfg(test)]
-    pub fn test_heap_view<Outputter>(&self, var_dir: &HeapVarDict, mut output: Outputter)
-                                     -> Outputter
+    pub fn test_heap_view<Outputter>(&self, mut output: Outputter) -> Outputter
        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);
 
         for (var, addr) in sorted_vars {
             output = self.machine_st.print_var_eq(var.clone(), addr.clone(), &self.indices.op_dir,
-                                                  var_dir, output);
+                                                  output);
         }
 
         output
@@ -677,7 +649,32 @@ impl Machine {
 
 
 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;
         
@@ -685,7 +682,7 @@ impl MachineState {
             self.flags = MachineFlags { double_quotes: DoubleQuotes::Atom };
             
             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.numbervars = false;
index 8230950c746efa534040b0e531dea641549d3ee1..a9cd571b54b2b249fb2cdfb61597d7d39852ce2d 100644 (file)
@@ -18,7 +18,7 @@ use prolog::read::{PrologStream, readline};
 
 use ref_thread_local::RefThreadLocal;
 
-use std::collections::HashSet;
+use std::collections::{HashMap, HashSet};
 use std::io::{stdout, Write};
 use std::iter::once;
 use std::mem;
@@ -356,7 +356,7 @@ impl MachineState {
                                 -> CallResult
     {
         let nx  = self[temp_v!(2)].clone();
-        
+
         if let Some(c) = string.chars().last() {
             if layout_char!(c) {
                 let err = ParserError::UnexpectedChar(c);
@@ -555,7 +555,7 @@ impl MachineState {
 
                 self.unify(a2, Addr::Con(Constant::Number(len)));
             },
-            &SystemClauseType::CharsToNumber => {                
+            &SystemClauseType::CharsToNumber => {
                 let stub = MachineError::functor_stub(clause_name!("number_chars"), 2);
 
                 match self.try_from_list(temp_v!(1), stub.clone()) {
@@ -585,7 +585,7 @@ impl MachineState {
                 let char_list = Addr::HeapCell(self.heap.to_list(chars));
 
                 self.unify(char_list, chs);
-            },            
+            },
             &SystemClauseType::NumberToCodes => {
                 let n = self[temp_v!(1)].clone();
                 let chs = self[temp_v!(2)].clone();
@@ -1666,6 +1666,47 @@ impl MachineState {
                     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);
                 print!("{}", output.result());
                 stdout().flush().unwrap();
index f2d952fff9b0cda9b7dc87265fe043f72750002e..fdd28c575c461c760b9563868daa2059773ec5a7 100644 (file)
@@ -289,13 +289,13 @@ impl<'a, R: Read> TermStream<'a, R> {
 
 impl MachineState {
     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 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;
 
-        for var in var_dict.keys() {
+        for var in self.heap_locs.keys() {
             max_var_length = std::cmp::max(var.len(), max_var_length);
         }
 
@@ -337,8 +337,10 @@ impl MachineState {
             self.reset();
             None
         } else {
-            let &TermWriteResult { heap_loc: _, ref var_dict } = &term_write_result;
-            let output = self.print_with_locs(Addr::HeapCell(h), &indices.op_dir, var_dict);
+            let TermWriteResult { var_dict, .. } = term_write_result;
+            
+            self.heap_locs = var_dict;
+            let output = self.print_with_locs(Addr::HeapCell(h), &indices.op_dir);
 
             self.reset();
             Some(output.result())
index 338ff52850f7f84da61422af78a75b58b5093d1e..2df7406b372df41698e855ab7b76d8f8e19af2fc 100644 (file)
@@ -84,30 +84,27 @@ impl HCValueOutputter for TestOutputter {
     }
 }
 
-pub fn collect_test_output(wam: &mut Machine, alloc_locs: AllocVarDict, mut heap_locs: HeapVarDict)
-                           -> Vec<HashSet<String>>
+pub fn collect_test_output(wam: &mut Machine, alloc_locs: AllocVarDict) -> Vec<HashSet<String>>
 {
     let mut output = TestOutputter::new();
 
-    output = wam.test_heap_view(&heap_locs, output);
+    output = wam.test_heap_view(output);
     output.cache();
 
-    while let EvalSession::SubsequentQuerySuccess = wam.continue_query(&alloc_locs, &mut heap_locs)
-    {
-        output = wam.test_heap_view(&heap_locs, output);
+    while let EvalSession::SubsequentQuerySuccess = wam.continue_query(&alloc_locs) {
+        output = wam.test_heap_view(output);
         output.cache();
     }
 
     output.result()
 }
 
-pub fn collect_test_output_with_limit(wam: &mut Machine, alloc_locs: AllocVarDict,
-                                      mut heap_locs: HeapVarDict, limit: usize)
+pub fn collect_test_output_with_limit(wam: &mut Machine, alloc_locs: AllocVarDict, limit: usize)                                      
                                       -> Vec<HashSet<String>>
 {
     let mut output = TestOutputter::new();
 
-    output = wam.test_heap_view(&heap_locs, output);
+    output = wam.test_heap_view(output);
     output.cache();
 
     let mut count  = 1;
@@ -116,9 +113,9 @@ pub fn collect_test_output_with_limit(wam: &mut Machine, alloc_locs: AllocVarDic
         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();
 
         count += 1;
@@ -137,7 +134,7 @@ pub fn submit(wam: &mut Machine, buffer: &str) -> bool
     wam.reset();
 
     match submit_code(wam, buffer) {
-        EvalSession::InitialQuerySuccess(_, _) |
+        EvalSession::InitialQuerySuccess(_) |
         EvalSession::EntrySuccess |
         EvalSession::SubsequentQuerySuccess =>
             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) {
         Ok(term) =>
             match compile_term(wam, term) {
-                EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
-                    result == collect_test_output(wam, alloc_locs, heap_locs),
+                EvalSession::InitialQuerySuccess(alloc_locs) =>
+                    result == collect_test_output(wam, alloc_locs),
                 EvalSession::EntrySuccess => true,
                 _ => 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) {
         Ok(term) =>
             match compile_term(wam, term) {
-                EvalSession::InitialQuerySuccess(alloc_locs, heap_locs) =>
-                    result == collect_test_output_with_limit(wam, alloc_locs,
-                                                             heap_locs, limit),
+                EvalSession::InitialQuerySuccess(alloc_locs) =>
+                    result == collect_test_output_with_limit(wam, alloc_locs, limit),
                 EvalSession::EntrySuccess => true,
                 _ => false
             },
@@ -1673,7 +1669,7 @@ fn test_queries_on_builtins()
 
     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"]]);
     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"]]);