summary refs log tree commit diff stats
path: root/src/vm/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/mod.rs')
-rw-r--r--src/vm/mod.rs181
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.