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/de.rs | 187 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 119 insertions(+), 68 deletions(-) (limited to 'src/vm/de.rs') diff --git a/src/vm/de.rs b/src/vm/de.rs index 3290ab0..9583962 100644 --- a/src/vm/de.rs +++ b/src/vm/de.rs @@ -52,47 +52,9 @@ impl<'packer, 'pat> FramesMut<'packer, 'pat> { fn iter_active_mut<'a>(&'a mut self) -> impl Iterator> where 'packer: 'a { self.iter_mut().filter(|frame| { - frame.matches() + frame.active() }) } - - /// Steps the VM into the next operation. - fn step_in(&mut self) { - self.iter_mut().for_each(|frame| { - if let Some(ref mut overstep) = frame.overstep { - *overstep += 1; - } else { - if !frame.next() { - frame.overstep = Some(1); - } else if matches!( - frame.op(), - PatternElement::ValueSubtree { .. }, - ) { - todo!() - } - } - }); - } - - fn step_out<'de>(&mut self, pack: Pack<'pat, 'de>) -> Pack<'pat, 'de> { - self.iter_mut().for_each(|frame| { - if let Some(ref mut overstep) = frame.overstep { - if *overstep > 0 { - *overstep -= 1; - } - } else { - if let Some(0) = frame.overstep { - frame.overstep = None; - } - if frame.overstep.is_none() { - if frame.prev() { - todo!(); - } - } - } - }); - pack - } } impl<'packer, 'pat> Frames<'packer, 'pat> { @@ -102,7 +64,7 @@ impl<'packer, 'pat> Frames<'packer, 'pat> { fn iter_active<'a>(&'a self) -> impl Iterator> where 'packer: 'a { self.iter().filter(|frame| { - frame.matches() + frame.active() }) } } @@ -131,33 +93,118 @@ impl<'pat, 'state, 'de, O: Serialize> Packer<'pat, 'state, O> { frames: &*self.interp.frames, } } -} -// what steps do we have to take? -// -// 1. figure out what type we need to deserialize (and ask the deserializer -// for it). -// 2. visit value. figure out whether we need to store it or not? -// 3. if we need to store it how do we figure out *where* to store it? -// 4. if we *don't* need to store it, what do we do? -// 5. how do we tell if we do or don't need to store it? how do we propagate -// those requirements deeper into the Deserialize's and how do we bring -// the values back out (recursively?) to parent Deserialize's, without -// wasting time storing things we don't actually care about? -// 5.a. just have a flag in the DeserializeSeed for whether to capture the -// values. propagation is more or less trivial from there. -// 6. how do you handle value subtrees? -// 6.a. you don't. for now. -// 7. how do you handle errors? -// 7.a. put them into a "state" and raise a D::Error::custom. then -// override it in the relevant Pattern call. + /// Steps the VM into the next operation. + fn step_in(&mut self) { + // iterate up to the *live* length (i.e. the loop is allowed to modify + // the length). + // NOTE: we need to use while-let so as to not borrow anything in an + // iterator. filtering happens on the *result* of the iterator. + let mut index_iter = 0..; + while let Some(index) = index_iter.next().filter(|&i| { + i < self.interp.frames.len() + }) { + let frame = &mut self.interp.frames[index]; + if frame.overstep > 0 || !frame.matches { + // overstepped and non-matching frames + frame.overstep += 1; + } else { + if !frame.next() { + // empty/end-of frames + // 1 layer of step-in. + // step-out will undo this. + // this is correct because this branch implies overstep = 0 + frame.overstep = 1; + } else if matches!( + frame.op(), + PatternElement::SubtreeMarker, + ) { + // subtrees! + // these are tricky, because the current frame can be moved + // in memory. so we have to use indexing every time. + // tho first we set it as overstep because it has special + // handling. + frame.overstep = 1; + let mut at = index + 1; + while self.interp.frames[index].next() { + let op = self.interp.frames[index].op(); + if let PatternElement::ValueSubtree { + index: subtree, .. + } = op { + let new_frame = Frame { + ops: &self.interp.pat.protos[subtree][..], + iar: None, + overstep: 0, + matches: true, + }; + // we want the "newest" frame last, so it is + // easier to unwind back. + self.interp.frames.insert(at, new_frame); + at += 1; + } else { + unreachable!() + } + } + } + } + } + } + + /// Steps the VM back into the previous operation. + fn step_out( + &mut self, + mut packs: Vec>, + ) -> Vec> { + let mut index_iter = 0..; + while let Some(index) = index_iter.next().filter(|&i| { + i < self.interp.frames.len() + }) { + // iterate backwards + let index = self.interp.frames.len() - index - 1; + let frame = &mut self.interp.frames[index]; + if frame.overstep > 0 { + // handle overstep + frame.overstep -= 1; + } else { + // unwind frame + if frame.prev() { + // successfully unwound. do nothing. + } else { + // find parent frame. + let mut count = 1; + let mut target = index; + while count > 0 && target > 0 { + target -= 1; + match self.interp.frames[target].num_subtrees() { + Some(num) if num <= count => { + count -= num; + }, + Some(num) => { + count = 0; + }, + None => { + count += 1; + }, + } + } + if count == 0 { + // has parent frame + let pack = packs.remove(index); + todo!("merge packs") + } + } + } + } + packs + } +} impl<'pat, 'state, 'de, O> serde::de::DeserializeSeed<'de> for &mut Packer<'pat, 'state, O> where O: Serialize, { - type Value = (Pack<'pat, 'de>, Option>); + type Value = (Vec>, Option>); fn deserialize( mut self, deserializer: D, @@ -165,7 +212,7 @@ where where D: serde::Deserializer<'de> { - self.frames_mut().step_in(); + self.step_in(); let pat = self.interp.pat; let target_type = self.frames().iter_active().fold( Type::IgnoredAny, @@ -248,7 +295,7 @@ where Type::Enum { name, variants } => { deserializer.deserialize_enum(name, variants, &mut *self) }, - }.map(|(pack, obj)| (self.frames_mut().step_out(pack), obj)) + }.map(|(packs, obj)| (self.step_out(packs), obj)) } } @@ -265,16 +312,18 @@ macro_rules! vs { if self.collecting { obj = Some(SerdeObject::$obj(v)); } - let mut pack = Pack::default(); + let mut packs = Vec::new(); self.frames_mut().iter_active_mut().try_for_each(|frame| { + let mut pack = Pack::default(); let mut map = IndexMap::new(); if let Some(name) = frame.get_name(pat) { map.insert(name, (Pack::default(), SerdeObject::$obj(v))); } pack.subpacks.push(map); + packs.push(pack); Ok(()) })?; - Ok((pack, obj)) + Ok((packs, obj)) } } } @@ -284,7 +333,7 @@ for &mut Packer<'pat, 'state, O> where O: Serialize, { - type Value = (Pack<'pat, 'de>, Option>); + type Value = (Vec>, Option>); fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "unsure") } @@ -390,6 +439,7 @@ where { // FIXME subtrees let mut obj = None; + let mut packs = Vec::new(); let mut pack = Pack::default(); if self.collecting { obj = Some(SerdeObject::Unit); @@ -399,7 +449,8 @@ where // map.insert(name, (Default::default(), SerdeObject::Unit)); //} pack.subpacks.push(map); - Ok((pack, obj)) + packs.push(pack); + Ok((packs, obj)) } fn visit_newtype_struct( self, @@ -633,9 +684,9 @@ mod tests { let mut frames = Default::default(); let interp = Interpreter::new(&consts, &mut err, &mut frames); let packed = Packer::new(interp, MAX_CALLS).deserialize(&mut der); - let (pack, obj) = packed.unwrap(); + let (packs, obj) = packed.unwrap(); assert!(obj.is_none()); - assert_eq!(pack.subpacks[0]["hello"].1, SerdeObject::U64(3)); + assert_eq!(packs[0].subpacks[0]["hello"].1, SerdeObject::U64(3)); } } -- cgit 1.4.1