From: Mark Thom Date: Thu, 13 Feb 2020 05:12:42 +0000 (-0700) Subject: remove partial strings, but represent strings as lists when warranted by double_quotes X-Git-Tag: v0.8.118~10 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=969bd8f82c32f30ec14f62b7fefa1ae3c016e335;p=scryer-prolog.git remove partial strings, but represent strings as lists when warranted by double_quotes --- diff --git a/Cargo.lock b/Cargo.lock index 535177e5..2e982c05 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -316,8 +316,7 @@ dependencies = [ [[package]] name = "prolog_parser" -version = "0.8.39" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.8.40" 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)", @@ -453,7 +452,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.39 (registry+https://github.com/rust-lang/crates.io-index)", + "prolog_parser 0.8.40", "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 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -614,7 +613,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "443c53b3c3531dfcbfa499d8893944db78474ad7a1d87fa2d94d1a2231693ac6" "checksum ordered-float 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7eb5259643245d3f292c7a146b2df53bba24d7eab159410e648eb73dc164669d" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum prolog_parser 0.8.39 (registry+https://github.com/rust-lang/crates.io-index)" = "021e4a08146013070183a4289404a0a5b8e14e1ea7df80d859e06ea98f67976b" "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 0b70510c..d044eec8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,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.39", default-features = false } +prolog_parser = { version = "0.8.40", path = "../prolog_parser", default-features = false } ref_thread_local = "0.0.0" rug = { version = "1.4.0", optional = true } rustyline = "5.0.3" diff --git a/src/prolog/clause_types.rs b/src/prolog/clause_types.rs index 78670b65..7d61cab7 100644 --- a/src/prolog/clause_types.rs +++ b/src/prolog/clause_types.rs @@ -78,7 +78,6 @@ pub enum InlinedClauseType { IsString(RegType), IsFloat(RegType), IsNonVar(RegType), - IsPartialString(RegType), IsVar(RegType), } @@ -109,7 +108,6 @@ ref_thread_local! { m.insert(("string", 1), ClauseType::Inlined(InlinedClauseType::IsString(r1))); m.insert(("float", 1), ClauseType::Inlined(InlinedClauseType::IsFloat(r1))); m.insert(("nonvar", 1), ClauseType::Inlined(InlinedClauseType::IsNonVar(r1))); - m.insert(("is_partial_string", 1), ClauseType::Inlined(InlinedClauseType::IsPartialString(r1))); m.insert(("var", 1), ClauseType::Inlined(InlinedClauseType::IsVar(r1))); m.insert(("acyclic_term", 1), ClauseType::BuiltIn(BuiltInClauseType::AcyclicTerm)); m.insert(("arg", 3), ClauseType::BuiltIn(BuiltInClauseType::Arg)); @@ -127,7 +125,6 @@ ref_thread_local! { m.insert(("keysort", 2), ClauseType::BuiltIn(BuiltInClauseType::KeySort)); m.insert(("nl", 0), ClauseType::BuiltIn(BuiltInClauseType::Nl)); m.insert(("\\==", 2), ClauseType::BuiltIn(BuiltInClauseType::NotEq)); - m.insert(("partial_string", 2), ClauseType::BuiltIn(BuiltInClauseType::PartialString)); m.insert(("read", 1), ClauseType::BuiltIn(BuiltInClauseType::Read)); m.insert(("sort", 2), ClauseType::BuiltIn(BuiltInClauseType::Sort)); @@ -147,7 +144,6 @@ impl InlinedClauseType { &InlinedClauseType::IsString(..) => "string", &InlinedClauseType::IsFloat(..) => "float", &InlinedClauseType::IsNonVar(..) => "nonvar", - &InlinedClauseType::IsPartialString(..) => "is_partial_string", &InlinedClauseType::IsVar(..) => "var", } } @@ -545,7 +541,6 @@ pub enum BuiltInClauseType { KeySort, Nl, NotEq, - PartialString, Read, Sort, } @@ -577,7 +572,6 @@ impl BuiltInClauseType { &BuiltInClauseType::KeySort => clause_name!("keysort"), &BuiltInClauseType::Nl => clause_name!("nl"), &BuiltInClauseType::NotEq => clause_name!("\\=="), - &BuiltInClauseType::PartialString => clause_name!("partial_string"), &BuiltInClauseType::Read => clause_name!("read"), &BuiltInClauseType::Sort => clause_name!("sort"), } @@ -598,7 +592,6 @@ impl BuiltInClauseType { &BuiltInClauseType::KeySort => 2, &BuiltInClauseType::NotEq => 2, &BuiltInClauseType::Nl => 0, - &BuiltInClauseType::PartialString => 1, &BuiltInClauseType::Read => 1, &BuiltInClauseType::Sort => 2, } diff --git a/src/prolog/codegen.rs b/src/prolog/codegen.rs index 0b5d6f63..eadbdded 100644 --- a/src/prolog/codegen.rs +++ b/src/prolog/codegen.rs @@ -18,7 +18,6 @@ use std::rc::Rc; use std::vec::Vec; pub struct CodeGenerator { - flags: MachineFlags, marker: TermMarker, pub var_count: IndexMap, usize>, non_counted_bt: bool, @@ -107,12 +106,11 @@ impl<'a> ConjunctInfo<'a> { } impl<'a, TermMarker: Allocator<'a>> CodeGenerator { - pub fn new(non_counted_bt: bool, flags: MachineFlags) -> Self { + pub fn new(non_counted_bt: bool) -> Self { CodeGenerator { marker: Allocator::new(), var_count: IndexMap::new(), non_counted_bt, - flags, } } @@ -435,7 +433,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { } }, &InlinedClauseType::IsString(..) => match terms[0].as_ref() { - &Term::Constant(_, Constant::String(_)) => { + &Term::Constant(_, Constant::String(..)) => { code.push(succeed!()); } &Term::Var(ref vr, ref name) => { @@ -459,8 +457,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { } }, &InlinedClauseType::IsInteger(..) => match terms[0].as_ref() { - &Term::Constant(_, Constant::CharCode(_)) - | &Term::Constant(_, Constant::Integer(_)) => { + &Term::Constant(_, Constant::Integer(_)) => { code.push(succeed!()); } &Term::Var(ref vr, ref name) => { @@ -483,13 +480,6 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { code.push(is_var!(r)); } }, - &InlinedClauseType::IsPartialString(..) => match terms[0].as_ref() { - &Term::Var(ref vr, ref name) => { - let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); - code.push(is_partial_string!(r)); - } - _ => code.push(fail!()), - }, } Ok(()) @@ -867,7 +857,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator { clauses: &'b [PredicateClause], ) -> Result { let mut code_body = Vec::new(); - let mut code_offsets = CodeOffsets::new(self.flags); + let mut code_offsets = CodeOffsets::new(); let num_clauses = clauses.len(); diff --git a/src/prolog/heap_iter.rs b/src/prolog/heap_iter.rs index 85afd015..13f2b355 100644 --- a/src/prolog/heap_iter.rs +++ b/src/prolog/heap_iter.rs @@ -46,39 +46,42 @@ impl<'a> HCPreOrderIterator<'a> { let da = self.machine_st.store(self.machine_st.deref(addr)); match da { - Addr::Con(Constant::String(ref s)) => { - match self.machine_st.machine_flags().double_quotes { - DoubleQuotes::Chars => { - if let Some(c) = s.head() { - let tail = s.tail(); - - self.state_stack.push(Addr::Con(Constant::String(tail))); - self.state_stack.push(Addr::Con(Constant::Char(c))); + Addr::Con(Constant::String(n, s)) => { + if !self.machine_st.machine_flags().double_quotes.is_atom() { + if s.len() > n { + if let Some(c) = s[n ..].chars().next() { + let o = c.len_utf8(); + + self.state_stack.push(Addr::Con(Constant::String(n+o, s.clone()))); + + if self.machine_st.machine_flags().double_quotes.is_codes() { + self.state_stack.push(Addr::Con(Constant::CharCode(c as u32))); + } else { + self.state_stack.push(Addr::Con(Constant::Char(c))); + } } + } else { + return Addr::Con(Constant::EmptyList); } - DoubleQuotes::Codes => { - if let Some(c) = s.head() { - let tail = s.tail(); - - self.state_stack.push(Addr::Con(Constant::String(tail))); - self.state_stack - .push(Addr::Con(Constant::CharCode(c as u8))); - } - } - _ => {} } - Addr::Con(Constant::String(s.clone())) + Addr::Con(Constant::String(n, s)) + } + Addr::Con(_) | Addr::DBRef(_) => { + da } - Addr::Con(_) | Addr::DBRef(_) => da, Addr::Lis(a) => { self.state_stack.push(Addr::HeapCell(a + 1)); self.state_stack.push(Addr::HeapCell(a)); da } - Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => da, - Addr::Str(s) => self.follow_heap(s), // record terms of structure. + Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => { + da + } + Addr::Str(s) => { + self.follow_heap(s) // record terms of structure. + } } } } @@ -88,11 +91,15 @@ impl<'a> Iterator for HCPreOrderIterator<'a> { fn next(&mut self) -> Option { self.state_stack.pop().map(|a| match self.follow(a) { - Addr::HeapCell(h) => self.machine_st.heap[h].clone(), + Addr::HeapCell(h) => { + self.machine_st.heap[h].clone() + } Addr::StackCell(fr, sc) => { HeapCellValue::Addr(self.machine_st.stack.index_and_frame(fr)[sc].clone()) } - da => HeapCellValue::Addr(da), + da => { + HeapCellValue::Addr(da) + } }) } } diff --git a/src/prolog/heap_print.rs b/src/prolog/heap_print.rs index aa3c9709..a89bbd4a 100644 --- a/src/prolog/heap_print.rs +++ b/src/prolog/heap_print.rs @@ -1,5 +1,4 @@ use prolog_parser::ast::*; -use prolog_parser::string_list::*; use crate::prolog::clause_types::*; use crate::prolog::forms::*; @@ -12,7 +11,7 @@ use crate::prolog::rug::Integer; use indexmap::{IndexMap, IndexSet}; use std::cell::Cell; -use std::iter::once; +use std::iter::{FromIterator, once}; use std::ops::{Range, RangeFrom}; use std::rc::Rc; @@ -789,12 +788,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { }); } } + Constant::CharCode(c) => { + self.append_str(&format!("{}", c as u32)); + } Constant::Char(c) if non_quoted_token(once(c)) => { let c = char_to_string(c); push_space_if_amb!(self, &c, { self.append_str(c.as_str()); - }); + }); } Constant::Char(c) => { let mut result = String::new(); @@ -806,51 +808,38 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } else { result += &char_to_string(c); } - + push_space_if_amb!(self, &result, { self.append_str(result.as_str()); - }); + }); } - Constant::CharCode(c) => self.append_str(&format!("{}", c)), Constant::CutPoint(b) => self.append_str(&format!("{}", b)), Constant::EmptyList => self.append_str("[]"), Constant::Integer(n) => self.print_number(Number::Integer(n), op), Constant::Float(n) => self.print_number(Number::Float(n), op), Constant::Rational(n) => self.print_number(Number::Rational(n), op), - Constant::String(s) => self.print_string(s), + Constant::String(n, s) => self.print_string(n, s), Constant::Usize(i) => self.append_str(&format!("u{}", i)), } } - fn print_string(&mut self, s: StringList) { - match self.machine_st.machine_flags().double_quotes { - DoubleQuotes::Chars | DoubleQuotes::Codes => { - if !s.is_empty() { - if self.ignore_ops { - self.format_struct(2, clause_name!(".")); - } else { - self.push_list(); - } - } else if s.is_expandable() { - if !self.at_cdr("|_") { - self.push_char('_'); - } - } else if !self.at_cdr("") { - self.append_str("[]"); + fn print_string(&mut self, offset: usize, s: Rc) { + if !self.machine_st.machine_flags().double_quotes.is_atom() { + if !s[offset ..].is_empty() { + if self.ignore_ops { + self.format_struct(2, clause_name!(".")); + } else { + self.push_list(); } + } else if !self.at_cdr("") { + self.append_str("[]"); } - DoubleQuotes::Atom => { - let borrowed_str = s.borrow(); - let mut atom = String::new(); - - for c in borrowed_str[s.cursor()..].chars() { - atom += &char_to_string(c); - } + } else { + let atom = String::from_iter(s[offset ..].chars().map(char_to_string)); - self.push_char('"'); - self.append_str(&atom); - self.push_char('"'); - } + self.push_char('"'); + self.append_str(&atom); + self.push_char('"'); } } diff --git a/src/prolog/indexing.rs b/src/prolog/indexing.rs index dddd7ef7..03208733 100644 --- a/src/prolog/indexing.rs +++ b/src/prolog/indexing.rs @@ -15,16 +15,14 @@ enum IntIndex { } pub struct CodeOffsets { - flags: MachineFlags, pub constants: IndexMap, pub lists: ThirdLevelIndex, pub structures: IndexMap<(ClauseName, usize), ThirdLevelIndex>, } impl CodeOffsets { - pub fn new(flags: MachineFlags) -> Self { + pub fn new() -> Self { CodeOffsets { - flags, constants: IndexMap::new(), lists: Vec::new(), structures: IndexMap::new(), @@ -65,18 +63,15 @@ impl CodeOffsets { let is_initial_index = self.lists.is_empty(); self.lists.push(Self::add_index(is_initial_index, index)); } - &Term::Constant(_, Constant::String(ref s)) - if !self.flags.double_quotes.is_atom() && !s.is_empty() => - { - // strings are lists in this case. - let is_initial_index = self.lists.is_empty(); - self.lists.push(Self::add_index(is_initial_index, index)); - } - &Term::Constant(_, Constant::String(ref s)) - if !self.flags.double_quotes.is_atom() && s.is_expandable() => - { + &Term::Constant(_, Constant::String(n, ref s)) => { let is_initial_index = self.lists.is_empty(); self.lists.push(Self::add_index(is_initial_index, index)); + + let constant = Constant::String(n, s.clone()); + let code = self.constants.entry(constant).or_insert(Vec::new()); + + let is_initial_index = code.is_empty(); + code.push(Self::add_index(is_initial_index, index)); } &Term::Constant(_, ref constant) => { let code = self.constants.entry(constant.clone()).or_insert(Vec::new()); @@ -260,8 +255,8 @@ impl CodeOffsets { for (index, line) in prelude.iter_mut().enumerate() { match line { &mut Line::IndexedChoice(IndexedChoiceInstruction::Try(ref mut i)) - | &mut Line::IndexedChoice(IndexedChoiceInstruction::Retry(ref mut i)) - | &mut Line::IndexedChoice(IndexedChoiceInstruction::Trust(ref mut i)) => { + | &mut Line::IndexedChoice(IndexedChoiceInstruction::Retry(ref mut i)) + | &mut Line::IndexedChoice(IndexedChoiceInstruction::Trust(ref mut i)) => { *i += prelude_length - index } _ => {} diff --git a/src/prolog/lib/builtins.pl b/src/prolog/lib/builtins.pl index 38a5fe39..5092d4c5 100644 --- a/src/prolog/lib/builtins.pl +++ b/src/prolog/lib/builtins.pl @@ -928,8 +928,12 @@ must_be_number(N, PI) :- ; throw(error(instantiation_error, PI)) ). -can_be_chars_or_vars(Cs, _) :- var(Cs), !. -can_be_chars_or_vars(Cs, PI) :- chars_or_vars(Cs, PI). +can_be_chars_or_vars(Cs, _) :- var(Cs), !. +can_be_chars_or_vars(Cs, PI) :- + ( string(Cs) -> + current_prolog_flag(double_quotes, chars) + ; chars_or_vars(Cs, PI) + ). chars_or_vars([], _). chars_or_vars([C|Cs], PI) :- @@ -943,8 +947,12 @@ chars_or_vars([C|Cs], PI) :- ; chars_or_vars(Cs, PI) ). -can_be_codes_or_vars(Cs, _) :- var(Cs), !. -can_be_codes_or_vars(Cs, PI) :- codes_or_vars(Cs, PI). +can_be_codes_or_vars(Cs, _) :- var(Cs), !. +can_be_codes_or_vars(Cs, PI) :- + ( string(Cs) -> + current_prolog_flag(double_quotes, codes) + ; codes_or_vars(Cs, PI) + ). codes_or_vars([], _). codes_or_vars([C|Cs], PI) :- diff --git a/src/prolog/machine/code_repo.rs b/src/prolog/machine/code_repo.rs index ac780f38..ac672d5a 100644 --- a/src/prolog/machine/code_repo.rs +++ b/src/prolog/machine/code_repo.rs @@ -1,5 +1,3 @@ -use prolog_parser::ast::MachineFlags; - use crate::prolog::clause_types::*; use crate::prolog::codegen::*; use crate::prolog::debray_allocator::*; @@ -67,7 +65,6 @@ impl CodeRepo { result: &CompiledResult, in_situ_code_dir: &mut InSituCodeDir, in_situ_module_dir: &mut ModuleStubDir, - flags: MachineFlags, non_counted_bt_preds: &IndexSet, ) -> Result<(), SessionError> { let (ref decl, ref queue) = result; @@ -94,10 +91,10 @@ impl CodeRepo { } } - let mut cg = CodeGenerator::::new(non_counted_bt, flags); + let mut cg = CodeGenerator::::new(non_counted_bt); let mut decl_code = cg.compile_predicate(&decl.0)?; - compile_appendix(&mut decl_code, queue, non_counted_bt, flags)?; + compile_appendix(&mut decl_code, queue, non_counted_bt)?; Ok(self.in_situ_code.extend(decl_code.into_iter())) } diff --git a/src/prolog/machine/compile.rs b/src/prolog/machine/compile.rs index efb62cda..ffa6d517 100644 --- a/src/prolog/machine/compile.rs +++ b/src/prolog/machine/compile.rs @@ -196,11 +196,10 @@ pub fn compile_appendix( code: &mut Code, queue: &VecDeque, non_counted_bt: bool, - flags: MachineFlags, ) -> Result<(), ParserError> { for tl in queue.iter() { set_first_index(code); - let mut cg = CodeGenerator::::new(non_counted_bt, flags); + let mut cg = CodeGenerator::::new(non_counted_bt); let decl_code = compile_relation(&mut cg, tl)?; code.extend(decl_code.into_iter()); } @@ -230,7 +229,6 @@ impl CodeRepo { pub fn compile_hook( &mut self, hook: CompileTimeHook, - flags: MachineFlags, ) -> Result<(), ParserError> { let key = (hook.name(), hook.arity()); @@ -238,10 +236,10 @@ impl CodeRepo { Some(ref mut preds) => { append_trivial_goal(&key.0, &mut preds.0); - let mut cg = CodeGenerator::::new(false, flags); + let mut cg = CodeGenerator::::new(false); let mut code = cg.compile_predicate(&(preds.0).0)?; - compile_appendix(&mut code, &preds.1, false, flags)?; + compile_appendix(&mut code, &preds.1, false)?; (preds.0).0.pop(); @@ -260,7 +258,7 @@ impl CodeRepo { let mut preds = Predicate::new(); append_trivial_goal(&key.0, &mut preds); - let mut cg = CodeGenerator::::new(false, flags); + let mut cg = CodeGenerator::::new(false); self.term_expanders = cg.compile_predicate(&preds.0)?; } } @@ -269,7 +267,7 @@ impl CodeRepo { let mut preds = Predicate::new(); append_trivial_goal(&key.0, &mut preds); - let mut cg = CodeGenerator::::new(false, flags); + let mut cg = CodeGenerator::::new(false); self.goal_expanders = cg.compile_predicate(&preds.0)?; } } @@ -281,13 +279,12 @@ impl CodeRepo { fn compile_query( terms: Vec, queue: VecDeque, - flags: MachineFlags, ) -> Result<(Code, AllocVarDict), ParserError> { // count backtracking inferences. - let mut cg = CodeGenerator::::new(false, flags); + let mut cg = CodeGenerator::::new(false); let mut code = cg.compile_query(&terms)?; - compile_appendix(&mut code, &queue, false, flags)?; + compile_appendix(&mut code, &queue, false)?; Ok((code, cg.take_vars())) } @@ -345,7 +342,7 @@ pub(super) fn compile_into_module( wam.indices.insert_module(module); } - compiler.drop_expansions(wam.machine_flags(), &mut wam.code_repo); + compiler.drop_expansions(&mut wam.code_repo); EvalSession::from(e) } } @@ -363,10 +360,8 @@ fn compile_into_module_impl( let module_name = module.module_decl.name.clone(); compiler.module = Some(module); - let flags = wam.machine_flags(); - - wam.code_repo.compile_hook(CompileTimeHook::TermExpansion, flags)?; - wam.code_repo.compile_hook(CompileTimeHook::GoalExpansion, flags)?; + wam.code_repo.compile_hook(CompileTimeHook::TermExpansion)?; + wam.code_repo.compile_hook(CompileTimeHook::GoalExpansion)?; let mut results = compiler.gather_items(wam, src, &mut indices)?; @@ -400,7 +395,7 @@ fn compile_into_module_impl( clause_code_generator.add_clause_code(wam, results.dynamic_clause_map); - Ok(compiler.drop_expansions(wam.machine_flags(), &mut wam.code_repo)) + Ok(compiler.drop_expansions(&mut wam.code_repo)) } pub struct GatherResult { @@ -462,14 +457,14 @@ impl ClauseCodeGenerator { ); let p = self.code.len() + wam.code_repo.code.len() + self.len_offset; - let mut cg = CodeGenerator::::new(false, wam.machine_flags()); + let mut cg = CodeGenerator::::new(false); let mut decl_code = compile_relation( &mut cg, &TopLevel::Predicate(predicate), )?; - compile_appendix(&mut decl_code, &VecDeque::new(), false, wam.machine_flags())?; + compile_appendix(&mut decl_code, &VecDeque::new(), false)?; self.pi_to_loc.insert((name.clone(), *arity), p); self.code.extend(decl_code.into_iter()); @@ -735,12 +730,11 @@ impl ListingCompiler { fn generate_init_goal_code( &mut self, - flags: MachineFlags ) -> Result { let query_terms = mem::replace(&mut self.initialization_goals.0, vec![]); let queue = mem::replace(&mut self.initialization_goals.1, VecDeque::new()); - compile_query(query_terms, queue, flags) + compile_query(query_terms, queue) .map(|(code, _)| code) .map_err(SessionError::from) } @@ -766,13 +760,12 @@ impl ListingCompiler { self.localize_self_calls(key, in_situ_code, *in_situ_p, p + *in_situ_p); } None => { - let flags = wam.machine_flags(); let (decl, queue) = decl; - let mut cg = CodeGenerator::::new(false, flags); + let mut cg = CodeGenerator::::new(false); let mut decl_code = cg.compile_predicate(&decl.0)?; - compile_appendix(&mut decl_code, &queue, false, flags)?; + compile_appendix(&mut decl_code, &queue, false)?; let in_situ_p = in_situ_code.len(); @@ -934,7 +927,7 @@ impl ListingCompiler { let result = wam .code_repo - .compile_hook(hook, flags) + .compile_hook(hook) .map_err(SessionError::from); wam.code_repo.truncate_terms(key, len, queue_len); @@ -1170,15 +1163,15 @@ impl ListingCompiler { }) } - fn drop_expansions(&self, flags: MachineFlags, code_repo: &mut CodeRepo) { + fn drop_expansions(&self, code_repo: &mut CodeRepo) { let (te_len, te_queue_len) = self.orig_term_expansion_lens; let (ge_len, ge_queue_len) = self.orig_goal_expansion_lens; code_repo.truncate_terms((clause_name!("term_expansion"), 2), te_len, te_queue_len); code_repo.truncate_terms((clause_name!("goal_expansion"), 2), ge_len, ge_queue_len); - discard_result!(code_repo.compile_hook(CompileTimeHook::UserGoalExpansion, flags)); - discard_result!(code_repo.compile_hook(CompileTimeHook::UserTermExpansion, flags)); + discard_result!(code_repo.compile_hook(CompileTimeHook::UserGoalExpansion)); + discard_result!(code_repo.compile_hook(CompileTimeHook::UserTermExpansion)); } fn print_error(&self, e: &SessionError) { @@ -1244,10 +1237,8 @@ fn compile_work_impl( } } - let flags = wam.machine_flags(); - - wam.code_repo.compile_hook(CompileTimeHook::UserTermExpansion, flags)?; - wam.code_repo.compile_hook(CompileTimeHook::UserGoalExpansion, flags)?; + wam.code_repo.compile_hook(CompileTimeHook::UserTermExpansion)?; + wam.code_repo.compile_hook(CompileTimeHook::UserGoalExpansion)?; if let Some(mut module) = compiler.module.take() { if module.is_impromptu_module { @@ -1280,7 +1271,7 @@ fn compile_work_impl( add_toplevel(wam, results.toplevel_indices, top_level_term_dir); wam.code_repo.code.extend(code.into_iter()); - + clause_code_generator.add_clause_code(wam, results.dynamic_clause_map); } else { add_non_module_code( @@ -1292,9 +1283,7 @@ fn compile_work_impl( )?; } - let init_goal_code = compiler.generate_init_goal_code( - wam.machine_flags() - )?; + let init_goal_code = compiler.generate_init_goal_code()?; if init_goal_code.len() > 0 { if !wam.run_init_code(init_goal_code) { @@ -1370,7 +1359,7 @@ pub fn compile_listing( match compile_work(&mut compiler, wam, src, indices) { EvalSession::Error(e) => { - compiler.drop_expansions(wam.machine_flags(), &mut wam.code_repo); + compiler.drop_expansions(&mut wam.code_repo); compiler.print_error(&e); EvalSession::Error(e) diff --git a/src/prolog/machine/machine_errors.rs b/src/prolog/machine/machine_errors.rs index 8670f9bf..5596d71b 100644 --- a/src/prolog/machine/machine_errors.rs +++ b/src/prolog/machine/machine_errors.rs @@ -1,11 +1,12 @@ use prolog_parser::ast::*; -use prolog_parser::string_list::*; use crate::prolog::forms::PredicateKey; use crate::prolog::machine::machine_indices::*; use crate::prolog::machine::machine_state::*; use crate::prolog::rug::Integer; +use std::rc::Rc; + pub(crate) type MachineStub = Vec; #[derive(Clone, Copy)] @@ -392,7 +393,7 @@ pub(super) enum CycleSearchResult { NotList, PartialList(usize, usize), // the list length (up to max), and an offset into the heap. ProperList(usize), // the list length. - String(usize, StringList), // the number of elements iterated, the string tail. + String(usize, usize, Rc), // the number of bytes iterated, the offset, the string. UntouchedList(usize), // the address of an uniterated Addr::Lis(address). } diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index 3aaeeb74..ab7c9b04 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -1,5 +1,4 @@ use prolog_parser::ast::*; -use prolog_parser::string_list::*; use crate::prolog::clause_types::*; use crate::prolog::forms::*; @@ -250,8 +249,6 @@ pub struct MachineState { pub(crate) stack: Stack, pub(super) registers: Registers, pub(super) trail: Vec, - pub(super) pstr_trail: Vec<(usize, StringList, usize)>, // b, String, trunc_pt - pub(super) pstr_tr: usize, pub(super) tr: usize, pub(super) hb: usize, pub(super) block: usize, // an offset into the OR stack. @@ -265,72 +262,58 @@ pub struct MachineState { } impl MachineState { - pub(super) fn try_char_list(&self, addrs: Vec) -> Result { + 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() { - match addr { - &Addr::Con(Constant::String(ref s)) if self.flags.double_quotes.is_chars() => { - chars += s.borrow().as_str(); - - if iter.next().is_some() { - return Err(MachineError::type_error(ValidType::Character, addr.clone())); - } - } - &Addr::Con(Constant::Char(c)) => chars.push(c), - &Addr::Con(Constant::Atom(ref name, _)) if name.as_str().len() == 1 => { - chars += name.as_str(); + match addr { + &Addr::Con(Constant::String(n, ref s)) + if self.flags.double_quotes.is_chars() => { + if s.len() < n { + chars += &s[n ..]; + } + + if iter.next().is_some() { + return Err(MachineError::type_error(ValidType::Character, addr.clone())); + } + } + &Addr::Con(Constant::Char(c)) => { + chars.push(c); } - _ => return Err(MachineError::type_error(ValidType::Character, addr.clone())), - } - } - - Ok(chars) - } - - pub(super) fn try_code_list(&self, addrs: Vec) -> Result, MachineError> { - let mut codes = vec![]; - let mut iter = addrs.iter(); - - while let Some(addr) = iter.next() { - match addr { - &Addr::Con(Constant::String(ref s)) if self.flags.double_quotes.is_codes() => { - codes.extend(s.borrow().chars().map(|c| c as u8)); - - if iter.next().is_some() { - return Err(MachineError::representation_error(RepFlag::CharacterCode)); + &Addr::Con(Constant::Atom(ref name, _)) + if name.as_str().len() == 1 => { + chars += name.as_str(); } + _ => { + return Err( + MachineError::type_error(ValidType::Character, addr.clone()) + ); } - &Addr::Con(Constant::CharCode(c)) => codes.push(c), - &Addr::Con(Constant::Integer(ref n)) => { - if let Some(c) = n.to_u8() { - codes.push(c); - } else { - return Err(MachineError::representation_error(RepFlag::CharacterCode)); - } - } - _ => return Err(MachineError::representation_error(RepFlag::CharacterCode)), } } - Ok(codes) + Ok(chars) } - pub(super) fn call_at_index(&mut self, arity: usize, p: LocalCodePtr) { + pub(super) + fn call_at_index(&mut self, arity: usize, p: LocalCodePtr) { self.cp.assign_if_local(self.p.clone() + 1); self.num_of_args = arity; self.b0 = self.b; self.p = CodePtr::Local(p); } - pub(super) fn execute_at_index(&mut self, arity: usize, p: LocalCodePtr) { + pub(super) + fn execute_at_index(&mut self, arity: usize, p: LocalCodePtr) { self.num_of_args = arity; self.b0 = self.b; self.p = CodePtr::Local(p); } - pub(super) fn module_lookup( + pub(super) + fn module_lookup( &mut self, indices: &IndexStore, key: PredicateKey, @@ -379,7 +362,7 @@ impl MachineState { self.call_at_index(arity, LocalCodePtr::InSituDirEntry(p)); } - return Ok(()); + return Ok(()); } _ => {} } @@ -460,19 +443,12 @@ pub(crate) trait CallPolicy: Any { machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); - - let old_pstr_tr = machine_st.stack.index_or_frame(b).prelude.pstr_tr; - let curr_pstr_tr = machine_st.pstr_tr; - - machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr); - machine_st.pstr_tr = machine_st.stack.index_or_frame(b).prelude.pstr_tr; - - machine_st.pstr_trail.truncate(machine_st.pstr_tr); - machine_st.heap.truncate(machine_st.stack.index_or_frame(b).prelude.h); - let attr_var_init_queue_b = machine_st.stack.index_or_frame(b).prelude.attr_var_init_queue_b; - let attr_var_init_bindings_b = machine_st.stack.index_or_frame(b).prelude.attr_var_init_bindings_b; + let attr_var_init_queue_b = + machine_st.stack.index_or_frame(b).prelude.attr_var_init_queue_b; + let attr_var_init_bindings_b = + machine_st.stack.index_or_frame(b).prelude.attr_var_init_bindings_b; machine_st.attr_var_init.backtrack( attr_var_init_queue_b, @@ -506,18 +482,12 @@ pub(crate) trait CallPolicy: Any { machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); - - let old_pstr_tr = machine_st.stack.index_or_frame(b).prelude.pstr_tr; - let curr_pstr_tr = machine_st.pstr_tr; - - machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr); - machine_st.pstr_tr = machine_st.stack.index_or_frame(b).prelude.pstr_tr; - - machine_st.pstr_trail.truncate(machine_st.pstr_tr); machine_st.heap.truncate(machine_st.stack.index_or_frame(b).prelude.h); - let attr_var_init_queue_b = machine_st.stack.index_or_frame(b).prelude.attr_var_init_queue_b; - let attr_var_init_bindings_b = machine_st.stack.index_or_frame(b).prelude.attr_var_init_bindings_b; + let attr_var_init_queue_b = + machine_st.stack.index_or_frame(b).prelude.attr_var_init_queue_b; + let attr_var_init_bindings_b = + machine_st.stack.index_or_frame(b).prelude.attr_var_init_bindings_b; machine_st.attr_var_init.backtrack(attr_var_init_queue_b, attr_var_init_bindings_b); @@ -546,18 +516,12 @@ pub(crate) trait CallPolicy: Any { machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); - - let old_pstr_tr = machine_st.stack.index_or_frame(b).prelude.pstr_tr; - let curr_pstr_tr = machine_st.pstr_tr; - - machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr); - machine_st.pstr_tr = machine_st.stack.index_or_frame(b).prelude.pstr_tr; - - machine_st.pstr_trail.truncate(machine_st.pstr_tr); machine_st.heap.truncate(machine_st.stack.index_or_frame(b).prelude.h); - let attr_var_init_queue_b = machine_st.stack.index_or_frame(b).prelude.attr_var_init_queue_b; - let attr_var_init_bindings_b = machine_st.stack.index_or_frame(b).prelude.attr_var_init_bindings_b; + let attr_var_init_queue_b = + machine_st.stack.index_or_frame(b).prelude.attr_var_init_queue_b; + let attr_var_init_bindings_b = + machine_st.stack.index_or_frame(b).prelude.attr_var_init_bindings_b; machine_st.attr_var_init.backtrack( attr_var_init_queue_b, @@ -591,20 +555,12 @@ pub(crate) trait CallPolicy: Any { machine_st.tr = machine_st.stack.index_or_frame(b).prelude.tr; machine_st.trail.truncate(machine_st.tr); - - let old_pstr_tr = machine_st.stack.index_or_frame(b).prelude.pstr_tr; - let curr_pstr_tr = machine_st.pstr_tr; - - machine_st.unwind_pstr_trail(old_pstr_tr, curr_pstr_tr); - machine_st.pstr_tr = machine_st.stack.index_or_frame(b).prelude.pstr_tr; - - machine_st.pstr_tr = machine_st.stack.index_or_frame(b).prelude.pstr_tr; - machine_st.pstr_trail.truncate(machine_st.pstr_tr); - machine_st.heap.truncate(machine_st.stack.index_or_frame(b).prelude.h); - let attr_var_init_queue_b = machine_st.stack.index_or_frame(b).prelude.attr_var_init_queue_b; - let attr_var_init_bindings_b = machine_st.stack.index_or_frame(b).prelude.attr_var_init_bindings_b; + let attr_var_init_queue_b = + machine_st.stack.index_or_frame(b).prelude.attr_var_init_queue_b; + let attr_var_init_bindings_b = + machine_st.stack.index_or_frame(b).prelude.attr_var_init_bindings_b; machine_st.attr_var_init.backtrack( attr_var_init_queue_b, @@ -802,15 +758,6 @@ pub(crate) trait CallPolicy: Any { return_from_clause!(machine_st.last_call, machine_st) } - &BuiltInClauseType::PartialString => { - let s = machine_st.try_string_list(temp_v!(1))?; - let a2 = machine_st[temp_v!(2)].clone(); - - s.set_expandable(true); - machine_st.write_constant_to_var(a2, Constant::String(s)); - - return_from_clause!(machine_st.last_call, machine_st) - } &BuiltInClauseType::Sort => { machine_st.check_sort_errors()?; @@ -1087,7 +1034,6 @@ fn cut_body(machine_st: &mut MachineState, addr: Addr) -> bool { if b > b0 { machine_st.b = b0; machine_st.tidy_trail(); - machine_st.tidy_pstr_trail(); } } _ => { @@ -1174,7 +1120,6 @@ impl CutPolicy for SCCCutPolicy { if b > b0 { machine_st.b = b0; machine_st.tidy_trail(); - machine_st.tidy_pstr_trail(); } } _ => { diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 57aeab5d..a305ab72 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -1,5 +1,4 @@ use prolog_parser::ast::*; -use prolog_parser::string_list::StringList; use prolog_parser::tabled_rc::*; use crate::prolog::arithmetic::*; @@ -24,7 +23,9 @@ use indexmap::{IndexMap, IndexSet}; use std::cmp::{max, min, Ordering}; use std::f64; +use std::iter::FromIterator; use std::mem; +use std::rc::Rc; macro_rules! try_numeric_result { ($s: ident, $e: expr, $caller: expr) => {{ @@ -64,8 +65,6 @@ impl MachineState { stack: Stack::new(), registers: vec![Addr::HeapCell(0); MAX_ARITY + 1], // self.registers[0] is never used. trail: vec![], - pstr_trail: vec![], - pstr_tr: 0, tr: 0, hb: 0, block: 0, @@ -95,8 +94,6 @@ impl MachineState { stack: Stack::new(), registers: vec![Addr::HeapCell(0); MAX_ARITY + 1], // self.registers[0] is never used. trail: vec![], - pstr_trail: vec![], - pstr_tr: 0, tr: 0, hb: 0, block: 0, @@ -190,138 +187,22 @@ impl MachineState { } } - pub(super) fn unify_strings( - &mut self, - pdl: &mut Vec, - s1: &mut StringList, - s2: &mut StringList, - ) -> bool { - if let Some(c1) = s1.head() { - if let Some(c2) = s2.head() { - if c1 == c2 { - pdl.push(Addr::Con(Constant::String(s1.tail()))); - pdl.push(Addr::Con(Constant::String(s2.tail()))); - - return true; - } - } else if s2.is_expandable() { - self.pstr_trail(s2.clone()); - - pdl.push(Addr::Con(Constant::String(s2.push_char(c1)))); - pdl.push(Addr::Con(Constant::String(s1.tail()))); - - return true; - } - } else if s1.is_expandable() { - if let Some(c) = s2.head() { - self.pstr_trail(s1.clone()); - - pdl.push(Addr::Con(Constant::String(s1.push_char(c)))); - pdl.push(Addr::Con(Constant::String(s2.tail()))); - } else if s2.is_expandable() { - return s1 == s2; - } else { - self.pstr_trail(s1.clone()); - s1.set_expandable(false); - } - - return true; - } else if s2.head().is_none() { - if s2.is_expandable() { - self.pstr_trail(s2.clone()); - } - - s2.set_expandable(false); - return true; - } - - false - } - fn deconstruct_chars( &mut self, - s: &mut StringList, - offset: usize, - pdl: &mut Vec, - ) -> bool { - if let Some(c) = s.head() { - pdl.push(Addr::Con(Constant::String(s.tail()))); - pdl.push(Addr::HeapCell(offset + 1)); - - pdl.push(Addr::Con(Constant::Char(c))); - pdl.push(Addr::HeapCell(offset)); - - return true; - } else if s.is_expandable() { - let prev_s = s.clone(); - - let mut stepper = |c| { - let new_s = s.push_char(c); - - pdl.push(Addr::HeapCell(offset + 1)); - pdl.push(Addr::Con(Constant::String(new_s))); - }; - - match self.heap[offset].clone() { - HeapCellValue::Addr(Addr::Con(Constant::Char(c))) => { - self.pstr_trail(prev_s); - stepper(c); - return true; - } - HeapCellValue::Addr(Addr::Con(Constant::Atom(ref a, _))) => { - if let Some(c) = a.as_str().chars().next() { - if c.len_utf8() == a.as_str().len() { - self.pstr_trail(prev_s); - stepper(c); - return true; - } - } - } - _ => {} - } - } - - false - } - - fn deconstruct_codes( - &mut self, - s: &mut StringList, - offset: usize, + s: Rc, + string_offset: usize, + list_cell: usize, pdl: &mut Vec, ) -> bool { - if let Some(c) = s.head() { - pdl.push(Addr::Con(Constant::String(s.tail()))); - pdl.push(Addr::HeapCell(offset + 1)); - - pdl.push(Addr::Con(Constant::CharCode(c as u8))); - pdl.push(Addr::HeapCell(offset)); - - return true; - } else if s.is_expandable() { - let prev_s = s.clone(); + if s.len() > string_offset { + if let Some(c) = s[string_offset ..].chars().next() { + pdl.push(Addr::Con(Constant::String(string_offset + c.len_utf8(), s))); + pdl.push(Addr::HeapCell(list_cell + 1)); - let mut stepper = |c| { - let new_s = s.push_char(c); + pdl.push(Addr::Con(Constant::Char(c))); + pdl.push(Addr::HeapCell(list_cell)); - pdl.push(Addr::HeapCell(offset + 1)); - pdl.push(Addr::Con(Constant::String(new_s))); - }; - - match self.heap[offset].clone() { - HeapCellValue::Addr(Addr::Con(Constant::CharCode(c))) => { - self.pstr_trail(prev_s); - stepper(c as char); - return true; - } - HeapCellValue::Addr(Addr::Con(Constant::Integer(n))) => { - if let Some(c) = n.to_u8() { - self.pstr_trail(prev_s); - stepper(c as char); - return true; - } - } - _ => {} + return true; } } @@ -346,7 +227,8 @@ impl MachineState { self.bind(r, addr); } - pub(super) fn unify_with_occurs_check(&mut self, a1: Addr, a2: Addr) { + pub(super) + fn unify_with_occurs_check(&mut self, a1: Addr, a2: Addr) { let mut pdl = vec![a1, a2]; let mut tabu_list: IndexSet<(Addr, Addr)> = IndexSet::new(); @@ -391,29 +273,23 @@ impl MachineState { self.fail = true; } - (Addr::Lis(a1), Addr::Con(Constant::String(ref mut s))) - | (Addr::Con(Constant::String(ref mut s)), Addr::Lis(a1)) => { - if match self.flags.double_quotes { - DoubleQuotes::Chars => self.deconstruct_chars(s, a1, &mut pdl), - DoubleQuotes::Codes => self.deconstruct_codes(s, a1, &mut pdl), - DoubleQuotes::Atom => false, - } { + (Addr::Lis(a1), Addr::Con(Constant::String(n, s))) + | (Addr::Con(Constant::String(n, s)), Addr::Lis(a1)) => { + if self.deconstruct_chars(s, n, a1, &mut pdl) { continue; } self.fail = true; } - (Addr::Con(Constant::EmptyList), Addr::Con(Constant::String(ref s))) - | (Addr::Con(Constant::String(ref s)), Addr::Con(Constant::EmptyList)) + (Addr::Con(Constant::EmptyList), Addr::Con(Constant::String(n, ref s))) + | (Addr::Con(Constant::String(n, ref s)), Addr::Con(Constant::EmptyList)) if !self.flags.double_quotes.is_atom() => { - if s.is_expandable() && s.is_empty() { - self.pstr_trail(s.clone()); - s.set_expandable(false); + if n >= s.len() { continue; } - self.fail = !s.is_empty(); + self.fail = true; } (Addr::Lis(a1), Addr::Lis(a2)) => { pdl.push(Addr::HeapCell(a1)); @@ -422,13 +298,6 @@ impl MachineState { pdl.push(Addr::HeapCell(a1 + 1)); pdl.push(Addr::HeapCell(a2 + 1)); } - ( - Addr::Con(Constant::String(ref mut s1)), - Addr::Con(Constant::String(ref mut s2)), - ) => { - self.fail = !(self.unify_strings(&mut pdl, s1, s2) - || self.unify_strings(&mut pdl, s2, s1)) - } (Addr::Con(ref c1), Addr::Con(ref c2)) => { if c1 != c2 { self.fail = true; @@ -459,7 +328,8 @@ impl MachineState { } } - pub(super) fn unify(&mut self, a1: Addr, a2: Addr) { + pub(super) + fn unify(&mut self, a1: Addr, a2: Addr) { let mut pdl = vec![a1, a2]; let mut tabu_list: IndexSet<(Addr, Addr)> = IndexSet::new(); @@ -481,12 +351,20 @@ impl MachineState { match (d1.clone(), d2.clone()) { (Addr::AttrVar(h), addr) | (addr, Addr::AttrVar(h)) => { - self.bind(Ref::AttrVar(h), addr) + self.bind(Ref::AttrVar(h), addr); + } + (Addr::HeapCell(h), _) => { + self.bind(Ref::HeapCell(h), d2); + } + (_, Addr::HeapCell(h)) => { + self.bind(Ref::HeapCell(h), d1); + } + (Addr::StackCell(fr, sc), _) => { + self.bind(Ref::StackCell(fr, sc), d2); + } + (_, Addr::StackCell(fr, sc)) => { + self.bind(Ref::StackCell(fr, sc), d1); } - (Addr::HeapCell(h), _) => self.bind(Ref::HeapCell(h), d2), - (_, Addr::HeapCell(h)) => self.bind(Ref::HeapCell(h), d1), - (Addr::StackCell(fr, sc), _) => self.bind(Ref::StackCell(fr, sc), d2), - (_, Addr::StackCell(fr, sc)) => self.bind(Ref::StackCell(fr, sc), d1), (Addr::Lis(a1), Addr::Str(a2)) | (Addr::Str(a2), Addr::Lis(a1)) => { if let &HeapCellValue::NamedStr(n2, ref f2, _) = &self.heap[a2] { if f2.as_str() == "." && n2 == 2 { @@ -502,29 +380,23 @@ impl MachineState { self.fail = true; } - (Addr::Lis(a1), Addr::Con(Constant::String(ref mut s))) - | (Addr::Con(Constant::String(ref mut s)), Addr::Lis(a1)) => { - if match self.flags.double_quotes { - DoubleQuotes::Chars => self.deconstruct_chars(s, a1, &mut pdl), - DoubleQuotes::Codes => self.deconstruct_codes(s, a1, &mut pdl), - DoubleQuotes::Atom => false, - } { + (Addr::Lis(a1), Addr::Con(Constant::String(n, s))) + | (Addr::Con(Constant::String(n, s)), Addr::Lis(a1)) => { + if self.deconstruct_chars(s, n, a1, &mut pdl) { continue; } self.fail = true; } - (Addr::Con(Constant::EmptyList), Addr::Con(Constant::String(ref s))) - | (Addr::Con(Constant::String(ref s)), Addr::Con(Constant::EmptyList)) + (Addr::Con(Constant::EmptyList), Addr::Con(Constant::String(n, ref s))) + | (Addr::Con(Constant::String(n, ref s)), Addr::Con(Constant::EmptyList)) if !self.flags.double_quotes.is_atom() => { - if s.is_expandable() && s.is_empty() { - self.pstr_trail(s.clone()); - s.set_expandable(false); + if n >= s.len() { continue; } - self.fail = !s.is_empty(); + self.fail = true; } (Addr::Lis(a1), Addr::Lis(a2)) => { pdl.push(Addr::HeapCell(a1)); @@ -533,13 +405,6 @@ impl MachineState { pdl.push(Addr::HeapCell(a1 + 1)); pdl.push(Addr::HeapCell(a2 + 1)); } - ( - Addr::Con(Constant::String(ref mut s1)), - Addr::Con(Constant::String(ref mut s2)), - ) => { - self.fail = !(self.unify_strings(&mut pdl, s1, s2) - || self.unify_strings(&mut pdl, s2, s1)) - } (Addr::Con(ref c1), Addr::Con(ref c2)) => { if c1 != c2 { self.fail = true; @@ -570,19 +435,6 @@ impl MachineState { } } - #[inline] - fn pstr_trail(&mut self, s: StringList) { - if let Some((prev_b, prev_s, _)) = self.pstr_trail.last().cloned() { - if prev_b == self.b && prev_s == s { - return; - } - } - - let truncate_end = s.len() + s.cursor(); - self.pstr_trail.push((self.b, s, truncate_end)); - self.pstr_tr += 1; - } - pub(super) fn trail(&mut self, r: TrailRef) { match r { TrailRef::Ref(Ref::HeapCell(h)) => { @@ -643,36 +495,6 @@ impl MachineState { } } - pub(super) fn unwind_pstr_trail(&mut self, a1: usize, a2: usize) { - for i in a1..a2 { - let (_, mut s, end) = self.pstr_trail[i].clone(); - s.truncate(end); - } - } - - pub(super) fn tidy_pstr_trail(&mut self) { - if self.b == 0 { - return; - } - - let b = self.b; - let mut i = self.stack.index_or_frame(b).prelude.pstr_tr; - - while i < self.pstr_tr { - let str_b = self.pstr_trail[i].0; - - if b < str_b { - let pstr_tr = self.pstr_tr; - let val = self.pstr_trail[pstr_tr - 1].clone(); - - self.pstr_trail[i] = val; - self.pstr_tr -= 1; - } else { - i += 1; - } - } - } - pub(super) fn tidy_trail(&mut self) { if self.b == 0 { return; @@ -708,85 +530,8 @@ impl MachineState { self.trail.truncate(self.tr); } - #[inline] - fn write_char_to_string(&mut self, s: &mut StringList, c: char) -> bool { - self.pstr_trail(s.clone()); - - let new_s = s.push_char(c); - self.heap - .push(HeapCellValue::Addr(Addr::Con(Constant::String(new_s)))); - false - } - - fn write_constant_to_string(&mut self, s: &mut StringList, c: Constant) -> bool { - match c { - Constant::EmptyList if !self.flags.double_quotes.is_atom() => !s.is_empty(), - Constant::String(ref s2) if s.is_expandable() && s2.starts_with(s) => { - self.pstr_trail(s.clone()); - s.append_suffix(s2); - s.set_expandable(s2.is_expandable()); - false - } - Constant::String(s2) => s.borrow()[s.cursor()..] != s2.borrow()[s2.cursor()..], - Constant::Atom(ref a, _) if a.as_str().starts_with(&s.borrow()[s.cursor()..]) => { - if let Some(c) = a.as_str().chars().next() { - if c.len_utf8() == a.as_str().len() { - // detect chars masquerading as atoms. - if s.is_empty() { - self.write_char_to_string(s, c); - } - - false - } else { - true - } - } else { - true - } - } - Constant::Char(ref c) if s.is_empty() && s.is_expandable() => { - match self.flags.double_quotes { - DoubleQuotes::Chars => self.write_char_to_string(s, *c), - _ => false, - } - } - Constant::Char(ref c) => match self.flags.double_quotes { - DoubleQuotes::Chars => { - if s.borrow().chars().next() == Some(*c) && c.len_utf8() == s.len() { - s.set_expandable(false); - false - } else { - true - } - } - _ => false, - }, - Constant::CharCode(ref c) if s.is_empty() && s.is_expandable() => { - match self.flags.double_quotes { - DoubleQuotes::Codes => self.write_char_to_string(s, *c as char), - _ => false, - } - } - Constant::CharCode(ref c) => match self.flags.double_quotes { - DoubleQuotes::Codes => { - if s.borrow().chars().next() == Some(*c as char) && 1 == s.len() { - s.set_expandable(false); - false - } else { - true - } - } - _ => false, - }, - _ => true, - } - } - pub(super) fn write_constant_to_var(&mut self, addr: Addr, c: Constant) { match self.store(self.deref(addr)) { - Addr::Con(Constant::String(ref mut s)) => { - self.fail = self.write_constant_to_string(s, c) - } Addr::Con(c1) => self.fail = self.eq_test(Addr::Con(c), Addr::Con(c1)), Addr::Lis(l) => @@ -1630,47 +1375,18 @@ impl MachineState { }; } - fn get_char_list(&mut self, s: &StringList) { - let h = self.heap.h; - - if let Some(c) = s.head() { - self.heap - .push(HeapCellValue::Addr(Addr::Con(Constant::Char(c)))); - self.heap - .push(HeapCellValue::Addr(Addr::Con(Constant::String(s.tail())))); - - self.s = h; - self.mode = MachineMode::Read; - } else if s.is_expandable() { - self.heap - .push(HeapCellValue::Addr(Addr::Con(Constant::String(s.clone())))); - - self.s = h; - self.mode = MachineMode::Read; - } else { - self.fail = true; - } - } - - fn get_code_list(&mut self, s: &StringList) { - let h = self.heap.h; - - if let Some(c) = s.head() { - self.heap - .push(HeapCellValue::Addr(Addr::Con(Constant::CharCode(c as u8)))); - self.heap - .push(HeapCellValue::Addr(Addr::Con(Constant::String(s.tail())))); + fn get_char_list(&mut self, offset: usize, s: Rc) { + if let Some(c) = s[offset ..].chars().next() { + let h = self.heap.h; - self.s = h; - self.mode = MachineMode::Read; - } else if s.is_expandable() { - self.heap - .push(HeapCellValue::Addr(Addr::Con(Constant::String(s.clone())))); + self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::Char(c)))); + self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::String( + offset + c.len_utf8(), + s, + )))); self.s = h; self.mode = MachineMode::Read; - } else { - self.fail = true; } } @@ -1684,10 +1400,15 @@ impl MachineState { let addr = self.store(self.deref(self[reg].clone())); match addr { - Addr::Con(Constant::String(ref s)) => match self.flags.double_quotes { - DoubleQuotes::Chars => self.get_char_list(s), - DoubleQuotes::Codes => self.get_code_list(s), - _ => self.fail = true, + Addr::Con(Constant::String(n, s)) => + match self.flags.double_quotes { + DoubleQuotes::Chars | DoubleQuotes::Codes + if s.len() > n => { + self.get_char_list(n, s) + } + _ => { + self.fail = true + } }, addr @ Addr::AttrVar(_) | addr @ Addr::StackCell(..) @@ -1838,15 +1559,15 @@ impl MachineState { let offset = match addr { Addr::HeapCell(_) | Addr::StackCell(..) | Addr::AttrVar(..) => v, - Addr::Con(Constant::String(ref s)) if !self.flags.double_quotes.is_atom() => { - if s.is_empty() { - if s.is_expandable() { - v - } else { + Addr::Con(Constant::String(n, ref s)) => { + if !self.flags.double_quotes.is_atom() { + if n >= s.len() { c + } else { + l } } else { - l + c } } Addr::Con(_) => c, @@ -2155,19 +1876,17 @@ impl MachineState { self.fail = true; } } - Addr::Con(Constant::String(ref s)) - if !self.flags.double_quotes.is_atom() && !s.is_empty() => + Addr::Con(Constant::String(o, ref s)) + if !self.flags.double_quotes.is_atom() && !s[o ..].is_empty() => { if n == 1 || n == 2 { let a3 = self[temp_v!(3)].clone(); + let c = s[o ..].chars().next().unwrap(); + let h_a = if n == 1 { - if self.flags.double_quotes.is_chars() { - Addr::Con(Constant::Char(s.head().unwrap())) - } else { - Addr::Con(Constant::CharCode(s.head().unwrap() as u8)) - } + Addr::Con(Constant::Char(c)) } else { - Addr::Con(Constant::String(s.tail())) + Addr::Con(Constant::String(o + c.len_utf8(), s.clone())) }; self.unify(a3, h_a); @@ -2243,12 +1962,12 @@ impl MachineState { (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) => continue, (HeapCellValue::Addr(Addr::Con(Constant::EmptyList)), - HeapCellValue::Addr(Addr::Con(Constant::String(s)))) - | (HeapCellValue::Addr(Addr::Con(Constant::String(s))), + HeapCellValue::Addr(Addr::Con(Constant::String(n, s)))) + | (HeapCellValue::Addr(Addr::Con(Constant::String(n, s))), HeapCellValue::Addr(Addr::Con(Constant::EmptyList))) => return match self.flags.double_quotes { DoubleQuotes::Atom => true, - _ => !s.is_empty() + _ => n < s.len() }, (HeapCellValue::Addr(a1), HeapCellValue::Addr(a2)) => if a1 != a2 { @@ -2269,17 +1988,18 @@ impl MachineState { match (v1, v2) { ( HeapCellValue::Addr(Addr::Lis(_)), - HeapCellValue::Addr(Addr::Con(Constant::String(_))), + HeapCellValue::Addr(Addr::Con(Constant::String(..))), ) | ( - HeapCellValue::Addr(Addr::Con(Constant::String(_))), + HeapCellValue::Addr(Addr::Con(Constant::String(..))), HeapCellValue::Addr(Addr::Lis(_)), - ) if !self.flags.double_quotes.is_atom() => {} + ) if !self.flags.double_quotes.is_atom() => { + } ( HeapCellValue::Addr(Addr::Con(Constant::EmptyList)), - HeapCellValue::Addr(Addr::Con(Constant::String(ref s))), + HeapCellValue::Addr(Addr::Con(Constant::String(n, ref s))), ) if !self.flags.double_quotes.is_atom() => { - if s.is_empty() { + if s[n ..].is_empty() { return Ordering::Equal; } else { return Ordering::Greater; @@ -2306,10 +2026,10 @@ impl MachineState { } } ( - HeapCellValue::Addr(Addr::Con(Constant::String(ref s))), + HeapCellValue::Addr(Addr::Con(Constant::String(n, ref s))), HeapCellValue::Addr(Addr::Con(Constant::EmptyList)), ) if !self.flags.double_quotes.is_atom() => { - if s.is_empty() { + if s[n ..].is_empty() { return Ordering::Equal; } else { return Ordering::Less; @@ -2336,7 +2056,9 @@ impl MachineState { } } (HeapCellValue::Addr(Addr::HeapCell(_)), _) - | (HeapCellValue::Addr(Addr::AttrVar(_)), _) => return Ordering::Less, + | (HeapCellValue::Addr(Addr::AttrVar(_)), _) => { + return Ordering::Less; + } ( HeapCellValue::Addr(Addr::StackCell(fr1, sc1)), HeapCellValue::Addr(Addr::StackCell(fr2, sc2)), @@ -2356,8 +2078,12 @@ impl MachineState { | ( HeapCellValue::Addr(Addr::StackCell(..)), HeapCellValue::Addr(Addr::AttrVar(_)), - ) => return Ordering::Greater, - (HeapCellValue::Addr(Addr::StackCell(..)), _) => return Ordering::Less, + ) => { + return Ordering::Greater; + } + (HeapCellValue::Addr(Addr::StackCell(..)), _) => { + return Ordering::Less; + } ( HeapCellValue::Addr(Addr::Con(Constant::Integer(..))), HeapCellValue::Addr(Addr::HeapCell(_)), @@ -2365,11 +2091,15 @@ impl MachineState { | ( HeapCellValue::Addr(Addr::Con(Constant::Integer(..))), HeapCellValue::Addr(Addr::AttrVar(_)), - ) => return Ordering::Greater, + ) => { + return Ordering::Greater; + } ( HeapCellValue::Addr(Addr::Con(Constant::Integer(..))), HeapCellValue::Addr(Addr::StackCell(..)), - ) => return Ordering::Greater, + ) => { + return Ordering::Greater; + } ( HeapCellValue::Addr(Addr::Con(Constant::Integer(n1))), HeapCellValue::Addr(Addr::Con(Constant::Integer(n2))), @@ -2386,11 +2116,15 @@ impl MachineState { | ( HeapCellValue::Addr(Addr::Con(Constant::Float(..))), HeapCellValue::Addr(Addr::AttrVar(_)), - ) => return Ordering::Greater, + ) => { + return Ordering::Greater; + } ( HeapCellValue::Addr(Addr::Con(Constant::Float(..))), HeapCellValue::Addr(Addr::StackCell(..)), - ) => return Ordering::Greater, + ) => { + return Ordering::Greater; + } ( HeapCellValue::Addr(Addr::Con(Constant::Float(n1))), HeapCellValue::Addr(Addr::Con(Constant::Float(n2))), @@ -2407,11 +2141,15 @@ impl MachineState { | ( HeapCellValue::Addr(Addr::Con(Constant::Rational(..))), HeapCellValue::Addr(Addr::AttrVar(_)), - ) => return Ordering::Greater, + ) => { + return Ordering::Greater; + } ( HeapCellValue::Addr(Addr::Con(Constant::Rational(..))), HeapCellValue::Addr(Addr::StackCell(..)), - ) => return Ordering::Greater, + ) => { + return Ordering::Greater; + } ( HeapCellValue::Addr(Addr::Con(Constant::Rational(n1))), HeapCellValue::Addr(Addr::Con(Constant::Rational(n2))), @@ -2430,42 +2168,42 @@ impl MachineState { | ( HeapCellValue::Addr(Addr::Con(Constant::String(..))), HeapCellValue::Addr(Addr::AttrVar(_)), - ) => return Ordering::Greater, + ) => { + return Ordering::Greater; + } ( HeapCellValue::Addr(Addr::Con(Constant::String(..))), HeapCellValue::Addr(Addr::StackCell(..)), - ) => return Ordering::Greater, + ) => { + return Ordering::Greater; + } ( - HeapCellValue::Addr(Addr::Con(Constant::String(_))), + HeapCellValue::Addr(Addr::Con(Constant::String(..))), HeapCellValue::Addr(Addr::Con(Constant::Integer(_))), - ) => return Ordering::Greater, + ) => { + return Ordering::Greater; + } ( - HeapCellValue::Addr(Addr::Con(Constant::String(_))), + HeapCellValue::Addr(Addr::Con(Constant::String(..))), HeapCellValue::Addr(Addr::Con(Constant::Rational(_))), - ) => return Ordering::Greater, + ) => { + return Ordering::Greater; + } ( - HeapCellValue::Addr(Addr::Con(Constant::String(_))), + HeapCellValue::Addr(Addr::Con(Constant::String(..))), HeapCellValue::Addr(Addr::Con(Constant::Float(_))), - ) => return Ordering::Greater, + ) => { + return Ordering::Greater; + } ( - HeapCellValue::Addr(Addr::Con(Constant::String(s1))), - HeapCellValue::Addr(Addr::Con(Constant::String(s2))), + HeapCellValue::Addr(Addr::Con(Constant::String(n1, s1))), + HeapCellValue::Addr(Addr::Con(Constant::String(n2, s2))), ) => { - return if s1.is_expandable() { - if s2.is_expandable() { - s1.cmp(&s2) - } else { - Ordering::Greater - } - } else { - if s2.is_expandable() { - Ordering::Less - } else { - s1.cmp(&s2) - } - } + return s1[n1 ..].cmp(&s2[n2 ..]); + } + (HeapCellValue::Addr(Addr::Con(Constant::String(..))), _) => { + return Ordering::Less; } - (HeapCellValue::Addr(Addr::Con(Constant::String(_))), _) => return Ordering::Less, ( HeapCellValue::Addr(Addr::Con(Constant::Atom(..))), HeapCellValue::Addr(Addr::HeapCell(_)), @@ -2492,7 +2230,7 @@ impl MachineState { ) => return Ordering::Greater, ( HeapCellValue::Addr(Addr::Con(Constant::Atom(..))), - HeapCellValue::Addr(Addr::Con(Constant::String(_))), + HeapCellValue::Addr(Addr::Con(Constant::String(..))), ) => return Ordering::Greater, ( HeapCellValue::Addr(Addr::Con(Constant::Atom(s1, _))), @@ -2502,7 +2240,9 @@ impl MachineState { return s1.cmp(&s2); } } - (HeapCellValue::Addr(Addr::Con(Constant::Atom(..))), _) => return Ordering::Less, + (HeapCellValue::Addr(Addr::Con(Constant::Atom(..))), _) => { + return Ordering::Less; + } (HeapCellValue::NamedStr(ar1, n1, _), HeapCellValue::NamedStr(ar2, n2, _)) => { if ar1 < ar2 { return Ordering::Less; @@ -2512,9 +2252,11 @@ impl MachineState { return n1.cmp(&n2); } } - (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) => continue, + (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) => { + continue; + } (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::NamedStr(ar, n, _)) - | (HeapCellValue::NamedStr(ar, n, _), HeapCellValue::Addr(Addr::Lis(_))) => { + | (HeapCellValue::NamedStr(ar, n, _), HeapCellValue::Addr(Addr::Lis(_))) => { if ar == 2 && n.as_str() == "." { continue; } else if ar < 2 { @@ -2572,6 +2314,8 @@ impl MachineState { match d { Addr::Con(Constant::Integer(_)) => self.p += 1, Addr::Con(Constant::CharCode(_)) => self.p += 1, + Addr::Con(Constant::Char(_)) + if self.flags.double_quotes.is_codes() => self.p += 1, Addr::Con(Constant::Rational(r)) => { if r.denom() == &1 { self.p += 1; @@ -2610,7 +2354,7 @@ impl MachineState { let d = self.store(self.deref(self[r1].clone())); match d { - Addr::Con(Constant::String(_)) => self.p += 1, + Addr::Con(Constant::String(..)) => self.p += 1, _ => self.fail = true, }; } @@ -2630,14 +2374,6 @@ impl MachineState { _ => self.fail = true, }; } - &InlinedClauseType::IsPartialString(r1) => { - let d = self.store(self.deref(self[r1].clone())); - - match d { - Addr::Con(Constant::String(ref s)) if s.is_expandable() => self.p += 1, - _ => self.fail = true, - }; - } } } @@ -2697,8 +2433,8 @@ impl MachineState { match a1.clone() { Addr::DBRef(_) => self.fail = true, - Addr::Con(Constant::String(ref s)) - if !self.flags.double_quotes.is_atom() && !s.is_empty() => + Addr::Con(Constant::String(n, ref s)) + if !self.flags.double_quotes.is_atom() && !s[n ..].is_empty() => { let shared_op_desc = fetch_op_spec(clause_name!("."), 2, None, &indices.op_dir); self.try_functor_compound_case(clause_name!("."), 2, shared_op_desc) @@ -2806,31 +2542,8 @@ impl MachineState { *list = result; } - pub(super) fn try_string_list(&self, r: RegType) -> Result { - let a1 = self[r].clone(); - let a1 = self.store(self.deref(a1)); - - if let Addr::Con(Constant::String(s)) = a1 { - return Ok(s); - } else { - let stub = MachineError::functor_stub(clause_name!("partial_string"), 2); - - match self.try_from_list(r, stub.clone()) { - Ok(addrs) => Ok(StringList::new( - match self.try_char_list(addrs) { - Ok(string) => string, - Err(err) => { - return Err(self.error_form(err, stub)); - } - }, - false, - )), - Err(err) => return Err(err), - } - } - } - - pub(super) fn try_from_list( + pub(super) + fn try_from_list( &self, r: RegType, caller: MachineStub, @@ -2851,13 +2564,15 @@ impl MachineState { result.push(self.heap[hcp].as_addr(hcp)); l = hcp + 1; } - Addr::Con(Constant::String(ref s)) + Addr::Con(Constant::String(n, ref s)) if !self.flags.double_quotes.is_atom() => { - result.push(Addr::Con(Constant::String(s.clone()))); + result.push(Addr::Con(Constant::String(n, s.clone()))); + break; + } + Addr::Con(Constant::EmptyList) => { break; } - Addr::Con(Constant::EmptyList) => break, Addr::HeapCell(_) | Addr::StackCell(..) => { return Err( self.error_form(MachineError::instantiation_error(), caller) @@ -2879,8 +2594,12 @@ impl MachineState { Ok(result) } - Addr::Con(Constant::String(ref s)) if !self.flags.double_quotes.is_atom() => { - Ok(vec![Addr::Con(Constant::String(s.clone()))]) + Addr::Con(Constant::String(n, ref s)) if !self.flags.double_quotes.is_atom() => { + if s.len() > n { + Ok(Vec::from_iter(s[n ..].chars().map(|c| Addr::Con(Constant::Char(c))))) + } else { + Ok(vec![]) + } } Addr::HeapCell(_) | Addr::StackCell(..) => { Err(self.error_form(MachineError::instantiation_error(), caller)) @@ -2921,36 +2640,6 @@ impl MachineState { self.unify(Addr::HeapCell(old_h), a2); } - fn structural_char_list_test(&self, s: &StringList, list_offset: usize) -> bool { - if !s.is_empty() { - if let HeapCellValue::Addr(Addr::Con(constant)) = self.heap[list_offset].clone() { - if let Some(c) = s.head() { - // checks equality on atoms, too. - if constant == Constant::Char(c) { - return true; - } - } - } - } - - false - } - - fn structural_code_list_test(&self, s: &StringList, list_offset: usize) -> bool { - if !s.is_empty() { - if let HeapCellValue::Addr(Addr::Con(constant)) = self.heap[list_offset].clone() { - if let Some(c) = s.head() { - // checks equality on integers, too. - if constant == Constant::CharCode(c as u8) { - return true; - } - } - } - } - - false - } - // returns true on failure. pub(super) fn structural_eq_test(&self) -> bool { let a1 = self[temp_v!(1)].clone(); @@ -2963,49 +2652,24 @@ impl MachineState { for (v1, v2) in iter { match (v1, v2) { ( - HeapCellValue::Addr(Addr::Lis(l)), - HeapCellValue::Addr(Addr::Con(Constant::String(ref s))), + HeapCellValue::Addr(Addr::Lis(_)), + HeapCellValue::Addr(Addr::Con(Constant::String(..))), ) | ( - HeapCellValue::Addr(Addr::Con(Constant::String(ref s))), - HeapCellValue::Addr(Addr::Lis(l)), - ) if !self.flags.double_quotes.is_atom() => match self.flags.double_quotes { - DoubleQuotes::Chars => { - if self.structural_char_list_test(s, l) { - continue; - } - } - DoubleQuotes::Codes => { - if self.structural_code_list_test(s, l) { - continue; - } - } - DoubleQuotes::Atom => unreachable!(), - }, - ( - HeapCellValue::Addr(Addr::Con(Constant::String(ref s1))), - HeapCellValue::Addr(Addr::Con(Constant::String(ref s2))), - ) => match s1.head() { - Some(c1) => { - if let Some(c2) = s2.head() { - if c1 != c2 { - return true; - } - } else { - return true; - } - } - None => return !s2.is_empty(), - }, + HeapCellValue::Addr(Addr::Con(Constant::String(..))), + HeapCellValue::Addr(Addr::Lis(_)), + ) if !self.flags.double_quotes.is_atom() => { + continue; + } ( - HeapCellValue::Addr(Addr::Con(Constant::String(ref s))), + HeapCellValue::Addr(Addr::Con(Constant::String(n, ref s))), HeapCellValue::Addr(Addr::Con(Constant::EmptyList)), ) | ( HeapCellValue::Addr(Addr::Con(Constant::EmptyList)), - HeapCellValue::Addr(Addr::Con(Constant::String(ref s))), + HeapCellValue::Addr(Addr::Con(Constant::String(n, ref s))), ) if !self.flags.double_quotes.is_atom() => { - if !s.is_empty() { + if !s[n ..].is_empty() { return true; } } @@ -3014,7 +2678,9 @@ impl MachineState { return true; } } - (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) => continue, + (HeapCellValue::Addr(Addr::Lis(_)), HeapCellValue::Addr(Addr::Lis(_))) => { + continue; + } ( HeapCellValue::Addr(v1 @ Addr::HeapCell(_)), HeapCellValue::Addr(v2 @ Addr::AttrVar(_)), @@ -3136,6 +2802,7 @@ impl MachineState { } let mut default_call_policy: Box = Box::new(DefaultCallPolicy {}); + let call_policy = if use_default_cp { &mut default_call_policy } else { @@ -3237,9 +2904,9 @@ impl MachineState { or_frame.prelude.b = self.b; or_frame.prelude.bp = self.p.local() + 1; or_frame.prelude.tr = self.tr; - or_frame.prelude.pstr_tr = self.pstr_tr; or_frame.prelude.h = self.heap.h; or_frame.prelude.b0 = self.b0; + or_frame.prelude.attr_var_init_queue_b = self.attr_var_init.attr_var_queue.len(); or_frame.prelude.attr_var_init_bindings_b = @@ -3276,7 +2943,6 @@ impl MachineState { or_frame.prelude.b = self.b; or_frame.prelude.bp = self.p.local() + offset; or_frame.prelude.tr = self.tr; - or_frame.prelude.pstr_tr = self.pstr_tr; or_frame.prelude.h = self.heap.h; or_frame.prelude.b0 = self.b0; or_frame.prelude.attr_var_init_queue_b = @@ -3321,7 +2987,6 @@ impl MachineState { if b > b0 { self.b = b0; self.tidy_trail(); - self.tidy_pstr_trail(); } self.p += 1; @@ -3356,7 +3021,6 @@ impl MachineState { self.b0 = 0; self.s = 0; self.tr = 0; - self.pstr_tr = 0; self.p = CodePtr::default(); self.cp = LocalCodePtr::default(); self.attr_var_init.reset(); @@ -3364,7 +3028,6 @@ impl MachineState { self.fail = false; self.trail.clear(); - self.pstr_trail.clear(); self.heap.clear(); self.mode = MachineMode::Write; self.registers = vec![Addr::HeapCell(0); MAX_ARITY + 1]; // self.registers[0] is never used. diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index ede50593..88e8eb63 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -161,27 +161,27 @@ impl SubModuleUser for IndexStore { fn use_qualified_module( &mut self, code_repo: &mut CodeRepo, - flags: MachineFlags, + _: MachineFlags, submodule: &Module, exports: &Vec, ) -> Result<(), SessionError> { use_qualified_module(self, submodule, exports)?; submodule - .dump_expansions(code_repo, flags) + .dump_expansions(code_repo) .map_err(SessionError::from) } fn use_module( &mut self, code_repo: &mut CodeRepo, - flags: MachineFlags, + _: MachineFlags, submodule: &Module, ) -> Result<(), SessionError> { use_module(self, submodule)?; if !submodule.inserted_expansions { submodule - .dump_expansions(code_repo, flags) + .dump_expansions(code_repo) .map_err(SessionError::from) } else { Ok(()) @@ -699,12 +699,10 @@ impl Machine { snapshot.b0 = self.machine_st.b0; snapshot.s = self.machine_st.s; snapshot.tr = self.machine_st.tr; - snapshot.pstr_tr = self.machine_st.pstr_tr; snapshot.num_of_args = self.machine_st.num_of_args; snapshot.fail = self.machine_st.fail; snapshot.trail = mem::replace(&mut self.machine_st.trail, vec![]); - snapshot.pstr_trail = mem::replace(&mut self.machine_st.pstr_trail, vec![]); snapshot.heap = self.machine_st.heap.take(); snapshot.mode = self.machine_st.mode; snapshot.stack = self.machine_st.stack.take(); @@ -724,12 +722,10 @@ impl Machine { self.machine_st.b0 = snapshot.b0; self.machine_st.s = snapshot.s; self.machine_st.tr = snapshot.tr; - self.machine_st.pstr_tr = snapshot.pstr_tr; self.machine_st.num_of_args = snapshot.num_of_args; self.machine_st.fail = snapshot.fail; self.machine_st.trail = mem::replace(&mut snapshot.trail, vec![]); - self.machine_st.pstr_trail = mem::replace(&mut snapshot.pstr_trail, vec![]); self.inner_heap = self.machine_st.heap.take(); self.inner_heap.truncate(0); diff --git a/src/prolog/machine/modules.rs b/src/prolog/machine/modules.rs index 00bb0bc1..00a258be 100644 --- a/src/prolog/machine/modules.rs +++ b/src/prolog/machine/modules.rs @@ -38,7 +38,6 @@ impl Module { pub fn dump_expansions( &self, code_repo: &mut CodeRepo, - flags: MachineFlags, ) -> Result<(), ParserError> { { let te = code_repo @@ -64,8 +63,8 @@ impl Module { ge.1.extend(self.user_goal_expansions.1.iter().cloned()); } - code_repo.compile_hook(CompileTimeHook::TermExpansion, flags)?; - code_repo.compile_hook(CompileTimeHook::GoalExpansion, flags)?; + code_repo.compile_hook(CompileTimeHook::TermExpansion)?; + code_repo.compile_hook(CompileTimeHook::GoalExpansion)?; Ok(()) } diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index d88dad91..0fc09b97 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -1,6 +1,5 @@ use prolog_parser::ast::*; use prolog_parser::parser::*; -use prolog_parser::string_list::*; use prolog_parser::tabled_rc::*; use crate::prolog::clause_types::*; @@ -88,8 +87,8 @@ impl MachineState { brent_st.steps, brent_st.hare, )), - Addr::Con(Constant::String(ref s)) if self.flags.double_quotes.is_chars() => { - Some(CycleSearchResult::String(brent_st.steps, s.clone())) + Addr::Con(Constant::String(n, ref s)) if !self.flags.double_quotes.is_atom() => { + Some(CycleSearchResult::String(brent_st.steps, n, s.clone())) } Addr::Lis(l) => { brent_st.hare = l + 1; @@ -104,7 +103,9 @@ impl MachineState { None } - _ => Some(CycleSearchResult::NotList), + _ => { + Some(CycleSearchResult::NotList) + } }, } } @@ -115,8 +116,8 @@ impl MachineState { Addr::Lis(offset) if max_steps > 0 => offset + 1, Addr::Lis(offset) => return CycleSearchResult::UntouchedList(offset), Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList, - Addr::Con(Constant::String(ref s)) if !self.flags.double_quotes.is_atom() => { - return CycleSearchResult::String(0, s.clone()) + Addr::Con(Constant::String(n, ref s)) if !self.flags.double_quotes.is_atom() => { + return CycleSearchResult::String(0, n, s.clone()) } _ => return CycleSearchResult::NotList, }; @@ -139,8 +140,8 @@ impl MachineState { let hare = match addr { Addr::Lis(offset) => offset + 1, Addr::Con(Constant::EmptyList) => return CycleSearchResult::EmptyList, - Addr::Con(Constant::String(ref s)) if !self.flags.double_quotes.is_atom() => { - return CycleSearchResult::String(0, s.clone()) + Addr::Con(Constant::String(n, ref s)) if !self.flags.double_quotes.is_atom() => { + return CycleSearchResult::String(0, n, s.clone()) } _ => return CycleSearchResult::NotList, }; @@ -198,10 +199,10 @@ impl MachineState { }; match search_result { - CycleSearchResult::String(n, s) => { + CycleSearchResult::String(n, offset, s) => { if max_steps == -1 { self.finalize_skip_max_list( - n + s.len(), + s[offset ..].len(), Addr::Con(Constant::EmptyList), ) } else { @@ -209,15 +210,13 @@ impl MachineState { if s.len() < i { self.finalize_skip_max_list( - n + s.len(), + s[n + offset + i..].len(), Addr::Con(Constant::EmptyList), ) } else { - let s = - StringList::new(s.char_span(i), s.is_expandable()); self.finalize_skip_max_list( - i + n, - Addr::Con(Constant::String(s)), + i + n + offset, + Addr::Con(Constant::String(n + i + offset, s)), ) } } @@ -436,8 +435,8 @@ impl MachineState { n: &Integer, stub: &'static str, arity: usize, - ) -> Result { - if let Some(c) = n.to_u8() { + ) -> Result { + if let Some(c) = n.to_u32() { Ok(c) } else { let stub = MachineError::functor_stub(clause_name!(stub), arity); @@ -644,7 +643,16 @@ impl MachineState { let list_of_chars = Addr::HeapCell(self.heap.to_list(iter)); let a2 = self[temp_v!(2)].clone(); - self.unify(a2, list_of_chars); + + match self.store(self.deref(a2)) { + Addr::Con(Constant::String(..)) + if !self.flags.double_quotes.is_chars() => { + self.fail = true; + } + a2 => { + self.unify(a2, list_of_chars); + } + } } Addr::Con(Constant::EmptyList) => { let a2 = self[temp_v!(2)].clone(); @@ -682,31 +690,50 @@ impl MachineState { match self.store(self.deref(a1)) { Addr::Con(Constant::Char(c)) => { - let iter = once(Addr::Con(Constant::CharCode(c as u8))); + let iter = once(Addr::Con(Constant::CharCode(c as u32))); let list_of_codes = Addr::HeapCell(self.heap.to_list(iter)); let a2 = self[temp_v!(2)].clone(); self.unify(a2, list_of_codes); } Addr::Con(Constant::Atom(name, _)) => { - let iter = name - .as_str() - .chars() - .map(|c| Addr::Con(Constant::CharCode(c as u8))); - let list_of_codes = Addr::HeapCell(self.heap.to_list(iter)); - let a2 = self[temp_v!(2)].clone(); - self.unify(a2, list_of_codes); + match self.store(self.deref(a2)) { + a2 @ Addr::Con(Constant::String(..)) => { + if !self.flags.double_quotes.is_codes() { + self.fail = true; + } else { + let iter = name + .as_str() + .chars() + .map(|c| Addr::Con(Constant::Char(c))); + + let list_of_codes = Addr::HeapCell(self.heap.to_list(iter)); + + self.unify(a2, list_of_codes); + } + } + a2 => { + let iter = name + .as_str() + .chars() + .map(|c| Addr::Con(Constant::CharCode(c as u32))); + + let list_of_codes = Addr::HeapCell(self.heap.to_list(iter)); + + self.unify(a2, list_of_codes); + } + } } Addr::Con(Constant::EmptyList) => { - let a2 = self[temp_v!(2)].clone(); let chars = vec![ - Addr::Con(Constant::CharCode('[' as u8)), - Addr::Con(Constant::CharCode(']' as u8)), + Addr::Con(Constant::CharCode('[' as u32)), + Addr::Con(Constant::CharCode(']' as u32)), ]; let list_of_codes = Addr::HeapCell(self.heap.to_list(chars.into_iter())); + let a2 = self[temp_v!(2)].clone(); self.unify(a2, list_of_codes); } @@ -718,14 +745,15 @@ impl MachineState { Ok(addrs) => { let mut chars = String::new(); - for addr in addrs.iter() { + for addr in addrs { match addr { - &Addr::Con(Constant::Integer(ref n)) => { + Addr::Con(Constant::Integer(n)) => { let c = self.int_to_char_code(&n, "atom_codes", 2)?; - chars.push(c as char); + chars.push(std::char::from_u32(c).unwrap()); + } + Addr::Con(Constant::CharCode(c)) => { + chars.push(std::char::from_u32(c).unwrap()); } - &Addr::Con(Constant::CharCode(c)) => - chars.push(c as char), _ => { let err = MachineError::type_error( ValidType::Integer, @@ -754,7 +782,7 @@ impl MachineState { _ => unreachable!(), }; - let len = Integer::from(atom.as_str().len()); + let len = Integer::from(atom.as_str().chars().count()); let a2 = self[temp_v!(2)].clone(); self.unify(a2, Addr::Con(Constant::Integer(len))); @@ -831,7 +859,7 @@ impl MachineState { let codes = string .trim() .chars() - .map(|c| Addr::Con(Constant::CharCode(c as u8))); + .map(|c| Addr::Con(Constant::CharCode(c as u32))); let codes_list = Addr::HeapCell(self.heap.to_list(codes)); self.unify(codes_list, chs); @@ -841,10 +869,9 @@ impl MachineState { match self.try_from_list(temp_v!(1), stub.clone()) { Err(e) => return Err(e), - Ok(addrs) => match self.try_code_list(addrs) { - Ok(codes) => { - let string = codes.iter().map(|c| *c as char).collect(); - self.parse_number_from_string(string, indices, stub)? + Ok(addrs) => match self.try_char_list(addrs) { + Ok(chars) => { + self.parse_number_from_string(chars, indices, stub)? } Err(err) => return Err(self.error_form(err, stub)), }, @@ -878,22 +905,24 @@ impl MachineState { let c = name.as_str().chars().next().unwrap(); let a2 = self[temp_v!(2)].clone(); - self.unify(Addr::Con(Constant::CharCode(c as u8)), a2); + self.unify(Addr::Con(Constant::CharCode(c as u32)), a2); } Addr::Con(Constant::Char(c)) => { let a2 = self[temp_v!(2)].clone(); - self.unify(Addr::Con(Constant::CharCode(c as u8)), a2); + self.unify(Addr::Con(Constant::CharCode(c as u32)), a2); } ref addr if addr.is_ref() => { let a2 = self[temp_v!(2)].clone(); match self.store(self.deref(a2)) { - Addr::Con(Constant::CharCode(code)) => { - self.unify(Addr::Con(Constant::Char(code as char)), addr.clone()) + Addr::Con(Constant::Char(code)) => { + self.unify(Addr::Con(Constant::Char(code)), addr.clone()) } Addr::Con(Constant::Integer(n)) => { let c = self.int_to_char_code(&n, "char_code", 2)?; - self.unify(Addr::Con(Constant::Char(c as char)), addr.clone()); + let c = std::char::from_u32(c).unwrap(); + + self.unify(Addr::Con(Constant::Char(c)), addr.clone()); } _ => self.fail = true, }; @@ -2325,7 +2354,7 @@ impl MachineState { let mut h = self.heap.h; let mut functors = vec![]; - + walk_code( &code_repo.code, first_idx, @@ -2334,10 +2363,10 @@ impl MachineState { functors.push(Addr::HeapCell(h)); h += section.len(); - self.heap.extend(section.into_iter()); + self.heap.extend(section.into_iter()); }, ); - + let listing = Addr::HeapCell(self.heap.to_list(functors.into_iter())); let listing_var = self[temp_v!(3)].clone(); diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs index 9af68c67..9c91e555 100644 --- a/src/prolog/machine/term_expansion.rs +++ b/src/prolog/machine/term_expansion.rs @@ -209,10 +209,10 @@ impl<'a, R: Read> TermStream<'a, R> { self.wam .code_repo - .compile_hook(CompileTimeHook::TermExpansion, self.flags)?; + .compile_hook(CompileTimeHook::TermExpansion)?; self.wam .code_repo - .compile_hook(CompileTimeHook::GoalExpansion, self.flags)?; + .compile_hook(CompileTimeHook::GoalExpansion)?; Ok(ExpansionAdditionResult { term_expansion_additions, diff --git a/src/prolog/machine/toplevel.rs b/src/prolog/machine/toplevel.rs index 05302225..3078beca 100644 --- a/src/prolog/machine/toplevel.rs +++ b/src/prolog/machine/toplevel.rs @@ -828,10 +828,6 @@ impl RelationWorker { Err(ParserError::InadmissibleQueryTerm) } } - ("partial_string", 2) => { - let ct = ClauseType::BuiltIn(BuiltInClauseType::PartialString); - return Ok(QueryTerm::Clause(Cell::default(), ct, terms, false)); - } _ => { let ct = indices.get_clause_type(name, terms.len(), fixity); Ok(QueryTerm::Clause(Cell::default(), ct, terms, false)) @@ -1190,7 +1186,6 @@ impl<'a, R: Read> TopLevelBatchWorker<'a, R> { &result, &mut indices.term_stream.wam.indices.in_situ_code_dir, &mut indices.term_stream.wam.indices.in_situ_module_dir, - indices.term_stream.flags, &self.non_counted_bt_preds, )?; diff --git a/src/prolog/macros.rs b/src/prolog/macros.rs index 66798683..89f971e7 100644 --- a/src/prolog/macros.rs +++ b/src/prolog/macros.rs @@ -106,16 +106,6 @@ macro_rules! is_var { }; } -macro_rules! is_partial_string { - ($r:expr) => { - call_clause!( - ClauseType::Inlined(InlinedClauseType::IsPartialString($r)), - 1, - 0 - ) - }; -} - macro_rules! call_clause { ($ct:expr, $arity:expr, $pvs:expr) => { Line::Control(ControlInstruction::CallClause(