[[package]]
name = "prolog_parser"
version = "0.8.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lexical 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-rug-adapter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-rug-adapter 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "prolog_parser 0.8.48",
+ "prolog_parser 0.8.48 (registry+https://github.com/rust-lang/crates.io-index)",
"ref_thread_local 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rug 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustyline 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc"
"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
+"checksum prolog_parser 0.8.48 (registry+https://github.com/rust-lang/crates.io-index)" = "301d67e5905691f8d5dc5f08c8c6e12cf849a12bea779af8b5221c35b89faf95"
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
nix = "0.15.0"
num-rug-adapter = { optional = true, version = "0.1.1" }
ordered-float = "0.5.0"
-prolog_parser = { version = "0.8.48", path = "../prolog_parser", default-features = false }
+prolog_parser = { version = "0.8.48", default-features = false }
ref_thread_local = "0.0.0"
rug = { version = "1.4.0", optional = true }
-rustyline = "6.0.0"
-
-[profile.release]
-debug = true
\ No newline at end of file
+rustyline = "6.0.0"
\ No newline at end of file
fn name_and_module(&self) -> Option<(ClauseName, ClauseName)> {
Some((self.head.0.owning_module(), self.head.0.clone()))
}
-
+
fn arity(&self) -> usize {
- self.head.1.len()
+ self.head.1.len()
}
}
}
}
-impl Number {
+impl Number {
#[inline]
pub fn is_positive(&self) -> bool {
match self {
&HeapCellValue::Addr(a) => {
self.follow(a)
}
- HeapCellValue::PartialString(_) => {
+ HeapCellValue::PartialString(..) => {
self.follow(Addr::PStrLocation(h, 0))
}
HeapCellValue::Atom(..) | HeapCellValue::DBRef(_)
da
}
Addr::PStrLocation(h, n) => {
- if let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
+ if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.machine_st.heap[h] {
if let Some(c) = pstr.range_from(n ..).next() {
if !pstr.at_end(n + c.len_utf8()) {
self.state_stack.push(Addr::PStrLocation(h, n + c.len_utf8()));
- } else {
+ } else if has_tail {
self.state_stack.push(Addr::HeapCell(h + 1));
+ } else {
+ self.state_stack.push(Addr::EmptyList);
}
self.state_stack.push(Addr::Char(c));
- } else {
- unreachable!()
+ } else if has_tail {
+ return self.follow(Addr::HeapCell(h + 1));
}
} else {
unreachable!()
self.follow_heap(s) // record terms of structure.
}
Addr::Con(h) => {
- if let HeapCellValue::PartialString(_) = &self.machine_st.heap[h] {
- self.state_stack.push(Addr::HeapCell(h + 1));
+ if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.machine_st.heap[h] {
+ if !self.machine_st.flags.double_quotes.is_atom() {
+ return if let Some(c) = pstr.range_from(0 ..).next() {
+ self.state_stack.push(Addr::PStrLocation(h, c.len_utf8()));
+ self.state_stack.push(Addr::Char(c));
+
+ Addr::PStrLocation(h, 0)
+ } else if has_tail {
+ self.follow(Addr::HeapCell(h + 1))
+ } else {
+ Addr::EmptyList
+ };
+ }
}
Addr::Con(h)
self.parent_stack.push((2, Addr::Lis(a)));
}
&HeapCellValue::Addr(Addr::PStrLocation(h, n)) => {
- if let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
- let c = pstr.range_from(n ..).next().unwrap();
- self.parent_stack.push((2, Addr::PStrLocation(h, n + c.len_utf8())));
- } else {
- unreachable!()
+ match &self.machine_st.heap[h] {
+ &HeapCellValue::PartialString(ref pstr, _) => {
+ let c = pstr.range_from(n ..).next().unwrap();
+ let next_n = n + c.len_utf8();
+
+ if !pstr.at_end(next_n) {
+ self.parent_stack.push((2, Addr::PStrLocation(h, next_n)));
+ }
+ }
+ _ => {
+ unreachable!()
+ }
}
}
_ => {
type Output;
fn new() -> Self;
- fn push_char(&mut self, _: char);
- fn append(&mut self, _: &str);
+ fn push_char(&mut self, c: char);
+ fn append(&mut self, s: &str);
fn begin_new_var(&mut self);
- fn insert(&mut self, _: usize, _: char);
+ fn insert(&mut self, index: usize, c: char);
fn result(self) -> Self::Output;
- fn ends_with(&self, _: &str) -> bool;
+ fn ends_with(&self, s: &str) -> bool;
fn len(&self) -> usize;
- fn truncate(&mut self, _: usize);
- fn range(&self, _: Range<usize>) -> &str;
- fn range_from(&self, _: RangeFrom<usize>) -> &str;
+ fn truncate(&mut self, len: usize);
+ fn range(&self, range: Range<usize>) -> &str;
+ fn range_from(&self, range: RangeFrom<usize>) -> &str;
}
pub struct PrinterOutputter {
}
}
- fn print_string_as_str(
- &mut self,
- mut h: usize,
- mut offset: usize,
- quoted: bool,
- ) {
- self.push_char('"');
-
- while let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
- let atom = String::from_iter(pstr.range_from(offset ..).map(|c| {
- char_to_string(quoted, c)
- }));
-
- self.append_str(&atom);
-
- h += 2;
- offset = 0;
- }
-
- self.push_char('"');
- }
-
fn print_string(
&mut self,
+ iter: &mut HCPreOrderIterator,
mut max_depth: usize,
- mut h: usize,
- mut offset: usize,
+ h: usize,
+ n: usize,
)
{
- if !self.machine_st.machine_flags().double_quotes.is_atom() {
- if self.check_max_depth(&mut max_depth) {
- self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
- return;
- }
-
- while let HeapCellValue::PartialString(ref pstr) = &self.machine_st.heap[h] {
- if pstr.at_end(offset) && !self.at_cdr("") {
- if let HeapCellValue::Addr(Addr::EmptyList) = &self.machine_st.heap[h+1] {
- self.append_str("[]");
- break;
- } else {
- h += 2;
- offset = 0;
- }
- } else if self.ignore_ops {
- let iter: Box<dyn Iterator<Item=char>> =
- if self.max_depth == 0 {
- Box::new(pstr.range_from(offset ..))
- } else {
- Box::new(pstr.range_from(offset ..).take(max_depth))
- };
+ iter.stack().pop();
+ iter.stack().pop();
- let mut char_count = 0;
- let mut byte_len = 0;
+ if self.check_max_depth(&mut max_depth) {
+ self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
+ return;
+ }
- for c in iter {
- self.print_char(self.quoted, '.');
- self.push_char('(');
+ let mut heap_pstr_iter =
+ self.machine_st.heap_pstr_iter(Addr::PStrLocation(h, n));
- self.print_char(self.quoted, c);
- self.push_char(',');
+ let mut buf = String::new();
- char_count += 1;
- byte_len += c.len_utf8();
- }
+ while let Some(Some(c)) = heap_pstr_iter.next() {
+ buf.push(c);
+ }
- let mut at_end = false;
-
- if self.max_depth > 0 && !pstr.at_end(offset + byte_len) {
- self.append_str("...");
- at_end = true;
- } else {
- if let HeapCellValue::Addr(Addr::EmptyList) = &self.machine_st.heap[h+1] {
- self.append_str("[]");
- at_end = true;
+ let end_addr =
+ if let &HeapCellValue::PartialString(_, has_tail) = &self.machine_st.heap[h] {
+ if has_tail {
+ self.machine_st.store(self.machine_st.deref(heap_pstr_iter.focus()))
+ } else {
+ Addr::EmptyList
+ }
+ } else {
+ unreachable!()
+ };
+
+ if let Addr::EmptyList = end_addr {
+ if !self.machine_st.flags.double_quotes.is_codes() {
+ self.push_char('"');
+
+ let buf =
+ if max_depth == 0 {
+ String::from_iter(buf.chars().map(|c| {
+ char_to_string(self.quoted, c)
+ }))
+ } else {
+ let mut char_count = 0;
+ let mut buf =
+ String::from_iter(buf.chars().take(max_depth).map(|c| {
+ char_count += 1;
+ char_to_string(self.quoted, c)
+ }));
+
+ if char_count == max_depth {
+ buf += " ...";
}
- }
- for _ in 0 .. char_count {
- self.push_char(')');
- }
+ buf
+ };
- if at_end {
- break;
- }
+ self.append_str(&buf);
+ self.push_char('"');
- max_depth -= char_count;
- } else {
- self.push_char('[');
+ return;
+ }
+ }
- let iter: Box<dyn Iterator<Item=char>> =
- if self.max_depth == 0 {
- Box::new(pstr.range_from(offset ..))
- } else {
- Box::new(pstr.range_from(offset ..).take(max_depth))
- };
+ let buf_len = buf.len();
- let mut byte_len = 0;
- let mut char_count = 0;
+ let buf_iter: Box<dyn Iterator<Item=char>> =
+ if self.max_depth == 0 {
+ Box::new(buf.chars())
+ } else {
+ Box::new(buf.chars().take(max_depth))
+ };
- for c in iter {
- self.print_char(false, c);
- self.push_char(',');
+ let mut byte_len = 0;
- byte_len += c.len_utf8();
- char_count += 1;
- }
+ let char_printer = |printer: &mut Self, c| {
+ if printer.machine_st.flags.double_quotes.is_codes() {
+ let s = (c as u32).to_string();
- if self.max_depth > 0 && !pstr.at_end(offset + byte_len) {
- self.append_str("...|...]");
- break;
- } else {
- self.outputter.truncate(self.outputter.len() - ','.len_utf8());
- self.push_char(']');
- }
+ push_space_if_amb!(printer, &s, {
+ printer.append_str(&s);
+ });
+ } else {
+ printer.print_char(printer.quoted, c);
+ }
+ };
- max_depth -= char_count;
- }
+ if self.ignore_ops {
+ let mut char_count = 0;
+
+ for c in buf_iter {
+ self.push_char('.');
+ self.push_char('(');
+
+ char_printer(self, c);
+ self.push_char(',');
+
+ char_count += 1;
+ byte_len += c.len_utf8();
+ }
+
+ for _ in 0 .. char_count {
+ self.state_stack.push(TokenOrRedirect::Close);
+ }
- h += 2;
- offset = 0;
+ if self.max_depth > 0 && buf_len > byte_len {
+ self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
+ } else {
+ self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
+ iter.stack().push(end_addr);
}
} else {
- self.print_string_as_str(h, 0, self.quoted);
+ let switch = if !self.at_cdr(",") {
+ self.push_char('[');
+ true
+ } else {
+ false
+ };
+
+ for c in buf_iter {
+ char_printer(self, c);
+ self.push_char(',');
+
+ byte_len += c.len_utf8();
+ }
+
+ self.state_stack.push(TokenOrRedirect::CloseList(Rc::new(
+ Cell::new((switch, 0))
+ )));
+
+ if self.max_depth > 0 && buf_len > byte_len {
+ self.state_stack.push(TokenOrRedirect::Atom(clause_name!("...")));
+ } else {
+ self.outputter.truncate(self.outputter.len() - ','.len_utf8());
+ self.state_stack.push(TokenOrRedirect::FunctorRedirect(max_depth));
+
+ iter.stack().push(end_addr);
+ }
+
+ self.state_stack.push(TokenOrRedirect::HeadTailSeparator);
}
}
Some(addr) => addr,
None => return,
};
-
+
match self.machine_st.heap.index_addr(&addr).as_ref() {
&HeapCellValue::NamedStr(arity, ref name, ref spec) => {
let spec = fetch_op_spec(name.clone(), arity, spec.clone(), self.op_dir);
&HeapCellValue::Addr(Addr::Usize(u)) => {
self.append_str(&format!("{}", u));
}
- &HeapCellValue::Addr(Addr::PStrLocation(..))
- if !self.machine_st.flags.double_quotes.is_atom() => {
- if self.ignore_ops {
- self.format_struct(iter, max_depth, 2, clause_name!("."));
- } else {
- self.push_list(iter, max_depth);
- }
- }
&HeapCellValue::Addr(Addr::PStrLocation(h, n)) => {
- if let HeapCellValue::PartialString(_) = &self.machine_st.heap[h] {
- self.print_string(max_depth, h, n);
-
- iter.stack().pop();
- iter.stack().pop();
- } else {
- unreachable!()
- }
+ self.print_string(iter, max_depth, h, n);
}
&HeapCellValue::Addr(Addr::Lis(_)) => {
if self.ignore_ops {
&HeapCellValue::Rational(ref n) => {
self.print_number(Number::Rational(n.clone()), &op);
}
- &HeapCellValue::PartialString(_)
- if self.print_strings_as_strs => {
- if let Addr::Con(h) = addr {
- self.print_string_as_str(h, 0, true);
- } else {
- unreachable!()
- }
- }
- &HeapCellValue::PartialString(_) => {
- if let Addr::Con(h) = addr {
- self.print_string(max_depth, h, 0);
- } else {
- unreachable!()
- }
- }
&HeapCellValue::Stream(ref stream) => {
if let Some(alias) = &stream.options.alias {
self.print_atom(alias);
}
}
_ => {
+ unreachable!()
}
}
}
functor!(
"get_constant",
- [aux(h, 0), constant(c), aux(h, 1)],
+ [aux(h, 0), constant(h, c), aux(h, 1)],
[lvl_stub, rt_stub]
)
}
)
}
&FactInstruction::UnifyConstant(ref c) => {
- functor!("unify_constant", [constant(c)], [])
+ functor!("unify_constant", [constant(h, c)], [])
}
&FactInstruction::UnifyLocalValue(r) => {
let rt_stub = reg_type_into_functor(r);
functor!(
"put_constant",
- [aux(h, 0), constant(c), aux(h, 1)],
+ [aux(h, 0), constant(h, c), aux(h, 1)],
[lvl_stub, rt_stub]
)
}
)
}
&QueryInstruction::SetConstant(ref c) => {
- functor!("set_constant", [constant(c)], [])
+ functor!("set_constant", [constant(h, c)], [])
}
&QueryInstruction::SetLocalValue(r) => {
let rt_stub = reg_type_into_functor(r);
'$put_attr'(V, Attr)),
(put_atts(V, Attr) :- !, functor(Attr, Head, Arity),
functor(AttrForm, Head, Arity),
- '$get_attr_list'(V, Ls),
- '$del_attr'(Ls, V, AttrForm),
+ '$get_attr_list'(V, Ls),
+ '$del_attr'(Ls, V, AttrForm),
'$put_attr'(V, Attr)),
(put_atts(V, -Attr) :- !, functor(Attr, _, _),
- '$get_attr_list'(V, Ls),
+ '$get_attr_list'(V, Ls),
'$del_attr'(Ls, V, Attr))].
get_attr(Name, Arity) -->
'$get_attr_var_queue_delim'(B),
call(Goal),
'$get_attr_var_queue_beyond'(B, Vars).
-
Term =.. List :- '$call_with_default_policy'(univ_errors(Term, List, N)),
'$call_with_default_policy'(univ_worker(Term, List, N)).
+
:- non_counted_backtracking univ_worker/3.
-univ_worker(Term, List, _) :- atomic(Term), !, '$call_with_default_policy'(List = [Term]).
+
+univ_worker(Term, List, _) :-
+ atomic(Term), !, '$call_with_default_policy'(List = [Term]).
univ_worker(Term, [Name|Args], N) :-
var(Term), !,
'$call_with_default_policy'(Arity is N-1),
'$call_with_default_policy'(get_args(Args, Term, 1, Arity)),
'$call_with_default_policy'(List = [Name|Args]).
+
:- non_counted_backtracking get_args/4.
+
get_args(Args, _, _, 0) :-
!, '$call_with_default_policy'(Args = []).
get_args([Arg], Func, N, N) :-
% write, write_canonical, writeq, write_term.
is_write_option(Functor) :-
Functor =.. [Name, Arg],
- ( Arg == true -> true
- ; Arg == false -> true
- ; Name == variable_names -> must_be_var_names_list(Arg)
- ; Name == max_depth -> integer(Arg), Arg >= 0
- ; var(Arg) -> throw(error(instantiation_error, write_term/2))
- ; throw(error(domain_error(write_option, Functor), write_term/2))
+ ( Arg == true -> true
+ ; Arg == false -> true
+ ; Name == variable_names -> must_be_var_names_list(Arg)
+ ; Name == max_depth -> integer(Arg), Arg >= 0
+ ; var(Arg) -> throw(error(instantiation_error, write_term/2))
+ ; throw(error(domain_error(write_option, Functor), write_term/2))
), % 8.14.2.3 e)
- ( Name == ignore_ops -> true
- ; Name == quoted -> true
- ; Name == numbervars -> true
- ; Name == variable_names -> true
- ; Name == max_depth -> true
- ; throw(error(domain_error(write_option, Functor), write_term/2))
+ ( Name == ignore_ops -> true
+ ; Name == quoted -> true
+ ; Name == numbervars -> true
+ ; Name == variable_names -> true
+ ; Name == max_depth -> true
+ ; throw(error(domain_error(write_option, Functor), write_term/2))
). % 8.14.2.3 e)
inst_member_or([X|Xs], Y, Z) :-
-
:- module(cont, [reset/3, shift/1]).
reset(Goal, Ball, Cont) :-
'$bind_from_register'(Cont, 3),
'$bind_from_register'(Ball, 4).
-shift(Term) :-
+shift(Ball) :-
'$nextEP'(first, E, P),
get_chunks(E, P, L),
( L == [] ->
Cont = none
; Cont = cont(call_continuation(L))
),
- '$write_cont_and_term'(_, _, Cont, Term),
+ '$write_cont_and_term'(_, _, Cont, Ball),
'$unwind_environments'.
get_chunks(E, P, L) :-
delim(Wrapper,Worker,Table) :-
% debug(tabling, 'ACT: ~p on ~p', [Wrapper, Table]),
- reset(Worker,SourceCall,Continuation),
+ reset(Worker,SourceCall,Continuation),
( Continuation == none, var(SourceCall) ->
( add_answer(Table,Wrapper)
-> true %debug(tabling, 'ADD: ~p', [Wrapper])
)
;
( Continuation = cont(Cont) ->
- true
+ true
; Continuation = none ->
- Cont = true
+ Cont = true
),
SourceCall = call_info(_,SourceTable),
TargetCall = call_info(Wrapper,Table),
fail
;
true
- ).
+ ).
table_get_work(NBWorklistID,Answer,Dependency) :-
% get_worklist(Table, Worklist),
table_get_work_(NBWorklistID,Answer,Dependency) :-
worklist_do_all_work(NBWorklistID,Answer,Dependency0), % This will eventually fail
copy_term(Dependency0,Dependency).
-
+
table_get_work_(NBWorklistID,_Answer,_Dependency) :-
bb_get(NBWorklistID, table_nb_worklist(Worklist)),
unset_flag_executing_all_work(Worklist),
dll_get_pointer_to_previous(List, Prev),
dll_get_reverse_contents_(Prev, Rest)
).
-
-/* Ported to Scryer Prolog by Mark Thom (2019/2020).
+/* Ported to Scryer Prolog by Mark Thom (2019/2020).
*/
:- module(global_worklist,
bb_b_put(table_global_worklist_initialized, [])
).
-add_to_global_worklist(TableIdentifier) :-
+add_to_global_worklist(TableIdentifier) :-
bb_get(table_global_worklist, TableGlobalWorklistFlag),
get_atts(TableGlobalWorklistFlag, table_global_worklist(L1)),
put_atts(TableGlobalWorklistFlag, table_global_worklist([TableIdentifier|L1])),
pop_worklist(TableIdentifier) :-
bb_get(table_global_worklist,TableGlobalWorklistFlag),
- get_atts(TableGlobalWorklistFlag, table_global_worklist(L1)),
+ get_atts(TableGlobalWorklistFlag, table_global_worklist(L1)),
L1 = [TableIdentifier|L2],
put_atts(TableGlobalWorklistFlag, table_global_worklist(L2)),
bb_put(table_global_worklist, TableGlobalWorklistFlag).
% Look in the right part of the assoc tree.
trie_insert_1_1(R,Assoc,FunctorData,Trie,First,Rest,Value).
-trie_insert_2(RegularTerm,Rest,Trie,Value) :-
+trie_insert_2(RegularTerm,Rest,Trie,Value) :-
p_trie_arity_univ(RegularTerm,FunctorData,KList),
append(KList,Rest,KList2),
trie_insert_1(KList2,FunctorData,Trie,Value).
&HeapCellValue::Addr(Addr::Float(n)) => {
interms.push(Number::Float(n))
}
+ &HeapCellValue::Addr(Addr::Usize(n)) => {
+ interms.push(Number::Integer(Rc::new(Integer::from(n))));
+ }
+ &HeapCellValue::Addr(Addr::CharCode(n)) => {
+ interms.push(Number::Integer(Rc::new(Integer::from(n))));
+ }
&HeapCellValue::Rational(ref n) => {
interms.push(Number::Rational(n.clone()))
}
call_verify_attributes([], _, _, []).
call_verify_attributes([Attr|Attrs], Var, Value, ListOfGoalLists) :-
gather_modules([Attr|Attrs], Modules0),
- sort(Modules0, Modules),
+ sort(Modules0, Modules),
verify_attrs(Modules, Var, Value, ListOfGoalLists).
verify_attrs([Module|Modules], Var, Value, [Goals|ListOfGoalLists]) :-
catch(Module:verify_attributes(Var, Value, Goals),
error(evaluation_error((Module:verify_attributes)/3), verify_attributes/3),
- Goals = []),
+ Goals = []),
verify_attrs(Modules, Var, Value, ListOfGoalLists).
verify_attrs([], _, _, []).
}
impl AttrVarInitializer {
- pub(super) fn new(verify_attrs_loc: usize, project_attrs_loc: usize) -> Self {
+ pub(super)
+ fn new(verify_attrs_loc: usize, project_attrs_loc: usize) -> Self {
AttrVarInitializer {
attribute_goals: vec![],
attr_var_queue: vec![],
}
#[inline]
- pub(super) fn reset(&mut self) {
- self.attribute_goals.clear();
+ pub(super)
+ fn reset(&mut self) {
+ self.attribute_goals.clear();
self.attr_var_queue.clear();
self.bindings.clear();
}
#[inline]
- pub(super) fn backtrack(&mut self, queue_b: usize, bindings_b: usize) {
+ pub(super)
+ fn backtrack(&mut self, queue_b: usize, bindings_b: usize) {
self.attr_var_queue.truncate(queue_b);
self.bindings.truncate(bindings_b);
}
}
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() {
self.attr_var_init.instigating_p = self.p.local();
self[temp_v!(2)] = value_list_addr;
}
- pub(super) fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter<Addr> {
+ pub(super)
+ fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter<Addr> {
let mut attr_vars: Vec<_> = self.attr_var_init.attr_var_queue[b..]
.iter()
.filter_map(|h| match self.store(self.deref(Addr::HeapCell(*h))) {
attr_vars.into_iter()
}
- pub(super) fn verify_attr_interrupt(&mut self, p: usize) {
+ pub(super)
+ fn verify_attr_interrupt(&mut self, p: usize) {
self.allocate(self.num_of_args + 2);
let e = self.e;
scan: usize,
old_h: usize,
target: T,
- attr_var_policy: AttrVarPolicy
+ attr_var_policy: AttrVarPolicy,
}
impl<T: CopierTarget> CopyTermState<T> {
fn new(target: T, attr_var_policy: AttrVarPolicy) -> Self {
CopyTermState {
- trail: vec![],
+ trail: Trail::new(),
scan: 0,
old_h: target.threshold(),
target,
&mut self.target[scan]
}
- fn copied_list(&mut self, addr: usize) -> bool {
- match &self.target[addr] {
- HeapCellValue::Addr(Addr::Lis(addr)) | HeapCellValue::Addr(Addr::HeapCell(addr)) => {
- if *addr >= self.old_h {
- *self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(*addr));
- self.scan += 1;
- return true;
- }
- }
- _ => {}
- };
-
- false
- }
-
fn copy_list(&mut self, addr: usize) {
- if self.copied_list(addr) {
- return;
+ if let Addr::Lis(h) = self.target[addr + 1].as_addr(addr + 1) {
+ if h >= self.old_h {
+ *self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(h));
+ self.scan += 1;
+
+ return;
+ }
}
let threshold = self.target.threshold();
*self.value_at_scan() = HeapCellValue::Addr(Addr::Lis(threshold));
- let ra = self.target[addr].as_addr(threshold);
- let rd = self.target.store(self.target.deref(ra));
-
- self.target.push(HeapCellValue::Addr(ra));
+ for i in 0 .. 2 {
+ let hcv = self.target[addr + i].context_free_clone();
+ self.target.push(hcv);
+ }
- let hcv = HeapCellValue::Addr(self.target[addr + 1].as_addr(addr + 1));
+ let cdr = self.target.store(self.target.deref(Addr::HeapCell(addr + 1)));
- self.target.push(hcv);
+ if let Addr::Lis(_) = cdr {
+ let tail_addr = self.target[addr + 1].as_addr(addr + 1);
- match rd {
- Addr::AttrVar(h) | Addr::HeapCell(h)
- if h >= self.old_h => {
- self.target[threshold] = HeapCellValue::Addr(rd)
- }
- var @ Addr::AttrVar(_)
- | var @ Addr::HeapCell(..)
- | var @ Addr::StackCell(..) => {
- if ra == rd {
- self.reinstantiate_var(var, threshold);
-
- if let AttrVarPolicy::StripAttributes = self.attr_var_policy {
- self.trail.push((Ref::HeapCell(addr), HeapCellValue::Addr(ra)));
- self.target[addr] = HeapCellValue::Addr(Addr::HeapCell(threshold));
- }
- } else {
- self.target[threshold] = HeapCellValue::Addr(ra);
- }
- }
- _ => {
- self.trail.push((
- Ref::HeapCell(addr),
- HeapCellValue::Addr(self.target[addr].as_addr(addr)),
- ));
+ self.trail.push((
+ Ref::HeapCell(addr + 1),
+ HeapCellValue::Addr(tail_addr),
+ ));
- self.target[addr] = HeapCellValue::Addr(Addr::Lis(threshold))
- }
- };
+ self.target[addr + 1] = HeapCellValue::Addr(Addr::Lis(threshold));
+ }
self.scan += 1;
}
- fn copied_partial_string(&mut self, addr: usize) -> bool {
- if let &HeapCellValue::Addr(Addr::PStrLocation(h, n)) = &self.target[addr + 1] {
+ fn copy_partial_string(&mut self, addr: usize, n: usize) {
+ if let &HeapCellValue::Addr(Addr::PStrLocation(h, _)) = &self.target[addr] {
if h >= self.old_h {
*self.value_at_scan() = HeapCellValue::Addr(Addr::PStrLocation(h, n));
self.scan += 1;
- return true;
+
+ return;
}
}
- false
- }
-
- fn copy_partial_string(&mut self, addr: usize, n: usize) {
let threshold = self.target.threshold();
- let tail_addr = self.target[addr + 1].as_addr(addr + 1);
- let trail_item = mem::replace(
- &mut self.target[addr + 1],
- HeapCellValue::Addr(Addr::PStrLocation(threshold, 0)),
- );
+ *self.value_at_scan() =
+ HeapCellValue::Addr(Addr::PStrLocation(threshold, 0));
- self.trail.push((
- Ref::HeapCell(addr + 1),
- trail_item,
- ));
+ self.scan += 1;
- let pstr =
+ let (pstr, has_tail) =
match &self.target[addr] {
- HeapCellValue::PartialString(ref pstr) => {
- pstr.clone_from_offset(n)
+ &HeapCellValue::PartialString(ref pstr, has_tail) => {
+ (pstr.clone_from_offset(n), has_tail)
}
_ => {
unreachable!()
}
};
- self.target.push(HeapCellValue::PartialString(pstr));
- self.target.push(HeapCellValue::Addr(tail_addr));
- }
+ self.target.push(HeapCellValue::PartialString(pstr, has_tail));
- fn copy_partial_string_from(&mut self, addr: usize, n: usize) {
- if self.copied_partial_string(addr) {
- return;
- }
+ let replacement = HeapCellValue::Addr(Addr::PStrLocation(threshold, 0));
- let threshold = self.target.threshold();
-
- self.target[self.scan] =
- HeapCellValue::Addr(Addr::PStrLocation(threshold, 0));
+ let trail_item = mem::replace(
+ &mut self.target[addr],
+ replacement,
+ );
- self.scan += 1;
+ self.trail.push((
+ Ref::HeapCell(addr),
+ trail_item,
+ ));
- self.copy_partial_string(addr, n);
+ if has_tail {
+ let tail_addr = self.target[addr + 1].as_addr(addr + 1);
+ self.target.push(HeapCellValue::Addr(tail_addr));
+ }
}
fn reinstantiate_var(&mut self, addr: Addr, frontier: usize) {
Addr::HeapCell(h) => {
self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(frontier));
self.target[h] = HeapCellValue::Addr(Addr::HeapCell(frontier));
+
self.trail.push((
Ref::HeapCell(h),
HeapCellValue::Addr(Addr::HeapCell(h)),
Addr::StackCell(fr, sc) => {
self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(frontier));
self.target.stack().index_and_frame_mut(fr)[sc] = Addr::HeapCell(frontier);
+
self.trail.push((
Ref::StackCell(fr, sc),
HeapCellValue::Addr(Addr::StackCell(fr, sc)),
};
self.target[frontier] = HeapCellValue::Addr(Addr::HeapCell(threshold));
- self.target[h] = HeapCellValue::Addr(Addr::HeapCell(threshold));
+ self.target[h] = HeapCellValue::Addr(Addr::HeapCell(frontier));
+
self.trail.push((
Ref::AttrVar(h),
HeapCellValue::Addr(Addr::AttrVar(h)),
self.target.push(list_val);
}
}
- _ => unreachable!()
+ _ => {
+ unreachable!()
+ }
}
}
}
}
+ fn copy_stream(&mut self, addr: usize) {
+ let threshold = self.target.threshold();
+
+ let trail_item = mem::replace(
+ &mut self.target[addr],
+ HeapCellValue::Addr(Addr::Stream(threshold)),
+ );
+
+ self.trail.push((
+ Ref::HeapCell(addr),
+ trail_item,
+ ));
+
+ self.target.push(HeapCellValue::Stream(Stream::null_stream()));
+
+ self.scan += 1;
+ }
+
fn copy_structure(&mut self, addr: usize) {
match self.target[addr].context_free_clone() {
HeapCellValue::NamedStr(arity, name, fixity) => {
let threshold = self.target.threshold();
*self.value_at_scan() = HeapCellValue::Addr(Addr::Str(threshold));
- self.target[addr] = HeapCellValue::Addr(Addr::Str(threshold));
+
+ let trail_item = mem::replace(
+ &mut self.target[addr],
+ HeapCellValue::Addr(Addr::Str(threshold)),
+ );
self.trail.push((
Ref::HeapCell(addr),
- HeapCellValue::NamedStr(arity, name.clone(), fixity.clone()),
+ trail_item,
));
self.target.push(HeapCellValue::NamedStr(arity, name, fixity));
HeapCellValue::Addr(Addr::Str(addr)) => {
*self.value_at_scan() = HeapCellValue::Addr(Addr::Str(addr))
}
- _ => {}
+ _ => {
+ unreachable!()
+ }
}
self.scan += 1;
&mut HeapCellValue::Addr(addr) => {
match addr {
Addr::Con(h) => {
- self.target.push(self.target[h].context_free_clone());
- self.scan += 1;
- }
- Addr::Stream(_) => {
- self.target.push(HeapCellValue::Stream(Stream::null_stream()));
- self.scan += 1;
+ let addr = self.target[h].as_addr(h);
+
+ if addr == Addr::Con(h) {
+ *self.value_at_scan() = self.target[h].context_free_clone();
+ } else {
+ *self.value_at_scan() = HeapCellValue::Addr(addr);
+ }
}
Addr::Lis(h) => {
self.copy_list(h);
}
- addr @ Addr::AttrVar(_)
- | addr @ Addr::HeapCell(_)
- | addr @ Addr::StackCell(..) => {
+ addr @ Addr::AttrVar(_) |
+ addr @ Addr::HeapCell(_) |
+ addr @ Addr::StackCell(..) => {
self.copy_var(addr);
}
Addr::Str(addr) => {
self.copy_structure(addr);
}
Addr::PStrLocation(addr, n) => {
- self.copy_partial_string_from(addr, n);
+ self.copy_partial_string(addr, n);
+ }
+ Addr::Stream(h) => {
+ self.copy_stream(h);
}
_ => {
self.scan += 1;
};
let arity = match self.machine_st.store(self.machine_st.deref(arity)) {
- Addr::Con(h) =>
+ Addr::Con(h) => {
if let HeapCellValue::Integer(ref arity) = &self.machine_st.heap[h] {
arity.to_usize().unwrap()
} else {
unreachable!()
- },
- _ => unreachable!(),
+ }
+ }
+ Addr::Usize(n) => {
+ n
+ }
+ _ => {
+ unreachable!()
+ }
};
(name, arity)
}
pub(crate)
-struct HeapIntoIterator<T: RawBlockTraits> {
+struct HeapIntoIter<T: RawBlockTraits> {
offset: usize,
buf: RawBlock<T>,
}
-impl<T: RawBlockTraits> Drop for HeapIntoIterator<T> {
+impl<T: RawBlockTraits> Drop for HeapIntoIter<T> {
fn drop(&mut self) {
let mut heap =
HeapTemplate { buf: self.buf.take(), _marker: PhantomData };
}
}
-impl<T: RawBlockTraits> Iterator for HeapIntoIterator<T> {
+impl<T: RawBlockTraits> Iterator for HeapIntoIter<T> {
type Item = HeapCellValue;
fn next(&mut self) -> Option<Self::Item> {
}
pub(crate)
-struct HeapIterator<'a, T: RawBlockTraits> {
+struct HeapIter<'a, T: RawBlockTraits> {
offset: usize,
buf: &'a RawBlock<T>,
}
-impl<'a, T: RawBlockTraits> HeapIterator<'a, T> {
+impl<'a, T: RawBlockTraits> HeapIter<'a, T> {
pub(crate)
fn new(buf: &'a RawBlock<T>, offset: usize) -> Self {
- HeapIterator { buf, offset }
+ HeapIter { buf, offset }
}
}
-impl<'a, T: RawBlockTraits> Iterator for HeapIterator<'a, T> {
+impl<'a, T: RawBlockTraits> Iterator for HeapIter<'a, T> {
type Item = &'a HeapCellValue;
fn next(&mut self) -> Option<Self::Item> {
}
}
+#[allow(dead_code)]
pub(crate)
-struct HeapIteratorMut<'a, T: RawBlockTraits> {
+fn print_heap_terms<'a, I: Iterator<Item = &'a HeapCellValue>>(heap: I, h: usize) {
+ for (index, term) in heap.enumerate() {
+ println!("{} : {}", h + index, term);
+ }
+}
+
+pub(crate)
+struct HeapIterMut<'a, T: RawBlockTraits> {
offset: usize,
buf: &'a mut RawBlock<T>,
}
-impl<'a, T: RawBlockTraits> HeapIteratorMut<'a, T> {
+impl<'a, T: RawBlockTraits> HeapIterMut<'a, T> {
pub(crate)
fn new(buf: &'a mut RawBlock<T>, offset: usize) -> Self {
- HeapIteratorMut { buf, offset }
+ HeapIterMut { buf, offset }
}
}
-impl<'a, T: RawBlockTraits> Iterator for HeapIteratorMut<'a, T> {
+impl<'a, T: RawBlockTraits> Iterator for HeapIterMut<'a, T> {
type Item = &'a mut HeapCellValue;
fn next(&mut self) -> Option<Self::Item> {
&HeapCellValue::Rational(ref r) => {
HeapCellValue::Rational(r.clone())
}
- &HeapCellValue::PartialString(_) => {
+ &HeapCellValue::PartialString(..) => {
HeapCellValue::Addr(Addr::PStrLocation(h, 0))
}
&HeapCellValue::Stream(_) => {
}
}
+ #[inline]
+ fn pop(&mut self) {
+ let h = self.h();
+
+ if h > 0 {
+ self.truncate(h - 1);
+ }
+ }
+
#[inline]
pub(crate)
fn put_constant(&mut self, c: Constant) -> Addr {
Addr::Con(self.push(HeapCellValue::Atom(name, op)))
}
Constant::Char(c) => {
- self.push(HeapCellValue::Addr(Addr::Char(c)));
Addr::Char(c)
}
Constant::CharCode(c) => {
- self.push(HeapCellValue::Addr(Addr::CharCode(c)));
Addr::CharCode(c)
}
- Constant::CutPoint(cp) => {
- self.push(HeapCellValue::Addr(Addr::CutPoint(cp)));
- Addr::CutPoint(cp)
- }
Constant::EmptyList => {
- self.push(HeapCellValue::Addr(Addr::EmptyList));
Addr::EmptyList
}
Constant::Integer(n) => {
- Addr::Con(self.push(HeapCellValue::Integer(n)))
+ Addr::Con(self.push(HeapCellValue::Integer(n)))
}
Constant::Rational(r) => {
Addr::Con(self.push(HeapCellValue::Rational(r)))
}
Constant::Float(f) => {
- self.push(HeapCellValue::Addr(Addr::Float(f)));
Addr::Float(f)
}
Constant::String(s) => {
- let addr = self.allocate_pstr(&s);
- let h = self.h();
-
- self[h - 1] = HeapCellValue::Addr(Addr::EmptyList);
- addr
+ if s.is_empty() {
+ Addr::EmptyList
+ } else {
+ let addr = self.allocate_pstr(&s);
+ self.pop();
+
+ let h = self.h();
+
+ match &mut self[h - 1] {
+ &mut HeapCellValue::PartialString(_, ref mut has_tail) => {
+ *has_tail = false;
+ }
+ _ => {
+ unreachable!()
+ }
+ }
+
+ addr
+ }
}
Constant::Usize(n) => {
- self.push(HeapCellValue::Addr(Addr::Usize(n)));
Addr::Usize(n)
}
}
false
}
}
-
+
#[inline]
pub(crate)
fn integer_at(&self, h: usize) -> bool {
val @ HeapCellValue::Stream(..) => {
Addr::Stream(self.push(val))
}
- val @ HeapCellValue::PartialString(_) => {
- let h = self.push(val);
- self.push(HeapCellValue::Addr(Addr::EmptyList));
+ HeapCellValue::PartialString(pstr, has_tail) => {
+ let h = self.push(HeapCellValue::PartialString(pstr, has_tail));
+
+ if has_tail {
+ self.push(HeapCellValue::Addr(Addr::EmptyList));
+ }
Addr::Con(h)
}
let h = self.h();
self.push(HeapCellValue::PartialString(
- PartialString::empty()
+ PartialString::empty(),
+ true,
));
self.push(HeapCellValue::Addr(
}
};
- self.push(HeapCellValue::PartialString(pstr));
+ self.push(HeapCellValue::PartialString(pstr, true));
if rest_src != "" {
self.push(HeapCellValue::Addr(Addr::PStrLocation(h + 2, 0)));
self.push(HeapCellValue::Addr(Addr::Lis(h + 1)));
self.push(value);
- h += mem::size_of::<HeapCellValue>() * 2;
+ h += 2;
}
self.push(HeapCellValue::Addr(Addr::EmptyList));
/* Create an iterator starting from the passed offset. */
pub(crate)
- fn iter_from<'a>(&'a self, offset: usize) -> HeapIterator<'a, T> {
- HeapIterator::new(&self.buf, offset * mem::size_of::<HeapCellValue>())
+ fn iter_from<'a>(&'a self, offset: usize) -> HeapIter<'a, T> {
+ HeapIter::new(&self.buf, offset * mem::size_of::<HeapCellValue>())
}
pub(crate)
- fn iter_mut_from<'a>(&'a mut self, offset: usize) -> HeapIteratorMut<'a, T> {
- HeapIteratorMut::new(&mut self.buf, offset * mem::size_of::<HeapCellValue>())
+ fn iter_mut_from<'a>(&'a mut self, offset: usize) -> HeapIterMut<'a, T> {
+ HeapIterMut::new(&mut self.buf, offset * mem::size_of::<HeapCellValue>())
}
pub(crate)
- fn into_iter(mut self) -> HeapIntoIterator<T> {
- HeapIntoIterator { buf: self.buf.take(), offset: 0 }
+ fn into_iter(mut self) -> HeapIntoIter<T> {
+ HeapIntoIter { buf: self.buf.take(), offset: 0 }
}
pub(crate)
SharedOpDesc::new(400, YFX),
[clause_name(name), integer(arity)]
);
-
+
let stub = functor!(
"existence_error",
[atom("procedure"), aux(h, 0)],
fn domain_error<T: DomainError>(error: DomainErrorType, culprit: T) -> Self {
culprit.domain_error(error)
}
-
+
pub(super)
fn instantiation_error() -> Self {
let stub = functor!("instantiation_error");
let location = err.line_and_col_num();
let stub = functor!(err.as_str());
-
+
let stub = functor!(
"syntax_error",
[aux(h, 0)],
pub(super)
fn check_keysort_errors(&self) -> CallResult {
let stub = MachineError::functor_stub(clause_name!("keysort"), 2);
-
+
let pairs = self.store(self.deref(self[temp_v!(1)].clone()));
let sorted = self.store(self.deref(self[temp_v!(2)].clone()));
}
impl Addr {
+ #[inline]
+ pub fn is_heap_bound(&self) -> bool {
+ match self {
+ Addr::Char(_) | Addr::CharCode(_) | Addr::EmptyList
+ | Addr::CutPoint(_) | Addr::Usize(_) | Addr::Float(_) => {
+ false
+ }
+ _ => {
+ true
+ }
+ }
+ }
+
+ #[inline]
pub fn is_ref(&self) -> bool {
match self {
Addr::HeapCell(_) | Addr::StackCell(_, _) | Addr::AttrVar(_) => {
}
}
+ #[inline]
pub fn as_var(&self) -> Option<Ref> {
match self {
&Addr::AttrVar(h) => Some(Ref::AttrVar(h)),
}
pub(super)
- fn order_category(&self, heap: &Heap) -> Option<TermOrderCategory> {
+ fn order_category(&self, heap: &Heap) -> Option<TermOrderCategory> {
match self {
Addr::HeapCell(_) | Addr::AttrVar(_) | Addr::StackCell(..) => {
Some(TermOrderCategory::Variable)
}
}
}
- Addr::Char(_) | Addr::CharCode(_) | Addr::EmptyList => {
+ Addr::Char(_) | Addr::EmptyList => {
Some(TermOrderCategory::Atom)
}
+ Addr::Usize(_) | Addr::CharCode(_) => {
+ Some(TermOrderCategory::Integer)
+ }
Addr::Lis(_) | Addr::PStrLocation(..) | Addr::Str(_) => {
Some(TermOrderCategory::Compound)
}
- Addr::CutPoint(_) | Addr::Usize(_) | Addr::Stream(_) => {
+ Addr::CutPoint(_) | Addr::Stream(_) => {
None
}
}
}
-
+
pub fn as_constant(&self, machine_st: &MachineState) -> Option<Constant> {
match self {
&Addr::Char(c) => {
}
}
}
+ &Addr::EmptyList => {
+ Some(Constant::EmptyList)
+ }
&Addr::Float(f) => {
Some(Constant::Float(f))
}
&Addr::PStrLocation(h, n) => {
- machine_st.to_complete_string(h, n)
- .map(|s| Constant::String(Rc::new(s)))
+ let mut heap_pstr_iter =
+ machine_st.heap_pstr_iter(Addr::PStrLocation(h, n));
+
+ let mut buf = String::new();
+
+ while let Some(Some(c)) = heap_pstr_iter.next() {
+ buf.push(c);
+ }
+
+ let end_addr =
+ machine_st.store(machine_st.deref(heap_pstr_iter.focus()));
+
+ if let Addr::EmptyList = end_addr {
+ Some(Constant::String(Rc::new(buf)))
+ } else {
+ None
+ }
}
_ => {
None
fn add(self, rhs: usize) -> Self::Output {
match self {
+ Addr::Stream(h) => Addr::Stream(h + rhs),
+ Addr::Con(h) => Addr::Con(h + rhs),
Addr::Lis(a) => Addr::Lis(a + rhs),
Addr::AttrVar(h) => Addr::AttrVar(h + rhs),
Addr::HeapCell(h) => Addr::HeapCell(h + rhs),
fn sub(self, rhs: i64) -> Self::Output {
if rhs < 0 {
match self {
+ Addr::Stream(h) => Addr::Stream(h + rhs.abs() as usize),
+ Addr::Con(h) => Addr::Con(h + rhs.abs() as usize),
Addr::Lis(a) => Addr::Lis(a + rhs.abs() as usize),
Addr::AttrVar(h) => Addr::AttrVar(h + rhs.abs() as usize),
Addr::HeapCell(h) => Addr::HeapCell(h + rhs.abs() as usize),
fn sub(self, rhs: usize) -> Self::Output {
match self {
+ Addr::Stream(h) => Addr::Stream(h - rhs),
+ Addr::Con(h) => Addr::Con(h - rhs),
Addr::Lis(a) => Addr::Lis(a - rhs),
Addr::AttrVar(h) => Addr::AttrVar(h - rhs),
Addr::HeapCell(h) => Addr::HeapCell(h - rhs),
DBRef(DBRef),
Integer(Rc<Integer>),
NamedStr(usize, ClauseName, Option<SharedOpDesc>), // arity, name, precedence/Specifier if it has one.
- Rational(Rc<Rational>),
- PartialString(PartialString),
+ Rational(Rc<Rational>),
+ PartialString(PartialString, bool), // the partial string, a bool indicating whether it came from a Constant.
Stream(Stream),
}
pub fn as_addr(&self, focus: usize) -> Addr {
match self {
HeapCellValue::Addr(ref a) => {
- a.clone()
+ *a
}
HeapCellValue::Atom(..) | HeapCellValue::DBRef(..) | HeapCellValue::Integer(..) |
HeapCellValue::Rational(..) => {
HeapCellValue::NamedStr(_, _, _) => {
Addr::Str(focus)
}
- HeapCellValue::PartialString(_) => {
+ HeapCellValue::PartialString(..) => {
Addr::PStrLocation(focus, 0)
}
HeapCellValue::Stream(_) => {
&HeapCellValue::Rational(ref r) => {
HeapCellValue::Rational(r.clone())
}
- &HeapCellValue::PartialString(ref pstr) => {
- HeapCellValue::PartialString(pstr.clone())
+ &HeapCellValue::PartialString(ref pstr, has_tail) => {
+ HeapCellValue::PartialString(pstr.clone(), has_tail)
}
&HeapCellValue::Stream(_) => {
HeapCellValue::Stream(Stream::null_stream())
use downcast::Any;
+use indexmap::IndexSet;
+
use std::cmp::Ordering;
use std::io::Write;
use std::mem;
use std::ops::{Index, IndexMut};
+pub(crate)
+struct HeapPStrIter<'a> {
+ focus: Addr,
+ machine_st: &'a MachineState,
+ seen: IndexSet<Addr>,
+}
+
+impl<'a> HeapPStrIter<'a> {
+ #[inline]
+ fn new(machine_st: &'a MachineState, focus: Addr) -> Self {
+ HeapPStrIter {
+ focus,
+ machine_st,
+ seen: IndexSet::new(),
+ }
+ }
+
+ #[inline]
+ pub(crate)
+ fn focus(&'a self) -> Addr {
+ self.focus
+ }
+}
+
+impl<'a> Iterator for HeapPStrIter<'a> {
+ type Item = Option<char>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let addr = self.machine_st.store(self.machine_st.deref(self.focus));
+
+ if !self.seen.contains(&addr) {
+ self.seen.insert(addr);
+ } else {
+ return None;
+ }
+
+ match addr {
+ Addr::PStrLocation(h, n) => {
+ if let &HeapCellValue::PartialString(ref pstr, _) = &self.machine_st.heap[h] {
+ if let Some(c) = pstr.range_from(n ..).next() {
+ self.focus = Addr::PStrLocation(h, n + c.len_utf8());
+ return Some(Some(c));
+ } else {
+ unreachable!()
+ }
+ } else {
+ unreachable!()
+ }
+ }
+ Addr::Lis(l) => {
+ let addr = self.machine_st.store(self.machine_st.deref(Addr::HeapCell(l)));
+
+ if let Addr::Char(c) = addr {
+ self.focus = Addr::HeapCell(l + 1);
+ return Some(Some(c));
+ } else {
+ return None;
+ }
+ }
+ Addr::EmptyList => {
+ self.focus = Addr::EmptyList;
+ return Some(None);
+ }
+ _ => {
+ return None;
+ }
+ }
+ }
+}
+
+#[inline]
+pub(super)
+fn compare_pstr<'a>(
+ pstr_iter: HeapPStrIter<'a>,
+ mut c_iter: impl Iterator<Item = char>,
+) -> bool {
+ for opt_c in pstr_iter {
+ match opt_c {
+ Some(_) => {
+ if opt_c != c_iter.next() {
+ return false;
+ }
+ }
+ None => {
+ return c_iter.next().is_none();
+ }
+ }
+ }
+
+ false
+}
+
pub struct Ball {
pub(super) boundary: usize,
pub(super) stub: Heap,
self.stub[index].as_addr(h)
}
Addr::StackCell(fr, sc) => {
- self.stack.index_and_frame(fr)[sc].clone()
+ self.stack.index_and_frame(fr)[sc]
}
addr => {
addr
fn deref(&self, mut addr: Addr) -> Addr {
loop {
- let value = self.store(addr.clone());
+ let value = self.store(addr);
if value.is_ref() && value != addr {
addr = value;
Addr::HeapCell(h)
}
&HeapPtr::PStrChar(h, n) => {
- if let HeapCellValue::PartialString(ref pstr) = &heap[h] {
+ if let &HeapCellValue::PartialString(ref pstr, has_tail) = &heap[h] {
if let Some(c) = pstr.range_from(n ..).next() {
Addr::Char(c)
- } else {
+ } else if has_tail {
Addr::HeapCell(h + 1)
+ } else {
+ Addr::EmptyList
}
} else {
unreachable!()
}
impl MachineState {
+ #[inline]
+ pub(crate)
+ fn heap_pstr_iter<'a>(&'a self, focus: Addr) -> HeapPStrIter<'a> {
+ HeapPStrIter::new(self, focus)
+ }
+
pub(super)
fn try_char_list(&self, addrs: Vec<Addr>) -> Result<String, MachineError> {
let mut chars = String::new();
let mut iter = addrs.iter();
while let Some(addr) = iter.next() {
- let addr = self.store(self.deref(addr.clone()));
+ let addr = self.store(self.deref(*addr));
match addr {
Addr::Char(c) => {
let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
for i in 1 .. n + 1 {
- machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1].clone();
+ machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1];
}
machine_st.num_of_args = n;
let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
for i in 1 .. n + 1 {
- machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1].clone();
+ machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1];
}
machine_st.num_of_args = n;
let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
for i in 1 .. n + 1 {
- machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1].clone();
+ machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1];
}
machine_st.num_of_args = n;
let n = machine_st.stack.index_or_frame(b).prelude.univ_prelude.num_cells;
for i in 1 .. n + 1 {
- machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1].clone();
+ machine_st.registers[i] = machine_st.stack.index_or_frame(b)[i-1];
}
machine_st.num_of_args = n;
) -> CallResult {
match ct {
&BuiltInClauseType::AcyclicTerm => {
- let addr = machine_st[temp_v!(1)].clone();
+ let addr = machine_st[temp_v!(1)];
machine_st.fail = machine_st.is_cyclic_term(addr);
return_from_clause!(machine_st.last_call, machine_st)
}
return_from_clause!(machine_st.last_call, machine_st)
}
&BuiltInClauseType::Compare => {
- let a1 = machine_st[temp_v!(1)].clone();
- let a2 = machine_st[temp_v!(2)].clone();
- let a3 = machine_st[temp_v!(3)].clone();
+ let a1 = machine_st[temp_v!(1)];
+ let a2 = machine_st[temp_v!(2)];
+ let a3 = machine_st[temp_v!(3)];
let atom = match machine_st.compare_term_test(&a2, &a3) {
Some(Ordering::Greater) => {
&indices.op_dir,
) {
Ok(offset) => {
- let addr = machine_st[temp_v!(1)].clone();
+ let addr = machine_st[temp_v!(1)];
machine_st.unify(addr, Addr::HeapCell(offset.heap_loc));
}
Err(e) => {
return_from_clause!(machine_st.last_call, machine_st)
}
&BuiltInClauseType::Eq => {
- let a1 = machine_st[temp_v!(1)].clone();
- let a2 = machine_st[temp_v!(2)].clone();
+ let a1 = machine_st[temp_v!(1)];
+ let a2 = machine_st[temp_v!(2)];
machine_st.fail = machine_st.eq_test(a1, a2);
return_from_clause!(machine_st.last_call, machine_st)
return_from_clause!(machine_st.last_call, machine_st)
}
&BuiltInClauseType::NotEq => {
- let a1 = machine_st[temp_v!(1)].clone();
- let a2 = machine_st[temp_v!(2)].clone();
+ let a1 = machine_st[temp_v!(1)];
+ let a2 = machine_st[temp_v!(2)];
machine_st.fail =
if let Some(Ordering::Equal) = machine_st.compare_term_test(&a1, &a2) {
let heap_addr = Addr::HeapCell(machine_st.heap.to_list(list.into_iter()));
- let r2 = machine_st[temp_v!(2)].clone();
+ let r2 = machine_st[temp_v!(2)];
machine_st.unify(r2, heap_addr);
return_from_clause!(machine_st.last_call, machine_st)
let key_pairs = key_pairs.into_iter().map(|kp| kp.1);
let heap_addr = Addr::HeapCell(machine_st.heap.to_list(key_pairs));
- let r2 = machine_st[temp_v!(2)].clone();
+ let r2 = machine_st[temp_v!(2)];
machine_st.unify(r2, heap_addr);
return_from_clause!(machine_st.last_call, machine_st)
}
&BuiltInClauseType::Is(r, ref at) => {
- let a1 = machine_st[r].clone();
+ let a1 = machine_st[r];
let n2 = machine_st.get_number(at)?;
let n2 = Addr::Con(machine_st.heap.push(n2.into()));
pub(crate) struct DefaultCutPolicy {}
pub(super) fn deref_cut(machine_st: &mut MachineState, r: RegType) {
- let addr = machine_st.store(machine_st.deref(machine_st[r].clone()));
+ let addr = machine_st.store(machine_st.deref(machine_st[r]));
cut_body(machine_st, &addr);
}
impl CutPolicy for DefaultCutPolicy {
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
- let addr = machine_st[r].clone();
+ let addr = machine_st[r];
cut_body(machine_st, &addr)
}
}
fn cut(&mut self, machine_st: &mut MachineState, r: RegType) -> bool {
let b = machine_st.b;
- match machine_st[r].clone() {
+ match machine_st[r] {
Addr::Usize(b0) | Addr::CutPoint(b0) => {
if b > b0 {
machine_st.b = b0;
}
}
- #[allow(dead_code)]
- pub fn print_heap(&self, start: usize) {
- for h in start .. self.heap.h() {
- println!("{} : {}", h, self.heap[h]);
- }
- }
-
#[inline]
pub fn machine_flags(&self) -> MachineFlags {
self.flags
self.heap[h].as_addr(h)
}
Addr::StackCell(fr, sc) => {
- self.stack.index_and_frame(fr)[sc].clone()
+ self.stack.index_and_frame(fr)[sc]
}
Addr::PStrLocation(h, n) => {
- if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
+ if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.heap[h] {
if !pstr.at_end(n) {
Addr::PStrLocation(h, n)
- } else {
+ } else if has_tail {
Addr::HeapCell(h + 1)
+ } else {
+ Addr::EmptyList
}
} else {
unreachable!()
pub(crate)
fn deref(&self, mut addr: Addr) -> Addr {
loop {
- let value = self.store(addr.clone());
+ let value = self.store(addr);
if value.is_ref() && value != addr {
addr = value;
self.trail(TrailRef::Ref(Ref::StackCell(fr, sc)));
}
_ => {
- self.push_attr_var_binding(h, addr.clone());
+ self.push_attr_var_binding(h, addr);
self.heap[h] = HeapCellValue::Addr(addr);
self.trail(TrailRef::Ref(Ref::AttrVar(h)));
}
pub(super)
fn bind(&mut self, r1: Ref, a2: Addr) {
let t1 = self.store(r1.as_addr());
- let t2 = self.store(a2.clone());
+ let t2 = self.store(a2);
if t1.is_ref() && (!t2.is_ref() || a2 < r1) {
match r1 {
let d1 = self.store(d1);
let d2 = self.store(d2);
- if tabu_list.contains(&(d1.clone(), d2.clone())) {
+ if tabu_list.contains(&(d1, d2)) {
continue;
} else {
- tabu_list.insert((d1.clone(), d2.clone()));
+ tabu_list.insert((d1, d2));
}
- match (d1.clone(), d2.clone()) {
+ match (d1, d2) {
(Addr::AttrVar(h), addr) | (addr, Addr::AttrVar(h)) => {
self.bind_with_occurs_check(Ref::AttrVar(h), addr)
}
}
(Addr::PStrLocation(h, n), Addr::Lis(l))
| (Addr::Lis(l), Addr::PStrLocation(h, n)) => {
- if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
+ if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] {
if let Some(c) = pstr.range_from(n ..).next() {
pdl.push(Addr::PStrLocation(h, n + c.len_utf8()));
pdl.push(Addr::HeapCell(l + 1));
}
}
(Addr::PStrLocation(h1, n1), Addr::PStrLocation(h2, n2)) => {
- if let HeapCellValue::PartialString(ref pstr1) = &self.heap[h1] {
- if let HeapCellValue::PartialString(ref pstr2) = &self.heap[h2] {
+ if let &HeapCellValue::PartialString(ref pstr1, has_tail_1) = &self.heap[h1] {
+ if let &HeapCellValue::PartialString(ref pstr2, has_tail_2) = &self.heap[h2] {
let pstr1_iter = pstr1.range_from(n1 ..);
let pstr2_iter = pstr2.range_from(n2 ..);
return;
}
- m_len += 1;
+ m_len += c1.len_utf8();
}
if pstr1.at_end(n1 + m_len) {
- pdl.push(Addr::HeapCell(h1 + 1));
- pdl.push(Addr::PStrLocation(h2, n2 + m_len));
+ if has_tail_1 {
+ pdl.push(Addr::HeapCell(h1 + 1));
+ } else {
+ pdl.push(Addr::EmptyList);
+ }
+
+ if pstr2.at_end(n2 + m_len) {
+ if has_tail_2 {
+ pdl.push(Addr::HeapCell(h2 + 1));
+ } else {
+ pdl.push(Addr::EmptyList);
+ }
+ } else {
+ pdl.push(Addr::PStrLocation(h2, n2 + m_len));
+ }
} else {
- pdl.push(Addr::HeapCell(h2 + 1));
pdl.push(Addr::PStrLocation(h1, n1 + m_len));
- }
- self.fail = true;
- break;
+ if pstr2.at_end(n2 + m_len) {
+ if has_tail_2 {
+ pdl.push(Addr::HeapCell(h2 + 1));
+ } else {
+ pdl.push(Addr::EmptyList);
+ }
+ } else {
+ pdl.push(Addr::PStrLocation(h2, n2 + m_len));
+ }
+ }
} else {
unreachable!()
}
pdl.push(Addr::HeapCell(a1 + 1));
pdl.push(Addr::HeapCell(a2 + 1));
}
- (Addr::Con(c1), Addr::Con(c2)) => {
- if c1 != c2 {
- self.fail = true;
- }
- }
(Addr::Str(a1), Addr::Str(a2)) => {
let r1 = &self.heap[a1];
let r2 = &self.heap[a2];
self.fail = true;
}
- _ => self.fail = true,
+ (Addr::Con(c1), Addr::Con(c2)) => {
+ match (&self.heap[c1], &self.heap[c2]) {
+ (
+ &HeapCellValue::Atom(ref n1, _),
+ &HeapCellValue::Atom(ref n2, _),
+ ) if n1.as_str() == n2.as_str() => {
+ }
+ (
+ &HeapCellValue::DBRef(ref db_ref_1),
+ &HeapCellValue::DBRef(ref db_ref_2),
+ ) if db_ref_1 == db_ref_2 => {
+ }
+ (
+ &HeapCellValue::Integer(ref n1),
+ &HeapCellValue::Integer(ref n2),
+ ) if &**n1 == &**n2 => {
+ }
+ (
+ &HeapCellValue::Rational(ref n1),
+ &HeapCellValue::Rational(ref n2),
+ ) if &**n1 == &**n2 => {
+ }
+ _ => {
+ self.fail = true;
+ }
+ }
+ }
+ (Addr::Con(h), Addr::Char(c)) | (Addr::Char(c), Addr::Con(h)) => {
+ match &self.heap[h] {
+ &HeapCellValue::Atom(ref name, _) if name.is_char() => {
+ if name.as_str().chars().next() != Some(c) {
+ self.fail = true;
+ return;
+ }
+ }
+ _ => {
+ self.fail = true;
+ return;
+ }
+ }
+ }
+ (Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
+ if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+ if let Some(n2) = n2.to_usize() {
+ if n1 == n2 {
+ continue;
+ }
+ }
+ }
+
+ self.fail = true;
+ }
+ (Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
+ if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+ if let Some(n2) = n2.to_u32() {
+ if n1 == n2 {
+ continue;
+ }
+ }
+ }
+
+ self.fail = true;
+ }
+ (Addr::Stream(s1), Addr::Stream(s2)) => {
+ if s1 != s2 {
+ self.fail = true;
+ }
+ }
+ (a1, a2) => {
+ if a1 != a2 {
+ self.fail = true;
+ }
+ }
};
}
}
let d1 = self.store(d1);
let d2 = self.store(d2);
- if tabu_list.contains(&(d1.clone(), d2.clone())) {
+ if tabu_list.contains(&(d1, d2)) {
continue;
} else {
- tabu_list.insert((d1.clone(), d2.clone()));
+ tabu_list.insert((d1, d2));
}
- match (d1.clone(), d2.clone()) {
+ match (d1, d2) {
(Addr::AttrVar(h), addr) | (addr, Addr::AttrVar(h)) => {
self.bind(Ref::AttrVar(h), addr);
}
}
(Addr::PStrLocation(h, n), Addr::Lis(l))
| (Addr::Lis(l), Addr::PStrLocation(h, n)) => {
- if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
+ if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] {
if let Some(c) = pstr.range_from(n ..).next() {
pdl.push(Addr::PStrLocation(h, n + c.len_utf8()));
pdl.push(Addr::HeapCell(l + 1));
}
}
(Addr::PStrLocation(h1, n1), Addr::PStrLocation(h2, n2)) => {
- if let HeapCellValue::PartialString(ref pstr1) = &self.heap[h1] {
- if let HeapCellValue::PartialString(ref pstr2) = &self.heap[h2] {
+ if let &HeapCellValue::PartialString(ref pstr1, has_tail_1) = &self.heap[h1] {
+ if let &HeapCellValue::PartialString(ref pstr2, has_tail_2) = &self.heap[h2] {
let pstr1_iter = pstr1.range_from(n1 ..);
let pstr2_iter = pstr2.range_from(n2 ..);
return;
}
- m_len += 1;
+ m_len += c1.len_utf8();
}
if pstr1.at_end(n1 + m_len) {
- pdl.push(Addr::HeapCell(h1 + 1));
- pdl.push(Addr::PStrLocation(h2, n2 + m_len));
+ if has_tail_1 {
+ pdl.push(Addr::HeapCell(h1 + 1));
+ } else {
+ pdl.push(Addr::EmptyList);
+ }
+
+ if pstr2.at_end(n2 + m_len) {
+ if has_tail_2 {
+ pdl.push(Addr::HeapCell(h2 + 1));
+ } else {
+ pdl.push(Addr::EmptyList);
+ }
+ } else {
+ pdl.push(Addr::PStrLocation(h2, n2 + m_len));
+ }
} else {
- pdl.push(Addr::HeapCell(h2 + 1));
pdl.push(Addr::PStrLocation(h1, n1 + m_len));
- }
- self.fail = true;
- break;
+ if pstr2.at_end(n2 + m_len) {
+ if has_tail_2 {
+ pdl.push(Addr::HeapCell(h2 + 1));
+ } else {
+ pdl.push(Addr::EmptyList);
+ }
+ } else {
+ pdl.push(Addr::PStrLocation(h2, n2 + m_len));
+ }
+ }
}
}
}
pdl.push(Addr::HeapCell(a1 + 1));
pdl.push(Addr::HeapCell(a2 + 1));
}
- (Addr::Con(c1), Addr::Con(c2)) => {
- if c1 != c2 {
- self.fail = true;
- }
- }
(Addr::Str(a1), Addr::Str(a2)) => {
let r1 = &self.heap[a1];
let r2 = &self.heap[a2];
self.fail = true;
}
- _ => self.fail = true,
- };
- }
- }
- }
-
- pub(super)
- fn to_complete_string(&self, h: usize, n: usize) -> Option<String> {
- if self.is_cyclic_term(Addr::PStrLocation(h, n)) {
- return None;
- }
+ (Addr::Con(c1), Addr::Con(c2)) => {
+ match (&self.heap[c1], &self.heap[c2]) {
+ (
+ &HeapCellValue::Atom(ref n1, _),
+ &HeapCellValue::Atom(ref n2, _),
+ ) if n1.as_str() == n2.as_str() => {
+ }
+(
+ &HeapCellValue::DBRef(ref db_ref_1),
+ &HeapCellValue::DBRef(ref db_ref_2),
+ ) if db_ref_1 == db_ref_2 => {
+ }
+ (
+ &HeapCellValue::Integer(ref n1),
+ &HeapCellValue::Integer(ref n2),
+ ) if &**n1 == &**n2 => {
+ }
+ (
+ &HeapCellValue::Rational(ref n1),
+ &HeapCellValue::Rational(ref n2),
+ ) if &**n1 == &**n2 => {
+ }
+ _ => {
+ self.fail = true;
+ }
+ }
+ }
+ (Addr::Con(h), Addr::Char(c)) | (Addr::Char(c), Addr::Con(h)) => {
+ match &self.heap[h] {
+ &HeapCellValue::Atom(ref name, _) if name.is_char() => {
+ if name.as_str().chars().next() != Some(c) {
+ self.fail = true;
+ return;
+ }
+ }
+ _ => {
+ self.fail = true;
+ return;
+ }
+ }
+ }
+ (Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
+ if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+ if let Some(n2) = n2.to_usize() {
+ if n1 == n2 {
+ continue;
+ }
+ }
+ }
- let mut addr = Addr::PStrLocation(h, n);
- let mut result = String::new();
+ self.fail = true;
+ }
+ (Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
+ if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+ if let Some(n2) = n2.to_u32() {
+ if n1 == n2 {
+ continue;
+ }
+ }
+ }
- loop {
- match addr {
- Addr::EmptyList => {
- break;
- }
- Addr::Lis(l) if !self.flags.double_quotes.is_atom() => {
- if let &HeapCellValue::Addr(Addr::Char(c)) = &self.heap[l] {
- result.push(c);
- addr = self.store(self.deref(Addr::HeapCell(l + 1)));
- } else {
- return None;
+ self.fail = true;
}
- }
- Addr::PStrLocation(h, n) => {
- if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
- result.extend(pstr.range_from(n ..));
- addr = self.store(self.deref(Addr::HeapCell(h + 1)));
- } else {
- unreachable!()
+ (Addr::Stream(s1), Addr::Stream(s2)) => {
+ if s1 != s2 {
+ self.fail = true;
+ }
}
- }
- _ => {
- return None;
- }
+ (a1, a2) => {
+ if a1 != a2 {
+ self.fail = true;
+ }
+ }
+ };
}
}
-
- Some(result)
}
pub(super)
&mut HeapPtr::PStrChar(h, ref mut n)
| &mut HeapPtr::PStrLocation(h, ref mut n) => {
match &self.heap[h] {
- HeapCellValue::PartialString(ref pstr) => {
+ HeapCellValue::PartialString(ref pstr, _) => {
for c in pstr.range_from(*n ..).take(rhs) {
*n += c.len_utf8();
}
match self.store(self.deref(addr)) {
Addr::Con(c1) => {
self.fail = match &self.heap[c1] {
- HeapCellValue::Atom(ref n1, ref op1) => {
- if let Constant::Atom(ref n2, ref op2) = c {
- !(n1 == n2 && op1 == op2)
- } else {
- true
+ HeapCellValue::Atom(ref n1, _) => {
+ match c {
+ Constant::Atom(ref n2, _) => {
+ n1 != n2
+ }
+ Constant::Char(c) if n1.is_char() => {
+ Some(*c) != n1.as_str().chars().next()
+ }
+ _ => {
+ true
+ }
}
}
HeapCellValue::Integer(ref n1) => {
- if let Constant::Integer(ref n2) = c {
- n1 != n2
- } else {
- true
+ match c {
+ Constant::Integer(ref n2) => {
+ n1 != n2
+ }
+ Constant::Usize(n2) => {
+ n1.to_usize() != Some(*n2)
+ }
+ _ => {
+ true
+ }
}
}
HeapCellValue::Rational(ref r1) => {
true
}
}
- HeapCellValue::PartialString(_) => {
- self.to_complete_string(c1, 0).map(|s1| {
- if let Constant::String(ref s2) = c {
- &s1 != &**s2
- } else {
- true
- }
- }).unwrap_or(true)
+ HeapCellValue::PartialString(..) => {
+ if let Constant::String(ref s2) = c {
+ let iter = self.heap_pstr_iter(Addr::PStrLocation(c1, 0));
+ !compare_pstr(iter, s2.chars())
+ } else {
+ true
+ }
}
_ => {
unreachable!()
}
};
}
+ Addr::Char(ch) => {
+ self.fail = match c {
+ Constant::Atom(ref n2, _) if n2.is_char() => {
+ Some(ch) != n2.as_str().chars().next()
+ }
+ Constant::Char(c) => {
+ *c != ch
+ }
+ _ => {
+ true
+ }
+ };
+ }
Addr::EmptyList => {
if let Constant::EmptyList = c {
} else {
self.unify(Addr::Lis(l), addr);
}
Addr::PStrLocation(h, n) => {
- self.fail = self.to_complete_string(h, n).map(|s1| {
- if let Constant::String(ref s2) = c {
- &s1 != &**s2
- } else {
- true
- }
- }).unwrap_or(true);
+ self.fail = if let Constant::String(ref s2) = c {
+ let iter = self.heap_pstr_iter(Addr::PStrLocation(h, n));
+ !compare_pstr(iter, s2.chars())
+ } else {
+ true
+ };
+ }
+ Addr::Stream(_) => {
+ self.fail = true;
}
addr => {
+ let c = self.heap.put_constant(c.clone());
+
if let Some(r) = addr.as_var() {
- let addr = self.heap.put_constant(c.clone());
- self.bind(r, addr);
+ self.bind(r, c);
} else {
- self.fail = true;
+ self.unify(addr, c);
}
}
};
fn execute_fact_instr(&mut self, instr: &FactInstruction) {
match instr {
&FactInstruction::GetConstant(_, ref c, reg) => {
- let addr = self[reg].clone();
+ let addr = self[reg];
self.write_constant_to_var(addr, c);
}
&FactInstruction::GetList(_, reg) => {
- let addr = self.store(self.deref(self[reg].clone()));
+ let addr = self.store(self.deref(self[reg]));
match addr {
Addr::PStrLocation(h, n) => {
};
}
&FactInstruction::GetStructure(ref ct, arity, reg) => {
- let addr = self.deref(self[reg].clone());
+ let addr = self.deref(self[reg]);
- match self.store(addr.clone()) {
+ match self.store(addr) {
Addr::Str(a) => {
let result = &self.heap[a];
};
}
&FactInstruction::GetVariable(norm, arg) => {
- self[norm] = self.registers[arg].clone();
+ self[norm] = self.registers[arg];
}
&FactInstruction::GetValue(norm, arg) => {
- let norm_addr = self[norm].clone();
- let reg_addr = self.registers[arg].clone();
+ let norm_addr = self[norm];
+ let reg_addr = self.registers[arg];
self.unify(norm_addr, reg_addr);
}
self.write_constant_to_var(addr, c);
}
MachineMode::Write => {
- self.heap.put_constant(c.clone());
+ let addr = self.heap.put_constant(c.clone());
+
+ if !addr.is_heap_bound() {
+ self.heap.push(HeapCellValue::Addr(addr));
+ }
}
};
&FactInstruction::UnifyLocalValue(reg) => {
match self.mode {
MachineMode::Read => {
- let reg_addr = self[reg].clone();
+ let reg_addr = self[reg];
self.unify(reg_addr, self.s.read(&self.heap));
}
MachineMode::Write => {
- let addr = self.deref(self[reg].clone());
+ let addr = self.deref(self[reg]);
let h = self.heap.h();
if let Addr::HeapCell(hc) = addr {
self.unify(reg_addr, self.s.read(&self.heap));
}
MachineMode::Write => {
- let heap_val = self.store(self[reg].clone());
+ let heap_val = self.store(self[reg]);
self.heap.push(HeapCellValue::Addr(heap_val));
}
};
let addr = self.store(self.deref(addr));
let offset = match addr {
- Addr::HeapCell(_) | Addr::StackCell(..)
- | Addr::AttrVar(..) | Addr::Stream(_) => {
+ Addr::HeapCell(_) | Addr::StackCell(..) |
+ Addr::AttrVar(..) | Addr::Stream(_) => {
v
}
Addr::PStrLocation(..) => {
c
}
}
- Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::CutPoint(_)
- | Addr::EmptyList | Addr::Float(_) | Addr::Usize(_) => {
- c
- }
+ Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::CutPoint(_) |
+ Addr::EmptyList | Addr::Float(_) | Addr::Usize(_) => {
+ c
+ }
Addr::Lis(_) => {
l
}
};
}
&IndexingInstruction::SwitchOnStructure(_, ref hm) => {
- let a1 = self.registers[1].clone();
+ let a1 = self.registers[1];
let addr = self.store(self.deref(a1));
let offset = match addr {
pub(super) fn execute_query_instr(&mut self, instr: &QueryInstruction) {
match instr {
&QueryInstruction::GetVariable(norm, arg) => {
- self[norm] = self.registers[arg].clone();
+ self[norm] = self.registers[arg];
}
&QueryInstruction::PutConstant(_, ref c, reg) => {
self[reg] = self.heap.put_constant(c.clone());
}
}
&QueryInstruction::PutValue(norm, arg) => {
- self.registers[arg] = self[norm].clone();
+ self.registers[arg] = self[norm];
}
&QueryInstruction::PutVariable(norm, arg) => {
match norm {
};
}
&QueryInstruction::SetConstant(ref c) => {
- self.heap.put_constant(c.clone());
+ let addr = self.heap.put_constant(c.clone());
+
+ if !addr.is_heap_bound() {
+ self.heap.push(HeapCellValue::Addr(addr));
+ }
}
&QueryInstruction::SetLocalValue(reg) => {
let addr = self.deref(self[reg]);
self[reg] = Addr::HeapCell(h);
}
&QueryInstruction::SetValue(reg) => {
- let heap_val = self.store(self[reg].clone());
+ let heap_val = self.store(self[reg]);
self.heap.push(HeapCellValue::Addr(heap_val));
}
&QueryInstruction::SetVoid(n) => {
pub(super) fn set_ball(&mut self) {
self.ball.reset();
- let addr = self[temp_v!(1)].clone();
+ let addr = self[temp_v!(1)];
self.ball.boundary = self.heap.h();
copy_term(
pub(super) fn handle_internal_call_n(&mut self, arity: usize) {
let arity = arity + 1;
- let pred = self.registers[1].clone();
+ let pred = self.registers[1];
for i in 2..arity {
- self.registers[i - 1] = self.registers[i].clone();
+ self.registers[i - 1] = self.registers[i];
}
if arity > 1 {
}
pub(super) fn setup_call_n(&mut self, arity: usize) -> Option<PredicateKey> {
- let addr = self.store(self.deref(self.registers[arity].clone()));
+ let addr = self.store(self.deref(self.registers[arity]));
let (name, narity) = match addr {
Addr::Str(a) => {
}
for i in (1 .. arity).rev() {
- self.registers[i + narity] = self.registers[i].clone();
+ self.registers[i + narity] = self.registers[i];
}
for i in 1 .. narity + 1 {
loop {
if let Some(addr) = iter.stack().last() {
if !seen.contains(addr) {
- seen.insert(addr.clone());
+ seen.insert(*addr);
} else {
fail = true;
break;
}
// arg(+N, +Term, ?Arg)
- pub(super) fn try_arg(&mut self) -> CallResult {
+ pub(super)
+ fn try_arg(&mut self) -> CallResult {
let stub = MachineError::functor_stub(clause_name!("arg"), 3);
let n = self.store(self.deref(self[temp_v!(1)]));
}
};
- let term = self.store(self.deref(self[temp_v!(2)].clone()));
+ let term = self.store(self.deref(self[temp_v!(2)]));
match term {
Addr::HeapCell(_) | Addr::StackCell(..) => { // 8.5.2.3 b)
}
Addr::Str(o) => match self.heap.clone(o) {
HeapCellValue::NamedStr(arity, _, _) if 1 <= n && n <= arity => {
- let a3 = self[temp_v!(3)].clone();
+ let a3 = self[temp_v!(3)];
let h_a = Addr::HeapCell(o + n);
self.unify(a3, h_a);
}
- _ => self.fail = true,
+ _ => {
+ self.fail = true;
+ }
},
Addr::Lis(l) => {
if n == 1 || n == 2 {
- let a3 = self[temp_v!(3)].clone();
+ let a3 = self[temp_v!(3)];
let h_a = Addr::HeapCell(l + n - 1);
self.unify(a3, h_a);
}
Addr::PStrLocation(h, offset) => {
if n == 1 || n == 2 {
- let a3 = self[temp_v!(3)].clone();
+ let a3 = self[temp_v!(3)];
let h_a =
- if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
+ if let HeapCellValue::PartialString(ref pstr, _) = &self.heap[h] {
if let Some(c) = pstr.range_from(offset ..).next() {
if n == 1 {
Addr::Char(c)
MachineError::type_error(
self.heap.h(),
ValidType::Integer,
- Addr::Con(h),
+ Addr::HeapCell(h),
),
stub,
))
}
pub(super) fn compare_term(&mut self, qt: CompareTermQT) {
- let a1 = self[temp_v!(1)].clone();
- let a2 = self[temp_v!(2)].clone();
+ let a1 = self[temp_v!(1)];
+ let a2 = self[temp_v!(2)];
match self.compare_term_test(&a1, &a2) {
Some(Ordering::Greater) => match qt {
}
}
(Addr::PStrLocation(..), Addr::Lis(_))
- | (Addr::Lis(_), Addr::PStrLocation(..))
+ | (Addr::Lis(_), Addr::PStrLocation(..))
if !self.flags.double_quotes.is_atom() => {
continue;
}
}
}
}
+ (Addr::Con(h), Addr::Char(c)) | (Addr::Char(c), Addr::Con(h)) => {
+ match &self.heap[h] {
+ &HeapCellValue::Atom(ref name, _) if name.is_char() => {
+ if name.as_str().chars().next() != Some(c) {
+ return true;
+ }
+ }
+ _ => {
+ return true;
+ }
+ }
+ }
+ (Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
+ if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+ if let Some(n2) = n2.to_usize() {
+ if n1 != n2 {
+ return true;
+ }
+ }
+ }
+ }
+ (Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
+ if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+ if let Some(n2) = n2.to_u32() {
+ if n1 == n2 {
+ return true;
+ }
+ }
+ }
+ }
(a1, a2) => {
if a1 != a2 {
return true;
}
pub(super) fn compare_term_test(&self, a1: &Addr, a2: &Addr) -> Option<Ordering> {
- let mut iter = self.zipped_acyclic_pre_order_iter(a1.clone(), a2.clone());
+ let mut iter = self.zipped_acyclic_pre_order_iter(*a1, *a2);
while let Some((v1, v2)) = iter.next() {
let order_cat_v1 = v1.order_category(&self.heap);
let order_cat_v2 = v2.order_category(&self.heap);
- if order_cat_v1 != order_cat_v1 {
+ if order_cat_v1 != order_cat_v2 {
return Some(order_cat_v1.cmp(&order_cat_v2));
}
}
}
}
+ (Addr::Usize(n1), Addr::Usize(n2)) => {
+ if n1 != n2 {
+ return Some(n1.cmp(&n2));
+ }
+ }
+ (Addr::CharCode(n1), Addr::CharCode(n2)) => {
+ if n1 != n2 {
+ return Some(n1.cmp(&n2));
+ }
+ }
+ (Addr::Usize(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::Usize(n1)) => {
+ if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+ if let Some(n2) = n2.to_usize() {
+ if n1 != n2 {
+ return Some(n1.cmp(&n2));
+ }
+ }
+ }
+ }
+ (Addr::CharCode(n1), Addr::Con(n2)) | (Addr::Con(n2), Addr::CharCode(n1)) => {
+ if let HeapCellValue::Integer(ref n2) = &self.heap[n2] {
+ if let Some(n2) = n2.to_u32() {
+ if n1 != n2 {
+ return Some(n1.cmp(&n2));
+ }
+ }
+ }
+ }
_ => {
unreachable!()
}
Some('['.cmp(&c))
};
}
+ (
+ Addr::EmptyList,
+ Addr::EmptyList,
+ ) => {
+ }
_ => {
return None;
}
self.compare_numbers(cmp, n1, n2);
}
&InlinedClauseType::IsAtom(r1) => {
- let d = self.store(self.deref(self[r1].clone()));
+ let d = self.store(self.deref(self[r1]));
match d {
Addr::Con(h) =>
};
}
&InlinedClauseType::IsAtomic(r1) => {
- let d = self.store(self.deref(self[r1].clone()));
+ let d = self.store(self.deref(self[r1]));
match d {
Addr::Con(_) => self.p += 1,
};
}
&InlinedClauseType::IsInteger(r1) => {
- let d = self.store(self.deref(self[r1].clone()));
+ let d = self.store(self.deref(self[r1]));
match d {
Addr::Con(h) => {
}
}
}
- Addr::CharCode(_) => {
+ Addr::CharCode(_) | Addr::Usize(_) => {
self.p += 1;
}
Addr::Char(_) if self.flags.double_quotes.is_codes() => {
};
}
&InlinedClauseType::IsFloat(r1) => {
- let d = self.store(self.deref(self[r1].clone()));
+ let d = self.store(self.deref(self[r1]));
match d {
Addr::Float(_) => self.p += 1,
};
}
&InlinedClauseType::IsRational(r1) => {
- let d = self.store(self.deref(self[r1].clone()));
+ let d = self.store(self.deref(self[r1]));
match d {
Addr::Con(h) => {
};
}
&InlinedClauseType::IsString(r1) => {
- let d = self.store(self.deref(self[r1].clone()));
+ let d = self.store(self.deref(self[r1]));
match d {
Addr::PStrLocation(..) => self.p += 1,
};
}
&InlinedClauseType::IsNonVar(r1) => {
- let d = self.store(self.deref(self[r1].clone()));
+ let d = self.store(self.deref(self[r1]));
match d {
Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(..) => {
};
}
&InlinedClauseType::IsVar(r1) => {
- let d = self.store(self.deref(self[r1].clone()));
+ let d = self.store(self.deref(self[r1]));
match d {
Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => {
Addr::Stream(_) => {
self.fail = true;
}
- Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Float(_) => {
+ Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Float(_) |
+ Addr::EmptyList | Addr::Usize(_) => {
self.try_functor_unify_components(a1, 0);
}
Addr::Str(o) => match self.heap.clone(o) {
return Err(self.error_form(MachineError::instantiation_error(), stub));
}
- if let Addr::Con(h) = arity {
- let arity = if let HeapCellValue::Integer(ref n) = &self.heap[h] {
- n.clone()
- } else {
+ let arity = match arity {
+ Addr::Con(h) => {
+ match &self.heap[h] {
+ &HeapCellValue::Integer(ref n) => {
+ n.to_isize()
+ }
+ &HeapCellValue::Addr(Addr::Usize(n)) => {
+ Some(n as isize)
+ }
+ _ => {
+ return Err(
+ self.error_form(
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Integer,
+ arity,
+ ),
+ stub,
+ )
+ );
+ }
+ }
+ },
+ Addr::Usize(n) => {
+ Some(n as isize)
+ }
+ Addr::CharCode(c) => {
+ Some(c as isize)
+ }
+ arity => {
return Err(
self.error_form(
MachineError::type_error(
stub,
)
);
- };
+ }
+ };
- let arity = match arity.to_isize() {
- Some(arity) => arity,
- None => {
- self.fail = true;
- return Ok(());
- }
- };
+ let arity = match arity {
+ Some(arity) => {
+ arity
+ }
+ None => {
+ self.fail = true;
+ return Ok(());
+ }
+ };
- if arity > MAX_ARITY as isize {
- // 8.5.1.3 f)
- let rep_err = MachineError::representation_error(RepFlag::MaxArity);
- return Err(self.error_form(rep_err, stub));
- } else if arity < 0 {
- // 8.5.1.3 g)
- let arity = Number::Integer(Rc::new(Integer::from(arity)));
- let dom_err = MachineError::domain_error(
- DomainErrorType::NotLessThanZero,
- arity,
- );
+ if arity > MAX_ARITY as isize {
+ // 8.5.1.3 f)
+ let rep_err = MachineError::representation_error(RepFlag::MaxArity);
+ return Err(self.error_form(rep_err, stub));
+ } else if arity < 0 {
+ // 8.5.1.3 g)
+ let arity = Number::Integer(Rc::new(Integer::from(arity)));
+ let dom_err = MachineError::domain_error(
+ DomainErrorType::NotLessThanZero,
+ arity,
+ );
- return Err(self.error_form(dom_err, stub));
- }
+ return Err(self.error_form(dom_err, stub));
+ }
- match name {
- Addr::Con(_) if arity == 0 => {
- self.unify(a1, name);
- }
- Addr::Con(h) => {
- if let HeapCellValue::Atom(name, spec) = self.heap.clone(h) {
- self.try_functor_fabricate_struct(
- name,
- arity,
- spec,
- &indices.op_dir,
- a1.as_var().unwrap(),
- );
- } else {
- // 8.5.1.3 e)
- return Err(self.error_form(
- MachineError::type_error(
- self.heap.h(),
- ValidType::Atom,
- name,
- ),
- stub,
- ))
- }
- }
- Addr::Char(c) => {
+ match name {
+ Addr::Char(_) | Addr::CharCode(_) | Addr::Con(_) | Addr::Float(_) |
+ Addr::EmptyList | Addr::PStrLocation(..) | Addr::Usize(_) if arity == 0 => {
+ self.unify(a1, name);
+ }
+ Addr::Con(h) => {
+ if let HeapCellValue::Atom(name, spec) = self.heap.clone(h) {
self.try_functor_fabricate_struct(
- clause_name!(c.to_string(), indices.atom_tbl),
+ name,
arity,
- None,
+ spec,
&indices.op_dir,
a1.as_var().unwrap(),
);
- }
- _ => {
+ } else {
+ // 8.5.1.3 e)
return Err(self.error_form(
- MachineError::type_error(self.heap.h(), ValidType::Atomic, name),
+ MachineError::type_error(
+ self.heap.h(),
+ ValidType::Atom,
+ name,
+ ),
stub,
- ));
- } // 8.5.1.3 c)
+ ))
+ }
}
- } else if !arity.is_ref() {
- // 8.5.1.3 d)
- return Err(
- self.error_form(
- MachineError::type_error(
- self.heap.h(),
- ValidType::Integer,
- arity,
- ),
+ Addr::Char(c) => {
+ self.try_functor_fabricate_struct(
+ clause_name!(c.to_string(), indices.atom_tbl),
+ arity,
+ None,
+ &indices.op_dir,
+ a1.as_var().unwrap(),
+ );
+ }
+ _ => {
+ return Err(self.error_form(
+ MachineError::type_error(self.heap.h(), ValidType::Atomic, name),
stub,
- )
- );
+ ));
+ } // 8.5.1.3 c)
}
}
_ => {
self.fail = true;
}
- };
+ }
Ok(())
}
- pub(super) fn term_dedup(&self, list: &mut Vec<Addr>) {
+ pub(super)
+ fn term_dedup(&self, list: &mut Vec<Addr>) {
let mut result = vec![];
for a2 in list.iter() {
) -> Result<Vec<Addr>, MachineStub> {
let a1 = self.store(self.deref(self[r]));
- match a1.clone() {
+ match a1 {
Addr::Lis(l) => {
self.try_from_inner_list(vec![], l, caller, a1)
}
loop {
match &self.heap[l] {
HeapCellValue::Addr(ref addr) =>
- match self.store(self.deref(addr.clone())) {
+ match self.store(self.deref(*addr)) {
Addr::Lis(hcp) => {
result.push(self.heap[hcp].as_addr(hcp));
l = hcp + 1;
a1: Addr,
) -> Result<Vec<Addr>, MachineStub> {
loop {
- if let HeapCellValue::PartialString(ref pstr) = &self.heap[h] {
+ if let &HeapCellValue::PartialString(ref pstr, has_tail) = &self.heap[h] {
chars.extend(pstr.range_from(n ..).map(Addr::Char));
+ if !has_tail {
+ return Ok(chars);
+ }
+
let tail = self.heap[h + 1].as_addr(h + 1);
match self.store(self.deref(tail)) {
return self.try_from_inner_list(chars, l, caller, a1);
}
Addr::PStrLocation(h1, n1) => {
+ chars.push(Addr::Char('\u{0}'));
+
h = h1;
n = n1;
}
pub(super) fn copy_term(&mut self, attr_var_policy: AttrVarPolicy) {
let old_h = self.heap.h();
- let a1 = self[temp_v!(1)].clone();
- let a2 = self[temp_v!(2)].clone();
+ let a1 = self[temp_v!(1)];
+ let a2 = self[temp_v!(2)];
copy_term(CopyTerm::new(self), a1, attr_var_policy);
}
},
(
- HeapCellValue::PartialString(ref pstr1),
- HeapCellValue::PartialString(ref pstr2),
+ HeapCellValue::PartialString(ref pstr1, has_tail_1),
+ HeapCellValue::PartialString(ref pstr2, has_tail_2),
) => {
+ if has_tail_1 != has_tail_2 {
+ return true;
+ }
+
let pstr1_iter = pstr1.range_from(0 ..);
let pstr2_iter = pstr2.range_from(0 ..);
// returns true on failure.
pub(super)
fn ground_test(&self) -> bool {
- let a = self.store(self.deref(self[temp_v!(1)].clone()));
+ let a = self.store(self.deref(self[temp_v!(1)]));
for v in self.acyclic_pre_order_iter(a) {
match v {
self.p += offset;
}
&ControlInstruction::Proceed => {
- self.p = CodePtr::Local(self.cp.clone());
+ self.p = CodePtr::Local(self.cp);
}
};
}
self.b = b;
for i in 1 .. n + 1 {
- self.stack.index_or_frame_mut(b)[i-1] = self.registers[i].clone();
+ self.stack.index_or_frame_mut(b)[i-1] = self.registers[i];
}
self.hb = self.heap.h();
self.b = b;
for i in 1 .. n + 1 {
- self.stack.index_or_frame_mut(b)[i-1] = self.registers[i].clone();
+ self.stack.index_or_frame_mut(b)[i-1] = self.registers[i];
}
self.hb = self.heap.h();
self.p += 1;
}
&CutInstruction::GetLevelAndUnify(r) => {
- let b0 = self[perm_v!(1)].clone();
- let a = self[r].clone();
+ let b0 = self[perm_v!(1)];
+ let a = self[r];
self.unify(a, b0);
self.p += 1;
+use core::marker::PhantomData;
+
use std::alloc;
use std::mem;
use std::ptr;
-use std::ops::{Range, RangeFrom};
+use std::ops::RangeFrom;
+use std::slice;
use std::str;
pub struct PartialString {
buf: *const u8,
+ len: usize,
+ _marker: PhantomData<[u8]>,
+}
+
+impl Drop for PartialString {
+ fn drop(&mut self) {
+ unsafe {
+ let layout = alloc::Layout::from_size_align_unchecked(self.len, mem::align_of::<u8>());
+ alloc::dealloc(self.buf as *mut u8, layout);
+
+ self.buf = ptr::null();
+ self.len = 0;
+ }
+ }
}
impl Clone for PartialString {
fn next(&mut self) -> Option<Self::Item> {
unsafe {
- let b = ptr::read(self.buf);
-
- if b == 0u8 {
- return None;
- }
+ let mut byte_count = 0;
- let c = ptr::read(self.buf as *const char);
- self.buf = self.buf.offset(c.len_utf8() as isize);
+ for n in 0 .. mem::size_of::<char>() {
+ let b = ptr::read((self.buf as usize + n) as *const u8);
- Some(c)
- }
- }
-}
-
-pub struct PStrIterBounded {
- buf: *const u8,
- end: *const u8,
-}
-
-impl PStrIterBounded {
- #[inline]
- fn from(buf: *const u8, start: usize, end: usize) -> Self {
- PStrIterBounded {
- buf: (buf as usize + start) as *const _,
- end: (buf as usize + end) as *const _,
- }
- }
-}
-
-impl Iterator for PStrIterBounded {
- type Item = char;
-
- fn next(&mut self) -> Option<Self::Item> {
- unsafe {
- if self.buf >= self.end {
- return None;
+ if b == 0u8 {
+ break;
+ } else {
+ byte_count += 1;
+ }
}
- let b = ptr::read(self.buf);
-
- if b == 0u8 {
+ if byte_count == 0 {
return None;
}
- let c = ptr::read(self.buf as *const char);
- self.buf = self.buf.offset(c.len_utf8() as isize);
+ let slice = slice::from_raw_parts(self.buf, byte_count);
+ let s = str::from_utf8(slice).unwrap();
- Some(c)
+ if let Some(c) = s.chars().next() {
+ self.buf = self.buf.offset(c.len_utf8() as isize);
+ Some(c)
+ } else {
+ None
+ }
}
}
}
fn new(src: &str) -> Option<(Self, &str)> {
let pstr = PartialString {
buf: ptr::null_mut(),
+ len: 0,
+ _marker: PhantomData,
};
unsafe {
pub(super)
fn empty() -> Self {
PartialString {
- buf: "\u{0}".as_bytes()[0] as *const _,
+ buf: &"\u{0}".as_bytes()[0] as *const _,
+ len: '\u{0}'.len_utf8(),
+ _marker: PhantomData,
}
}
}
let layout = alloc::Layout::from_size_align_unchecked(
- src.len() + '\u{0}'.len_utf8(),
+ terminator_idx + '\u{0}'.len_utf8(),
mem::align_of::<u8>(),
);
self.buf = alloc::alloc(layout) as *const _;
+ self.len = terminator_idx + '\u{0}'.len_utf8();
ptr::copy(
src.as_ptr(),
})
}
- #[inline]
- pub(crate)
- fn iter(&self) -> PStrIter {
- PStrIter {
- buf: self.buf,
- }
- }
-
pub(super)
fn clone_from_offset(&self, n: usize) -> Self {
+ let len = if self.len > n { self.len - n } else { 0 };
+
let mut pstr = PartialString {
buf: ptr::null_mut(),
+ len: len + '\u{0}'.len_utf8(),
+ _marker: PhantomData,
};
unsafe {
- let len = scan_for_terminator(self.range_from(0 ..));
- let len = if len > n { len - n } else { 0 };
-
let layout = alloc::Layout::from_size_align_unchecked(
len + '\u{0}'.len_utf8(),
mem::align_of::<u8>(),
}
}
- #[inline]
- pub fn range(&self, index: Range<usize>) -> PStrIterBounded {
- PStrIterBounded::from(self.buf, index.start, index.end)
- }
-
#[inline]
pub fn range_from(&self, index: RangeFrom<usize>) -> PStrIter {
PStrIter::from(self.buf, index.start)
use std::ptr;
pub(crate) trait RawBlockTraits {
- fn init_size() -> usize;
+ fn init_size() -> usize;
fn align() -> usize;
#[inline]
block
}
- pub(crate)
- fn with_capacity(cap: usize) -> Self {
- let mut block = RawBlock { size: 0,
- base: ptr::null(),
- top: ptr::null(),
- _marker: PhantomData };
-
- unsafe {
- block.init_at_size(cap);
- }
-
- block
- }
-
unsafe fn init_at_size(&mut self, cap: usize) {
let layout = alloc::Layout::from_size_align_unchecked(cap, T::align());
mem::replace(self, Self::empty_block())
}
-
#[inline]
fn free_space(&self) -> usize {
debug_assert!(self.top >= self.base,
#[derive(Clone, Copy)]
pub struct FramePrelude {
- is_or_frame: u8,
pub num_cells: usize,
}
pub struct AndFrame {
pub prelude: AndFramePrelude,
- _marker: PhantomData<Addr>,
}
impl AndFrame {
impl IndexMut<usize> for AndFrame {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
- debug_assert!(self.prelude.univ_prelude.is_or_frame == 0);
-
let prelude_offset = prelude_size::<AndFramePrelude>();
let index_offset = (index - 1) * mem::size_of::<Addr>();
}
}
-impl Drop for AndFrame {
- fn drop(&mut self) {
- let prelude_offset = prelude_size::<AndFramePrelude>();
-
- unsafe {
- let ptr = mem::transmute::<&mut AndFrame, *const u8>(self);
- let ptr = ptr as usize + prelude_offset;
-
- for idx in 0 .. self.prelude.univ_prelude.num_cells {
- let index_offset = idx * mem::size_of::<Addr>();
- let ptr = (ptr + index_offset) as *mut Addr;
-
- ptr::drop_in_place(ptr);
- }
- }
- }
-}
-
pub struct OrFramePrelude {
pub univ_prelude: FramePrelude,
pub e: usize,
pub struct OrFrame {
pub prelude: OrFramePrelude,
- _marker: PhantomData<Addr>
}
impl Index<usize> for OrFrame {
#[inline]
fn index(&self, index: usize) -> &Self::Output {
- debug_assert!(self.prelude.univ_prelude.is_or_frame == 1);
-
let prelude_offset = prelude_size::<OrFramePrelude>();
let index_offset = index * mem::size_of::<Addr>();
impl IndexMut<usize> for OrFrame {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
- debug_assert!(self.prelude.univ_prelude.is_or_frame == 1);
-
let prelude_offset = prelude_size::<OrFramePrelude>();
let index_offset = index * mem::size_of::<Addr>();
}
}
-impl Drop for OrFrame {
- fn drop(&mut self) {
- let prelude_offset = prelude_size::<OrFramePrelude>();
-
- unsafe {
- let ptr = mem::transmute::<&mut OrFrame, *const u8>(self);
- let ptr = ptr as usize + prelude_offset;
-
- for idx in 0 .. self.prelude.univ_prelude.num_cells {
- let index_offset = idx * mem::size_of::<Addr>();
- let ptr = (ptr + index_offset) as *mut Addr;
-
- ptr::drop_in_place(ptr);
- }
- }
- }
-}
-
impl OrFrame {
pub fn size_of(num_cells: usize) -> usize {
prelude_size::<OrFramePrelude>() + num_cells * mem::size_of::<Addr>()
}
let and_frame = &mut *(self.buf.top as *mut AndFrame);
-
- and_frame.prelude.univ_prelude.is_or_frame = 0;
and_frame.prelude.univ_prelude.num_cells = num_cells;
let e = self.buf.top as usize - self.buf.base as usize;
}
let or_frame = &mut *(self.buf.top as *mut OrFrame);
-
- or_frame.prelude.univ_prelude.is_or_frame = 1;
or_frame.prelude.univ_prelude.num_cells = num_cells;
let b = self.buf.top as usize - self.buf.base as usize;
Stack { buf: self.buf.take(), _marker: PhantomData }
}
+ #[inline]
pub fn truncate(&mut self, b: usize) {
if b == 0 {
self.inner_truncate(mem::align_of::<Addr>());
}
}
+ #[inline]
fn inner_truncate(&mut self, b: usize) {
- let mut b = b + self.buf.base as usize;
- let base = b;
+ let base = b + self.buf.base as usize;
- unsafe {
- while b as *const _ < self.buf.top {
- let univ_prelude = ptr::read(b as *const FramePrelude);
-
- let offset = if univ_prelude.is_or_frame == 0 {
- let frame_ptr = b as *mut AndFrame;
- let frame = &mut *frame_ptr;
- let size_of_frame = AndFrame::size_of(frame.prelude.univ_prelude.num_cells);
-
- ptr::drop_in_place(frame_ptr);
-
- b + size_of_frame
- } else {
- debug_assert!(univ_prelude.is_or_frame == 1);
-
- let frame_ptr = b as *mut OrFrame;
- let frame = &mut *frame_ptr;
- let size_of_frame = OrFrame::size_of(frame.prelude.univ_prelude.num_cells);
-
- ptr::drop_in_place(frame_ptr);
-
- b + size_of_frame
- };
-
- b = offset;
- }
-
- if base < self.buf.top as usize {
- self.buf.top = base as *const _;
- }
+ if base < self.buf.top as usize {
+ self.buf.top = base as *const _;
}
}
impl BrentAlgState {
fn new(hare: Addr) -> Self {
BrentAlgState {
- hare: hare.clone(),
+ hare: hare,
tortoise: hare,
power: 2,
steps: 0,
if self.tortoise == self.hare {
return Some(CycleSearchResult::NotList);
} else if self.steps == self.power {
- self.tortoise = self.hare.clone();
+ self.tortoise = self.hare;
self.power <<= 1;
}
}
Addr::PStrLocation(h, n) => {
match &self.heap[h] {
- HeapCellValue::PartialString(ref pstr) => {
+ HeapCellValue::PartialString(ref pstr, _) => {
if let Some(c) = pstr.range_from(n ..).next() {
brent_st.step(Addr::PStrLocation(h, n + c.len_utf8()))
} else {
return CycleSearchResult::EmptyList;
}
Addr::Con(h) if max_steps > 0 => {
- if let HeapCellValue::PartialString(_) = &self.heap[h] {
+ if let HeapCellValue::PartialString(..) = &self.heap[h] {
if !self.flags.double_quotes.is_atom() {
Addr::PStrLocation(h, 0)
} else {
}
}
Addr::Con(h) => {
- if let HeapCellValue::PartialString(_) = &self.heap[h] {
+ if let HeapCellValue::PartialString(..) = &self.heap[h] {
if !self.flags.double_quotes.is_atom() {
return CycleSearchResult::UntouchedList(h);
}
Addr::PStrLocation(h, n)
}
Addr::Con(h) => {
- if let HeapCellValue::PartialString(_) = &self.heap[h] {
+ if let HeapCellValue::PartialString(..) = &self.heap[h] {
if !self.flags.double_quotes.is_atom() {
Addr::PStrLocation(h, 0)
} else {
&indices.op_dir,
) {
Ok(term_write_result) => {
- let a1 = self[temp_v!(1)].clone();
+ let a1 = self[temp_v!(1)];
self.unify(Addr::HeapCell(term_write_result.heap_loc), a1);
if self.fail {
list_of_var_eqs.push(Addr::Str(h));
}
- let a2 = self[temp_v!(2)].clone();
+ let a2 = self[temp_v!(2)];
let list_offset =
Addr::HeapCell(self.heap.to_list(list_of_var_eqs.into_iter()));
self.block = self.b;
let c = Constant::Usize(self.block);
- let addr = self[r].clone();
+ let addr = self[r];
self.write_constant_to_var(addr, &c);
self.block
where
AddrConstr: Fn(usize) -> Addr,
{
- match self.store(self.deref(self[temp_v!(1)].clone())) {
+ match self.store(self.deref(self[temp_v!(1)])) {
Addr::Usize(lh_offset) => {
if lh_offset >= self.lifted_heap.h() {
self.lifted_heap.truncate(lh_offset);
continue;
}
- let a2 = self[temp_v!(2)].clone();
+ let a2 = self[temp_v!(2)];
if let Some(r) = a2.as_var() {
let spec = get_clause_spec(
match op_dir.range(key..).skip(1).next() {
Some((OrderedOpDirKey(name, _), (priority, spec))) => {
- let a2 = self[temp_v!(2)].clone();
+ let a2 = self[temp_v!(2)];
if let Some(r) = a2.as_var() {
let addr = self.heap.to_unifiable(
indices: &IndexStore,
stub: MachineStub,
) -> CallResult {
- let nx = self[temp_v!(2)].clone();
+ let nx = self[temp_v!(2)];
if let Some(c) = string.chars().last() {
if layout_char!(c) {
self.term_dedup(&mut attr_goals);
let attr_goals = Addr::HeapCell(self.heap.to_list(attr_goals.into_iter()));
- let target = self[temp_v!(1)].clone();
+ let target = self[temp_v!(1)];
self.unify(attr_goals, target);
}
return Ok(());
}
&SystemClauseType::BindFromRegister => {
- let reg = self.store(self.deref(self[temp_v!(2)].clone()));
+ let reg = self.store(self.deref(self[temp_v!(2)]));
let n = match reg {
Addr::Con(h) =>
if let HeapCellValue::Integer(ref n) = &self.heap[h] {
} else {
unreachable!()
}
- _ => unreachable!()
+ _ => {
+ unreachable!()
+ }
};
if let Some(n) = n {
if n <= MAX_ARITY {
- let target = self[temp_v!(n)].clone();
- let addr = self[temp_v!(1)].clone();
+ let target = self[temp_v!(n)];
+ let addr = self[temp_v!(1)];
self.unify(addr, target);
return return_from_clause!(self.last_call, self);
}
}
&SystemClauseType::CurrentOutput => {
- let addr = self.store(self.deref(self[temp_v!(1)].clone()));
+ let addr = self.store(self.deref(self[temp_v!(1)]));
let stream = current_output_stream.clone();
match addr {
}
}
&SystemClauseType::AtomChars => {
- let a1 = self[temp_v!(1)].clone();
+ let a1 = self[temp_v!(1)];
match self.store(self.deref(a1)) {
Addr::Char(c) => {
self.unify(a2, list_of_chars);
}
Addr::Con(h) if self.heap.atom_at(h) => {
- if let HeapCellValue::Atom(name, _) = self.heap.clone(h) {
+ if let HeapCellValue::Atom(name, _) = self.heap.clone(h) {
let iter = name.as_str().chars().map(|c| Addr::Char(c));
let list_of_chars = Addr::HeapCell(self.heap.to_list(iter));
}
}
Addr::EmptyList => {
- let a2 = self[temp_v!(2)].clone();
+ let a2 = self[temp_v!(2)];
let chars = vec![
Addr::Char('['),
Addr::Char(']'),
};
}
&SystemClauseType::AtomCodes => {
- let a1 = self[temp_v!(1)].clone();
+ let a1 = self[temp_v!(1)];
match self.store(self.deref(a1)) {
Addr::Char(c) => {
let iter = once(Addr::CharCode(c as u32));
let list_of_codes = Addr::HeapCell(self.heap.to_list(iter));
- let a2 = self[temp_v!(2)].clone();
+ let a2 = self[temp_v!(2)];
self.unify(a2, list_of_codes);
}
Addr::Con(h) if self.heap.atom_at(h) => {
];
let list_of_codes = Addr::HeapCell(self.heap.to_list(chars.into_iter()));
- let a2 = self[temp_v!(2)].clone();
+ let a2 = self[temp_v!(2)];
self.unify(a2, list_of_codes);
}
}
}
&SystemClauseType::IsPartialString => {
- let pstr = self.store(self.deref(self[temp_v!(1)].clone()));
+ let pstr = self.store(self.deref(self[temp_v!(1)]));
match pstr {
Addr::PStrLocation(..) => {
return Ok(());
}
&SystemClauseType::LiftedHeapLength => {
- let a1 = self[temp_v!(1)].clone();
+ let a1 = self[temp_v!(1)];
let lh_len = Addr::Usize(self.lifted_heap.h());
self.unify(a1, lh_len);
};
}
&SystemClauseType::CheckCutPoint => {
- let addr = self.store(self.deref(self[temp_v!(1)].clone()));
+ let addr = self.store(self.deref(self[temp_v!(1)]));
match addr {
Addr::Usize(old_b) | Addr::CutPoint(old_b) => {
};
}
&SystemClauseType::FetchGlobalVarWithOffset => {
- let key = self[temp_v!(1)].clone();
+ let key = self[temp_v!(1)];
let key = match self.store(self.deref(key)) {
Addr::Con(h) if self.heap.atom_at(h) => {
*offset = Some(h);
}
Some((_, Some(h))) => {
- let offset = self[temp_v!(3)].clone();
+ let offset = self[temp_v!(3)];
self.unify(offset, Addr::Usize(*h));
let mut iter = parsing_stream(current_input_stream.clone());
let result = iter.next();
- let a1 = self[temp_v!(1)].clone();
+ let a1 = self[temp_v!(1)];
match result {
Some(Ok(b)) => {
};
}
&SystemClauseType::HeadIsDynamic => {
- let head = self[temp_v!(1)].clone();
+ let head = self[temp_v!(1)];
self.fail = !match self.store(self.deref(head)) {
Addr::Str(s) => match &self.heap[s] {
for addr in self.lifted_heap.iter_mut_from(old_threshold + 1) {
match addr {
HeapCellValue::Addr(ref mut addr) => {
- *addr -= self.heap.h() + lh_offset
+ *addr -= self.heap.h() + lh_offset;
}
_ => {}
}
let iter = self.gather_attr_vars_created_since(b);
let var_list_addr = Addr::HeapCell(self.heap.to_list(iter));
- let list_addr = self[temp_v!(2)].clone();
+ let list_addr = self[temp_v!(2)];
self.unify(var_list_addr, list_addr);
} else {
),
);
- let target = self[temp_v!(1)].clone();
+ let target = self[temp_v!(1)];
self.unify(target, module);
}
ContinueResult::PrintWithMaxDepth => 'p',
};
- let target = self[temp_v!(1)];
+ let target = self[temp_v!(1)];
self.unify(Addr::Char(c), target);
}
&SystemClauseType::NextEP => {
self.reset_block(addr);
}
&SystemClauseType::ResetContinuationMarker => {
- let h = self.heap.h();
-
self[temp_v!(3)] = self.heap.to_unifiable(
HeapCellValue::Atom(clause_name!("none"), None)
);
+ let h = self.heap.h();
+
self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h)));
self[temp_v!(4)] = Addr::HeapCell(h);
}
let mut ball = Ball::new();
ball.boundary = self.heap.h();
-
+
copy_term(
CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut ball.stub),
value,
h,
ExistenceError::Procedure(name, arity),
);
-
+
let err = self.error_form(err, stub);
self.throw_exception(err);
);
let listing = Addr::HeapCell(self.heap.to_list(functors.into_iter()));
- let listing_var = self[temp_v!(3)].clone();
+ let listing_var = self[temp_v!(3)];
self.unify(listing, listing_var);
}
while let Some(term) = self.stack.pop() {
match machine_st.try_expand_term(self.wam, &term, CompileTimeHook::TermExpansion) {
- Some(term_string) => {
+ Some(term_string) => {
let term = self.parse_expansion_output(term_string.as_str(), op_dir)?;
self.enqueue_term(term)?;
}
unreachable!()
}
-
+
pub fn read_term(&mut self, op_dir: &OpDir) -> Result<Term, ParserError> {
loop {
if let Some(term) = self.stack.pop() {
}
impl MachineState {
- pub(super) fn print_with_locs(&self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter {
+ pub(super)
+ fn print_with_locs(&self, addr: Addr, op_dir: &OpDir) -> PrinterOutputter {
let output = PrinterOutputter::new();
let mut printer = HCPrinter::from_heap_locs(&self, op_dir, output);
let mut max_var_length = 0;
printer.quoted = true;
printer.numbervars = true;
-
- // the purpose of the offset is to avoid clashes with variable names that might
- // occur after the addresses in the expanded term are substituted with the variable
- // names in the pre-expansion term. This formula ensures that all generated "numbervars"-
- // style variable names will be longer than the keys of the var_dict, and therefore
- // not equal to any of them.
+
+ // the purpose of the offset is to avoid clashes with variable
+ // names that might occur after the addresses in the expanded
+ // term are substituted with the variable names in the
+ // pre-expansion term. This formula ensures that all generated
+ // "numbervars"- style variable names will be longer than the
+ // keys of the var_dict, and therefore not equal to any of
+ // them.
printer.numbervars_offset = Integer::from(10).pow(max_var_length as u32) * 26;
printer.print_strings_as_strs = true;
printer.drop_toplevel_spec();
}
// reset the machine, but keep the heap contents as they were.
- // this prevents clashes between underscored variable names
- // in the same query.
+ // this prevents clashes between underscored variable names in the
+ // same query.
fn reset_with_heap_preservation(&mut self) {
let heap = self.heap.take();
self.reset();
wam.code_repo.cached_query = code;
self.cp = LocalCodePtr::TopLevel(0, 0);
+
self.at_end_of_expansion = false;
+ self.flags.double_quotes = DoubleQuotes::Chars;
self.query_stepper(
&mut wam.indices,
(number($e:expr), $arity:expr, $aux_lens:expr, $addendum:ident) => (
$e.into()
);
- /*
- (string($s:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => ({
- let len: usize = $aux_lens.iter().sum();
- let h = len + $arity + 1 + $addendum.h();
-
- $addendum.allocate_pstr(&$s);
-
- HeapCell::PStrLocation(h, 0)
- });
- */
(integer($e:expr), $arity:expr, $aux_lens:expr, $addendum: ident) => (
HeapCellValue::Integer(Rc::new(Integer::from($e)))
);
&Constant::CharCode(c) => {
HeapCellValue::Addr(Addr::CharCode(c))
}
- &Constant::CutPoint(cp) => {
- HeapCellValue::Addr(Addr::CutPoint(cp))
- }
&Constant::Integer(ref n) => {
HeapCellValue::Integer(n.clone())
}
pub(crate) var_dict: HeapVarDict,
}
-pub(crate) fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult {
+pub(crate)
+fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult {
let heap_loc = machine_st.heap.h();
let mut queue = SubtermDeque::new();
continue;
}
}
- &TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..) => {
- let value = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
- machine_st.heap.push(value);
- }
- &TermRef::Var(Level::Root, ..) => {
- let value = HeapCellValue::Addr(term.as_addr(&mut machine_st.heap, h));
- machine_st.heap.push(value);
+ &TermRef::AnonVar(Level::Root) | &TermRef::Constant(Level::Root, ..)
+ | &TermRef::Var(Level::Root, ..) => {
+ let addr = term.as_addr(&mut machine_st.heap, h);
+
+ if !addr.is_heap_bound() {
+ machine_st.heap.push(HeapCellValue::Addr(addr));
+ }
}
&TermRef::AnonVar(_) => {
if let Some((arity, site_h)) = queue.pop_front() {
).
'$submit_query_and_print_results'(Term0, VarList) :-
- write('oh brother'), nl,
( expand_goals(Term0, Term) -> true
; Term0 = Term
),
&HeapCellValue::NamedStr(arity, ref name, None) => {
write!(f, "{}/{}", name.as_str(), arity)
}
- &HeapCellValue::PartialString(ref pstr) => {
- write!(f, "pstr ( buf: 0x{:x} )", (pstr as *const _) as usize)
+ &HeapCellValue::PartialString(ref pstr, has_tail) => {
+ write!(f, "pstr ( buf: 0x{:x}, has_tail({}) )",
+ (pstr as *const _) as usize,
+ has_tail)
}
&HeapCellValue::Stream(ref stream) => {
write!(f, "$stream({})", stream.as_ptr() as usize)
retract(p(_,_,_)),
assertz(p(Z, h(Z, W), f(W))),
p(f(f(a)), h(f(f(a)), f(a)), f(f(a))),
- retract(p(Z, h(Z, W), f(W))).
+ retract(p(Z, h(Z, W), f(W))).[
:- initialization(test_queries_on_facts).