diff options
author | SoniEx2 <endermoneymod@gmail.com> | 2022-10-16 21:52:48 -0300 |
---|---|---|
committer | SoniEx2 <endermoneymod@gmail.com> | 2022-10-16 21:52:48 -0300 |
commit | 890d10cc4fd131ee27059e3c309ea38679293ab2 (patch) | |
tree | d838c3fe07bc4e4f18273e00f10f7844b358529e /src/vm/mod.rs | |
parent | e8a11468fefd81c2d9181ca15bceaf71e09a5345 (diff) |
Finish step_in and step_out (VM core)
Diffstat (limited to 'src/vm/mod.rs')
-rw-r--r-- | src/vm/mod.rs | 66 |
1 files changed, 50 insertions, 16 deletions
diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 8122778..dca15a9 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -95,6 +95,8 @@ pub(crate) enum PatternElement { /// expected value of this entry. name_and_value: These<usize, Value>, }, + /// Marks the end of pattern iteration and the start of subtrees (if any). + SubtreeMarker, /// A value subtree is a subtree for values. /// /// It is applied *after* tags, and thus any value subtrees come last in @@ -102,10 +104,10 @@ pub(crate) enum PatternElement { ValueSubtree { /// The proto index of the subtree. index: usize, - /// Whether to allow this value subtree to produce no results. + /// Whether to allow this value subtree to match nothing. /// /// By default, a datafu pattern only matches a tree if every branch of - /// the tree produces results. This enables opting out of that. + /// the tree matches something. This enables opting out of that. optional: bool, }, } @@ -292,15 +294,16 @@ pub(crate) enum SerdeObject<'de> { } impl<'de> SerdeObject<'de> { - fn check<E: serde::de::Error>(self, ty: Option<Type>) -> Result<Self, E> { + /// Checks the type of this object. + fn check<E: serde::de::Error>(&self, ty: Option<Type>) -> Result<(), E> { let ty = match ty { - None => return Ok(self), + None => return Ok(()), Some(ty) => ty, }; match (ty, self) { | (Type::Any, v) | (Type::IgnoredAny, v) - => Ok(v), + => Ok(()), | (Type::Bool, v @ SerdeObject::Bool(_)) | (Type::I8, v @ SerdeObject::I8(_)) | (Type::I16, v @ SerdeObject::I16(_)) @@ -324,7 +327,7 @@ impl<'de> SerdeObject<'de> { | (Type::Unit, v @ SerdeObject::Unit) | (Type::Seq, v @ SerdeObject::Seq(_)) | (Type::Map, v @ SerdeObject::Map(_)) - => Ok(v), + => Ok(()), _ => todo!(), } } @@ -358,8 +361,6 @@ pub(crate) struct Interpreter<'pat, 'state, O: Serialize> { error: &'state mut Option<crate::errors::MatchError>, /// The current interpreter frames. frames: &'state mut Vec<Frame<'pat>>, - ///// The final output. - //output: &'state Cell<Pack<'pat, 'de>>, } pub(crate) struct Frame<'pat> { @@ -367,10 +368,12 @@ pub(crate) struct Frame<'pat> { ops: &'pat [PatternElement], /// The instruction index being processed. iar: Option<usize>, - /// How many steps this frame has failed to match. - overstep: Option<usize>, - ///// Elements collected while processing this frame? - //path: Pack<'pat, 'de>, + /// How many steps this frame has not actually advanced for. + /// + /// This is used at end of frame and on match failure. + overstep: usize, + /// Whether this frame matches the data so far. + matches: bool, } impl<'pat, 'state, O: Serialize> Interpreter<'pat, 'state, O> { @@ -384,7 +387,8 @@ impl<'pat, 'state, O: Serialize> Interpreter<'pat, 'state, O> { frames.push(Frame { ops: &pat.protos[0], iar: None, - overstep: None, + overstep: 0, + matches: true, //path: Default::default(), }); Self { @@ -461,12 +465,42 @@ impl<'pat> Frame<'pat> { /// /// 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"); + assert!(self.active(), "op() called on inactive frame"); + self.ops[self.iar.expect("ops[iar]")] + } + + /// Counts the number of *active* subtrees, if any. + /// + /// # Panics + /// + /// Panics if iteration hasn't begun. + fn num_subtrees(&self) -> Option<usize> { + let iar = self.iar.expect("iar"); + // check if there are any subtrees + matches!( + self.ops[iar], + | PatternElement::ValueSubtree { .. } + | PatternElement::SubtreeMarker + ).then(|| { + // count the number of subtrees + self.ops[0..=iar].iter().rev().take_while(|x| { + matches!(x, PatternElement::ValueSubtree { .. }) + }).count() + }) + } + + /// Returns the raw instruction. + /// + /// # Panics + /// + /// Panics if iteration hasn't begun. + fn raw_op(&self) -> PatternElement { self.ops[self.iar.expect("ops[iar]")] } - fn matches(&self) -> bool { - self.overstep.is_none() + /// Returns whether this frame is active (not overstepped). + fn active(&self) -> bool { + self.overstep == 0 } /// Rewinds the instruction address register. |