From 890d10cc4fd131ee27059e3c309ea38679293ab2 Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Sun, 16 Oct 2022 21:52:48 -0300 Subject: Finish step_in and step_out (VM core) --- src/vm/mod.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 16 deletions(-) (limited to 'src/vm/mod.rs') 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, }, + /// 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(self, ty: Option) -> Result { + /// Checks the type of this object. + fn check(&self, ty: Option) -> 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, /// The current interpreter frames. frames: &'state mut Vec>, - ///// The final output. - //output: &'state Cell>, } pub(crate) struct Frame<'pat> { @@ -367,10 +368,12 @@ pub(crate) struct Frame<'pat> { ops: &'pat [PatternElement], /// The instruction index being processed. iar: Option, - /// How many steps this frame has failed to match. - overstep: Option, - ///// 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 { + 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. -- cgit 1.4.1