Commits

Lucian Brănescu-Mihăilă committed 0e22796

Deque as list.

Comments (0)

Files changed (4)

-import pdb
 import operator
+from itertools import islice
 
 from lsp.types import *
 
 
 
 def slice_list(coll, start, end, step=1):
-    return List(coll[start:end:step])
+    return List(islice(coll, start, end, step))
 
 
 def is_empty(coll):
 
             self.rest_arg = self.args[i + 1]
             if not isinstance(self.rest_arg, Symbol):
-                raise SyntaxError("Expected symbol as rest argument, got: {0}" \
+                raise SyntaxError("Expected symbol as rest argument, got: {0}"\
                     .format(self.rest_arg))
 
             self.args = self.args[:i]
     def __call__(self, *args):
         if self.rest_arg is not None:
             if len(args) < len(self.args):
-                raise RuntimeError("Expected at least {0} args, got {1}: {2}" \
+                raise RuntimeError("Expected at least {0} args, got {1}: {2}"\
                     .format(len(self.args), len(args), args))
 
         elif len(args) != len(self.args):
 
             self.rest_arg = self.args[i + 1]
             if not isinstance(self.rest_arg, Symbol):
-                raise SyntaxError("Expected symbol as rest argument, got: {0}" \
+                raise SyntaxError("Expected symbol as rest argument, got: {0}"\
                     .format(self.rest_arg))
 
             self.args = List(self.args[:i])
     def __call__(self, args, env):
         if self.rest_arg is not None:
             if len(args) < len(self.args):
-                raise RuntimeError("Expected at least {0} args, got {1}: {2}" \
+                raise RuntimeError("Expected at least {0} args, got {1}: {2}"\
                     .format(len(self.args), len(args), args))
 
         elif len(args) != len(self.args):
 
 def call_method(body, env):
     if len(body) < 2:
-        raise SyntaxError("method call expects at least 2 parts, got: {0}" \
+        raise SyntaxError("method call expects at least 2 parts, got: {0}"\
             .format(len(body)))
 
     obj = body[0]
             return List(l)
 
     return sexp
-
-
-from lsp.env import top
 from fractions import Fraction
+from collections import deque
+from itertools import izip, islice, chain
 
 
 class Atom(object):
         "Even empty collections are truthy"
         return True
 
-    __bool__ = __nonzero__
-
     def __call__(self, index):
         return self[index]
 
+    def __eq__(self, other):
+        for this, that in izip(iter(self), iter(other)):
+            if this != that:
+                return False
 
-class List(list, Collection):
+        return True
+
+
+class List(deque, Collection):
     start = '('
     stop = ')'
 
     def __repr__(self):
         return '(' + ' '.join(map(str, self)) + ')'
 
+    def __getitem__(self, key):
+        if isinstance(key, slice):
+            return List(islice(self, key.start, key.stop, key.step))
+
+        return super(List, self).__getitem__(key)
+
+    def index(self, value):
+        for i, e in enumerate(self):
+            if e == value:
+                return i
+
+        return -1
+
+    def __add__(self, other):
+        return List(chain(self, other))
+
 
 class Vector(list, Collection):
     start = '['
 
 
 def test_parse_list():
-    assert parse(['(', '1', '2', ')']) == [1, 2]
+    assert parse(['(', '1', '2', ')']) == List([1, 2])
 
-    assert parse(['(', '1', '(', '2', '3', ')', ')']) == [1, [2, 3]]
-    assert parse(['(', '(', '1', '2', ')', '3', ')']) == [[1, 2], 3]
-    assert parse(['(', '1', '(', '2', ')', '3', ')']) == [1, [2], 3]
-    assert parse(['(', '(', '1', ')', '(', '2', ')', ')']) == [[1], [2]]
+    assert parse(['(', '1', '(', '2', '3', ')', ')']) == \
+        List([1, List([2, 3])])
+    assert parse(['(', '(', '1', '2', ')', '3', ')']) == \
+        List([List([1, 2]), 3])
+    assert parse(['(', '1', '(', '2', ')', '3', ')']) == \
+        List([1, List([2]), 3])
+    assert parse(['(', '(', '1', ')', '(', '2', ')', ')']) == \
+        List([List([1]), List([2])])
 
 
 def test_parse_vector():
 
 
 def test_read_func():
-    assert read('(+ 1 2)') == ['+', 1, 2]
-    assert read('(fn (x) (+ x 1))') == ['fn', ['x'], ['+', 'x', 1]]
+    assert read('(+ 1 2)') == List(['+', 1, 2])
+    assert read('(fn (x) (+ x 1))') == \
+        List(['fn', List(['x']), List(['+', 'x', 1])])
 
 
 def test_repr():
     assert lsp('((fn (x) x) 1)') == 1
     assert lsp('((fn (x) (+ x 1)) 1)') == 2
 
-    assert read('(fn (x & xs) xs)') == ['fn', ['x', '&', 'xs'], 'xs']
-    assert lsp('((fn (x & xs) xs) 1 2 3 4)') == [2, 3, 4]
+    assert read('(fn (x & xs) xs)') == \
+        List(['fn', List(['x', '&', 'xs']), 'xs'])
+    assert lsp('((fn (x & xs) xs) 1 2 3 4)') == List([2, 3, 4])
 
 
 def test_defn():
 
 
 def test_quote():
-    assert lsp('(quote (+))') == ['+']
-    assert lsp("'(+)") == ['+']
+    assert lsp('(quote (+))') == List(['+'])
+    assert lsp("'(+)") == List(['+'])
 
-    assert lsp('(quote (1 2))') == [1, 2]
-    assert lsp("'(1 2)") == [1, 2]
+    assert lsp('(quote (1 2))') == List([1, 2])
+    assert lsp("'(1 2)") == List([1, 2])
 
-    assert lsp("'((1 2))") == [[1, 2]]
-    assert lsp("'((1 2) (1 2))") == [[1, 2], [1, 2]]
+    assert lsp("'((1 2))") == List([List([1, 2])])
+    assert lsp("'((1 2) (1 2))") == List([List([1, 2]), List([1, 2])])
 
 
 def test_quasiquote():
     assert lsp('({0} 5)'.format(fact)) == 120
 
 
-def test_list_slicing():
-    assert lsp("('(1 2 3) 0)") == 1
-    assert lsp("(first '(1 2 3))") == 1
-    assert lsp("(rest '(1 2 3))") == [2, 3]
-
-
 def test_call_method():
     assert lsp("(. 1 __str__)") == "1"
     assert lsp("(. 1 __add__ 2)") == 3
 
 
 # Prelude
+def test_list_slicing():
+    assert lsp("('(1 2 3) 0)") == 1
+    assert lsp("(first '(1 2 3))") == 1
+    assert lsp("(rest '(1 2 3))") == List([2, 3])
+
+
 def test_reduce():
     assert lsp("(reduce + 0 '(1 2 3))") == 6
 
 
 def test_map():
-    assert lsp("(map inc '(1 2 3))") == [2, 3, 4]
+    assert lsp("(map inc '(1 2 3))") == List([2, 3, 4])
 
 
 def test_let():
 
 
 def test_filter():
-    assert lsp("(filter (fn (x) (> x 2)) '(1 2 3 4))") == [3, 4]
+    assert lsp("(filter (fn (x) (> x 2)) '(1 2 3 4))") == List([3, 4])
 
 
 def test_comp():
 
 
 def test_range():
-    assert lsp("(range 1 5)") == [1, 2, 3, 4]
-    assert lsp("(range 1 5 2)") == [1, 3]
+    assert lsp("(range 1 5)") == List([1, 2, 3, 4])
+    assert lsp("(range 1 5 2)") == List([1, 3])