summary refs log tree commit diff stats
path: root/src/vm/de.rs
diff options
context:
space:
mode:
authorSoniEx2 <endermoneymod@gmail.com>2022-10-16 21:52:48 -0300
committerSoniEx2 <endermoneymod@gmail.com>2022-10-16 21:52:48 -0300
commit890d10cc4fd131ee27059e3c309ea38679293ab2 (patch)
treed838c3fe07bc4e4f18273e00f10f7844b358529e /src/vm/de.rs
parente8a11468fefd81c2d9181ca15bceaf71e09a5345 (diff)
Finish step_in and step_out (VM core)
Diffstat (limited to 'src/vm/de.rs')
-rw-r--r--src/vm/de.rs187
1 files changed, 119 insertions, 68 deletions
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<Item=&'a mut Frame<'pat>> 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<Item=&'a Frame<'pat>> 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<Pack<'pat, 'de>>,
+    ) -> Vec<Pack<'pat, 'de>> {
+        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<SerdeObject<'de>>);
+    type Value = (Vec<Pack<'pat, 'de>>, Option<SerdeObject<'de>>);
     fn deserialize<D>(
         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<SerdeObject<'de>>);
+    type Value = (Vec<Pack<'pat, 'de>>, Option<SerdeObject<'de>>);
     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<D>(
         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));
     }
 }