summary refs log tree commit diff stats
path: root/abdl/_vm.py
diff options
context:
space:
mode:
authorSoniEx2 <endermoneymod@gmail.com>2020-04-17 14:25:21 -0300
committerSoniEx2 <endermoneymod@gmail.com>2020-04-17 14:26:01 -0300
commitb259b179f5ceba60a1d04fef07559c0b01720c31 (patch)
treea0315c67fddc7919e6d6892e8d1eb15f328057a6 /abdl/_vm.py
parent3f9f66712aaa071bd3bb32c46e1e4dc1fed13378 (diff)
Fix bugs with empty and predicate-only matches
Also clarified the behaviour of empty matches, which match anything,
but only once. This behaviour is required for consistency with the
rest of the matching rules.
Diffstat (limited to 'abdl/_vm.py')
-rw-r--r--abdl/_vm.py16
1 files changed, 12 insertions, 4 deletions
diff --git a/abdl/_vm.py b/abdl/_vm.py
index 5ab7efb..2f76586 100644
--- a/abdl/_vm.py
+++ b/abdl/_vm.py
@@ -255,7 +255,15 @@ class ApplyPredicate(PatternElement):
 
     def on_end(self, frame, path, defs, in_key):
         assert not in_key
-        raise NotImplementedError
+        res = {}
+        for holder in path:
+            if holder.subtree:
+                for name, pair in holder.match.items():
+                    res[name] = pair
+            elif holder.name is not None:
+                res[holder.name] = (holder.match, holder.value)
+        path.clear()
+        return (False, res)
 
 class End(PatternElement):
     """Pseudo-token, used to advance iteration."""
@@ -282,7 +290,8 @@ class End(PatternElement):
             elif holder.name is not None:
                 res[holder.name] = (holder.match, holder.value)
         if not frame.prev():
-            return (None, res)
+            # this should never happen
+            assert False
         return (True, res)
 
     @classmethod
@@ -382,6 +391,7 @@ def match_helper(ops, defs, tree):
 
     frame = _Frame(ops)
     if not len(frame.ops): # no ops?
+        yield {}
         return # do nothing
 
     path = [Holder(value=tree, parent=None, iterator=iter(()))]
@@ -390,8 +400,6 @@ def match_helper(ops, defs, tree):
         if not frame.next():
             in_key, res = frame.current_op.on_end(frame, path, defs, in_key)
             yield res
-            if in_key is None:
-                return
         else:
             if in_key:
                 in_key = frame.current_op.on_in_key(frame, path, defs)