From 72397506c3529f4878b5a1cf8205599764ac4088 Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Sun, 13 Nov 2022 12:30:11 -0300 Subject: Finish most "core" VM functionality Still need to do lists --- src/vm/mod.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 15 deletions(-) (limited to 'src/vm/mod.rs') diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 9f76ec5..81131c0 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -75,8 +75,7 @@ impl std::fmt::Debug for PatternConstants { } } -/// A pattern element. -// FIXME: docs +/// A datafu pattern element. #[derive(Copy, Clone, Debug)] pub(crate) enum PatternElement { /// A value is the core capturing element. @@ -87,9 +86,19 @@ pub(crate) enum PatternElement { value: Option, }, /// A tag is the core iterative element. It is always followed by a value. + /// + /// This one is empty. + EmptyTag, + /// A tag is the core iterative element. It is always followed by a value. Tag { /// The index of the (proto) key to match against. - key_subtree: Option, + key_subtree: usize, + /// Whether to allow this tree subtree to match nothing. + /// + /// By default, a datafu pattern only matches a tree if every branch of + /// the tree matches something. This enables opting out of that. + // TODO this isn't currently implemented. + optional: bool, }, /// Marks the end of pattern iteration and the start of subtrees (if any). SubtreeMarker, @@ -163,6 +172,7 @@ pub(crate) enum Value { } /// A pattern token. +// TODO docs #[derive(Copy, Clone, Debug)] pub(crate) enum PatternToken { /// Start of a tag. @@ -173,7 +183,7 @@ pub(crate) enum PatternToken { String(usize, bool), Regex(usize, bool), Parameter(usize, bool), - KeySubtree(usize), + KeySubtree(usize, bool), ValueSubtree(usize, bool), /// Represents a predicate which must be applied. @@ -409,6 +419,8 @@ pub(crate) struct Frame<'pat> { overstep: usize, /// Whether this frame matches the data so far. matches: bool, + /// Whether this frame must not be allowed to match in the key step. + poison: bool, } impl<'pat, 'state, O: Serialize> Interpreter<'pat, 'state, O> { @@ -416,7 +428,6 @@ impl<'pat, 'state, O: Serialize> Interpreter<'pat, 'state, O> { pat: &'pat PatternConstants, error: &'state mut Option, frames: &'state mut Vec>, - //output: &'state mut Pack<'pat, 'de>, ) -> Self { debug_assert!(frames.is_empty()); frames.push(Frame { @@ -424,13 +435,12 @@ impl<'pat, 'state, O: Serialize> Interpreter<'pat, 'state, O> { iar: None, overstep: 0, matches: true, - //path: Default::default(), + poison: false, }); Self { pat: pat, error: error, frames: frames, - //output: Cell::from_mut(output), } } } @@ -455,7 +465,9 @@ impl<'pat> Frame<'pat> { }, } }, - PatternElement::Tag { .. } => panic!("attempt to get type of tag"), + | PatternElement::EmptyTag + | PatternElement::Tag { .. } + => panic!("attempt to get type of tag"), _ => None, } } @@ -470,7 +482,9 @@ impl<'pat> Frame<'pat> { PatternElement::Value { name: Some(name), .. } => { Some(&*strings[name]) }, - PatternElement::Tag { .. } => panic!("attempt to get name of tag"), + | PatternElement::EmptyTag + | PatternElement::Tag { .. } + => panic!("attempt to get name of tag"), _ => None, } } @@ -522,19 +536,35 @@ impl<'pat> Frame<'pat> { }) } - /// Returns whether this key has a subtree. + /// Returns whether this key has a subtree, and if so, its index and + /// whether it is optional, as an `(index, optional)` pair. /// /// # Panics /// /// Panics if iteration hasn't begun, or this isn't a key. - fn key_subtree(&self) -> Option { - if let PatternElement::Tag { key_subtree } = self.op() { - key_subtree - } else { - unreachable!() + fn key_subtree(&self) -> Option<(usize, bool)> { + match self.op() { + PatternElement::Tag { key_subtree, optional } => { + Some((key_subtree, optional)) + }, + PatternElement::EmptyTag => None, + _ => unreachable!(), } } + /// Returns whether this frame is in a value operation. + /// + /// # Panics + /// + /// Panics if the frame isn't active or iteraction hasn't begun. + #[inline] + fn is_value(&self) -> bool { + self.active() && matches!( + self.raw_op(), + PatternElement::Value { .. }, + ) + } + /// Returns this value subtree, as an `(index, optional)` pair. /// /// # Panics @@ -561,6 +591,7 @@ impl<'pat> Frame<'pat> { } /// Returns whether this frame is active (not overstepped). + #[inline] fn active(&self) -> bool { self.overstep == 0 } -- cgit 1.4.1