From 381ad12104fa6a030fbd1323041ff76d64e16f96 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 27 Mar 2019 23:00:59 -0600 Subject: [PATCH] add db refs --- src/prolog/clause_types.rs | 11 ++- src/prolog/heap_iter.rs | 4 +- src/prolog/lib/builtins.pl | 60 +++--------- src/prolog/machine/copier.rs | 2 +- src/prolog/machine/machine_indices.rs | 11 ++- src/prolog/machine/machine_state_impl.rs | 16 +++- src/prolog/machine/system_calls.rs | 111 +++++++++++++++++++---- src/prolog/write.rs | 10 ++ 8 files changed, 146 insertions(+), 79 deletions(-) diff --git a/src/prolog/clause_types.rs b/src/prolog/clause_types.rs index 537605b4..405a6106 100644 --- a/src/prolog/clause_types.rs +++ b/src/prolog/clause_types.rs @@ -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), diff --git a/src/prolog/heap_iter.rs b/src/prolog/heap_iter.rs index 7f32c1bf..a5bf3d25 100644 --- a/src/prolog/heap_iter.rs +++ b/src/prolog/heap_iter.rs @@ -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)); diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index ff7a6a71..c429d65d 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -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). diff --git a/src/prolog/machine/copier.rs b/src/prolog/machine/copier.rs index edb54042..7f87e937 100644 --- a/src/prolog/machine/copier.rs +++ b/src/prolog/machine/copier.rs @@ -184,7 +184,7 @@ impl CopyTermState { self.copy_var(addr), Addr::Str(addr) => self.copy_structure(addr), - Addr::Con(_) => + Addr::Con(_) | Addr::DBRef(_) => self.scan += 1 } } diff --git a/src/prolog/machine/machine_indices.rs b/src/prolog/machine/machine_indices.rs index d88090b1..d9e69411 100644 --- a/src/prolog/machine/machine_indices.rs +++ b/src/prolog/machine/machine_indices.rs @@ -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; +pub type CodeDir = BTreeMap; pub type TermDir = HashMap)>; #[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd)] diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 7b3accc5..01803bec 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -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 { + fn max(&self, n1: Number, n2: Number) -> Result { Ok(max(n1, n2)) } - + fn remainder(&self, n1: Number, n2: Number) -> Result, 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); } diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 25ab0fa2..873b34ec 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -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)), diff --git a/src/prolog/write.rs b/src/prolog/write.rs index c667c0f9..a81da297 100644 --- a/src/prolog/write.rs +++ b/src/prolog/write.rs @@ -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), -- 2.54.0