Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b1879a6fa | ||
|
|
24e5e39c28 |
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "scryer-prolog"
|
name = "scryer-prolog"
|
||||||
version = "0.8.113"
|
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"
|
||||||
|
|||||||
22
README.md
22
README.md
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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'([], _, _) --> [].
|
||||||
|
|||||||
@@ -1159,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).
|
||||||
|
|
||||||
@@ -1245,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
|
||||||
)
|
)
|
||||||
).
|
).
|
||||||
|
|
||||||
@@ -1358,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, _, _).
|
||||||
@@ -1509,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),
|
||||||
|
|||||||
@@ -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(_)) }.
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -130,11 +130,12 @@ variant(X, Y) :- '$variant'(X, Y).
|
|||||||
maybe :- '$maybe'.
|
maybe :- '$maybe'.
|
||||||
|
|
||||||
set_random(Seed) :-
|
set_random(Seed) :-
|
||||||
( nonvar(Seed) ->
|
( nonvar(Seed) ->
|
||||||
( Seed = seed(S) ->
|
( Seed = seed(S) ->
|
||||||
( integer(S) -> '$set_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(type_error(integer(S), set_random/1)))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
; throw(error(instantiation_error, set_random/1))
|
; throw(error(instantiation_error, set_random/1))
|
||||||
).
|
).
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -41,10 +43,12 @@ impl AttrVarInitializer {
|
|||||||
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);
|
||||||
@@ -127,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();
|
||||||
|
|
||||||
@@ -201,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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -469,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,
|
||||||
|
|||||||
@@ -741,29 +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];
|
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::AttrVarHeapLink(tr_i)
|
| TrailRef::AttrVarHeapLink(tr_i)
|
||||||
| TrailRef::AttrVarListLink(tr_i, _) => {
|
| TrailRef::AttrVarListLink(tr_i, _) =>
|
||||||
if tr_i < hb {
|
if tr_i >= hb {
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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
|
||||||
@@ -771,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];
|
|
||||||
self.trail[i] = val;
|
|
||||||
self.trail.pop();
|
|
||||||
self.tr -= 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.tr -= offset;
|
||||||
|
self.trail.truncate(self.tr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -1675,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 {
|
||||||
@@ -3240,6 +3231,8 @@ impl MachineState {
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.last_call = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn execute_ctrl_instr(
|
pub(super) fn execute_ctrl_instr(
|
||||||
@@ -3275,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())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3434,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![]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1686,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(());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user