]> Repositorios git - scryer-prolog.git/commitdiff
add db refs
authorMark Thom <[email protected]>
Thu, 28 Mar 2019 05:00:59 +0000 (23:00 -0600)
committerMark Thom <[email protected]>
Thu, 28 Mar 2019 05:00:59 +0000 (23:00 -0600)
src/prolog/clause_types.rs
src/prolog/heap_iter.rs
src/prolog/lib/builtins.pl
src/prolog/machine/copier.rs
src/prolog/machine/machine_indices.rs
src/prolog/machine/machine_state_impl.rs
src/prolog/machine/system_calls.rs
src/prolog/write.rs

index 537605b4055a6d0a5461956d075a25aeffd89d25..405a6106522df339510f5c4fc8dbc30c5b1f0d53 100644 (file)
@@ -86,7 +86,7 @@ pub enum InlinedClauseType {
 }
 
 ref_thread_local! {
-    static managed CLAUSE_TYPE_FORMS: BTreeMap<(&'static str, usize), ClauseType> = {
+    pub static managed CLAUSE_TYPE_FORMS: BTreeMap<(&'static str, usize), ClauseType> = {
         let mut m = BTreeMap::new();
 
         let r1 = temp_v!(1);
@@ -180,8 +180,9 @@ pub enum SystemClauseType {
     GetAttrVarQueueBeyond,
     GetBValue,
     GetClause,
-    GetCurrentPredicateList,
     GetModuleClause,
+    GetNextDBRef,
+    LookupDBRef,
     Halt,
     ModuleHeadIsDynamic,
     GetLiftedHeapFromOffset,
@@ -251,9 +252,10 @@ impl SystemClauseType {
             &SystemClauseType::GetAttrVarQueueBeyond => clause_name!("$get_attr_var_queue_beyond"),
             &SystemClauseType::GetLiftedHeapFromOffset => clause_name!("$get_lh_from_offset"),
             &SystemClauseType::GetLiftedHeapFromOffsetDiff => clause_name!("$get_lh_from_offset_diff"),
-            &SystemClauseType::GetCurrentPredicateList => clause_name!("$get_current_predicate_list"),
             &SystemClauseType::GetBValue => clause_name!("$get_b_value"),
             &SystemClauseType::GetClause => clause_name!("$get_clause"),
+            &SystemClauseType::GetNextDBRef => clause_name!("$get_next_db_ref"),
+            &SystemClauseType::LookupDBRef => clause_name!("$lookup_db_ref"),
             &SystemClauseType::GetDoubleQuotes => clause_name!("$get_double_quotes"),
             &SystemClauseType::GetModuleClause => clause_name!("$get_module_clause"),
             &SystemClauseType::GetSCCCleaner => clause_name!("$get_scc_cleaner"),
@@ -309,6 +311,8 @@ impl SystemClauseType {
             ("$copy_to_lh", 2) => Some(SystemClauseType::CopyToLiftedHeap),
             ("$del_attr_non_head", 1) => Some(SystemClauseType::DeleteAttribute),
             ("$del_attr_head", 1) => Some(SystemClauseType::DeleteHeadAttribute),
+            ("$get_next_db_ref", 2) => Some(SystemClauseType::GetNextDBRef),
+            ("$lookup_db_ref", 3) => Some(SystemClauseType::LookupDBRef),
             ("$module_call", 2) => Some(SystemClauseType::DynamicModuleResolution),
             ("$enqueue_attribute_goal", 1) => Some(SystemClauseType::EnqueueAttributeGoal),
             ("$enqueue_attr_var", 1) => Some(SystemClauseType::EnqueueAttributedVar),
@@ -321,7 +325,6 @@ impl SystemClauseType {
             ("$get_b_value", 1) => Some(SystemClauseType::GetBValue),
             ("$get_clause", 2) => Some(SystemClauseType::GetClause),
             ("$get_module_clause", 3) => Some(SystemClauseType::GetModuleClause),
-            ("$get_current_predicate_list", 1) => Some(SystemClauseType::GetCurrentPredicateList),
             ("$get_lh_from_offset", 2) => Some(SystemClauseType::GetLiftedHeapFromOffset),
             ("$get_lh_from_offset_diff", 3) => Some(SystemClauseType::GetLiftedHeapFromOffsetDiff),
             ("$get_double_quotes", 1) => Some(SystemClauseType::GetDoubleQuotes),
index 7f32c1bf2f343c7f67997f1f6a7b53a374338949..a5bf3d256e6da4f3ffdcd6bd64afbf4733e99c2a 100644 (file)
@@ -47,7 +47,7 @@ impl<'a> HCPreOrderIterator<'a> {
     {
         let da = self.machine_st.store(self.machine_st.deref(addr));
 
-        match da {
+        match da {            
             Addr::Con(Constant::String(ref s))
                 if self.machine_st.machine_flags().double_quotes.is_chars() => {
                     if let Some(c) = s.head() {
@@ -59,7 +59,7 @@ impl<'a> HCPreOrderIterator<'a> {
 
                     Addr::Con(Constant::String(s.clone()))
                 },
-            Addr::Con(_) => da,
+            Addr::Con(_) | Addr::DBRef(_) => da,
             Addr::Lis(a) => {
                 self.state_stack.push(Addr::HeapCell(a + 1));
                 self.state_stack.push(Addr::HeapCell(a));
index ff7a6a7102a7a58a230c6c3713e5fbf0ab099b26..c429d65daf047d33219f970f5d3506d2a091774c 100644 (file)
@@ -682,58 +682,20 @@ abolish(Pred) :-
     ;  throw(error(type_error(predicate_indicator, Pred), abolish/1))
     ).
 
-match_builtins(acyclic_term, 1).
-match_builtins(arg, 3).
-match_builtins(compare, 3).
-match_builtins(cyclic_term, 1).
-match_builtins(@>, 2).
-match_builtins(@<, 2).
-match_builtins(@>=, 2).
-match_builtins(@=<, 2).
-match_builtins(\=@=, 2).
-match_builtins(=@=, 2).
-match_builtins(copy_term, 2).
-match_builtins(==, 2).
-match_builtins(functor, 3).
-match_builtins(ground, 1).
-match_builtins(is, 2).
-match_builtins(keysort, 2).
-match_builtins(nl, 0).
-match_builtins(\==, 2).
-match_builtins(is_partial_string, 1).
-match_builtins(partial_string, 2).
-match_builtins(read, 1).
-match_builtins(sort, 2).
-match_builtins(>, 2).
-match_builtins(<, 2).
-match_builtins(>=, 2).
-match_builtins(=<, 2).
-match_builtins(=\=, 2).
-match_builtins(=:=, 2).
-match_builtins(atom, 1).
-match_builtins(atomic, 1).
-match_builtins(compound, 1).
-match_builtins(integer, 1).
-match_builtins(rational, 1).
-match_builtins(string, 1).
-match_builtins(float, 1).
-match_builtins(nonvar, 1).
-match_builtins(var, 1).
-match_builtins(call, N) :-
-    max_arity(Max),
-    between:between(0, Max, N).
-
-'$iterate_predicate_list'([Name/Arity|Preds], Name/Arity).
-'$iterate_predicate_list'([_|Preds], Pred) :-
-    '$iterate_predicate_list'(Preds, Pred).
-'$iterate_predicate_list'([], Name/Arity) :-
-    match_builtins(Name, Arity).
+'$iterate_db_refs'(Ref, Name/Arity) :-
+    '$lookup_db_ref'(Ref, Name, Arity).
+'$iterate_db_refs'(Ref, Name/Arity) :-
+    '$get_next_db_ref'(Ref, NextRef),
+    '$iterate_db_refs'(NextRef, Name/Arity).
 
 current_predicate(Pred) :-
     (  nonvar(Pred), Pred \= _ / _
-    -> throw(error(type_error(predicate_indicator,Pred), current_predicate/1))
-    ;  '$get_current_predicate_list'(Ls),
-       '$iterate_predicate_list'(Ls, Pred)
+    -> throw(error(type_error(predicate_indicator, Pred), current_predicate/1))
+    ;  '$get_next_db_ref'(Ref, _),
+       '$iterate_db_refs'(Ref, Pred)
+    ;  Pred = call/N,
+       max_arity(Max),
+       between:between(0, Max, N)
     ).
 
 bb_put(Key, Value) :- atom(Key), !, '$store_global_var'(Key, Value).
index edb540426d60dc9af912b78db39edd9a87b8798a..7f87e937d3f12d3a5f1bea615840cd694a9e0d5f 100644 (file)
@@ -184,7 +184,7 @@ impl<T: CopierTarget> CopyTermState<T> {
                             self.copy_var(addr),
                         Addr::Str(addr) =>
                             self.copy_structure(addr),
-                        Addr::Con(_) =>
+                        Addr::Con(_) | Addr::DBRef(_) =>
                             self.scan += 1
                     }
             }
index d88090b1a4d07102131a285a66738d5efcaa3e94..d9e6941161eab29645dfb70957e6aa633dc0a6b2 100644 (file)
@@ -7,15 +7,22 @@ use prolog::forms::*;
 
 use std::cell::RefCell;
 use std::cmp::Ordering;
-use std::collections::{HashMap, VecDeque};
+use std::collections::{BTreeMap, HashMap, VecDeque};
 use std::mem;
 use std::ops::{Add, AddAssign, Sub, SubAssign};
 use std::rc::Rc;
 
+#[derive(Clone, PartialEq, Eq, Hash)]
+pub enum DBRef {
+    BuiltInPred(ClauseName, usize),
+    NamedPred(ClauseName, usize)
+}
+
 #[derive(Clone, PartialEq, Eq, Hash)]
 pub enum Addr {
     AttrVar(usize),
     Con(Constant),
+    DBRef(DBRef),
     Lis(usize),
     HeapCell(usize),
     StackCell(usize, usize),
@@ -502,7 +509,7 @@ impl IndexStore {
     }
 }
 
-pub type CodeDir = HashMap<PredicateKey, CodeIndex>;
+pub type CodeDir = BTreeMap<PredicateKey, CodeIndex>;
 pub type TermDir = HashMap<PredicateKey, (Predicate, VecDeque<TopLevel>)>;
 
 #[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
index 7b3accc517363e61b87cdb87612eedb9fab7e26e..01803becbceb0ece43bcdb91026f3557b0c11ad1 100644 (file)
@@ -628,7 +628,7 @@ impl MachineState {
                         "+" => interms.push(a1 + a2),
                         "-" => interms.push(a1 - a2),
                         "*" => interms.push(a1 * a2),
-                        "/" => interms.push(self.div(a1, a2)?),                        
+                        "/" => interms.push(self.div(a1, a2)?),
                         "**" => interms.push(self.pow(a1, a2)?),
                         "max"  => interms.push(self.max(a1, a2)?),
                         "rdiv" => {
@@ -850,10 +850,10 @@ impl MachineState {
         }
     }
 
-    fn max(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {        
+    fn max(&self, n1: Number, n2: Number) -> Result<Number, MachineStub> {
         Ok(max(n1, n2))
     }
-    
+
     fn remainder(&self, n1: Number, n2: Number) -> Result<Rc<BigInt>, MachineStub>
     {
         let stub = MachineError::functor_stub(clause_name!("(rem)"), 2);
@@ -923,7 +923,7 @@ impl MachineState {
                 let n2 = try_or_fail!(self, self.get_number(a2));
 
                 self.interms[t - 1] = try_or_fail!(self, self.max(n1, n2));
-                self.p += 1;                
+                self.p += 1;
             },
             &ArithmeticInstruction::Pow(ref a1, ref a2, t) => {
                 let n1 = try_or_fail!(self, self.get_number(a1));
@@ -1208,6 +1208,10 @@ impl MachineState {
                     Addr::Con(_) => c,
                     Addr::Lis(_) => l,
                     Addr::Str(_) => s,
+                    Addr::DBRef(_) => {
+                        self.fail = true;
+                        return;
+                    }
                 };
 
                 match offset {
@@ -1885,6 +1889,8 @@ impl MachineState {
         let a1 = self.store(self.deref(self[temp_v!(1)].clone()));
 
         match a1.clone() {
+            Addr::DBRef(_) =>
+                self.fail = true,
             Addr::Con(_) =>
                 self.try_functor_unify_components(a1, Addr::Con(integer!(0))),
             Addr::Str(o) =>
@@ -2223,7 +2229,7 @@ impl MachineState {
                 try_or_fail!(self, call_policy.compile_hook(self, hook)),
             &ClauseType::Inlined(ref ct) => {
                 self.execute_inlined(ct);
-                
+
                 if lco {
                     self.p = CodePtr::Local(self.cp);
                 }
index 25ab0fa21bc152fcb4bbe0b2ba6e1332de24eabb..873b34ec63e116575bcda7a1129fcc815da83bf2 100644 (file)
@@ -7,9 +7,11 @@ use prolog::machine::copier::*;
 use prolog::machine::machine_errors::*;
 use prolog::machine::machine_indices::*;
 use prolog::machine::machine_state::*;
-use prolog::num::{ToPrimitive, Zero};
+use prolog::num::{FromPrimitive, ToPrimitive, Zero};
 use prolog::num::bigint::{BigInt};
 
+use ref_thread_local::RefThreadLocal;
+
 use std::collections::HashSet;
 use std::io::{stdout, Write};
 use std::mem;
@@ -213,6 +215,57 @@ impl MachineState {
         }
     }
 
+    fn get_next_db_ref(&mut self, db_ref: &DBRef, code_dir: &CodeDir) {
+        match db_ref {
+            &DBRef::BuiltInPred(ref name, arity) => {
+                let key = (name.as_str(), arity);
+
+                match CLAUSE_TYPE_FORMS.borrow().range(&key ..).skip(1).next() {
+                    Some(((_, arity), ct)) => {
+                        let a2 = self[temp_v!(2)].clone();
+
+                        if let Some(r) = a2.as_var() {
+                            self.bind(r, Addr::DBRef(DBRef::BuiltInPred(ct.name(), *arity)));
+                        } else {
+                            self.fail = true;
+                        }
+                    },
+                    None => 
+                        match code_dir.iter().next() {
+                            Some(((ref name, arity), _)) => {
+                                let a2 = self[temp_v!(2)].clone();
+
+                                if let Some(r) = a2.as_var() {
+                                    self.bind(r, Addr::DBRef(DBRef::NamedPred(name.clone(), *arity)));
+                                } else {
+                                    self.fail = true;
+                                }
+                            },
+                            None => {
+                                self.fail = true;
+                            }
+                        }
+                }
+            },
+            &DBRef::NamedPred(ref name, arity) => {
+                let key = (name.clone(), arity);
+
+                match code_dir.range(key ..).skip(1).next() {
+                    Some(((name, arity), _)) => {
+                        let a2 = self[temp_v!(2)].clone();
+
+                        if let Some(r) = a2.as_var() {
+                            self.bind(r, Addr::DBRef(DBRef::NamedPred(name.clone(), *arity)));
+                        } else {
+                            self.fail = true;
+                        }
+                    },
+                    None => self.fail = true
+                }
+            }
+        }
+    }
+
     pub(super) fn system_call(&mut self,
                               ct: &SystemClauseType,
                               indices: &mut IndexStore,
@@ -462,27 +515,53 @@ impl MachineState {
                 self.p = CodePtr::Local(LocalCodePtr::UserTermExpansion(0));
                 return Ok(());
             },
-            &SystemClauseType::GetCurrentPredicateList => {
-                let mut addrs = vec![];
+            &SystemClauseType::GetNextDBRef => {
+                let a1 = self[temp_v!(1)].clone();
 
-                for ((name, arity), idx) in indices.code_dir.iter() {
-                    if idx.is_undefined() {
-                        continue;
+                match self.store(self.deref(a1)) {
+                    addr @ Addr::HeapCell(_)
+                  | addr @ Addr::StackCell(..)
+                  | addr @ Addr::AttrVar(_) =>
+                      match CLAUSE_TYPE_FORMS.borrow().iter().next() {
+                          Some(((_, arity), ct)) => {
+                              let db_ref = DBRef::BuiltInPred(ct.name(), *arity);
+                              let r = addr.as_var().unwrap();
+
+                              self.bind(r, Addr::DBRef(db_ref));
+                          },
+                          None => {
+                              self.fail = true;
+                              return Ok(());
+                          }
+                      },
+                    Addr::DBRef(ref db_ref) =>
+                      self.get_next_db_ref(db_ref, &indices.code_dir),
+                    _ => {
+                      self.fail = true;
                     }
+                };
+            },
+            &SystemClauseType::LookupDBRef => {
+                let a1 = self[temp_v!(1)].clone();
 
-                    let h = self.heap.h;
-
-                    self.heap.push(HeapCellValue::NamedStr(2, clause_name!("/"), Some((400, YFX))));
-                    self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::Atom(name.clone(), None))));
-                    self.heap.push(heap_integer!(*arity));
+                match self.store(self.deref(a1)) {
+                    Addr::DBRef(db_ref) =>
+                        match db_ref {
+                            DBRef::BuiltInPred(name, arity) | DBRef::NamedPred(name, arity) => {
+                                let a2 = self[temp_v!(2)].clone();
+                                let a3 = self[temp_v!(3)].clone();
 
-                    addrs.push(Addr::Str(h));
-                }
+                                let arity = Number::Integer(Rc::new(BigInt::from_usize(arity).unwrap()));
 
-                let list_addr   = Addr::HeapCell(self.heap.to_list(addrs.into_iter()));
-                let target_addr = self[temp_v!(1)].clone();
+                                self.unify(a2, Addr::Con(Constant::Atom(name, None)));
 
-                self.unify(list_addr, target_addr);
+                                if !self.fail {
+                                    self.unify(a3, Addr::Con(Constant::Number(arity)));
+                                }
+                            }
+                        },
+                    _ => self.fail = true
+                }
             },
             &SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff =>
                 self.truncate_if_no_lifted_heap_diff(|h| Addr::HeapCell(h)),
index c667c0f90fe2362e88d1884bdd24ce4132794aef..a81da29792db435f2e667cc333588a353843eb73 100644 (file)
@@ -159,10 +159,20 @@ impl fmt::Display for HeapCellValue {
     }
 }
 
+impl fmt::Display for DBRef {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            &DBRef::BuiltInPred(ref name, arity) => write!(f, "db_ref:builtin:{}/{}", name, arity),
+            &DBRef::NamedPred(ref name, arity) =>   write!(f, "db_ref:named:{}/{}", name, 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::DBRef(ref db_ref) => write!(f, "Addr::DBRef({})", db_ref),
             &Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
             &Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
             &Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),