diff options
Diffstat (limited to 'src/vm/mod.rs')
-rw-r--r-- | src/vm/mod.rs | 181 |
1 files changed, 124 insertions, 57 deletions
diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 5f1e86c..190fa3d 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -7,6 +7,7 @@ use std::borrow::Cow; use std::cell::Cell; +use std::cell::RefCell; use std::collections::BTreeMap; use std::marker::PhantomData; @@ -212,7 +213,7 @@ pub(crate) enum PatternToken { /// /// These are used as expectations for serde (e.g. /// `Deserializer::deserialize_string`). -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub(crate) enum Type { Any, IgnoredAny, @@ -237,17 +238,23 @@ pub(crate) enum Type { Option, Unit, Seq, - // Tuple(usize), + Tuple(usize), Map, - // // these aren't really supported: - // // UnitStruct, UnitVariant, NewtypeStruct, NewtypeVariant, TupleStruct, - // // TupleVariant, Struct, StructVariant - // // instead we use type trees for that. - // /// Adapter for Type Trees. See `crate::type_tree` for more details. - // Of { - // /// The type tree index (in `PatternConstants.type_trees`). - // type_tree: usize, - // }, + UnitStruct(&'static str), + NewtypeStruct(&'static str), + TupleStruct { + name: &'static str, + len: usize, + }, + Identifier, + Struct { + name: &'static str, + fields: &'static [&'static str], + }, + Enum { + name: &'static str, + variants: &'static [&'static str], + }, } /// The types which can be deserialized by serde. @@ -278,8 +285,6 @@ pub(crate) enum SerdeObject<'de> { // NOTE: support for multimaps! Map(Vec<(SerdeObject<'de>, SerdeObject<'de>)>), NewtypeStruct(Box<SerdeObject<'de>>), - // NOTE: currently unused! - #[allow(unused)] Enum { variant: Box<SerdeObject<'de>>, data: Box<SerdeObject<'de>>, @@ -351,69 +356,131 @@ pub(crate) struct Interpreter<'pat, 'state, O: Serialize> { pat: &'pat PatternConstants<O>, /// The error override (if any). error: &'state Cell<Option<crate::errors::MatchError>>, + /// The current interpreter frames. + frames: &'state RefCell<Vec<Frame<'pat>>>, + ///// The final output. + //output: &'state Cell<Pack<'pat, 'de>>, } -struct Frame<'pat, 'de> { +pub(crate) struct Frame<'pat> { /// The instructions/function currently being processed. ops: &'pat [PatternElement], /// The instruction index being processed. iar: Option<usize>, - /// Elements collected while processing this frame? - path: Vec<Pack<'pat, 'de>>, + /// Whether this frame matches. + matches: bool, + ///// Elements collected while processing this frame? + //path: Pack<'pat, 'de>, } impl<'pat, 'state, O: Serialize> Interpreter<'pat, 'state, O> { pub(crate) fn new( pat: &'pat PatternConstants<O>, error: &'state mut Option<crate::errors::MatchError>, + frames: &'state RefCell<Vec<Frame<'pat>>>, + //output: &'state mut Pack<'pat, 'de>, ) -> Self { + let mut mut_frames = frames.borrow_mut(); + debug_assert!(mut_frames.is_empty()); + mut_frames.push(Frame { + ops: &pat.protos[0], + iar: None, + matches: true, + //path: Default::default(), + }); + drop(mut_frames); Self { pat: pat, error: Cell::from_mut(error), - //frames: vec![ - // Frame { - // ops: &pat.protos[0], - // iar: None, - // path: Vec::new(), - // } - //], + frames: frames, + //output: Cell::from_mut(output), } } } -// -//impl<'a, 'b, T: PatternTypes> Frame<'a, 'b, T> { -// /// Advances the instruction address register. -// /// -// /// # Returns -// /// -// /// `true` if successful, `false` otherwise. -// fn next(&mut self) -> bool { -// let new = self.iar.map_or(0, |v| v + 1); -// new < self.ops.len() && { -// self.iar = Some(new); -// true -// } -// } -// -// /// Returns the current instruction. -// fn op(&self) -> PatternElement { -// self.ops[self.iar.expect("ops[iar]")] -// } -// -// /// Rewinds the instruction address register. -// /// -// /// # Returns -// /// -// /// `true` if successful, `false` otherwise. -// fn prev(&mut self) -> bool { -// let new = self.iar.expect("iar").checked_sub(1); -// new.is_some() && { -// self.iar = new; -// true -// } -// } -//} -// + +impl<'pat> Frame<'pat> { + /// Gets the type currently associated with this frame. + /// + /// Returns the type and whether it is required to match. + fn get_type<O: Serialize>( + &self, + pat: &'pat PatternConstants<O>, + ) -> Option<(Type, bool)> { + match self.op() { + | PatternElement::Value { name_and_value, .. } + | PatternElement::Tag { name_and_value, .. } + if name_and_value.is_there() + => { + match name_and_value.there() { + | Some(Value::String { skippable, .. }) + | Some(Value::Regex { skippable, .. }) + => { + Some((Type::Str, !skippable)) + }, + Some(Value::Type { ty, skippable }) => { + Some((ty, !skippable)) + }, + None => todo!(), + } + }, + _ => None, + } + } + + /// Gets the name currently associated with this frame. + fn get_name<O: Serialize>( + &self, + pat: &'pat PatternConstants<O>, + ) -> Option<&'pat str> { + let strings = &pat.strings; + match self.op() { + | PatternElement::Value { name_and_value, .. } + | PatternElement::Tag { name_and_value, .. } + if name_and_value.is_here() + => { + Some(&*strings[name_and_value.here().unwrap()]) + }, + _ => None, + } + } + + /// Advances the instruction address register. + /// + /// # Returns + /// + /// `true` if successful, `false` otherwise. + fn next(&mut self) -> bool { + let new = self.iar.map_or(0, |v| v + 1); + new < self.ops.len() && { + self.iar = Some(new); + true + } + } + + /// Returns the current instruction. + /// + /// # Panics + /// + /// Panics if called on a non-matching frame or if iteration hasn't begun. + fn op(&self) -> PatternElement { + assert!(self.matches, "op() called on non-matching frame"); + self.ops[self.iar.expect("ops[iar]")] + } + + /// Rewinds the instruction address register. + /// + /// # Returns + /// + /// `true` if successful, `false` otherwise. + fn prev(&mut self) -> bool { + let new = self.iar.expect("iar").checked_sub(1); + new.is_some() && { + self.iar = new; + true + } + } +} + ///// Stores a single match. ///// ///// See also Holder. |