]> Repositorios git - scryer-prolog.git/commitdiff
add atts.pl, various fixes
authorMark Thom <[email protected]>
Thu, 31 Jan 2019 04:31:48 +0000 (21:31 -0700)
committerMark Thom <[email protected]>
Thu, 31 Jan 2019 04:31:48 +0000 (21:31 -0700)
12 files changed:
Cargo.lock
Cargo.toml
src/prolog/copier.rs
src/prolog/heap_iter.rs
src/prolog/heap_print.rs
src/prolog/instructions.rs
src/prolog/lib/atts.pl [new file with mode: 0644]
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/system_calls.rs
src/prolog/machine/term_expansion.rs
src/prolog/read.rs
src/prolog/write.rs

index eeba396642bf1a944a0b4e505d69e659b225e67a..7367bf383b22e61b8943e296dc28c9f14d640398 100644 (file)
@@ -86,8 +86,7 @@ dependencies = [
 
 [[package]]
 name = "prolog_parser"
-version = "0.7.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
+version = "0.8.0"
 dependencies = [
  "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -108,12 +107,12 @@ dependencies = [
 
 [[package]]
 name = "rusty-wam"
-version = "0.7.17"
+version = "0.8.0"
 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)",
  "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "prolog_parser 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "prolog_parser 0.8.0",
  "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -152,7 +151,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
 "checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe"
 "checksum ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f"
-"checksum prolog_parser 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "73457bb9d32e6c60048f7cb10f41ed6f9d07053bccd188ff14f79e0af3046789"
 "checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
 "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
index 628aa795969ceccb2012387b2e9b652126059d09..5eb3335cbe2f9e1a44c30b92b96e20852030add8 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "rusty-wam"
-version = "0.7.17"
+version = "0.8.0"
 authors = ["Mark Thom <[email protected]>"]
 repository = "https://github.com/mthom/rusty-wam"
 description = "The Warren Abstract Machine in Rust."
@@ -10,7 +10,7 @@ license = "BSD-3-Clause"
 downcast = "0.9.1"
 num = "0.2"
 ordered-float = "0.5.0"
-prolog_parser = "0.7.22"
+prolog_parser = { version = "0.8.0", path = "../prolog_parser" }
 
 [dependencies.termion]
 version = "1.4.0"
\ No newline at end of file
index 1e08424659b76fd51cf0d1e3f3f905ebdc55ecbf..7efefef1b585a5672d6f8895be1390b987a5e9af 100644 (file)
@@ -100,12 +100,12 @@ pub(crate) trait CopierTarget: IndexMut<usize, Output=HeapCellValue>
 
                             scan += 1;
                         },
-                        Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => {
+                        Addr::AttrVar(..) | Addr::HeapCell(_) | Addr::StackCell(_, _) => {
                             let ra = a;
                             let rd = self.store(self.deref(ra.clone()));
 
                             match rd.clone() {
-                                Addr::AttrVar(h) | Addr::HeapCell(h) if h >= old_h => {
+                                Addr::AttrVar(h, _) | Addr::HeapCell(h) if h >= old_h => {
                                     self[scan] = HeapCellValue::Addr(rd);
                                     scan += 1;
                                 },
index 2b96ff6931578d7e99388a70e28469b9963756bd..eb4dfe611b53e3582ba297442e5b820a9f4143a7 100644 (file)
@@ -65,7 +65,8 @@ impl<'a> HCPreOrderIterator<'a> {
 
                 da
             },
-            Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => da,
+            Addr::HeapCell(_) | Addr::StackCell(_, _) => da,
+            Addr::AttrVar(h, _) => self.follow_heap(h + 1),
             Addr::Str(s) => self.follow_heap(s) // record terms of structure.
         }
     }
index 28e6e48f5f831b102ef307ddd6048351c4838ca2..86f946d01b52a0bdb8a3faa145686de86cf42a5e 100644 (file)
@@ -373,6 +373,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter>
 
     fn offset_as_string(&self, addr: Addr) -> Option<String> {
         match addr {
+            Addr::AttrVar(h, _) =>
+                Some(format!("_{}", h + 1)),
             Addr::HeapCell(h) | Addr::Lis(h) | Addr::Str(h) =>
                 Some(format!("_{}", h)),
             Addr::StackCell(fr, sc) =>
index 88a707a2e1760db102a60522c1c67d63b9370dcb..e2eaed467b332a4ae09ea93ee42e6cdbcb86949f 100644 (file)
@@ -238,9 +238,12 @@ pub struct Module {
 #[derive(Copy, Clone, PartialEq)]
 pub enum SystemClauseType {
     CheckCutPoint,
+    DeleteAttribute,
+    DeleteHeadAttribute,
     DynamicModuleResolution,
     ExpandGoal,
     ExpandTerm,
+    GetAttributedVariableList,
     GetBValue,
     GetSCCCleaner,
     InstallSCCCleaner,
@@ -273,9 +276,12 @@ impl SystemClauseType {
     pub fn name(&self) -> ClauseName {
         match self {
             &SystemClauseType::CheckCutPoint => clause_name!("$check_cp"),
+            &SystemClauseType::DeleteAttribute => clause_name!("$del_attr"),
+            &SystemClauseType::DeleteHeadAttribute => clause_name!("$del_attr_head"),
             &SystemClauseType::DynamicModuleResolution => clause_name!("$module_call"),
             &SystemClauseType::ExpandTerm => clause_name!("$expand_term"),
             &SystemClauseType::ExpandGoal => clause_name!("$expand_goal"),
+            &SystemClauseType::GetAttributedVariableList => clause_name!("$get_attr_list"),
             &SystemClauseType::GetBValue => clause_name!("$get_b_value"),
             &SystemClauseType::GetDoubleQuotes => clause_name!("$get_double_quotes"),
             &SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"),
@@ -311,9 +317,12 @@ impl SystemClauseType {
     pub fn from(name: &str, arity: usize) -> Option<SystemClauseType> {
         match (name, arity) {
             ("$check_cp", 1) => Some(SystemClauseType::CheckCutPoint),
+            ("$del_attr", 1) => Some(SystemClauseType::DeleteAttribute),
+            ("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute),
             ("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution),
             ("$expand_term", 2) => Some(SystemClauseType::ExpandTerm),
             ("$expand_goal", 2) => Some(SystemClauseType::ExpandGoal),
+            ("$get_attr_list", 2) => Some(SystemClauseType::GetAttributedVariableList),
             ("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
             ("$get_double_quotes", 1) => Some(SystemClauseType::GetDoubleQuotes),
             ("$get_scc_cleaner", 1) => Some(SystemClauseType::GetSCCCleaner),
@@ -708,7 +717,7 @@ pub type CodeDeque = VecDeque<Line>;
 
 #[derive(Clone, PartialEq, Eq, Hash)]
 pub enum Addr {
-    AttrVar(usize),
+    AttrVar(usize, usize), // the location of the AttrVal in the heap, the location of the attribute list.
     Con(Constant),
     Lis(usize),
     HeapCell(usize),
@@ -751,14 +760,15 @@ impl PartialOrd<Ref> for Addr {
 impl Addr {
     pub fn is_ref(&self) -> bool {
         match self {
-            &Addr::HeapCell(_) | &Addr::StackCell(_, _) => true,
+            &Addr::AttrVar(..) | &Addr::HeapCell(_) | &Addr::StackCell(_, _) => true,
             _ => false
         }
     }
 
     pub fn as_var(&self) -> Option<Ref> {
         match self {
-            &Addr::HeapCell(hc) => Some(Ref::HeapCell(hc)),
+            &Addr::AttrVar(h, _) => Some(Ref::HeapCell(h)), 
+            &Addr::HeapCell(h) => Some(Ref::HeapCell(h)),
             &Addr::StackCell(fr, sc) => Some(Ref::StackCell(fr, sc)),
             _ => None
         }
@@ -777,7 +787,6 @@ impl Add<usize> for Addr {
 
     fn add(self, rhs: usize) -> Self::Output {
         match self {
-            Addr::AttrVar(a) => Addr::AttrVar(a + rhs),
             Addr::Lis(a) => Addr::Lis(a + rhs),
             Addr::HeapCell(h) => Addr::HeapCell(h + rhs),
             Addr::Str(s) => Addr::Str(s + rhs),
@@ -791,7 +800,6 @@ impl Sub<usize> for Addr {
 
     fn sub(self, rhs: usize) -> Self::Output {
         match self {
-            Addr::AttrVar(a) => Addr::AttrVar(a - rhs),
             Addr::Lis(a) => Addr::Lis(a - rhs),
             Addr::HeapCell(h) => Addr::HeapCell(h - rhs),
             Addr::Str(s) => Addr::Str(s - rhs),
diff --git a/src/prolog/lib/atts.pl b/src/prolog/lib/atts.pl
new file mode 100644 (file)
index 0000000..a202e2d
--- /dev/null
@@ -0,0 +1,119 @@
+:- module(atts, [attribute/1, absent_attr/2, get_attr/2, put_attr/2,
+                absent_from_list/2, get_from_list/2, add_to_list/2,
+                del_attr/3, del_attr_step/2, del_attr_non_head/3]).
+
+:- use_module(library(control)).
+:- use_module(library(dcgs)).
+:- use_module(library(terms)).
+
+:- op(1199, fx, attribute).
+
+absent_attr(V, Attr) :-
+    '$get_attr_list'(V, Ls),
+    absent_from_list(Ls, Attr).
+
+absent_from_list(X, _) :-
+    var(X), !.
+absent_from_list([L|Ls], Attr) :-
+    ( L \= Attr -> absent_from_list(Ls, Attr) ).
+
+get_attr(V, Attr) :-
+    '$get_attr_list'(V, Ls), nonvar(Ls), get_from_list(Ls, Attr).
+
+get_from_list([L|Ls], Attr) :-
+    nonvar(L),
+    ( L \= Attr -> nonvar(Ls), get_from_list(Ls, Attr)
+    ; copy_term(L, L0), L0 = Attr
+    ; get_from_list(Ls, Attr)
+    ).
+
+put_attr(V, Attr) :-
+    '$get_attr_list'(V, Ls), add_to_list(Ls, Attr).
+
+add_to_list(Ls, Attr) :-
+    ( var(Ls) -> Ls = [Attr | _]
+    ; Ls = [_ | Ls0] -> add_to_list(Ls0, Attr)
+    ).
+
+del_attr(Ls0, _, _) :-
+    var(Ls0), !.
+del_attr(Ls0, V, Attr) :-
+    Ls0 = [Att | Ls1],
+    nonvar(Att),
+    ( Att \= Attr -> del_attr_non_head(Ls0, Ls1, Attr)
+    ; '$del_attr_head'(V), del_attr(Ls1, V, Attr)
+    ).
+
+del_attr_step(Ls1, Attr) :-
+    ( nonvar(Ls1) -> Ls1 = [_ | Ls2], del_attr_non_head(Ls1, Ls2, Attr)
+    ; true ).
+
+%% assumptions: Ls0 is a list, Ls1 is its tail;
+%%              the head of Ls0 can be ignored.
+del_attr_non_head(Ls0, Ls1, Attr) :-
+    Ls0 = [_, Att | _],
+    nonvar(Att),
+    !,
+    ( Att \= Attr -> del_attr_step(Ls1, Attr)
+    ; '$del_attr'(Ls0), %% set tail of Ls0 = tail of Ls1. can be undone by backtracking.
+      del_attr_step(Ls1, Attr)
+    ).
+del_attr_non_head(_, _, _).
+
+user:term_expansion(Term0, Terms) :-
+    nonvar(Term0),
+    Term0 = (:- attribute Atts),
+    nonvar(Atts),
+    phrase(put_attrs_var_check, Terms, Terms1),
+    phrase(put_attrs(Atts), Terms1, Terms2),
+    phrase(get_attrs_var_check, Terms2, Terms3),
+    phrase(get_attrs(Atts), Terms3).
+
+put_attrs_var_check -->
+    { numbervars([Var, Attr], 0, _) },
+    [(put_atts(Var, Attr) :- nonvar(Var), throw(error(type_error(variable, Var), put_atts/2))),
+     (put_atts(Var, Attr) :- var(Attr), throw(error(instantiation_error, put_atts/2)))].
+
+get_attrs_var_check -->
+    { numbervars([Var, Attr], 0, _) },
+    [(get_atts(Var, Attr) :- nonvar(Var), throw(error(type_error(variable, Var), get_atts/2))),
+     (get_atts(Var, Attr) :- var(Attr), !, '$get_attr_list'(Var, Attr))].
+
+put_attrs(Name/Arity) -->
+    put_attr(Name, Arity),
+    { numbervars([Var, Attr], 0, _) },
+    [(put_atts(Var, Attr) :- lists:maplist(put_atts(Var), Attr))].
+put_attrs((Name/Arity, Atts)) -->
+    { nonvar(Atts) },
+    put_attr(Name, Arity),
+    put_attrs(Atts).
+
+get_attrs(Name/Arity) -->
+    get_attr(Name, Arity).
+get_attrs((Name/Arity, Atts)) -->
+    { nonvar(Atts) },
+    get_attr(Name, Arity),
+    get_attrs(Atts).
+
+put_attr(Name, Arity) -->
+    { functor(Attr, Name, Arity),
+      numbervars(Attr, 0, Arity),
+      V = '$VAR'(Arity) },
+    [(put_atts(V, +Attr) :- !, functor(Attr, _, _), put_attr(V, Attr)),
+     (put_atts(V,  Attr) :- !, functor(Attr, _, _), put_attr(V, Attr)),
+     (put_atts(V, -Attr) :- !, functor(Attr, _, _), '$get_attr_list'(V, Ls), del_attr(Ls, V, Attr))].
+
+get_attr(Name, Arity) -->
+    { functor(Attr, Name, Arity),
+      numbervars(Attr, 0, Arity),
+      V = '$VAR'(Arity) },
+    [(get_atts(V, +Attr) :- !, functor(Attr, _, _), get_attr(V, Attr)),
+     (get_atts(V,  Attr) :- !, functor(Attr, _, _), get_attr(V, Attr)),
+     (get_atts(V, -Attr) :- !, functor(Attr, _, _), absent_attr(V, Attr))].
+
+user:goal_expansion(Term, [M:put_atts(Var, Attr)]) :-
+    nonvar(Term),
+    Term = put_atts(Var, M, Attr).
+user:goal_expansion(Term, [M:get_atts(Var, Attr)]) :-
+    nonvar(Term),
+    Term = get_atts(Var, M, Attr).
index dae948059806715737cd1f360b31d7141c3cd78a..efe72501a3bc50b48ac69480be7d6744327215eb 100644 (file)
@@ -65,7 +65,7 @@ impl MachineState {
             println!("{} : {}", h, self.heap[h]);
         }
     }
-    
+
     #[inline]
     pub fn machine_flags(&self) -> MachineFlags {
         self.flags
@@ -78,7 +78,7 @@ impl MachineState {
 
     pub(crate) fn store(&self, a: Addr) -> Addr {
         match a {
-            Addr::AttrVar(h)        => self.heap[h+1].as_addr(h+1),
+            Addr::AttrVar(h, _)     => self.heap[h].as_addr(h),
             Addr::HeapCell(h)       => self.heap[h].as_addr(h),
             Addr::StackCell(fr, sc) => self.and_stack[fr][sc].clone(),
             addr                    => addr
@@ -130,7 +130,7 @@ impl MachineState {
     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();
 
@@ -158,7 +158,7 @@ impl MachineState {
     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)
@@ -220,7 +220,7 @@ impl MachineState {
 
             if d1 != d2 {
                 match (self.store(d1.clone()), self.store(d2.clone())) {
-                    (Addr::AttrVar(h), addr) | (addr, Addr::AttrVar(h)) => {
+                    (Addr::AttrVar(h, _), addr) | (addr, Addr::AttrVar(h, _)) => {
                         pdl.push(Addr::HeapCell(h+1));
                         pdl.push(addr);
                     },
@@ -248,7 +248,7 @@ impl MachineState {
                         self.fail = true;
                     },
                     (Addr::Lis(a1), Addr::Con(Constant::String(ref mut s)))
-                  | (Addr::Con(Constant::String(ref mut s)), Addr::Lis(a1))
+                        | (Addr::Con(Constant::String(ref mut s)), Addr::Lis(a1))
                         if self.flags.double_quotes.is_chars() => {
                             if let Some(c) = s.head() {
                                 pdl.push(Addr::Con(Constant::String(s.tail())));
@@ -289,7 +289,7 @@ impl MachineState {
                             self.fail = true;
                         },
                     (Addr::Con(Constant::EmptyList), Addr::Con(Constant::String(ref s)))
-                  | (Addr::Con(Constant::String(ref s)), Addr::Con(Constant::EmptyList))
+                        | (Addr::Con(Constant::String(ref s)), Addr::Con(Constant::EmptyList))
                         if self.flags.double_quotes.is_chars() => {
                             if s.is_expandable() && s.is_empty() {
                                 self.pstr_trail(s.clone());
@@ -309,7 +309,7 @@ impl MachineState {
                     (Addr::Con(Constant::String(ref mut s1)),
                      Addr::Con(Constant::String(ref mut s2))) =>
                         self.fail = !(self.unify_string(&mut pdl, s1, s2)
-                                   || self.unify_string(&mut pdl, s2, s1)),
+                                      || self.unify_string(&mut pdl, s2, s1)),
                     (Addr::Con(ref c1), Addr::Con(ref c2)) =>
                         if c1 != c2 {
                             self.fail = true;
@@ -352,7 +352,7 @@ impl MachineState {
         self.pstr_tr += 1;
     }
 
-    fn trail(&mut self, r: TrailRef) {
+    pub(super) fn trail(&mut self, r: TrailRef) {
         match r {
             TrailRef::HeapCell(h) =>
                 if h < self.hb {
@@ -486,7 +486,7 @@ impl MachineState {
     }
 
     pub(super) fn write_constant_to_var(&mut self, addr: Addr, c: Constant) {
-        match self.store(self.deref(addr)) {            
+        match self.store(self.deref(addr)) {
             Addr::HeapCell(h) => {
                 self.heap[h] = HeapCellValue::Addr(Addr::Con(c.clone()));
                 self.trail(TrailRef::HeapCell(h));
@@ -1168,11 +1168,11 @@ impl MachineState {
                 let addr = self.store(self.deref(a1));
 
                 let offset = match addr {
-                    Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => v,
+                    Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(..) => v,
                     Addr::Con(Constant::String(_)) if self.flags.double_quotes.is_chars() => l,
                     Addr::Con(_) => c,
                     Addr::Lis(_) => l,
-                    Addr::Str(_) => s
+                    Addr::Str(_) => s,
                 };
 
                 match offset {
@@ -1789,6 +1789,17 @@ impl MachineState {
 
                 match d {
                     Addr::HeapCell(_) | Addr::StackCell(..) => self.fail = true,
+                    Addr::AttrVar(h, _) => {
+                        let addr = self.heap[h].as_addr(h);
+
+                        if let Some(_) = addr.as_var() {
+                            if self.store(self.deref(addr)).as_var().is_some() {
+                                self.fail = true;
+                            }
+                        }
+
+                        self.p += 1;
+                    },
                     _ => self.p += 1
                 };
             },
@@ -1797,6 +1808,17 @@ impl MachineState {
 
                 match d {
                     Addr::HeapCell(_) | Addr::StackCell(_,_) => self.p += 1,
+                    Addr::AttrVar(h, _) => {
+                        let addr = self.heap[h].as_addr(h);
+
+                        if let Some(_) = addr.as_var() {
+                            if self.store(self.deref(addr)).as_var().is_none() {
+                                self.fail = true;
+                            }
+                        }
+
+                        self.p += 1;
+                    },
                     _ => self.fail = true
                 };
             },
@@ -1844,7 +1866,7 @@ impl MachineState {
                 },
             Addr::Lis(_) =>
                 self.try_functor_compound_case(clause_name!("."), 2),
-            Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(..) => {
+            Addr::AttrVar(..) | Addr::HeapCell(_) | Addr::StackCell(..) => {
                 let name  = self.store(self.deref(self[temp_v!(2)].clone()));
                 let arity = self.store(self.deref(self[temp_v!(3)].clone()));
 
index 5de4f3970dae9618a960eb8827af13bd5df7650b..46dede2932d9dc66d4605cf33e44c108033df3ff 100644 (file)
@@ -203,6 +203,36 @@ impl MachineState {
                     _ => self.fail = true
                 };
             },
+            &SystemClauseType::DeleteAttribute => {
+                let ls0 = self.store(self.deref(self[temp_v!(1)].clone()));
+
+                if let Addr::Lis(l1) = ls0 {
+                    if let Addr::Lis(l2) = self.store(self.deref(Addr::HeapCell(l1 + 1))) {
+                        let addr = self.heap[l1 + 1].as_addr(l1 + 1);                        
+                        self.heap[l1 + 1] = HeapCellValue::Addr(Addr::HeapCell(l2 + 1));
+                        self.trail(TrailRef::AttrVarLink(l2 + 1, addr));
+                    }
+                }                
+            },
+            &SystemClauseType::DeleteHeadAttribute => {
+                let addr = self.store(self.deref(self[temp_v!(1)].clone()));
+                
+                match addr {
+                    Addr::AttrVar(_, attr_var) => {
+                        let addr = self.heap[attr_var].as_addr(attr_var).clone();
+                        let addr = self.store(self.deref(addr));
+                        
+                        match addr {
+                            Addr::Lis(l) => {
+                                self.heap[attr_var] = HeapCellValue::Addr(Addr::HeapCell(l+1));
+                                self.trail(TrailRef::AttrVarLink(attr_var, Addr::Lis(l)));
+                            },
+                            _ => {}
+                        }
+                    },
+                    _ => {}
+                }
+            },
             &SystemClauseType::DynamicModuleResolution => {
                 let module_name = self.store(self.deref(self[temp_v!(1)].clone()));
 
@@ -213,14 +243,14 @@ impl MachineState {
                                 for i in 1 .. arity + 1 {
                                     self.registers[i] = self.heap[a+i].as_addr(a+i);
                                 }
-                                
+
                                 return self.module_lookup(indices, (name, arity), module_name, true);
                             },
                         Addr::Con(Constant::Atom(name, _)) =>
                             return self.module_lookup(indices, (name, 0), module_name, true),
                         addr => {
                             let stub = MachineError::functor_stub(clause_name!("(:)"), 2);
-                            
+
                             let type_error = MachineError::type_error(ValidType::Callable, addr);
                             let type_error = self.error_form(type_error, stub);
 
@@ -237,6 +267,40 @@ impl MachineState {
                 self.p = CodePtr::Local(LocalCodePtr::UserTermExpansion(0));
                 return Ok(());
             },
+            &SystemClauseType::GetAttributedVariableList => {
+                let attr_var = self.store(self.deref(self[temp_v!(1)].clone()));
+                let mut attr_var_list = match attr_var {
+                    Addr::AttrVar(_, attr_var_list) => attr_var_list,
+                    attr_var @ Addr::HeapCell(_) | attr_var @ Addr::StackCell(..) => {
+                        // create an AttrVar in the heap.
+                        let h = self.heap.h;
+                        
+                        self.heap.push(HeapCellValue::Addr(Addr::AttrVar(h, h + 2)));
+                        self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h + 1)));
+                        self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h + 2)));
+
+                        match attr_var.as_var().unwrap() {
+                            Ref::HeapCell(r) => {
+                                self.heap[r] = HeapCellValue::Addr(Addr::HeapCell(h));
+                                self.trail(TrailRef::HeapCell(r));
+                            },
+                            Ref::StackCell(fr, sc) => {
+                                self.and_stack[fr][sc] = Addr::HeapCell(h);
+                                self.trail(TrailRef::StackCell(fr, sc));
+                            }
+                        }
+
+                        h + 2
+                    },
+                    _ => {
+                        self.fail = true;
+                        return Ok(());
+                    }
+                };
+
+                let list_var = self[temp_v!(2)].clone();
+                self.unify(Addr::HeapCell(attr_var_list), list_var);
+            },
             &SystemClauseType::GetDoubleQuotes => {
                 let a1 = self[temp_v!(1)].clone();
 
index 850786e0cdb7107921cb1f4569f99f56ec07c03d..2106895ad3749ddc3f320a1e6d84eb4ebca14fad 100644 (file)
@@ -196,7 +196,7 @@ impl<'a, R: Read> TermStream<'a, R> {
     fn parse_expansion_output(&mut self, term_string: &str, op_dir: &OpDir)
                               -> Result<Term, ParserError>
     {
-        let mut parser = Parser::new(term_string.trim().as_bytes(), self.indices.atom_tbl.clone(),
+        let mut parser = Parser::new(term_string.trim().as_bytes(), self.parser.get_atom_tbl(),
                                      self.flags);
         parser.read_term(composite_op!(self.in_module, &self.indices.op_dir, op_dir))
     }
@@ -288,6 +288,18 @@ impl<'a, R: Read> TermStream<'a, R> {
 }
 
 impl MachineState {
+    fn print_with_locs(&self, target: usize, var_dict: &HeapVarDict) -> PrinterOutputter {
+        let output = PrinterOutputter::new();
+        let mut printer = HCPrinter::from_heap_locs(&self, output, &var_dict);
+
+        printer.quoted = true;
+        printer.numbervars = true;
+
+        printer.see_all_locs();
+
+        printer.print(Addr::HeapCell(target))
+    }
+
     fn try_expand_term(&mut self, indices: &mut IndexStore, policies: &mut MachinePolicies,
                        code_repo: &mut CodeRepo, term: &Term, hook: CompileTimeHook)
                        -> Option<String>
@@ -308,17 +320,7 @@ impl MachineState {
             self.reset();
             None
         } else {
-            let mut output  = {
-                let output = PrinterOutputter::new();
-                let mut printer = HCPrinter::from_heap_locs(&self, output, &var_dict);
-
-                printer.quoted = true;
-                printer.numbervars = true;
-
-                printer.see_all_locs();
-
-                printer.print(Addr::HeapCell(h))
-            };
+            let mut output = self.print_with_locs(h, &var_dict);
 
             output.push_char('.');
             self.reset();
index 3b6053c0485e42568d42e6fc7165d4ae3afba55c..891280ad3b794bb522a1149bec03f76358eed793 100644 (file)
@@ -31,7 +31,7 @@ pub enum Input {
     Term(Term)
 }
 
-pub fn read_toplevel(wam: &mut Machine) -> Result<Input, ParserError> {    
+pub fn read_toplevel(wam: &mut Machine) -> Result<Input, ParserError> {
     let mut buffer = String::new();
 
     let stdin = stdin();
@@ -48,7 +48,7 @@ pub fn read_toplevel(wam: &mut Machine) -> Result<Input, ParserError> {
             let mut term_stream = TermStream::new(stdin.lock(), wam.indices.atom_tbl.clone(),
                                                   wam.machine_flags(), &mut wam.indices,
                                                   &mut wam.policies, &mut wam.code_repo);
-            
+
             term_stream.add_to_top(buffer.as_str());
             Ok(Input::Term(term_stream.read_term(&mut wam.machine_st, &OpDir::new())?))
         }
index 9b5004b21c771a5834593cc43cdcd632c5d74c1b..1b6bf0c1fb90c8c785164852361fc4d86169606f 100644 (file)
@@ -146,7 +146,7 @@ impl fmt::Display for Addr {
         match self {
             &Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
             &Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
-            &Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
+            &Addr::AttrVar(h, attr_var_list) => write!(f, "Addr::AttrVar({}, {})", h, attr_var_list),
             &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)