From: Mark Thom Date: Fri, 3 Apr 2020 16:22:46 +0000 (-0600) Subject: harmonize partial strings with complete strings (#276), make Addr a copyable type X-Git-Tag: v0.8.119~29 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=141f3bcec31d131c001d99e125b02b1e72eff95a;p=scryer-prolog.git harmonize partial strings with complete strings (#276), make Addr a copyable type --- diff --git a/Cargo.lock b/Cargo.lock index 0fe6e3f4..ea022e95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -445,6 +445,7 @@ dependencies = [ [[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)", @@ -579,7 +580,7 @@ dependencies = [ "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)", @@ -790,6 +791,7 @@ dependencies = [ "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" diff --git a/Cargo.toml b/Cargo.toml index 7c3338f3..b8a57623 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,10 +25,7 @@ libc = "0.2.62" 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 diff --git a/src/prolog/forms.rs b/src/prolog/forms.rs index 4f569227..f26361de 100644 --- a/src/prolog/forms.rs +++ b/src/prolog/forms.rs @@ -282,9 +282,9 @@ impl ClauseConsistency for Rule { 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() } } @@ -597,7 +597,7 @@ impl Into for Number { } } -impl Number { +impl Number { #[inline] pub fn is_positive(&self) -> bool { match self { diff --git a/src/prolog/heap_iter.rs b/src/prolog/heap_iter.rs index 57434fd9..8a3ce492 100644 --- a/src/prolog/heap_iter.rs +++ b/src/prolog/heap_iter.rs @@ -37,7 +37,7 @@ impl<'a> HCPreOrderIterator<'a> { &HeapCellValue::Addr(a) => { self.follow(a) } - HeapCellValue::PartialString(_) => { + HeapCellValue::PartialString(..) => { self.follow(Addr::PStrLocation(h, 0)) } HeapCellValue::Atom(..) | HeapCellValue::DBRef(_) @@ -64,17 +64,19 @@ impl<'a> HCPreOrderIterator<'a> { 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!() @@ -86,8 +88,19 @@ impl<'a> HCPreOrderIterator<'a> { 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) @@ -157,11 +170,18 @@ impl<'a> Iterator for HCPostOrderIterator<'a> { 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!() + } } } _ => { diff --git a/src/prolog/heap_print.rs b/src/prolog/heap_print.rs index 0ccc155b..03659752 100644 --- a/src/prolog/heap_print.rs +++ b/src/prolog/heap_print.rs @@ -184,16 +184,16 @@ pub trait HCValueOutputter { 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) -> &str; - fn range_from(&self, _: RangeFrom) -> &str; + fn truncate(&mut self, len: usize); + fn range(&self, range: Range) -> &str; + fn range_from(&self, range: RangeFrom) -> &str; } pub struct PrinterOutputter { @@ -1022,130 +1022,149 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } } - 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> = - 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> = - 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> = + 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); } } @@ -1250,7 +1269,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { 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); @@ -1320,23 +1339,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { &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 { @@ -1358,21 +1362,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { &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); @@ -1385,6 +1374,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } } _ => { + unreachable!() } } } diff --git a/src/prolog/instructions.rs b/src/prolog/instructions.rs index eb6db521..903fbd3c 100644 --- a/src/prolog/instructions.rs +++ b/src/prolog/instructions.rs @@ -482,7 +482,7 @@ impl FactInstruction { functor!( "get_constant", - [aux(h, 0), constant(c), aux(h, 1)], + [aux(h, 0), constant(h, c), aux(h, 1)], [lvl_stub, rt_stub] ) } @@ -524,7 +524,7 @@ impl FactInstruction { ) } &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); @@ -589,7 +589,7 @@ impl QueryInstruction { functor!( "put_constant", - [aux(h, 0), constant(c), aux(h, 1)], + [aux(h, 0), constant(h, c), aux(h, 1)], [lvl_stub, rt_stub] ) } @@ -640,7 +640,7 @@ impl QueryInstruction { ) } &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); diff --git a/src/prolog/lib/atts.pl b/src/prolog/lib/atts.pl index 1522e0ce..1d6fddf7 100644 --- a/src/prolog/lib/atts.pl +++ b/src/prolog/lib/atts.pl @@ -132,11 +132,11 @@ put_attr(Name, Arity) --> '$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) --> @@ -158,4 +158,3 @@ call_residue_vars(Goal, Vars) :- '$get_attr_var_queue_delim'(B), call(Goal), '$get_attr_var_queue_beyond'(B, Vars). - diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index 352a18a9..cff33c77 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -262,8 +262,11 @@ univ_errors(Term, List, N) :- 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), @@ -274,7 +277,9 @@ univ_worker(Term, List, _) :- '$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) :- @@ -287,19 +292,19 @@ get_args([Arg|Args], Func, I0, 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) :- diff --git a/src/prolog/lib/cont.pl b/src/prolog/lib/cont.pl index 18d97005..032234e6 100644 --- a/src/prolog/lib/cont.pl +++ b/src/prolog/lib/cont.pl @@ -1,4 +1,3 @@ - :- module(cont, [reset/3, shift/1]). reset(Goal, Ball, Cont) :- @@ -7,14 +6,14 @@ 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) :- diff --git a/src/prolog/lib/tabling.pl b/src/prolog/lib/tabling.pl index 0c2aa766..153d7f47 100644 --- a/src/prolog/lib/tabling.pl +++ b/src/prolog/lib/tabling.pl @@ -135,7 +135,7 @@ activate(Wrapper,Worker,T) :- 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]) @@ -144,9 +144,9 @@ delim(Wrapper,Worker,Table) :- ) ; ( Continuation = cont(Cont) -> - true + true ; Continuation = none -> - Cont = true + Cont = true ), SourceCall = call_info(_,SourceTable), TargetCall = call_info(Wrapper,Table), @@ -178,7 +178,7 @@ completion_step(SourceTableID) :- fail ; true - ). + ). table_get_work(NBWorklistID,Answer,Dependency) :- % get_worklist(Table, Worklist), @@ -192,7 +192,7 @@ table_get_work(NBWorklistID,Answer,Dependency) :- 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), diff --git a/src/prolog/lib/tabling/double_linked_list.pl b/src/prolog/lib/tabling/double_linked_list.pl index 4cd1aab3..d80ee6db 100644 --- a/src/prolog/lib/tabling/double_linked_list.pl +++ b/src/prolog/lib/tabling/double_linked_list.pl @@ -208,4 +208,3 @@ dll_get_reverse_contents_(List, Contents) :- dll_get_pointer_to_previous(List, Prev), dll_get_reverse_contents_(Prev, Rest) ). - diff --git a/src/prolog/lib/tabling/global_worklist.pl b/src/prolog/lib/tabling/global_worklist.pl index dbe8b4c5..19502a92 100644 --- a/src/prolog/lib/tabling/global_worklist.pl +++ b/src/prolog/lib/tabling/global_worklist.pl @@ -1,4 +1,4 @@ -/* Ported to Scryer Prolog by Mark Thom (2019/2020). +/* Ported to Scryer Prolog by Mark Thom (2019/2020). */ :- module(global_worklist, @@ -21,7 +21,7 @@ put_new_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])), @@ -34,7 +34,7 @@ worklist_empty :- 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). diff --git a/src/prolog/lib/tabling/trie.pl b/src/prolog/lib/tabling/trie.pl index eb102df1..18e77d9f 100644 --- a/src/prolog/lib/tabling/trie.pl +++ b/src/prolog/lib/tabling/trie.pl @@ -187,7 +187,7 @@ trie_insert_1_1_1(>,_V,_L,R,Assoc,FunctorData,Trie,First,Rest,Value) :- % 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). diff --git a/src/prolog/machine/arithmetic_ops.rs b/src/prolog/machine/arithmetic_ops.rs index 647c88b8..cf2a3b91 100644 --- a/src/prolog/machine/arithmetic_ops.rs +++ b/src/prolog/machine/arithmetic_ops.rs @@ -175,6 +175,12 @@ impl MachineState { &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())) } diff --git a/src/prolog/machine/attributed_variables.pl b/src/prolog/machine/attributed_variables.pl index 2a18d639..af8d8af8 100644 --- a/src/prolog/machine/attributed_variables.pl +++ b/src/prolog/machine/attributed_variables.pl @@ -21,13 +21,13 @@ call_verify_attributes(Attrs, _, _, []) :- 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([], _, _, []). diff --git a/src/prolog/machine/attributed_variables.rs b/src/prolog/machine/attributed_variables.rs index f21c8926..b216a48c 100644 --- a/src/prolog/machine/attributed_variables.rs +++ b/src/prolog/machine/attributed_variables.rs @@ -19,7 +19,8 @@ pub(super) struct AttrVarInitializer { } 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![], @@ -32,21 +33,24 @@ impl AttrVarInitializer { } #[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(); @@ -92,7 +96,8 @@ impl MachineState { self[temp_v!(2)] = value_list_addr; } - pub(super) fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter { + pub(super) + fn gather_attr_vars_created_since(&self, b: usize) -> IntoIter { 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))) { @@ -109,7 +114,8 @@ impl MachineState { 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; diff --git a/src/prolog/machine/copier.rs b/src/prolog/machine/copier.rs index 724b6c54..10b67d4e 100644 --- a/src/prolog/machine/copier.rs +++ b/src/prolog/machine/copier.rs @@ -33,13 +33,13 @@ struct CopyTermState { scan: usize, old_h: usize, target: T, - attr_var_policy: AttrVarPolicy + attr_var_policy: AttrVarPolicy, } impl CopyTermState { fn new(target: T, attr_var_policy: AttrVarPolicy) -> Self { CopyTermState { - trail: vec![], + trail: Trail::new(), scan: 0, old_h: target.threshold(), target, @@ -53,124 +53,86 @@ impl CopyTermState { &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) { @@ -178,6 +140,7 @@ impl CopyTermState { 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)), @@ -186,6 +149,7 @@ impl CopyTermState { 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)), @@ -199,7 +163,8 @@ impl CopyTermState { }; 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)), @@ -212,7 +177,9 @@ impl CopyTermState { self.target.push(list_val); } } - _ => unreachable!() + _ => { + unreachable!() + } } } @@ -234,17 +201,39 @@ impl CopyTermState { } } + 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)); @@ -257,7 +246,9 @@ impl CopyTermState { HeapCellValue::Addr(Addr::Str(addr)) => { *self.value_at_scan() = HeapCellValue::Addr(Addr::Str(addr)) } - _ => {} + _ => { + unreachable!() + } } self.scan += 1; @@ -272,26 +263,30 @@ impl CopyTermState { &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; diff --git a/src/prolog/machine/dynamic_database.rs b/src/prolog/machine/dynamic_database.rs index e82aaa04..a4862771 100644 --- a/src/prolog/machine/dynamic_database.rs +++ b/src/prolog/machine/dynamic_database.rs @@ -51,13 +51,19 @@ impl Machine { }; 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) diff --git a/src/prolog/machine/heap.rs b/src/prolog/machine/heap.rs index d8d39036..f979d38a 100644 --- a/src/prolog/machine/heap.rs +++ b/src/prolog/machine/heap.rs @@ -39,12 +39,12 @@ impl Drop for HeapTemplate { } pub(crate) -struct HeapIntoIterator { +struct HeapIntoIter { offset: usize, buf: RawBlock, } -impl Drop for HeapIntoIterator { +impl Drop for HeapIntoIter { fn drop(&mut self) { let mut heap = HeapTemplate { buf: self.buf.take(), _marker: PhantomData }; @@ -54,7 +54,7 @@ impl Drop for HeapIntoIterator { } } -impl Iterator for HeapIntoIterator { +impl Iterator for HeapIntoIter { type Item = HeapCellValue; fn next(&mut self) -> Option { @@ -72,19 +72,19 @@ impl Iterator for HeapIntoIterator { } pub(crate) -struct HeapIterator<'a, T: RawBlockTraits> { +struct HeapIter<'a, T: RawBlockTraits> { offset: usize, buf: &'a RawBlock, } -impl<'a, T: RawBlockTraits> HeapIterator<'a, T> { +impl<'a, T: RawBlockTraits> HeapIter<'a, T> { pub(crate) fn new(buf: &'a RawBlock, 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 { @@ -101,20 +101,28 @@ impl<'a, T: RawBlockTraits> Iterator for HeapIterator<'a, T> { } } +#[allow(dead_code)] pub(crate) -struct HeapIteratorMut<'a, T: RawBlockTraits> { +fn print_heap_terms<'a, I: Iterator>(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, } -impl<'a, T: RawBlockTraits> HeapIteratorMut<'a, T> { +impl<'a, T: RawBlockTraits> HeapIterMut<'a, T> { pub(crate) fn new(buf: &'a mut RawBlock, 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 { @@ -160,7 +168,7 @@ impl HeapTemplate { &HeapCellValue::Rational(ref r) => { HeapCellValue::Rational(r.clone()) } - &HeapCellValue::PartialString(_) => { + &HeapCellValue::PartialString(..) => { HeapCellValue::Addr(Addr::PStrLocation(h, 0)) } &HeapCellValue::Stream(_) => { @@ -169,6 +177,15 @@ impl HeapTemplate { } } + #[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 { @@ -177,40 +194,45 @@ impl HeapTemplate { 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) } } @@ -239,7 +261,7 @@ impl HeapTemplate { false } } - + #[inline] pub(crate) fn integer_at(&self, h: usize) -> bool { @@ -279,9 +301,12 @@ impl HeapTemplate { 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) } @@ -296,7 +321,8 @@ impl HeapTemplate { let h = self.h(); self.push(HeapCellValue::PartialString( - PartialString::empty() + PartialString::empty(), + true, )); self.push(HeapCellValue::Addr( @@ -343,7 +369,7 @@ impl HeapTemplate { } }; - self.push(HeapCellValue::PartialString(pstr)); + self.push(HeapCellValue::PartialString(pstr, true)); if rest_src != "" { self.push(HeapCellValue::Addr(Addr::PStrLocation(h + 2, 0))); @@ -414,7 +440,7 @@ impl HeapTemplate { self.push(HeapCellValue::Addr(Addr::Lis(h + 1))); self.push(value); - h += mem::size_of::() * 2; + h += 2; } self.push(HeapCellValue::Addr(Addr::EmptyList)); @@ -424,18 +450,18 @@ impl HeapTemplate { /* 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::()) + fn iter_from<'a>(&'a self, offset: usize) -> HeapIter<'a, T> { + HeapIter::new(&self.buf, offset * mem::size_of::()) } pub(crate) - fn iter_mut_from<'a>(&'a mut self, offset: usize) -> HeapIteratorMut<'a, T> { - HeapIteratorMut::new(&mut self.buf, offset * mem::size_of::()) + fn iter_mut_from<'a>(&'a mut self, offset: usize) -> HeapIterMut<'a, T> { + HeapIterMut::new(&mut self.buf, offset * mem::size_of::()) } pub(crate) - fn into_iter(mut self) -> HeapIntoIterator { - HeapIntoIterator { buf: self.buf.take(), offset: 0 } + fn into_iter(mut self) -> HeapIntoIter { + HeapIntoIter { buf: self.buf.take(), offset: 0 } } pub(crate) diff --git a/src/prolog/machine/machine_errors.rs b/src/prolog/machine/machine_errors.rs index 0a352a66..1f3dc180 100644 --- a/src/prolog/machine/machine_errors.rs +++ b/src/prolog/machine/machine_errors.rs @@ -222,7 +222,7 @@ impl MachineError { SharedOpDesc::new(400, YFX), [clause_name(name), integer(arity)] ); - + let stub = functor!( "existence_error", [atom("procedure"), aux(h, 0)], @@ -286,7 +286,7 @@ impl MachineError { fn domain_error(error: DomainErrorType, culprit: T) -> Self { culprit.domain_error(error) } - + pub(super) fn instantiation_error() -> Self { let stub = functor!("instantiation_error"); @@ -352,7 +352,7 @@ impl MachineError { let location = err.line_and_col_num(); let stub = functor!(err.as_str()); - + let stub = functor!( "syntax_error", [aux(h, 0)], @@ -608,7 +608,7 @@ impl MachineState { 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())); diff --git a/src/prolog/machine/machine_indices.rs b/src/prolog/machine/machine_indices.rs index b2dff159..c5fc505a 100644 --- a/src/prolog/machine/machine_indices.rs +++ b/src/prolog/machine/machine_indices.rs @@ -152,6 +152,20 @@ impl PartialOrd for Addr { } 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(_) => { @@ -163,6 +177,7 @@ impl Addr { } } + #[inline] pub fn as_var(&self) -> Option { match self { &Addr::AttrVar(h) => Some(Ref::AttrVar(h)), @@ -173,7 +188,7 @@ impl Addr { } pub(super) - fn order_category(&self, heap: &Heap) -> Option { + fn order_category(&self, heap: &Heap) -> Option { match self { Addr::HeapCell(_) | Addr::AttrVar(_) | Addr::StackCell(..) => { Some(TermOrderCategory::Variable) @@ -200,18 +215,21 @@ impl Addr { } } } - 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 { match self { &Addr::Char(c) => { @@ -236,12 +254,30 @@ impl Addr { } } } + &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 @@ -262,6 +298,8 @@ impl Add for Addr { 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), @@ -278,6 +316,8 @@ impl Sub for Addr { 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), @@ -296,6 +336,8 @@ impl Sub for Addr { 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), @@ -331,8 +373,8 @@ pub enum HeapCellValue { DBRef(DBRef), Integer(Rc), NamedStr(usize, ClauseName, Option), // arity, name, precedence/Specifier if it has one. - Rational(Rc), - PartialString(PartialString), + Rational(Rc), + PartialString(PartialString, bool), // the partial string, a bool indicating whether it came from a Constant. Stream(Stream), } @@ -341,7 +383,7 @@ impl HeapCellValue { 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(..) => { @@ -350,7 +392,7 @@ impl HeapCellValue { HeapCellValue::NamedStr(_, _, _) => { Addr::Str(focus) } - HeapCellValue::PartialString(_) => { + HeapCellValue::PartialString(..) => { Addr::PStrLocation(focus, 0) } HeapCellValue::Stream(_) => { @@ -380,8 +422,8 @@ impl HeapCellValue { &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()) diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 88862e0f..f5077d9d 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -14,11 +14,105 @@ use crate::prolog::rug::Integer; 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, +} + +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; + + fn next(&mut self) -> Option { + 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, +) -> 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, @@ -185,7 +279,7 @@ impl<'a> CopierTarget for CopyBallTerm<'a> { 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 @@ -195,7 +289,7 @@ impl<'a> CopierTarget for CopyBallTerm<'a> { 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; @@ -264,11 +358,13 @@ impl HeapPtr { 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!() @@ -315,13 +411,19 @@ pub struct MachineState { } 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) -> Result { 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) => { @@ -480,7 +582,7 @@ pub(crate) trait CallPolicy: Any { 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; @@ -519,7 +621,7 @@ pub(crate) trait CallPolicy: Any { 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; @@ -555,7 +657,7 @@ pub(crate) trait CallPolicy: Any { 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; @@ -595,7 +697,7 @@ pub(crate) trait CallPolicy: Any { 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; @@ -717,7 +819,7 @@ pub(crate) trait CallPolicy: Any { ) -> 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) } @@ -726,9 +828,9 @@ pub(crate) trait CallPolicy: Any { 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) => { @@ -769,7 +871,7 @@ pub(crate) trait CallPolicy: Any { &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) => { @@ -789,8 +891,8 @@ pub(crate) trait CallPolicy: Any { 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) @@ -804,8 +906,8 @@ pub(crate) trait CallPolicy: Any { 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) { @@ -830,7 +932,7 @@ pub(crate) trait CallPolicy: Any { 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) @@ -854,13 +956,13 @@ pub(crate) trait CallPolicy: Any { 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())); @@ -1142,13 +1244,13 @@ fn cut_body(machine_st: &mut MachineState, addr: &Addr) -> bool { 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) } } @@ -1209,7 +1311,7 @@ impl CutPolicy for SCCCutPolicy { 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; diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index fd721fa1..b7c56b78 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -96,13 +96,6 @@ impl MachineState { } } - #[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 @@ -115,14 +108,16 @@ impl MachineState { 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!() @@ -137,7 +132,7 @@ impl MachineState { 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; @@ -159,7 +154,7 @@ impl MachineState { 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))); } @@ -169,7 +164,7 @@ impl MachineState { 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 { @@ -235,13 +230,13 @@ impl MachineState { 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) } @@ -268,7 +263,7 @@ impl MachineState { } (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)); @@ -283,8 +278,8 @@ impl MachineState { } } (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 ..); @@ -296,19 +291,38 @@ impl MachineState { 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!() } @@ -323,11 +337,6 @@ impl MachineState { 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]; @@ -347,7 +356,79 @@ impl MachineState { 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; + } + } }; } } @@ -369,13 +450,13 @@ impl MachineState { 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); } @@ -402,7 +483,7 @@ impl MachineState { } (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)); @@ -417,8 +498,8 @@ impl MachineState { } } (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 ..); @@ -430,19 +511,38 @@ impl MachineState { 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)); + } + } } } } @@ -453,11 +553,6 @@ impl MachineState { 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]; @@ -477,49 +572,82 @@ impl MachineState { self.fail = true; } - _ => self.fail = true, - }; - } - } - } - - pub(super) - fn to_complete_string(&self, h: usize, n: usize) -> Option { - 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) @@ -566,7 +694,7 @@ impl MachineState { &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(); } @@ -648,18 +776,30 @@ impl MachineState { 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) => { @@ -669,20 +809,32 @@ impl MachineState { 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 { @@ -694,20 +846,23 @@ impl MachineState { 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); } } }; @@ -1003,11 +1158,11 @@ impl MachineState { 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) => { @@ -1032,9 +1187,9 @@ impl MachineState { }; } &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]; @@ -1062,11 +1217,11 @@ impl MachineState { }; } &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); } @@ -1077,7 +1232,11 @@ impl MachineState { 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)); + } } }; @@ -1099,11 +1258,11 @@ impl MachineState { &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 { @@ -1131,7 +1290,7 @@ impl MachineState { 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)); } }; @@ -1161,8 +1320,8 @@ impl MachineState { 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(..) => { @@ -1172,10 +1331,10 @@ impl MachineState { 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 } @@ -1212,7 +1371,7 @@ impl MachineState { }; } &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 { @@ -1242,7 +1401,7 @@ impl MachineState { 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()); @@ -1272,7 +1431,7 @@ impl MachineState { } } &QueryInstruction::PutValue(norm, arg) => { - self.registers[arg] = self[norm].clone(); + self.registers[arg] = self[norm]; } &QueryInstruction::PutVariable(norm, arg) => { match norm { @@ -1292,7 +1451,11 @@ impl MachineState { }; } &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]); @@ -1312,7 +1475,7 @@ impl MachineState { 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) => { @@ -1328,7 +1491,7 @@ impl MachineState { 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( @@ -1340,10 +1503,10 @@ impl MachineState { 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 { @@ -1355,7 +1518,7 @@ impl MachineState { } pub(super) fn setup_call_n(&mut self, arity: usize) -> Option { - 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) => { @@ -1375,7 +1538,7 @@ impl MachineState { } 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 { @@ -1436,7 +1599,7 @@ impl MachineState { loop { if let Some(addr) = iter.stack().last() { if !seen.contains(addr) { - seen.insert(addr.clone()); + seen.insert(*addr); } else { fail = true; break; @@ -1452,7 +1615,8 @@ impl MachineState { } // 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)])); @@ -1480,7 +1644,7 @@ impl MachineState { } }; - 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) @@ -1488,16 +1652,18 @@ impl MachineState { } 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); @@ -1507,9 +1673,9 @@ impl MachineState { } 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) @@ -1544,7 +1710,7 @@ impl MachineState { MachineError::type_error( self.heap.h(), ValidType::Integer, - Addr::Con(h), + Addr::HeapCell(h), ), stub, )) @@ -1582,8 +1748,8 @@ impl MachineState { } 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 { @@ -1625,7 +1791,7 @@ impl MachineState { } } (Addr::PStrLocation(..), Addr::Lis(_)) - | (Addr::Lis(_), Addr::PStrLocation(..)) + | (Addr::Lis(_), Addr::PStrLocation(..)) if !self.flags.double_quotes.is_atom() => { continue; } @@ -1674,6 +1840,36 @@ impl MachineState { } } } + (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; @@ -1687,13 +1883,13 @@ impl MachineState { } pub(super) fn compare_term_test(&self, a1: &Addr, a2: &Addr) -> Option { - 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)); } @@ -1761,6 +1957,34 @@ impl MachineState { } } } + (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!() } @@ -1956,6 +2180,11 @@ impl MachineState { Some('['.cmp(&c)) }; } + ( + Addr::EmptyList, + Addr::EmptyList, + ) => { + } _ => { return None; } @@ -2076,7 +2305,7 @@ impl MachineState { 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) => @@ -2091,7 +2320,7 @@ impl MachineState { }; } &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, @@ -2099,7 +2328,7 @@ impl MachineState { }; } &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) => { @@ -2119,7 +2348,7 @@ impl MachineState { } } } - Addr::CharCode(_) => { + Addr::CharCode(_) | Addr::Usize(_) => { self.p += 1; } Addr::Char(_) if self.flags.double_quotes.is_codes() => { @@ -2139,7 +2368,7 @@ impl MachineState { }; } &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, @@ -2147,7 +2376,7 @@ impl MachineState { }; } &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) => { @@ -2163,7 +2392,7 @@ impl MachineState { }; } &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, @@ -2171,7 +2400,7 @@ impl MachineState { }; } &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(..) => { @@ -2183,7 +2412,7 @@ impl MachineState { }; } &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(_, _) => { @@ -2255,7 +2484,8 @@ impl MachineState { 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) { @@ -2280,10 +2510,36 @@ impl MachineState { 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( @@ -2294,95 +2550,87 @@ impl MachineState { 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) { + pub(super) + fn term_dedup(&self, list: &mut Vec) { let mut result = vec![]; for a2 in list.iter() { @@ -2406,7 +2654,7 @@ impl MachineState { ) -> Result, 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) } @@ -2441,7 +2689,7 @@ impl MachineState { 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; @@ -2486,9 +2734,13 @@ impl MachineState { a1: Addr, ) -> Result, 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)) { @@ -2499,6 +2751,8 @@ impl MachineState { return self.try_from_inner_list(chars, l, caller, a1); } Addr::PStrLocation(h1, n1) => { + chars.push(Addr::Char('\u{0}')); + h = h1; n = n1; } @@ -2557,8 +2811,8 @@ impl MachineState { 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); @@ -2650,9 +2904,13 @@ impl MachineState { } }, ( - 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 ..); @@ -2731,7 +2989,7 @@ impl MachineState { // 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 { @@ -2895,7 +3153,7 @@ impl MachineState { self.p += offset; } &ControlInstruction::Proceed => { - self.p = CodePtr::Local(self.cp.clone()); + self.p = CodePtr::Local(self.cp); } }; } @@ -2928,7 +3186,7 @@ impl MachineState { 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(); @@ -2966,7 +3224,7 @@ impl MachineState { 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(); @@ -3015,8 +3273,8 @@ impl MachineState { 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; diff --git a/src/prolog/machine/partial_string.rs b/src/prolog/machine/partial_string.rs index 32015030..0a74ecff 100644 --- a/src/prolog/machine/partial_string.rs +++ b/src/prolog/machine/partial_string.rs @@ -1,11 +1,28 @@ +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::()); + alloc::dealloc(self.buf as *mut u8, layout); + + self.buf = ptr::null(); + self.len = 0; + } + } } impl Clone for PartialString { @@ -47,54 +64,31 @@ impl Iterator for PStrIter { fn next(&mut self) -> Option { 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::() { + 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 { - 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 + } } } } @@ -105,6 +99,8 @@ impl PartialString { fn new(src: &str) -> Option<(Self, &str)> { let pstr = PartialString { buf: ptr::null_mut(), + len: 0, + _marker: PhantomData, }; unsafe { @@ -116,7 +112,9 @@ impl PartialString { 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, } } @@ -128,11 +126,12 @@ impl PartialString { } let layout = alloc::Layout::from_size_align_unchecked( - src.len() + '\u{0}'.len_utf8(), + terminator_idx + '\u{0}'.len_utf8(), mem::align_of::(), ); self.buf = alloc::alloc(layout) as *const _; + self.len = terminator_idx + '\u{0}'.len_utf8(); ptr::copy( src.as_ptr(), @@ -149,24 +148,17 @@ impl PartialString { }) } - #[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::(), @@ -199,11 +191,6 @@ impl PartialString { } } - #[inline] - pub fn range(&self, index: Range) -> PStrIterBounded { - PStrIterBounded::from(self.buf, index.start, index.end) - } - #[inline] pub fn range_from(&self, index: RangeFrom) -> PStrIter { PStrIter::from(self.buf, index.start) diff --git a/src/prolog/machine/raw_block.rs b/src/prolog/machine/raw_block.rs index 3ae383d5..64135048 100644 --- a/src/prolog/machine/raw_block.rs +++ b/src/prolog/machine/raw_block.rs @@ -5,7 +5,7 @@ use std::mem; use std::ptr; pub(crate) trait RawBlockTraits { - fn init_size() -> usize; + fn init_size() -> usize; fn align() -> usize; #[inline] @@ -36,20 +36,6 @@ impl RawBlock { 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()); @@ -86,7 +72,6 @@ impl RawBlock { mem::replace(self, Self::empty_block()) } - #[inline] fn free_space(&self) -> usize { debug_assert!(self.top >= self.base, diff --git a/src/prolog/machine/stack.rs b/src/prolog/machine/stack.rs index 6e0731d5..e2602e72 100644 --- a/src/prolog/machine/stack.rs +++ b/src/prolog/machine/stack.rs @@ -49,7 +49,6 @@ impl Drop for Stack { #[derive(Clone, Copy)] pub struct FramePrelude { - is_or_frame: u8, pub num_cells: usize, } @@ -62,7 +61,6 @@ pub struct AndFramePrelude { pub struct AndFrame { pub prelude: AndFramePrelude, - _marker: PhantomData, } impl AndFrame { @@ -89,8 +87,6 @@ impl Index for AndFrame { impl IndexMut 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::(); let index_offset = (index - 1) * mem::size_of::(); @@ -103,24 +99,6 @@ impl IndexMut for AndFrame { } } -impl Drop for AndFrame { - fn drop(&mut self) { - let prelude_offset = prelude_size::(); - - 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::(); - let ptr = (ptr + index_offset) as *mut Addr; - - ptr::drop_in_place(ptr); - } - } - } -} - pub struct OrFramePrelude { pub univ_prelude: FramePrelude, pub e: usize, @@ -137,7 +115,6 @@ pub struct OrFramePrelude { pub struct OrFrame { pub prelude: OrFramePrelude, - _marker: PhantomData } impl Index for OrFrame { @@ -145,8 +122,6 @@ impl Index 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::(); let index_offset = index * mem::size_of::(); @@ -162,8 +137,6 @@ impl Index for OrFrame { impl IndexMut 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::(); let index_offset = index * mem::size_of::(); @@ -176,24 +149,6 @@ impl IndexMut for OrFrame { } } -impl Drop for OrFrame { - fn drop(&mut self) { - let prelude_offset = prelude_size::(); - - 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::(); - 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::() + num_cells * mem::size_of::() @@ -217,8 +172,6 @@ impl Stack { } 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; @@ -240,8 +193,6 @@ impl Stack { } 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; @@ -287,6 +238,7 @@ impl Stack { Stack { buf: self.buf.take(), _marker: PhantomData } } + #[inline] pub fn truncate(&mut self, b: usize) { if b == 0 { self.inner_truncate(mem::align_of::()); @@ -295,40 +247,12 @@ impl Stack { } } + #[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 _; } } diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 9f927da2..dbbc25e5 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -77,7 +77,7 @@ struct BrentAlgState { impl BrentAlgState { fn new(hare: Addr) -> Self { BrentAlgState { - hare: hare.clone(), + hare: hare, tortoise: hare, power: 2, steps: 0, @@ -89,7 +89,7 @@ impl BrentAlgState { 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; } @@ -144,7 +144,7 @@ impl MachineState { } 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 { @@ -184,7 +184,7 @@ impl MachineState { 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 { @@ -195,7 +195,7 @@ impl MachineState { } } 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); } @@ -235,7 +235,7 @@ impl MachineState { 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 { @@ -425,7 +425,7 @@ impl MachineState { &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 { @@ -447,7 +447,7 @@ impl MachineState { 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())); @@ -475,7 +475,7 @@ impl MachineState { 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 @@ -513,7 +513,7 @@ impl MachineState { 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); @@ -542,7 +542,7 @@ impl MachineState { 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( @@ -578,7 +578,7 @@ impl MachineState { 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( @@ -627,7 +627,7 @@ impl MachineState { 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) { @@ -696,7 +696,7 @@ impl MachineState { 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); } @@ -773,7 +773,7 @@ impl MachineState { 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] { @@ -781,13 +781,15 @@ impl MachineState { } 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); @@ -843,7 +845,7 @@ impl MachineState { } } &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 { @@ -879,7 +881,7 @@ impl MachineState { } } &SystemClauseType::AtomChars => { - let a1 = self[temp_v!(1)].clone(); + let a1 = self[temp_v!(1)]; match self.store(self.deref(a1)) { Addr::Char(c) => { @@ -890,7 +892,7 @@ impl MachineState { 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)); @@ -910,7 +912,7 @@ impl MachineState { } } Addr::EmptyList => { - let a2 = self[temp_v!(2)].clone(); + let a2 = self[temp_v!(2)]; let chars = vec![ Addr::Char('['), Addr::Char(']'), @@ -954,14 +956,14 @@ impl MachineState { }; } &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) => { @@ -1005,7 +1007,7 @@ impl MachineState { ]; 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); } @@ -1170,7 +1172,7 @@ impl MachineState { } } &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(..) => { @@ -1289,7 +1291,7 @@ impl MachineState { 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); @@ -1350,7 +1352,7 @@ impl MachineState { }; } &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) => { @@ -1400,7 +1402,7 @@ impl MachineState { }; } &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) => { @@ -1428,7 +1430,7 @@ impl MachineState { *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)); @@ -1445,7 +1447,7 @@ impl MachineState { 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)) => { @@ -1559,7 +1561,7 @@ impl MachineState { }; } &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] { @@ -1595,7 +1597,7 @@ impl MachineState { 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; } _ => {} } @@ -2094,7 +2096,7 @@ impl MachineState { 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 { @@ -2416,7 +2418,7 @@ impl MachineState { ), ); - let target = self[temp_v!(1)].clone(); + let target = self[temp_v!(1)]; self.unify(target, module); } @@ -2885,7 +2887,7 @@ impl MachineState { ContinueResult::PrintWithMaxDepth => 'p', }; - let target = self[temp_v!(1)]; + let target = self[temp_v!(1)]; self.unify(Addr::Char(c), target); } &SystemClauseType::NextEP => { @@ -3008,12 +3010,12 @@ impl MachineState { 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); } @@ -3079,7 +3081,7 @@ impl MachineState { let mut ball = Ball::new(); ball.boundary = self.heap.h(); - + copy_term( CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut ball.stub), value, @@ -3238,7 +3240,7 @@ impl MachineState { h, ExistenceError::Procedure(name, arity), ); - + let err = self.error_form(err, stub); self.throw_exception(err); @@ -3262,7 +3264,7 @@ impl MachineState { ); 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); } diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs index 94ad5951..2af0c13f 100644 --- a/src/prolog/machine/term_expansion.rs +++ b/src/prolog/machine/term_expansion.rs @@ -235,7 +235,7 @@ impl<'a> TermStream<'a> { 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)?; } @@ -247,7 +247,7 @@ impl<'a> TermStream<'a> { unreachable!() } - + pub fn read_term(&mut self, op_dir: &OpDir) -> Result { loop { if let Some(term) = self.stack.pop() { @@ -304,7 +304,8 @@ impl<'a> TermStream<'a> { } 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; @@ -315,12 +316,14 @@ impl MachineState { 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(); @@ -334,8 +337,8 @@ impl MachineState { } // 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(); @@ -359,7 +362,9 @@ impl MachineState { 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, diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index c08532dd..1ba6e07a 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -112,16 +112,6 @@ macro_rules! functor_term { (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))) ); @@ -148,9 +138,6 @@ macro_rules! from_constant { &Constant::CharCode(c) => { HeapCellValue::Addr(Addr::CharCode(c)) } - &Constant::CutPoint(cp) => { - HeapCellValue::Addr(Addr::CutPoint(cp)) - } &Constant::Integer(ref n) => { HeapCellValue::Integer(n.clone()) } diff --git a/src/prolog/read.rs b/src/prolog/read.rs index 33bea7cd..af70cd02 100644 --- a/src/prolog/read.rs +++ b/src/prolog/read.rs @@ -153,7 +153,8 @@ pub struct TermWriteResult { 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(); @@ -188,13 +189,13 @@ pub(crate) fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> 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() { diff --git a/src/prolog/toplevel.pl b/src/prolog/toplevel.pl index 73011c35..d4437fdd 100644 --- a/src/prolog/toplevel.pl +++ b/src/prolog/toplevel.pl @@ -43,7 +43,6 @@ ). '$submit_query_and_print_results'(Term0, VarList) :- - write('oh brother'), nl, ( expand_goals(Term0, Term) -> true ; Term0 = Term ), diff --git a/src/prolog/write.rs b/src/prolog/write.rs index e3e018c7..a1d8bb97 100644 --- a/src/prolog/write.rs +++ b/src/prolog/write.rs @@ -158,8 +158,10 @@ impl fmt::Display for HeapCellValue { &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) diff --git a/src/tests/facts.pl b/src/tests/facts.pl index a81f6814..762fca97 100644 --- a/src/tests/facts.pl +++ b/src/tests/facts.pl @@ -23,6 +23,6 @@ test_queries_on_facts :- 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).