[package]
name = "scryer-prolog"
-version = "0.8.112"
+version = "0.8.113"
build = "build.rs"
repository = "https://github.com/mthom/scryer-prolog"
use crate::prolog::forms::Number;
use crate::prolog::machine::machine_indices::*;
+use crate::prolog::rug::rand::RandState;
use ref_thread_local::RefThreadLocal;
IsVar(RegType),
}
+ref_thread_local! {
+ pub static managed RANDOM_STATE: RandState<'static> = RandState::new();
+}
+
ref_thread_local! {
pub static managed CLAUSE_TYPE_FORMS: BTreeMap<(&'static str, usize), ClauseType> = {
let mut m = BTreeMap::new();
GetCutPoint,
GetDoubleQuotes,
InstallNewBlock,
+ Maybe,
ResetBlock,
ReturnFromAttributeGoals,
ReturnFromVerifyAttr,
SetBall,
SetCutPointByDefault(RegType),
SetDoubleQuotes,
+ SetSeed,
SkipMaxList,
Succeed,
TermVariables,
clause_name!("$install_inference_counter")
}
&SystemClauseType::LiftedHeapLength => clause_name!("$lh_length"),
+ &SystemClauseType::Maybe => clause_name!("maybe"),
&SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"),
&SystemClauseType::ModuleOf => clause_name!("$module_of"),
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
&SystemClauseType::RemoveInferenceCounter => clause_name!("$remove_inference_counter"),
&SystemClauseType::RestoreCutPolicy => clause_name!("$restore_cut_policy"),
&SystemClauseType::SetCutPoint(_) => clause_name!("$set_cp"),
+ &SystemClauseType::SetSeed => clause_name!("$set_seed"),
&SystemClauseType::StoreGlobalVar => clause_name!("$store_global_var"),
&SystemClauseType::StoreGlobalVarWithOffset => {
clause_name!("$store_global_var_with_offset")
("$install_scc_cleaner", 2) => Some(SystemClauseType::InstallSCCCleaner),
("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter),
("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength),
+ ("$maybe", 0) => Some(SystemClauseType::Maybe),
("$module_of", 2) => Some(SystemClauseType::ModuleOf),
("$module_retract_clause", 5) => Some(SystemClauseType::ModuleRetractClause),
("$module_head_is_dynamic", 2) => Some(SystemClauseType::ModuleHeadIsDynamic),
("$set_ball", 1) => Some(SystemClauseType::SetBall),
("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))),
("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes),
+ ("$set_seed", 1) => Some(SystemClauseType::SetSeed),
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar),
("$store_global_var_with_offset", 2) => Some(SystemClauseType::StoreGlobalVarWithOffset),
%% ?- use_module(library(non_iso)).
:- module(non_iso, [bb_b_put/2, bb_get/2, bb_put/2, call_cleanup/2,
- call_with_inference_limit/3, forall/2,
- setup_call_cleanup/3, variant/2]).
+ call_with_inference_limit/3, forall/2, maybe/0,
+ set_random/1, setup_call_cleanup/3, variant/2]).
forall(Generate, Test) :-
\+ (Generate, \+ Test).
'$call_with_default_policy'(handle_ile(B, Ball, R)).
variant(X, Y) :- '$variant'(X, Y).
+
+% succeeds with probability 0.5.
+maybe :- '$maybe'.
+
+set_random(Seed) :-
+ ( nonvar(Seed) ->
+ ( Seed = seed(S) ->
+ ( integer(S) -> '$set_seed'(S)
+ ; throw(error(type_error(integer(S), set_random/1)))
+ )
+ )
+ ; throw(error(instantiation_error, set_random/1))
+ ).
}
}
-#[derive(Clone)]
+#[derive(Clone, Copy)]
pub enum TrailRef {
Ref(Ref),
- AttrVarLink(usize, Addr),
+ AttrVarHeapLink(usize),
+ AttrVarListLink(usize, usize),
}
impl From<Ref> for TrailRef {
self.tr += 1;
}
}
- TrailRef::AttrVarLink(h, prev_addr) => {
+ TrailRef::AttrVarHeapLink(h) => {
if h < self.hb {
- self.trail.push(TrailRef::AttrVarLink(h, prev_addr));
+ self.trail.push(TrailRef::AttrVarHeapLink(h));
+ self.tr += 1;
+ }
+ }
+ TrailRef::AttrVarListLink(h, l) => {
+ if h < self.hb {
+ self.trail.push(TrailRef::AttrVarListLink(h, l));
self.tr += 1;
}
}
// additions, now that deleted attributes can be undeleted by
// backtracking.
for i in (a1..a2).rev() {
- match self.trail[i].clone() {
+ match self.trail[i] {
TrailRef::Ref(Ref::HeapCell(h)) => {
self.heap[h] = HeapCellValue::Addr(Addr::HeapCell(h))
}
TrailRef::Ref(Ref::StackCell(fr, sc)) => {
self.and_stack[fr][sc] = Addr::StackCell(fr, sc)
}
- TrailRef::AttrVarLink(h, prev_addr) => {
- self.heap[h] = HeapCellValue::Addr(prev_addr)
+ TrailRef::AttrVarHeapLink(h) => {
+ self.heap[h] = HeapCellValue::Addr(Addr::HeapCell(h));
+ }
+ TrailRef::AttrVarListLink(h, l) => {
+ self.heap[h] = HeapCellValue::Addr(Addr::Lis(l));
}
}
}
let mut i = self.or_stack[b].tr;
while i < self.tr {
- let tr_i = self.trail[i].clone();
+ let tr_i = self.trail[i];
let hb = self.hb;
match tr_i {
TrailRef::Ref(Ref::AttrVar(tr_i))
- | TrailRef::Ref(Ref::HeapCell(tr_i))
- | TrailRef::AttrVarLink(tr_i, _) => {
+ | TrailRef::Ref(Ref::HeapCell(tr_i))
+ | TrailRef::AttrVarHeapLink(tr_i)
+ | TrailRef::AttrVarListLink(tr_i, _) => {
if tr_i < hb {
i += 1;
} else {
i += 1;
} else {
let tr = self.tr;
- let val = self.trail[tr - 1].clone();
+ let val = self.trail[tr - 1];
self.trail[i] = val;
self.trail.pop();
self.tr -= 1;
use crate::prolog::read::{readline, PrologStream};
use crate::prolog::rug::Integer;
+use crate::ref_thread_local::RefThreadLocal;
+
use indexmap::{IndexMap, IndexSet};
use std::collections::VecDeque;
let c = self.int_to_char_code(&n, "atom_codes", 2)?;
chars.push(c as char);
}
- &Addr::Con(Constant::CharCode(c)) => chars.push(c as char),
+ &Addr::Con(Constant::CharCode(c)) =>
+ chars.push(c as char),
_ => {
let err = MachineError::type_error(
ValidType::Integer,
tail
};
+ let trail_ref = match old_addr {
+ Addr::HeapCell(h) => TrailRef::AttrVarHeapLink(h),
+ Addr::Lis(l) => TrailRef::AttrVarListLink(l1 + 1, l),
+ _ => unreachable!()
+ };
+
self.heap[l1 + 1] = HeapCellValue::Addr(tail);
- self.trail(TrailRef::AttrVarLink(l1 + 1, old_addr));
+ self.trail(trail_ref);
}
}
}
};
self.heap[h + 1] = HeapCellValue::Addr(tail);
- self.trail(TrailRef::AttrVarLink(h + 1, Addr::Lis(l)));
+ self.trail(TrailRef::AttrVarListLink(h + 1, l));
}
_ => unreachable!(),
}
_ => self.fail = true,
}
}
+ &SystemClauseType::Maybe => {
+ let result = {
+ let mut rand = RANDOM_STATE.borrow_mut();
+
+ if rand.bits(1) == 0 {
+ true
+ } else {
+ false
+ }
+ };
+
+ self.fail = result;
+ }
&SystemClauseType::OpDeclaration => {
let priority = self[temp_v!(1)].clone();
let specifier = self[temp_v!(2)].clone();
}
&SystemClauseType::SetBall =>
self.set_ball(),
+ &SystemClauseType::SetSeed => {
+ let seed = self.store(self.deref(self[temp_v!(1)].clone()));
+
+ let seed = match seed {
+ Addr::Con(Constant::Integer(n)) =>
+ n,
+ Addr::Con(Constant::CharCode(c)) =>
+ Integer::from(c),
+ Addr::Con(Constant::Rational(r)) => {
+ if r.denom() == &1 {
+ r.numer().clone()
+ } else {
+ self.fail = true;
+ return Ok(());
+ }
+ }
+ _ => {
+ self.fail = true;
+ return Ok(());
+ }
+ };
+
+ let mut rand = RANDOM_STATE.borrow_mut();
+ rand.seed(&seed);
+ }
&SystemClauseType::SkipMaxList =>
if let Err(err) = self.skip_max_list() {
return Err(err);