7 Commits

Author SHA1 Message Date
Mark Thom
1b1879a6fa fix attributed variables bug causing weighted_maximum/3 example to omit a variable binding 2019-10-20 14:50:46 -06:00
Mark Thom
24e5e39c28 add order preserving tidy_trail, fix random_labeling/2 2019-10-19 00:29:50 -06:00
Mark Thom
ab9a14cc6a add randomness predicates, small but consequential changes to TrailRef 2019-10-17 00:21:21 -06:00
Mark Thom
a641822a1b Merge pull request #206 from triska/master
weighted_maximum/3 now works
2019-10-16 16:17:05 -03:00
Markus Triska
145fee0d36 weighted_maximum/3 now works 2019-10-16 19:18:38 +02:00
Markus Triska
567af2648c support must_be(var, ...) 2019-10-16 19:18:38 +02:00
Mark Thom
42a3bdc357 eliminate lingering attribute goals 2019-10-16 11:38:33 -03:00
17 changed files with 268 additions and 137 deletions

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "scryer-prolog" name = "scryer-prolog"
version = "0.8.111" version = "0.8.115"
authors = ["Mark Thom <markjordanthom@gmail.com>"] authors = ["Mark Thom <markjordanthom@gmail.com>"]
build = "build.rs" build = "build.rs"
repository = "https://github.com/mthom/scryer-prolog" repository = "https://github.com/mthom/scryer-prolog"

View File

@@ -93,7 +93,7 @@ strings.
First, install the latest stable version of First, install the latest stable version of
[Rust](https://www.rust-lang.org/en-US/install.html) using your [Rust](https://www.rust-lang.org/en-US/install.html) using your
preferred method. Then install the latest Scryer Prolog with cargo, preferred method. Then install Scryer Prolog with cargo,
like so: like so:
``` ```
@@ -101,13 +101,27 @@ $> cargo install scryer-prolog
``` ```
cargo will download and install the libraries Scryer Prolog uses cargo will download and install the libraries Scryer Prolog uses
automatically. You can find the `scryer-prolog` executable in automatically from crates.io. You can find the `scryer-prolog`
`~/.cargo/bin`. executable in `~/.cargo/bin`.
Publishing Rust crates to crates.io and pushing to git are entirely
distinct, independent processes, so to be sure you have the latest
commit, it is recommended to clone directly from this git repository,
which can be done as follows:
```
$> git clone https://github.com/mthom/scryer-prolog
$> cd scryer-prolog
$> cargo run [--release]
```
The optional `--release` flag will perform various optimizations,
producing a faster executable.
Note on compatibility: Scryer Prolog should work on Linux, Mac OS X, Note on compatibility: Scryer Prolog should work on Linux, Mac OS X,
and BSD variants on which Rust runs. Windows support hinges on and BSD variants on which Rust runs. Windows support hinges on
rustyline and Termion being functional in that environment, which to rustyline and Termion being functional in that environment, which to
my knowledge is not currently the case. my knowledge is not presently the case.
## Built-in predicates ## Built-in predicates

View File

@@ -2,6 +2,7 @@ use prolog_parser::ast::*;
use crate::prolog::forms::Number; use crate::prolog::forms::Number;
use crate::prolog::machine::machine_indices::*; use crate::prolog::machine::machine_indices::*;
use crate::prolog::rug::rand::RandState;
use ref_thread_local::RefThreadLocal; use ref_thread_local::RefThreadLocal;
@@ -81,6 +82,10 @@ pub enum InlinedClauseType {
IsVar(RegType), IsVar(RegType),
} }
ref_thread_local! {
pub static managed RANDOM_STATE: RandState<'static> = RandState::new();
}
ref_thread_local! { ref_thread_local! {
pub 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 mut m = BTreeMap::new();
@@ -223,12 +228,14 @@ pub enum SystemClauseType {
GetCutPoint, GetCutPoint,
GetDoubleQuotes, GetDoubleQuotes,
InstallNewBlock, InstallNewBlock,
Maybe,
ResetBlock, ResetBlock,
ReturnFromAttributeGoals, ReturnFromAttributeGoals,
ReturnFromVerifyAttr, ReturnFromVerifyAttr,
SetBall, SetBall,
SetCutPointByDefault(RegType), SetCutPointByDefault(RegType),
SetDoubleQuotes, SetDoubleQuotes,
SetSeed,
SkipMaxList, SkipMaxList,
Succeed, Succeed,
TermVariables, TermVariables,
@@ -319,6 +326,7 @@ impl SystemClauseType {
clause_name!("$install_inference_counter") clause_name!("$install_inference_counter")
} }
&SystemClauseType::LiftedHeapLength => clause_name!("$lh_length"), &SystemClauseType::LiftedHeapLength => clause_name!("$lh_length"),
&SystemClauseType::Maybe => clause_name!("maybe"),
&SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"), &SystemClauseType::ModuleHeadIsDynamic => clause_name!("$module_head_is_dynamic"),
&SystemClauseType::ModuleOf => clause_name!("$module_of"), &SystemClauseType::ModuleOf => clause_name!("$module_of"),
&SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"), &SystemClauseType::NoSuchPredicate => clause_name!("$no_such_predicate"),
@@ -329,6 +337,7 @@ impl SystemClauseType {
&SystemClauseType::RemoveInferenceCounter => clause_name!("$remove_inference_counter"), &SystemClauseType::RemoveInferenceCounter => clause_name!("$remove_inference_counter"),
&SystemClauseType::RestoreCutPolicy => clause_name!("$restore_cut_policy"), &SystemClauseType::RestoreCutPolicy => clause_name!("$restore_cut_policy"),
&SystemClauseType::SetCutPoint(_) => clause_name!("$set_cp"), &SystemClauseType::SetCutPoint(_) => clause_name!("$set_cp"),
&SystemClauseType::SetSeed => clause_name!("$set_seed"),
&SystemClauseType::StoreGlobalVar => clause_name!("$store_global_var"), &SystemClauseType::StoreGlobalVar => clause_name!("$store_global_var"),
&SystemClauseType::StoreGlobalVarWithOffset => { &SystemClauseType::StoreGlobalVarWithOffset => {
clause_name!("$store_global_var_with_offset") clause_name!("$store_global_var_with_offset")
@@ -417,6 +426,7 @@ impl SystemClauseType {
("$install_scc_cleaner", 2) => Some(SystemClauseType::InstallSCCCleaner), ("$install_scc_cleaner", 2) => Some(SystemClauseType::InstallSCCCleaner),
("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter), ("$install_inference_counter", 3) => Some(SystemClauseType::InstallInferenceCounter),
("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength), ("$lh_length", 1) => Some(SystemClauseType::LiftedHeapLength),
("$maybe", 0) => Some(SystemClauseType::Maybe),
("$module_of", 2) => Some(SystemClauseType::ModuleOf), ("$module_of", 2) => Some(SystemClauseType::ModuleOf),
("$module_retract_clause", 5) => Some(SystemClauseType::ModuleRetractClause), ("$module_retract_clause", 5) => Some(SystemClauseType::ModuleRetractClause),
("$module_head_is_dynamic", 2) => Some(SystemClauseType::ModuleHeadIsDynamic), ("$module_head_is_dynamic", 2) => Some(SystemClauseType::ModuleHeadIsDynamic),
@@ -450,6 +460,7 @@ impl SystemClauseType {
("$set_ball", 1) => Some(SystemClauseType::SetBall), ("$set_ball", 1) => Some(SystemClauseType::SetBall),
("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))), ("$set_cp_by_default", 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))),
("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes), ("$set_double_quotes", 1) => Some(SystemClauseType::SetDoubleQuotes),
("$set_seed", 1) => Some(SystemClauseType::SetSeed),
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList), ("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar), ("$store_global_var", 2) => Some(SystemClauseType::StoreGlobalVar),
("$store_global_var_with_offset", 2) => Some(SystemClauseType::StoreGlobalVarWithOffset), ("$store_global_var_with_offset", 2) => Some(SystemClauseType::StoreGlobalVarWithOffset),

View File

@@ -191,7 +191,7 @@ impl<'a> VariableFixtures<'a> {
for term_ref in iter { for term_ref in iter {
if let &TermRef::Var(lvl, cell, ref var) = &term_ref { if let &TermRef::Var(lvl, cell, ref var) = &term_ref {
let mut status = self.perm_vars.remove(var).unwrap_or(( let mut status = self.perm_vars.swap_remove(var).unwrap_or((
VarStatus::Temp(chunk_num, TempVarData::new(lt_arity)), VarStatus::Temp(chunk_num, TempVarData::new(lt_arity)),
Vec::new(), Vec::new(),
)); ));

View File

@@ -20,7 +20,7 @@
'$default_attr_list'([PG | PGs], Module, AttrVar) --> '$default_attr_list'([PG | PGs], Module, AttrVar) -->
( { '$module_of'(Module, PG) } -> [Module:put_atts(AttrVar, PG)] ( { '$module_of'(Module, PG) } -> [Module:put_atts(AttrVar, PG)]
; true ; { true }
), ),
'$default_attr_list'(PGs, Module, AttrVar). '$default_attr_list'(PGs, Module, AttrVar).
'$default_attr_list'([], _, _) --> []. '$default_attr_list'([], _, _) --> [].

View File

@@ -34,7 +34,7 @@
:- use_module(library(lists)). :- use_module(library(lists)).
:- use_module(library(non_iso)). :- use_module(library(non_iso)).
:- use_module(library(dcgs)). :- use_module(library(dcgs)).
%:- use_module(library(types)). :- use_module(library(error), []).
:- attribute :- attribute
clpb/1, clpb/1,
@@ -77,8 +77,8 @@ must_be(list(What), Where, Term) :- !,
must_be(ground, _, Term) :- !, must_be(ground, _, Term) :- !,
functor(Term, _, _). functor(Term, _, _).
must_be(Type, Goal-Arg, Term) :- must_be(Type, _, Term) :-
must_be(Term, Type, Goal, Arg). error:must_be(Type, Term).
clpz_list(Nil, _) :- Nil == []. clpz_list(Nil, _) :- Nil == [].
clpz_list(Ls, Where) :- clpz_list(Ls, Where) :-
@@ -87,7 +87,6 @@ clpz_list(Ls, Where) :-
; Ls = [_|Rest], ; Ls = [_|Rest],
clpz_list(Rest, Where) clpz_list(Rest, Where)
). ).
instantiation_error(Term) :- instantiation_error(Term, unknown(Term)-1). instantiation_error(Term) :- instantiation_error(Term, unknown(Term)-1).
@@ -139,7 +138,10 @@ partition(Pred, Ls0, As, Bs) :-
include(Pred, Ls0, As), include(Pred, Ls0, As),
exclude(Pred, Ls0, Bs). exclude(Pred, Ls0, Bs).
sum_list(Ls, S) :- sumlist(Ls, S). sum_list(Ls, S) :-
foldl(sum_, Ls, 0, S).
sum_(L, S0, S) :- S is S0 + L.
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Pairs. Pairs.
@@ -1157,7 +1159,7 @@ labeling_var(V) :- V == 1, !.
labeling_var(V) :- domain_error(clpb_variable, V). labeling_var(V) :- domain_error(clpb_variable, V).
variables_in_index_order(Vs0, Vs) :- variables_in_index_order(Vs0, Vs) :-
maplist(var_with_index, Vs0, IVs0), maplist(var_with_index, Vs0, IVs0),
keysort(IVs0, IVs), keysort(IVs0, IVs),
pairs_values(IVs, Vs). pairs_values(IVs, Vs).
@@ -1243,7 +1245,7 @@ bdd_count(Node, VNum, Count) :-
bdd_pow(Low, V, VNum, LPow), bdd_pow(Low, V, VNum, LPow),
bdd_pow(High, V, VNum, HPow), bdd_pow(High, V, VNum, HPow),
Count0 is LPow*LCount + HPow*HCount, Count0 is LPow*LCount + HPow*HCount,
Count = Count0 Count0 = Count
) )
). ).
@@ -1356,7 +1358,7 @@ weighted_maximum(Ws, Vars, Max) :-
pairs_values(IVs1, VarsIndexOrder), pairs_values(IVs1, VarsIndexOrder),
% Pairs is a list of Var-Weight terms, in index order of Vars % Pairs is a list of Var-Weight terms, in index order of Vars
pairs_keys_values(Pairs, VarsIndexOrder, WeightsIndexOrder), pairs_keys_values(Pairs, VarsIndexOrder, WeightsIndexOrder),
bdd_maximum(BDD, Pairs, Max), bdd_maximum(BDD, Pairs, Max), %% A,B are in BDD, but not C; A,B,C *are* in Pairs.
max_labeling(BDD, Pairs). max_labeling(BDD, Pairs).
max_labeling(1, Pairs) :- max_upto(Pairs, _, _). max_labeling(1, Pairs) :- max_upto(Pairs, _, _).
@@ -1507,7 +1509,7 @@ max_variable_node(Node, V0-N0, V-N) :-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
ands_fusion(Ands0, Ands) :- ands_fusion(Ands0, Ands) :-
maplist(with_variables, Ands0, Pairs0), maplist(with_variables, Ands0, Pairs0),
keysort(Pairs0, Pairs), keysort(Pairs0, Pairs),
group_pairs_by_key(Pairs, Groups), group_pairs_by_key(Pairs, Groups),
pairs_values(Groups, Andss), pairs_values(Groups, Andss),

View File

@@ -51,4 +51,5 @@ gather_dif_goals([(X \== Y) | Goals]) -->
attribute_goals(X) --> attribute_goals(X) -->
{ get_atts(X, +dif(Goals)) }, { get_atts(X, +dif(Goals)) },
gather_dif_goals(Goals). gather_dif_goals(Goals),
{ put_atts(X, -dif(_)) }.

View File

@@ -33,6 +33,10 @@ must_be(Type, Term) :-
must_be_(Type, _) :- must_be_(Type, _) :-
var(Type), var(Type),
instantiation_error(Type). instantiation_error(Type).
must_be_(var, Term) :-
( var(Term) -> true
; throw(error(uninstantiation_error, _))
).
must_be_(integer, Term) :- check_(integer, integer, Term). must_be_(integer, Term) :- check_(integer, integer, Term).
must_be_(atom, Term) :- check_(atom, atom, Term). must_be_(atom, Term) :- check_(atom, atom, Term).
must_be_(list, Term) :- check_(ilist, list, Term). must_be_(list, Term) :- check_(ilist, list, Term).
@@ -52,6 +56,7 @@ type(type).
type(integer). type(integer).
type(atom). type(atom).
type(list). type(list).
type(var).
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
can_be(Type, Term) can_be(Type, Term)

View File

@@ -26,6 +26,7 @@ gather_freeze_goals(Attrs, _) -->
!. !.
gather_freeze_goals([frozen(X) | _], Var) --> gather_freeze_goals([frozen(X) | _], Var) -->
[freeze(Var, X)], [freeze(Var, X)],
{ put_atts(Var, -frozen(_)) },
!. !.
gather_freeze_goals([_ | Attrs], Var) --> gather_freeze_goals([_ | Attrs], Var) -->
gather_freeze_goals(Attrs, Var). gather_freeze_goals(Attrs, Var).

View File

@@ -3,6 +3,7 @@
maplist/4, maplist/5, maplist/6, maplist/7, maplist/4, maplist/5, maplist/6, maplist/7,
maplist/8, maplist/9]). maplist/8, maplist/9]).
length(Xs, N) :- length(Xs, N) :-
var(N), !, var(N), !,
'$skip_max_list'(M, -1, Xs, Xs0), '$skip_max_list'(M, -1, Xs, Xs0),
@@ -30,17 +31,22 @@ length_rundown([_|Xs], N) :-
N1 is N-1, N1 is N-1,
length_rundown(Xs, N1). length_rundown(Xs, N1).
member(X, [X|_]). member(X, [X|_]).
member(X, [_|Xs]) :- member(X, Xs). member(X, [_|Xs]) :- member(X, Xs).
select(X, [X|Xs], Xs). select(X, [X|Xs], Xs).
select(X, [Y|Xs], [Y|Ys]) :- select(X, Xs, Ys). select(X, [Y|Xs], [Y|Ys]) :- select(X, Xs, Ys).
append([], R, R). append([], R, R).
append([X|L], R, [X|S]) :- append(L, R, S). append([X|L], R, [X|S]) :- append(L, R, S).
memberchk(X, Xs) :- member(X, Xs), !. memberchk(X, Xs) :- member(X, Xs), !.
reverse(Xs, Ys) :- reverse(Xs, Ys) :-
( nonvar(Xs) -> reverse(Xs, Ys, [], Xs) ( nonvar(Xs) -> reverse(Xs, Ys, [], Xs)
; reverse(Ys, Xs, [], Ys) ; reverse(Ys, Xs, [], Ys)
@@ -50,6 +56,7 @@ reverse([], [], YsRev, YsRev).
reverse([X1|Xs], [Y1|Ys], YsPreludeRev, Xss) :- reverse([X1|Xs], [Y1|Ys], YsPreludeRev, Xss) :-
reverse(Xs, Ys, [Y1|YsPreludeRev], Xss). reverse(Xs, Ys, [Y1|YsPreludeRev], Xss).
maplist(_, []). maplist(_, []).
maplist(Cont1, [E1|E1s]) :- maplist(Cont1, [E1|E1s]) :-
call(Cont1, E1), call(Cont1, E1),

View File

@@ -4,8 +4,8 @@
%% ?- use_module(library(non_iso)). %% ?- use_module(library(non_iso)).
:- module(non_iso, [bb_b_put/2, bb_get/2, bb_put/2, call_cleanup/2, :- module(non_iso, [bb_b_put/2, bb_get/2, bb_put/2, call_cleanup/2,
call_with_inference_limit/3, forall/2, call_with_inference_limit/3, forall/2, maybe/0,
setup_call_cleanup/3, variant/2]). set_random/1, setup_call_cleanup/3, variant/2]).
forall(Generate, Test) :- forall(Generate, Test) :-
\+ (Generate, \+ Test). \+ (Generate, \+ Test).
@@ -125,3 +125,17 @@ call_with_inference_limit(_, _, R, Bb, B) :-
'$call_with_default_policy'(handle_ile(B, Ball, R)). '$call_with_default_policy'(handle_ile(B, Ball, R)).
variant(X, Y) :- '$variant'(X, Y). variant(X, Y) :- '$variant'(X, Y).
% succeeds with probability 0.5.
maybe :- '$maybe'.
set_random(Seed) :-
( nonvar(Seed) ->
( Seed = seed(S) ->
( var(S) -> throw(error(instantiation_error, set_random/1))
; integer(S) -> '$set_seed'(S)
; throw(error(type_error(integer(S), set_random/1)))
)
)
; throw(error(instantiation_error, set_random/1))
).

View File

@@ -25,6 +25,7 @@ verify_attrs([], _, _, []).
call_verify_attributes(Attrs, _, _, []) :- call_verify_attributes(Attrs, _, _, []) :-
var(Attrs), !. var(Attrs), !.
call_verify_attributes([], _, _, []).
call_verify_attributes([Attr|Attrs], Var, Value, ListOfGoalLists) :- call_verify_attributes([Attr|Attrs], Var, Value, ListOfGoalLists) :-
gather_modules([Attr|Attrs], Modules0), gather_modules([Attr|Attrs], Modules0),
sort(Modules0, Modules), sort(Modules0, Modules),

View File

@@ -14,6 +14,7 @@ pub(super) struct AttrVarInitializer {
pub(super) attr_var_queue: Vec<usize>, pub(super) attr_var_queue: Vec<usize>,
pub(super) bindings: Bindings, pub(super) bindings: Bindings,
pub(super) cp: LocalCodePtr, pub(super) cp: LocalCodePtr,
pub(super) instigating_p: LocalCodePtr,
pub(super) verify_attrs_loc: usize, pub(super) verify_attrs_loc: usize,
pub(super) project_attrs_loc: usize, pub(super) project_attrs_loc: usize,
} }
@@ -24,6 +25,7 @@ impl AttrVarInitializer {
attribute_goals: vec![], attribute_goals: vec![],
attr_var_queue: vec![], attr_var_queue: vec![],
bindings: vec![], bindings: vec![],
instigating_p: LocalCodePtr::default(),
cp: LocalCodePtr::default(), cp: LocalCodePtr::default(),
verify_attrs_loc, verify_attrs_loc,
project_attrs_loc, project_attrs_loc,
@@ -34,16 +36,19 @@ impl AttrVarInitializer {
pub(super) fn reset(&mut self) { pub(super) fn reset(&mut self) {
self.attr_var_queue.clear(); self.attr_var_queue.clear();
self.bindings.clear(); self.bindings.clear();
self.attribute_goals.clear();
} }
} }
impl MachineState { impl MachineState {
pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr) { pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr) {
if self.attr_var_init.bindings.is_empty() { if self.attr_var_init.bindings.is_empty() {
self.attr_var_init.instigating_p = self.p.local();
if self.last_call { if self.last_call {
self.attr_var_init.cp = self.cp; self.attr_var_init.cp = self.cp;
} else { } else {
self.attr_var_init.cp = self.p.local(); self.attr_var_init.cp = self.p.local() + 1;
} }
self.p = CodePtr::VerifyAttrInterrupt(self.attr_var_init.verify_attrs_loc); self.p = CodePtr::VerifyAttrInterrupt(self.attr_var_init.verify_attrs_loc);
@@ -126,24 +131,17 @@ impl MachineState {
} }
pub(super) fn verify_attr_interrupt(&mut self, p: usize) { pub(super) fn verify_attr_interrupt(&mut self, p: usize) {
let rs = MAX_ARITY; self.allocate(self.num_of_args + 2);
// store temp vars in perm vars slots along with self.b0 and
// self.num_of_args. why self.b0? if we return to a NeckCut
// after finishing the interrupt, it won't work correctly if
// self.b == self.b0. we must change it back when we return,
// as if nothing happened.
self.allocate(rs + 2);
let e = self.e; let e = self.e;
self.and_stack[e].interrupt_cp = self.attr_var_init.cp; self.and_stack[e].interrupt_cp = self.attr_var_init.cp;
for i in 1..rs + 1 { for i in 1 .. self.num_of_args + 1 {
self.and_stack[e][i] = self[RegType::Temp(i)].clone(); self.and_stack[e][i] = self[RegType::Temp(i)].clone();
} }
self.and_stack[e][rs + 1] = Addr::Con(Constant::Usize(self.b0)); self.and_stack[e][self.num_of_args + 1] = Addr::Con(Constant::Usize(self.b0));
self.and_stack[e][rs + 2] = Addr::Con(Constant::Usize(self.num_of_args)); self.and_stack[e][self.num_of_args + 2] = Addr::Con(Constant::Usize(self.num_of_args));
self.verify_attributes(); self.verify_attributes();
@@ -200,7 +198,7 @@ impl Machine {
&mut self.code_repo, &mut self.code_repo,
&mut readline::input_stream(), &mut readline::input_stream(),
); );
self.machine_st self.machine_st
.print_attribute_goals_string(&self.indices.op_dir) .print_attribute_goals_string(&self.indices.op_dir)
} }

View File

@@ -178,10 +178,11 @@ impl From<Ref> for Addr {
} }
} }
#[derive(Clone)] #[derive(Clone, Copy)]
pub enum TrailRef { pub enum TrailRef {
Ref(Ref), Ref(Ref),
AttrVarLink(usize, Addr), AttrVarHeapLink(usize),
AttrVarListLink(usize, usize),
} }
impl From<Ref> for TrailRef { impl From<Ref> for TrailRef {
@@ -468,6 +469,12 @@ pub struct IndexStore {
} }
impl IndexStore { impl IndexStore {
pub fn reset_global_variable_offsets(&mut self) {
for (_, ref mut offset) in self.global_variables.values_mut() {
*offset = None;
}
}
pub fn predicate_exists( pub fn predicate_exists(
&self, &self,
name: ClauseName, name: ClauseName,

View File

@@ -648,9 +648,15 @@ impl MachineState {
self.tr += 1; self.tr += 1;
} }
} }
TrailRef::AttrVarLink(h, prev_addr) => { TrailRef::AttrVarHeapLink(h) => {
if h < self.hb { 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; self.tr += 1;
} }
} }
@@ -680,7 +686,7 @@ impl MachineState {
// additions, now that deleted attributes can be undeleted by // additions, now that deleted attributes can be undeleted by
// backtracking. // backtracking.
for i in (a1..a2).rev() { for i in (a1..a2).rev() {
match self.trail[i].clone() { match self.trail[i] {
TrailRef::Ref(Ref::HeapCell(h)) => { TrailRef::Ref(Ref::HeapCell(h)) => {
self.heap[h] = HeapCellValue::Addr(Addr::HeapCell(h)) self.heap[h] = HeapCellValue::Addr(Addr::HeapCell(h))
} }
@@ -690,8 +696,11 @@ impl MachineState {
TrailRef::Ref(Ref::StackCell(fr, sc)) => { TrailRef::Ref(Ref::StackCell(fr, sc)) => {
self.and_stack[fr][sc] = Addr::StackCell(fr, sc) self.and_stack[fr][sc] = Addr::StackCell(fr, sc)
} }
TrailRef::AttrVarLink(h, prev_addr) => { TrailRef::AttrVarHeapLink(h) => {
self.heap[h] = HeapCellValue::Addr(prev_addr) self.heap[h] = HeapCellValue::Addr(Addr::HeapCell(h));
}
TrailRef::AttrVarListLink(h, l) => {
self.heap[h] = HeapCellValue::Addr(Addr::Lis(l));
} }
} }
} }
@@ -732,28 +741,21 @@ impl MachineState {
} }
let b = self.b - 1; let b = self.b - 1;
let mut i = self.or_stack[b].tr; let hb = self.hb;
let mut offset = 0;
while i < self.tr { for i in self.or_stack[b].tr .. self.tr {
let tr_i = self.trail[i].clone(); match self.trail[i] {
let hb = self.hb;
match tr_i {
TrailRef::Ref(Ref::AttrVar(tr_i)) TrailRef::Ref(Ref::AttrVar(tr_i))
| TrailRef::Ref(Ref::HeapCell(tr_i)) | TrailRef::Ref(Ref::HeapCell(tr_i))
| TrailRef::AttrVarLink(tr_i, _) => { | TrailRef::AttrVarHeapLink(tr_i)
if tr_i < hb { | TrailRef::AttrVarListLink(tr_i, _) =>
i += 1; if tr_i >= hb {
} else { offset += 1;
let tr = self.tr; } else {
let val = self.trail[tr - 1].clone(); self.trail[i - offset] = self.trail[i];
self.trail[i] = val; },
self.trail.pop();
self.tr -= 1;
}
}
TrailRef::Ref(Ref::StackCell(fr, _)) => { TrailRef::Ref(Ref::StackCell(fr, _)) => {
let b = self.b - 1;
let fr_gi = self.and_stack[fr].global_index; let fr_gi = self.and_stack[fr].global_index;
let b_gi = if !self.or_stack.is_empty() { let b_gi = if !self.or_stack.is_empty() {
self.or_stack[b].global_index self.or_stack[b].global_index
@@ -761,18 +763,17 @@ impl MachineState {
0 0
}; };
if fr_gi < b_gi { if fr_gi >= b_gi {
i += 1; offset += 1;
} else { } else {
let tr = self.tr; self.trail[i - offset] = self.trail[i];
let val = self.trail[tr - 1].clone();
self.trail[i] = val;
self.trail.pop();
self.tr -= 1;
} }
} }
}; }
} }
self.tr -= offset;
self.trail.truncate(self.tr);
} }
#[inline] #[inline]
@@ -1665,7 +1666,7 @@ impl MachineState {
} else if s.is_expandable() { } else if s.is_expandable() {
self.heap self.heap
.push(HeapCellValue::Addr(Addr::Con(Constant::String(s.clone())))); .push(HeapCellValue::Addr(Addr::Con(Constant::String(s.clone()))));
self.s = h; self.s = h;
self.mode = MachineMode::Read; self.mode = MachineMode::Read;
} else { } else {
@@ -3230,6 +3231,8 @@ impl MachineState {
) )
), ),
}; };
self.last_call = false;
} }
pub(super) fn execute_ctrl_instr( pub(super) fn execute_ctrl_instr(
@@ -3265,7 +3268,7 @@ impl MachineState {
self.b0 = self.b; self.b0 = self.b;
self.p += offset; self.p += offset;
} }
&ControlInstruction::Proceed => self.p = CodePtr::Local(self.cp.clone()), &ControlInstruction::Proceed => self.p = CodePtr::Local(self.cp.clone())
}; };
} }
@@ -3424,56 +3427,4 @@ impl MachineState {
self.heap_locs.clear(); self.heap_locs.clear();
self.lifted_heap.clear(); self.lifted_heap.clear();
} }
pub(super) fn sink_to_snapshot(&mut self) -> MachineState {
let mut snapshot = MachineState::with_capacity(0);
snapshot.hb = self.hb;
snapshot.e = self.e;
snapshot.b = self.b;
snapshot.b0 = self.b0;
snapshot.s = self.s;
snapshot.tr = self.tr;
snapshot.pstr_tr = self.pstr_tr;
snapshot.num_of_args = self.num_of_args;
snapshot.fail = self.fail;
snapshot.trail = mem::replace(&mut self.trail, vec![]);
snapshot.pstr_trail = mem::replace(&mut self.pstr_trail, vec![]);
snapshot.heap = self.heap.take();
snapshot.mode = self.mode;
snapshot.and_stack = self.and_stack.take();
snapshot.or_stack = self.or_stack.take();
snapshot.registers = mem::replace(&mut self.registers, vec![]);
snapshot.block = self.block;
snapshot.ball = self.ball.take();
snapshot.lifted_heap = mem::replace(&mut self.lifted_heap, vec![]);
snapshot
}
pub(super) fn absorb_snapshot(&mut self, mut snapshot: MachineState) {
self.hb = snapshot.hb;
self.e = snapshot.e;
self.b = snapshot.b;
self.b0 = snapshot.b0;
self.s = snapshot.s;
self.tr = snapshot.tr;
self.pstr_tr = snapshot.pstr_tr;
self.num_of_args = snapshot.num_of_args;
self.fail = snapshot.fail;
self.trail = mem::replace(&mut snapshot.trail, vec![]);
self.pstr_trail = mem::replace(&mut snapshot.pstr_trail, vec![]);
self.heap = snapshot.heap.take();
self.mode = snapshot.mode;
self.and_stack = snapshot.and_stack.take();
self.or_stack = snapshot.or_stack.take();
self.registers = mem::replace(&mut snapshot.registers, vec![]);
self.block = snapshot.block;
self.ball = snapshot.ball.take();
self.lifted_heap = mem::replace(&mut snapshot.lifted_heap, vec![]);
}
} }

View File

@@ -6,6 +6,7 @@ use crate::prolog::fixtures::*;
use crate::prolog::forms::*; use crate::prolog::forms::*;
use crate::prolog::heap_print::*; use crate::prolog::heap_print::*;
use crate::prolog::instructions::*; use crate::prolog::instructions::*;
use crate::prolog::machine::heap::Heap;
use crate::prolog::read::*; use crate::prolog::read::*;
use crate::prolog::write::{next_keypress, ContinueResult}; use crate::prolog::write::{next_keypress, ContinueResult};
@@ -71,6 +72,7 @@ impl MachinePolicies {
pub struct Machine { pub struct Machine {
pub(super) machine_st: MachineState, pub(super) machine_st: MachineState,
pub(super) inner_heap: Heap,
pub(super) policies: MachinePolicies, pub(super) policies: MachinePolicies,
pub(super) indices: IndexStore, pub(super) indices: IndexStore,
pub(super) code_repo: CodeRepo, pub(super) code_repo: CodeRepo,
@@ -227,13 +229,13 @@ impl Machine {
} }
pub fn run_init_code(&mut self, code: Code) { pub fn run_init_code(&mut self, code: Code) {
let old_machine_st = self.machine_st.sink_to_snapshot(); let old_machine_st = self.sink_to_snapshot();
self.machine_st.reset(); self.machine_st.reset();
self.code_repo.cached_query = code; self.code_repo.cached_query = code;
self.run_query(&AllocVarDict::new()); self.run_query(&AllocVarDict::new());
self.machine_st.absorb_snapshot(old_machine_st); self.absorb_snapshot(old_machine_st);
} }
pub fn run_top_level(&mut self) { pub fn run_top_level(&mut self) {
@@ -260,6 +262,7 @@ impl Machine {
pub fn new(prolog_stream: PrologStream) -> Self { pub fn new(prolog_stream: PrologStream) -> Self {
let mut wam = Machine { let mut wam = Machine {
machine_st: MachineState::new(), machine_st: MachineState::new(),
inner_heap: Heap::with_capacity(256 * 256),
policies: MachinePolicies::new(), policies: MachinePolicies::new(),
indices: IndexStore::new(), indices: IndexStore::new(),
code_repo: CodeRepo::new(), code_repo: CodeRepo::new(),
@@ -570,9 +573,14 @@ impl Machine {
}; };
let stream = parsing_stream(s.as_bytes()); let stream = parsing_stream(s.as_bytes());
let snapshot = self.sink_to_snapshot();
let policies = mem::replace(&mut self.policies, MachinePolicies::new());
let snapshot = self.machine_st.sink_to_snapshot();
self.machine_st.reset(); self.machine_st.reset();
self.machine_st.heap = mem::replace(
&mut self.inner_heap,
Heap::with_capacity(0),
);
let result = match stream_to_toplevel(stream, self) { let result = match stream_to_toplevel(stream, self) {
Ok(packet) => compile_term(self, packet), Ok(packet) => compile_term(self, packet),
@@ -580,6 +588,8 @@ impl Machine {
}; };
self.handle_eval_session(result, snapshot); self.handle_eval_session(result, snapshot);
self.indices.reset_global_variable_offsets();
self.policies = policies;
} }
REPLCodePtr::UseModule => REPLCodePtr::UseModule =>
self.use_module(ModuleSource::Library), self.use_module(ModuleSource::Library),
@@ -594,10 +604,66 @@ impl Machine {
self.machine_st.p = CodePtr::Local(p); self.machine_st.p = CodePtr::Local(p);
} }
fn sink_to_snapshot(&mut self) -> MachineState {
let mut snapshot = MachineState::with_capacity(0);
snapshot.hb = self.machine_st.hb;
snapshot.e = self.machine_st.e;
snapshot.b = self.machine_st.b;
snapshot.b0 = self.machine_st.b0;
snapshot.s = self.machine_st.s;
snapshot.tr = self.machine_st.tr;
snapshot.pstr_tr = self.machine_st.pstr_tr;
snapshot.num_of_args = self.machine_st.num_of_args;
snapshot.fail = self.machine_st.fail;
snapshot.trail = mem::replace(&mut self.machine_st.trail, vec![]);
snapshot.pstr_trail = mem::replace(&mut self.machine_st.pstr_trail, vec![]);
snapshot.heap = self.machine_st.heap.take();
snapshot.mode = self.machine_st.mode;
snapshot.and_stack = self.machine_st.and_stack.take();
snapshot.or_stack = self.machine_st.or_stack.take();
snapshot.registers = mem::replace(&mut self.machine_st.registers, vec![]);
snapshot.block = self.machine_st.block;
snapshot.ball = self.machine_st.ball.take();
snapshot.lifted_heap = mem::replace(&mut self.machine_st.lifted_heap, vec![]);
snapshot
}
fn absorb_snapshot(&mut self, mut snapshot: MachineState) {
self.machine_st.hb = snapshot.hb;
self.machine_st.e = snapshot.e;
self.machine_st.b = snapshot.b;
self.machine_st.b0 = snapshot.b0;
self.machine_st.s = snapshot.s;
self.machine_st.tr = snapshot.tr;
self.machine_st.pstr_tr = snapshot.pstr_tr;
self.machine_st.num_of_args = snapshot.num_of_args;
self.machine_st.fail = snapshot.fail;
self.machine_st.trail = mem::replace(&mut snapshot.trail, vec![]);
self.machine_st.pstr_trail = mem::replace(&mut snapshot.pstr_trail, vec![]);
self.inner_heap = self.machine_st.heap.take();
self.inner_heap.truncate(0);
self.machine_st.heap = snapshot.heap.take();
self.machine_st.mode = snapshot.mode;
self.machine_st.and_stack = snapshot.and_stack.take();
self.machine_st.or_stack = snapshot.or_stack.take();
self.machine_st.registers = mem::replace(&mut snapshot.registers, vec![]);
self.machine_st.block = snapshot.block;
self.machine_st.ball = snapshot.ball.take();
self.machine_st.lifted_heap = mem::replace(&mut snapshot.lifted_heap, vec![]);
}
fn propagate_exception_to_toplevel(&mut self, snapshot: MachineState) { fn propagate_exception_to_toplevel(&mut self, snapshot: MachineState) {
let ball = self.machine_st.ball.take(); let ball = self.machine_st.ball.take();
self.machine_st.absorb_snapshot(snapshot); self.absorb_snapshot(snapshot);
self.machine_st.ball = ball; self.machine_st.ball = ball;
let h = self.machine_st.heap.h; let h = self.machine_st.heap.h;
@@ -617,7 +683,7 @@ impl Machine {
}; };
let attr_goals = self.attribute_goals(); let attr_goals = self.attribute_goals();
if !(self.machine_st.b > 0) { if !(self.machine_st.b > 0) {
if bindings.is_empty() { if bindings.is_empty() {
let space = if requires_space(&attr_goals, ".") { let space = if requires_space(&attr_goals, ".") {
@@ -632,7 +698,7 @@ impl Machine {
println!("true."); println!("true.");
} }
self.machine_st.absorb_snapshot(snapshot); self.absorb_snapshot(snapshot);
return; return;
} }
} else if bindings.is_empty() && attr_goals.is_empty() { } else if bindings.is_empty() && attr_goals.is_empty() {
@@ -664,7 +730,7 @@ impl Machine {
} }
ContinueResult::Conclude => { ContinueResult::Conclude => {
print!(" ...\r\n"); print!(" ...\r\n");
self.machine_st.absorb_snapshot(snapshot); self.absorb_snapshot(snapshot);
return; return;
} }
}; };
@@ -676,12 +742,12 @@ impl Machine {
return; return;
} else { } else {
print!("false.\r\n"); print!("false.\r\n");
self.machine_st.absorb_snapshot(snapshot); self.absorb_snapshot(snapshot);
return; return;
} }
} }
EvalSession::Error(err) => { EvalSession::Error(err) => {
self.machine_st.absorb_snapshot(snapshot); self.absorb_snapshot(snapshot);
self.throw_session_error(err, (clause_name!("repl"), 0)); self.throw_session_error(err, (clause_name!("repl"), 0));
return; return;
} }
@@ -712,7 +778,7 @@ impl Machine {
} }
}, },
EvalSession::Error(err) => { EvalSession::Error(err) => {
self.machine_st.absorb_snapshot(snapshot); self.absorb_snapshot(snapshot);
self.throw_session_error(err, (clause_name!("repl"), 0)); self.throw_session_error(err, (clause_name!("repl"), 0));
return; return;
} }
@@ -725,7 +791,7 @@ impl Machine {
_ => println!("true.") _ => println!("true.")
} }
self.machine_st.absorb_snapshot(snapshot); self.absorb_snapshot(snapshot);
} }
pub(super) fn run_query(&mut self, alloc_locs: &AllocVarDict) { pub(super) fn run_query(&mut self, alloc_locs: &AllocVarDict) {
@@ -1046,9 +1112,15 @@ impl MachineState {
match self.p { match self.p {
CodePtr::VerifyAttrInterrupt(_) => { CodePtr::VerifyAttrInterrupt(_) => {
self.p = CodePtr::Local(self.attr_var_init.cp); self.p = CodePtr::Local(self.attr_var_init.cp);
if !self.verify_attr_stepper(indices, policies, code_repo, prolog_stream) { let instigating_p = CodePtr::Local(self.attr_var_init.instigating_p);
let instigating_instr = code_repo.lookup_instr(false, &instigating_p).unwrap();
if !instigating_instr.as_ref().is_head_instr() {
let cp = self.p.local();
self.run_verify_attr_interrupt(cp);
} else if !self.verify_attr_stepper(indices, policies, code_repo, prolog_stream) {
if self.fail { if self.fail {
break; break;
} }

View File

@@ -17,6 +17,8 @@ use crate::prolog::ordered_float::OrderedFloat;
use crate::prolog::read::{readline, PrologStream}; use crate::prolog::read::{readline, PrologStream};
use crate::prolog::rug::Integer; use crate::prolog::rug::Integer;
use crate::ref_thread_local::RefThreadLocal;
use indexmap::{IndexMap, IndexSet}; use indexmap::{IndexMap, IndexSet};
use std::collections::VecDeque; use std::collections::VecDeque;
@@ -679,7 +681,8 @@ impl MachineState {
let c = self.int_to_char_code(&n, "atom_codes", 2)?; let c = self.int_to_char_code(&n, "atom_codes", 2)?;
chars.push(c as char); 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( let err = MachineError::type_error(
ValidType::Integer, ValidType::Integer,
@@ -1018,8 +1021,14 @@ impl MachineState {
tail 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.heap[l1 + 1] = HeapCellValue::Addr(tail);
self.trail(TrailRef::AttrVarLink(l1 + 1, old_addr)); self.trail(trail_ref);
} }
} }
} }
@@ -1041,7 +1050,7 @@ impl MachineState {
}; };
self.heap[h + 1] = HeapCellValue::Addr(tail); self.heap[h + 1] = HeapCellValue::Addr(tail);
self.trail(TrailRef::AttrVarLink(h + 1, Addr::Lis(l))); self.trail(TrailRef::AttrVarListLink(h + 1, l));
} }
_ => unreachable!(), _ => unreachable!(),
} }
@@ -1255,6 +1264,19 @@ impl MachineState {
_ => self.fail = true, _ => 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 => { &SystemClauseType::OpDeclaration => {
let priority = self[temp_v!(1)].clone(); let priority = self[temp_v!(1)].clone();
let specifier = self[temp_v!(2)].clone(); let specifier = self[temp_v!(2)].clone();
@@ -1664,7 +1686,7 @@ impl MachineState {
return Ok(()); return Ok(());
} }
&SystemClauseType::ReturnFromAttributeGoals => { &SystemClauseType::ReturnFromAttributeGoals => {
self.deallocate(); self.deallocate();
self.p = CodePtr::Local(LocalCodePtr::TopLevel(0, 0)); self.p = CodePtr::Local(LocalCodePtr::TopLevel(0, 0));
return Ok(()); return Ok(());
} }
@@ -1834,6 +1856,31 @@ impl MachineState {
} }
&SystemClauseType::SetBall => &SystemClauseType::SetBall =>
self.set_ball(), 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 => &SystemClauseType::SkipMaxList =>
if let Err(err) = self.skip_max_list() { if let Err(err) = self.skip_max_list() {
return Err(err); return Err(err);