Jelajahi Sumber

Scope removing/replacing is now done using numeric indices instead of node references.

Taddeus Kroes 13 tahun lalu
induk
melakukan
91a264526c
3 mengubah file dengan 39 tambahan dan 34 penghapusan
  1. 14 6
      src/node.py
  2. 12 11
      tests/test_rules_factors.py
  3. 13 17
      tests/test_rules_numerics.py

+ 14 - 6
src/node.py

@@ -556,6 +556,9 @@ class Scope(object):
         self.node = node
         self.nodes = get_scope(node)
 
+        for i, n in enumerate(self.nodes):
+            n.scope_index = i
+
     def __getitem__(self, key):
         return self.nodes[key]
 
@@ -576,17 +579,22 @@ class Scope(object):
         return '<Scope of "%s">' % repr(self.node)
 
     def index(self, node):
-        return self.nodes.index(node)
+        return node.scope_index
 
-    def remove(self, node, **kwargs):
+    def remove(self, node, replacement=None):
         try:
-            i = self.nodes.index(node)
+            i = node.scope_index
 
-            if 'replacement' in kwargs:
-                self[i] = kwargs['replacement']
+            if replacement:
+                self[i] = replacement
+                replacement.scope_index = i
             else:
                 del self.nodes[i]
-        except ValueError:
+
+                # Update remaining scope indices
+                for n in self[max(i, 1):]:
+                    n.scope_index -= 1
+        except AttributeError:
             raise ValueError('Node "%s" is not in the scope of "%s".'
                              % (node, self.node))
 

+ 12 - 11
tests/test_rules_factors.py

@@ -34,24 +34,25 @@ class TestRulesFactors(RulesTestCase):
                  P(root, expand_single, (Scope(root), ab, e))])
 
     def test_expand_single(self):
-        a, b, c, d = tree('a,b,c,d')
-        bc = b + c
-
-        root = a * bc
+        root, expect = tree('a(b + c), ab + ac')
+        a, bc = root
         self.assertEqualNodes(expand_single(root, (Scope(root), a, bc)),
-                              a * b + a * c)
+                              expect)
 
-        root = a * bc * d
+        root, expect = tree('a(b+c)d, a(bd + cd)')
+        (a, bc), d = root
         self.assertEqualNodes(expand_single(root, (Scope(root), bc, d)),
-                              a * (b * d + c * d))
+                              expect)
 
     def test_expand_double(self):
         (a, b), (c, d) = ab, cd = tree('a + b,c + d')
 
-        root = ab * cd
+        root, expect = tree('(a + b)(c + d), ac + ad + bc + bd')
+        ab, cd = root
         self.assertEqualNodes(expand_double(root, (Scope(root), ab, cd)),
-                              a * c + a * d + b * c + b * d)
+                              expect)
 
-        root = a * ab * b * cd * c
+        root, expect = tree('a(a + b)b(c + d)c, a(ac + ad + bc + bd)bc')
+        (((a, ab), b), cd), c = root
         self.assertEqualNodes(expand_double(root, (Scope(root), ab, cd)),
-                              a * (a * c + a * d + b * c + b * d) * b * c)
+                              expect)

+ 13 - 17
tests/test_rules_numerics.py

@@ -21,21 +21,17 @@ class TestRulesNumerics(RulesTestCase):
                 [P(root, add_numerics, (Scope(root), l1, l2))])
 
     def test_add_numerics(self):
-        l0, a, l1 = tree('1,a,2')
+        l1, l2 = root = tree('1 + 2')
+        self.assertEqual(add_numerics(root, (Scope(root), l1, l2)), 3)
 
-        root = l0 + l1
-        self.assertEqual(add_numerics(root, (Scope(root), l0, l1)), 3)
-        root = l0 + a + l1
-        self.assertEqual(add_numerics(root, (Scope(root), l0, l1)), L(3) + a)
+        (l1, a), l2 = root = tree('1 + a + 2')
+        self.assertEqual(add_numerics(root, (Scope(root), l1, l2)), L(3) + a)
 
     def test_add_numerics_negations(self):
-        l1, a, l2 = tree('1,a,2')
-        ml1, ml2 = -l1, -l2
-
-        r = ml1 + l2
-        self.assertEqual(add_numerics(r, (Scope(r), ml1, l2)), 1)
-        r = l1 + ml2
-        self.assertEqual(add_numerics(r, (Scope(r), l1, ml2)), -1)
+        ml1, l2 = root = tree('-1 + 2')
+        self.assertEqual(add_numerics(root, (Scope(root), ml1, l2)), 1)
+        l1, ml2 = root = tree('1 - 2')
+        self.assertEqual(add_numerics(root, (Scope(root), l1, ml2)), -1)
 
     def test_match_divide_numerics(self):
         a, b, i2, i3, i4, i6, f1, f2, f3 = tree('a,b,2,3,4,6,1.0,2.0,3.0')
@@ -127,16 +123,16 @@ class TestRulesNumerics(RulesTestCase):
     def test_multiply_numerics(self):
         a, b, i2, i3, i6, f2, f3, f6 = tree('a,b,2,3,6,2.0,3.0,6.0')
 
-        root = i3 * i2
+        i3, i2 = root = tree('3 * 2')
         self.assertEqual(multiply_numerics(root, (Scope(root), i3, i2)), 6)
-        root = f3 * i2
+        f3, i2 = root = tree('3.0 * 2')
         self.assertEqual(multiply_numerics(root, (Scope(root), f3, i2)), 6.0)
-        root = i3 * f2
+        i3, f2 = root = tree('3 * 2.0')
         self.assertEqual(multiply_numerics(root, (Scope(root), i3, f2)), 6.0)
-        root = f3 * f2
+        f3, f2 = root = tree('3.0 * 2.0')
         self.assertEqual(multiply_numerics(root, (Scope(root), f3, f2)), 6.0)
 
-        root = a * i3 * i2 * b
+        ((a, i3), i2), b = root = tree('a * 3 * 2 * b')
         self.assertEqualNodes(multiply_numerics(root,
                               (Scope(root), i3, i2)), a * 6 * b)