diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 68 | ||||
-rw-r--r-- | src/parser.rs | 2 | ||||
-rw-r--r-- | src/pattern.rs | 9 | ||||
-rw-r--r-- | src/vm.rs | 33 |
4 files changed, 79 insertions, 33 deletions
diff --git a/src/lib.rs b/src/lib.rs index 08609ab..b5d7bc6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,47 +6,73 @@ mod vm; pub use pattern::Pattern; // TODO replace with GATs -/// The key returned from pairs and get. -pub enum Key<'b, T, U> { - /// Reference. +/// A borrowed or owned value of various types. +pub enum RefOwn<'b, T: ?Sized, U> { + /// Borrowed T. Ref(&'b T), /// Borrowed string. Str(&'b str), - /// Owned types. + /// Owned U. Own(U), } -impl<'b, T, U: Copy> Copy for Key<'b, T, U> { +impl<'b, T, U> PartialEq for RefOwn<'b, T, U> +where + T: ?Sized + PartialEq<T> + PartialEq<U> + PartialEq<str>, + U: PartialEq<T> + PartialEq<U> + PartialEq<str>, + str: PartialEq<T> + PartialEq<U> + PartialEq<str> +{ + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (RefOwn::Ref(l), RefOwn::Ref(r)) => l.eq(r), + (RefOwn::Own(l), RefOwn::Own(r)) => l.eq(r), + (RefOwn::Str(l), RefOwn::Str(r)) => l.eq(r), + (RefOwn::Ref(l), RefOwn::Own(r)) => PartialEq::eq(*l, r), + (RefOwn::Own(l), RefOwn::Str(r)) => PartialEq::eq(l, *r), + (RefOwn::Str(l), RefOwn::Ref(r)) => l.eq(r), + (RefOwn::Ref(l), RefOwn::Str(r)) => l.eq(r), + (RefOwn::Own(l), RefOwn::Ref(r)) => PartialEq::eq(l, *r), + (RefOwn::Str(l), RefOwn::Own(r)) => PartialEq::eq(*l, r), + } + } +} + +impl<'b, T: ?Sized, U: Copy> Copy for RefOwn<'b, T, U> { } -impl<'b, T, U: Clone> Clone for Key<'b, T, U> { +impl<'b, T: ?Sized, U: Clone> Clone for RefOwn<'b, T, U> { fn clone(&self) -> Self { match self { - Key::Ref(r) => Key::Ref(r), - Key::Str(r) => Key::Str(r), - Key::Own(v) => Key::Own(v.clone()), + RefOwn::Ref(r) => RefOwn::Ref(r), + RefOwn::Str(r) => RefOwn::Str(r), + RefOwn::Own(v) => RefOwn::Own(v.clone()), } } } -pub type KVPair<'b, T> = (Key<'b, <T as PatternTypes>::Value, <T as PatternTypes>::OwnKey>, &'b <T as PatternTypes>::Value); +pub type KVPair<'b, T> = (RefOwn<'b, <T as PatternTypes>::Ref, <T as PatternTypes>::Own>, RefOwn<'b, <T as PatternTypes>::Ref, <T as PatternTypes>::Own>); + +impl<'b, T, U> From<&'b T> for RefOwn<'b, T, U> { + fn from(x: &'b T) -> RefOwn<'b, T, U> { + RefOwn::Ref(x) + } +} // TODO investigate if this should be PatternTypes: Default /// Defines the types and operations used for matching. pub trait PatternTypes { - // TODO investigate Value: ?Sized - /// The value type. - type Value; + /// The borrowed type. + type Ref: ?Sized; // TODO replace with GATs. // TODO potentially relax with Clone? - /// The owned key type. May be uninhabited. - type OwnKey: Copy + 'static; + /// The owned type. + type Own: Copy + 'static; /// Returns an iterator over key-value pairs contained within an item, or /// None if this operation is unsupported for the given value. fn pairs<'b>( - item: &'b Self::Value + item: RefOwn<'b, Self::Ref, Self::Own> ) -> Option<Box<dyn Iterator<Item=KVPair<'b, Self>> + 'b>> { // TODO remove these default impls that only exist for testing purposes let x = None; @@ -56,8 +82,8 @@ pub trait PatternTypes { /// Returns an optional key-value pair keyed by the given key, or None if /// this operation is unsupported for the given value. fn get<'a, 'b>( - item: &'b Self::Value, - key: Key<'a, Self::Value, Self::OwnKey> + item: RefOwn<'b, Self::Ref, Self::Own>, + key: RefOwn<'a, Self::Ref, Self::Own> ) -> Option<Option<KVPair<'b, Self>>> { // TODO remove these default impls that only exist for testing purposes Some(None) @@ -68,10 +94,10 @@ pub trait PatternTypes { /// the same guarantees as PartialEq. In fact, this is a replacement for /// PartialEq for cases where it's not possible to just use PartialEq. fn matches( - left: Key<'_, Self::Value, Self::OwnKey>, - right: Key<'_, Self::Value, Self::OwnKey> + left: RefOwn<'_, Self::Ref, Self::Own>, + right: RefOwn<'_, Self::Ref, Self::Own> ) -> bool; } // TODO -type Predicate<T> = dyn (Fn(&<T as PatternTypes>::Value) -> bool) + Send + Sync; +type Predicate<T> = dyn (Fn(RefOwn<<T as PatternTypes>::Ref, <T as PatternTypes>::Own>) -> bool) + Send + Sync; diff --git a/src/parser.rs b/src/parser.rs index 0a7d858..17c0529 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -5,6 +5,6 @@ use crate::errors::PatternError; use crate::vm::PatternConstants; //use crate::vm::PatternElement; -pub(crate) fn parse<T: PatternTypes>(s: &str) -> Result<PatternConstants<T>, PatternError> { +pub(crate) fn parse<T: PatternTypes>(s: &str, defs: Option<()>/*TODO*/) -> Result<PatternConstants<T>, PatternError> { unimplemented!() } diff --git a/src/pattern.rs b/src/pattern.rs index 0368a88..2b99163 100644 --- a/src/pattern.rs +++ b/src/pattern.rs @@ -1,4 +1,5 @@ use crate::PatternTypes; +use crate::RefOwn; use crate::errors::PatternError; use crate::parser::parse; use crate::vm::Matcher; @@ -10,16 +11,16 @@ pub struct Pattern<T: PatternTypes> { } impl<T: PatternTypes> Pattern<T> { - pub fn compile(s: &str) -> Result<Self, PatternError> { + pub fn compile(s: &str, defs: Option<()>/*TODO*/) -> Result<Self, PatternError> { Ok(Self { - consts: parse(s)? + consts: parse(s, defs)? }) } pub fn attempt_match<'a, 'b>( &'a self, - value: &'b T::Value + value: impl Into<RefOwn<'b, T::Ref, T::Own>> ) -> Matcher<'a, 'b, T> { - Matcher::new(value, &self.consts, self.consts.protos.len() - 1, MAX_CALLS).ok().expect("datafu internal error: MAX_CALLS must not be 0") + Matcher::new(value.into(), &self.consts, self.consts.protos.len() - 1, MAX_CALLS).ok().expect("datafu internal error: MAX_CALLS must not be 0") } } diff --git a/src/vm.rs b/src/vm.rs index 5b27a36..44675f3 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -1,4 +1,23 @@ +/* + * This file is part of Datafu + * Copyright (C) 2021 Soni L. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + use crate::KVPair; +use crate::RefOwn; use crate::PatternTypes; use crate::Predicate; use crate::errors::MatchError; @@ -23,7 +42,7 @@ pub(crate) struct PatternConstants<T: PatternTypes> { // NOTE these are part of the constant pool and so have lifetime analogous // to 'a (consistently used to indicate constant pool lifetime) when used // elsewhere. In particular, they can't be yielded by the iterator. - pub(crate) defs: Vec<T::Value>, + pub(crate) defs: Vec<T::Own>, } /// A pattern element. @@ -49,7 +68,7 @@ impl<T: PatternTypes> Clone for PatternElement<T> { } struct Frame<'a, 'b, T: PatternTypes> { - obj: &'b T::Value, + obj: RefOwn<'b, T::Ref, T::Own>, ops: &'a Vec<PatternElement<T>>, iar: Option<usize>, depth: usize, @@ -97,7 +116,7 @@ enum HolderState<'a, 'b, T: PatternTypes> { EmptyKey, EmptySubtree, Key(KVPair<'b, T>), - Subtree(Matches<'a, 'b, T>, &'b T::Value), + Subtree(Matches<'a, 'b, T>, RefOwn<'b, T::Ref, T::Own>), } impl<'a, 'b, T: PatternTypes> Clone for HolderState<'a, 'b, T> { @@ -120,8 +139,8 @@ impl<'a, 'b, T: PatternTypes> HolderState<'a, 'b, T> { matches!(self, HolderState::EmptySubtree | HolderState::Subtree {..}) } - fn value(&self) -> Option<&'b T::Value> { - match self { + fn value(&self) -> Option<RefOwn<'b, T::Ref, T::Own>> { + match *self { HolderState::Key((_, value)) => Some(value), HolderState::Subtree(_, value) => Some(value), _ => None @@ -136,7 +155,7 @@ impl<'a, 'b, T: PatternTypes> HolderState<'a, 'b, T> { struct Holder<'a, 'b, T: PatternTypes> { name: Option<&'a str>, value: HolderState<'a, 'b, T>, - parent: Option<&'b T::Value>, + parent: Option<RefOwn<'b, T::Ref, T::Own>>, iterator: Box<dyn Iterator<Item=KVPair<'b, T>> + 'b>, filters: Vec<Box<dyn for<'c> Fn(&'c mut HolderState<'a, 'b, T>) + 'a>>, } @@ -176,7 +195,7 @@ pub struct Matcher<'a, 'b, T: PatternTypes> { } impl<'a, 'b, T: PatternTypes> Matcher<'a, 'b, T> { - pub(crate) fn new(obj: &'b T::Value, defs: &'a PatternConstants<T>, proto: usize, rlimit: usize) -> Result<Self, MatchError> { + pub(crate) fn new(obj: RefOwn<'b, T::Ref, T::Own>, defs: &'a PatternConstants<T>, proto: usize, rlimit: usize) -> Result<Self, MatchError> { let depth = rlimit.checked_sub(1).ok_or(MatchError::StackOverflow)?; let ops: &Vec<_> = &defs.protos[proto]; Ok(Self { |