If: Conditional actions.
[python-bulletml.git] / bulletml / parser.py
index 653b90f..2075ac9 100644 (file)
@@ -377,6 +377,58 @@ class Repeat(object):
     def __repr__(self):
         return "%s(%r, %r)" % (type(self).__name__, self.times, self.action)
 
+class If(object):
+    """Conditional actions."""
+
+    def __init__(self, cond, then, else_=None):
+        self.cond = cond
+        self.then = then
+        self.else_ = else_
+
+    def __getstate__(self):
+        if self.else_:
+            return [('cond', self.cond.expr),
+                    ('then', self.then),
+                    ('else', self.else_)]
+        else:
+            return [('cond', self.cond.expr), ('then', self.then)]
+
+    def __setstate__(self, state):
+        state = dict(state)
+        state["else_"] = state.pop("else", None)
+        state["cond"] = INumberDef(state["cond"])
+        self.__init__(**state)
+
+    @classmethod
+    def FromXML(cls, doc, element):
+        """Construct using an ElementTree-style element."""
+        else_ = None
+        for subelem in element.getchildren():
+            tag = realtag(subelem)
+            if tag == "cond":
+                cond = INumberDef(subelem.text)
+            elif tag == "then":
+                then = ActionDef.FromXML(doc, subelem)
+            elif tag == "else":
+                else_ = ActionDef.FromXML(doc, subelem)
+        try:
+            return cls(cond, then, else_)
+        except UnboundLocalError as exc:
+            raise ParseError(str(exc))
+
+    def __call__(self, owner, action, params, rank, created):
+        if self.cond(params, rank):
+            branch = self.then
+        else:
+            branch = self.else_
+
+        if branch:
+            actions, params = branch(params, rank)
+            child = action.__class__(owner, action, actions, params, rank)
+            owner.replace(action, child)
+            child.step(owner, created)
+            return True
+        
 class Accel(object):
     """Accelerate over some time."""
 
@@ -976,3 +1028,4 @@ ActionDef.CONSTRUCTORS = dict(
     untag=Untag,
     action=ActionDef,
     actionRef=ActionRef)
+ActionDef.CONSTRUCTORS["if"] = If