From: Mark Thom Date: Tue, 21 Aug 2018 04:00:38 +0000 (-0600) Subject: add StringList internal datatype X-Git-Tag: v0.8.110~428 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=01d6ef099f8b921e6386ec0e936c05ad0c0e651d;p=scryer-prolog.git add StringList internal datatype --- diff --git a/src/prolog/ast.rs b/src/prolog/ast.rs index b67c3391..54eee85e 100644 --- a/src/prolog/ast.rs +++ b/src/prolog/ast.rs @@ -897,8 +897,7 @@ impl ClauseName { ClauseName::BuiltIn(s) => ClauseName::BuiltIn(defrock_brackets(s)), ClauseName::User(s) => - ClauseName::User(tabled_rc!(defrock_brackets(s.as_str()).to_owned(), - s.atom_tbl())) + ClauseName::User(tabled_rc!(defrock_brackets(s.as_str()).to_owned(), s.table())) } } } diff --git a/src/prolog/mod.rs b/src/prolog/mod.rs index 6d16892d..eb4e57f4 100644 --- a/src/prolog/mod.rs +++ b/src/prolog/mod.rs @@ -27,3 +27,4 @@ pub mod heap_print; pub mod targets; pub mod tabled_rc; pub mod read; +pub mod string_list; diff --git a/src/prolog/string_list.rs b/src/prolog/string_list.rs new file mode 100644 index 00000000..3c1dc63a --- /dev/null +++ b/src/prolog/string_list.rs @@ -0,0 +1,82 @@ +use prolog::tabled_rc::*; + +use std::cell::{Ref, RefCell}; +use std::cmp::Ordering; +use std::hash::{Hash, Hasher}; +use std::ops::{Index, RangeTo}; + +#[derive(PartialOrd, PartialEq, Ord, Eq)] +pub struct StringListWrapper(RefCell); + +impl Hash for StringListWrapper { + fn hash(&self, state: &mut H) { + self.0.borrow().hash(state) + } +} + +// cursor is ignored if the double_quotes flag is set to atom +#[derive(Clone)] +pub struct StringList { + body: TabledRc, + cursor: usize, // use this to generate a chars() iterator on the fly, + // and skip over the first cursor chars. + expandable: bool +} + +impl Hash for StringList { + fn hash(&self, state: &mut H) { + self.borrow().hash(state) + } +} + +impl PartialOrd for StringList { + fn partial_cmp(&self, other: &Self) -> Option + { + Some(self.body.cmp(&other.body)) + } +} + +impl Ord for StringList { + fn cmp(&self, other: &Self) -> Ordering + { + self.body.cmp(&other.body) + } +} + +impl PartialEq for StringList { + fn eq(&self, other: &Self) -> bool + { + self.body == other.body + } +} + +impl Eq for StringList {} + +impl StringList { + #[inline] + pub fn new(s: String, expandable: bool, string_tbl: TabledData) -> Self { + let body = TabledRc::new(StringListWrapper(RefCell::new(s)), string_tbl); + + StringList { + cursor: 0, + body, + expandable + } + } + + #[inline] + pub fn tail(&self) -> Self { + let mut new_string_list = self.clone(); + + if let Some(c) = self.borrow()[self.cursor ..].chars().next() { + new_string_list.cursor += c.len_utf8(); + } + + new_string_list + } + + #[inline] + pub fn borrow(&self) -> Ref { + self.body.0.borrow() + } +} diff --git a/src/prolog/tabled_rc.rs b/src/prolog/tabled_rc.rs index 30824f91..a7a093fb 100644 --- a/src/prolog/tabled_rc.rs +++ b/src/prolog/tabled_rc.rs @@ -8,12 +8,19 @@ use std::rc::Rc; pub type TabledData = Rc>>>; -#[derive(Clone)] pub struct TabledRc { atom: Rc, table: TabledData } +// this Clone instance is manually defined to prevent the compiler +// from complaining when deriving Clone for StringList. +impl Clone for TabledRc { + fn clone(&self) -> Self { + TabledRc { atom: self.atom.clone(), table: self.table().clone() } + } +} + impl PartialOrd for TabledRc { fn partial_cmp(&self, other: &Self) -> Option { @@ -55,7 +62,7 @@ impl TabledRc { TabledRc { atom, table } } - pub fn atom_tbl(&self) -> TabledData { + pub fn table(&self) -> TabledData { self.table.clone() } }