github.com/google/skylark@v0.0.0-20181101142754-a5f7082aabed/testdata/list.sky (about)

     1  # Tests of Skylark 'list'
     2  
     3  load("assert.sky", "assert", "freeze")
     4  
     5  # literals
     6  assert.eq([], [])
     7  assert.eq([1], [1])
     8  assert.eq([1,], [1])
     9  assert.eq([1, 2], [1, 2])
    10  assert.ne([1, 2, 3], [1, 2, 4])
    11  
    12  # truth
    13  assert.true([0])
    14  assert.true(not [])
    15  
    16  # indexing, x[i]
    17  abc = list("abc".elems())
    18  assert.fails(lambda: abc[-4], "list index -1 out of range \\[0:3\\]")
    19  assert.eq(abc[-3], "a")
    20  assert.eq(abc[-2], "b")
    21  assert.eq(abc[-1], "c")
    22  assert.eq(abc[0], "a")
    23  assert.eq(abc[1], "b")
    24  assert.eq(abc[2], "c")
    25  assert.fails(lambda: abc[3], "list index 3 out of range \\[0:3\\]")
    26  
    27  # x[i] = ...
    28  x3 = [0, 1, 2]
    29  x3[1] = 2
    30  x3[2] += 3
    31  assert.eq(x3, [0, 2, 5])
    32  def f2(): x3[3] = 4
    33  assert.fails(f2, "out of range")
    34  freeze(x3)
    35  def f3(): x3[0] = 0
    36  assert.fails(f3, "cannot assign to element of frozen list")
    37  assert.fails(x3.clear, "cannot clear frozen list")
    38  
    39  # list + list
    40  assert.eq([1, 2, 3] + [3, 4, 5], [1, 2, 3, 3, 4, 5])
    41  assert.fails(lambda: [1, 2] + (3, 4), "unknown.*list \+ tuple")
    42  assert.fails(lambda: (1, 2) + [3, 4], "unknown.*tuple \+ list")
    43  
    44  # list * int,  int * list
    45  assert.eq(abc * 0, [])
    46  assert.eq(abc * -1, [])
    47  assert.eq(abc * 1, abc)
    48  assert.eq(abc * 3, ["a", "b", "c", "a", "b", "c", "a", "b", "c"])
    49  assert.eq(0 * abc, [])
    50  assert.eq(-1 * abc, [])
    51  assert.eq(1 * abc, abc)
    52  assert.eq(3 * abc, ["a", "b", "c", "a", "b", "c", "a", "b", "c"])
    53  
    54  # list comprehensions
    55  assert.eq([2 * x for x in [1, 2, 3]], [2, 4, 6])
    56  assert.eq([2 * x for x in [1, 2, 3] if x > 1], [4, 6])
    57  assert.eq([(x, y) for x in [1, 2] for y in [3, 4]],
    58            [(1, 3), (1, 4), (2, 3), (2, 4)])
    59  assert.eq([(x, y) for x in [1, 2] if x == 2 for y in [3, 4]],[(2, 3), (2, 4)])
    60  assert.eq([2 * x for x in (1, 2, 3)], [2, 4, 6])
    61  assert.eq([x for x in "abc".elems()], ["a", "b", "c"])
    62  assert.eq([x for x in {"a": 1, "b": 2}], ["a", "b"])
    63  assert.eq([(y, x) for x, y in {1: 2, 3: 4}.items()], [(2, 1), (4, 3)])
    64  # corner cases of parsing:
    65  assert.eq([x for x in range(12) if x%2 == 0 if x%3 == 0], [0, 6])
    66  assert.eq([x for x in [1, 2] if lambda: None], [1, 2])
    67  assert.eq([x for x in [1, 2] if (lambda: 3 if True else 4)], [1, 2])
    68  
    69  # list function
    70  assert.eq(list(), [])
    71  assert.eq(list("ab".elems()), ["a", "b"])
    72  
    73  # A list comprehension defines a separate lexical block,
    74  # whether at top-level...
    75  a = [1, 2]
    76  b = [a for a in [3, 4]]
    77  assert.eq(a, [1, 2])
    78  assert.eq(b, [3, 4])
    79  # ...or local to a function.
    80  def listcompblock():
    81    c = [1, 2]
    82    d = [c for c in [3, 4]]
    83    assert.eq(c, [1, 2])
    84    assert.eq(d, [3, 4])
    85  listcompblock()
    86  
    87  # list.pop
    88  x4 = [1,2,3,4,5]
    89  assert.eq(x4.pop(), 5)
    90  assert.eq(x4, [1,2,3,4])
    91  assert.eq(x4.pop(1), 2)
    92  assert.eq(x4, [1,3,4])
    93  assert.eq(x4.pop(0), 1)
    94  assert.eq(x4, [3,4])
    95  
    96  # TODO(adonovan): test uses of list as sequence
    97  # (for loop, comprehension, library functions).
    98  
    99  # x += y for lists is equivalent to x.extend(y).
   100  # y may be a sequence.
   101  # TODO: Test that side-effects of 'x' occur only once.
   102  def list_extend():
   103    a = [1, 2, 3]
   104    b = a
   105    a = a + [4] # creates a new list
   106    assert.eq(a, [1, 2, 3, 4])
   107    assert.eq(b, [1, 2, 3]) # b is unchanged
   108  
   109    a = [1, 2, 3]
   110    b = a
   111    a += [4] # updates a (and thus b) in place
   112    assert.eq(a, [1, 2, 3, 4])
   113    assert.eq(b, [1, 2, 3, 4]) # alias observes the change
   114  
   115    a = [1, 2, 3]
   116    b = a
   117    a.extend([4]) # updates existing list
   118    assert.eq(a, [1, 2, 3, 4])
   119    assert.eq(b, [1, 2, 3, 4]) # alias observes the change
   120  list_extend()
   121  
   122  # Unlike list.extend(iterable), list += iterable makes its LHS name local.
   123  a_list = []
   124  def f4():
   125    a_list += [1] # binding use => a_list is a local var
   126  assert.fails(f4, "local variable a_list referenced before assignment")
   127  
   128  # list += <not iterable>
   129  def f5():
   130    x = []
   131    x += 1
   132  assert.fails(f5, "unknown binary op: list \\+ int")
   133  
   134  # frozen list += iterable
   135  def f6():
   136    x = []
   137    freeze(x)
   138    x += [1]
   139  assert.fails(f6, "cannot apply \\+= to frozen list")
   140  
   141  # list += hasfields (hasfields is not iterable but defines list+hasfields)
   142  def f7():
   143    x = []
   144    x += hasfields()
   145    return x
   146  assert.eq(f7(), 42) # weird, but exercises a corner case in list+=x.
   147  
   148  # append
   149  x5 = [1, 2, 3]
   150  x5.append(4)
   151  x5.append("abc")
   152  assert.eq(x5, [1, 2, 3, 4, "abc"])
   153  
   154  # extend
   155  x5a = [1, 2, 3]
   156  x5a.extend("abc".elems()) # string
   157  x5a.extend((True, False))       # tuple
   158  assert.eq(x5a, [1, 2, 3, "a", "b", "c", True, False])
   159  
   160  # list.insert
   161  def insert_at(index):
   162    x = list(range(3))
   163    x.insert(index, 42)
   164    return x
   165  assert.eq(insert_at(-99), [42, 0, 1, 2])
   166  assert.eq(insert_at(-2), [0, 42, 1, 2])
   167  assert.eq(insert_at(-1), [0, 1, 42, 2])
   168  assert.eq(insert_at( 0), [42, 0, 1, 2])
   169  assert.eq(insert_at( 1), [0, 42, 1, 2])
   170  assert.eq(insert_at( 2), [0, 1, 42, 2])
   171  assert.eq(insert_at( 3), [0, 1, 2, 42])
   172  assert.eq(insert_at( 4), [0, 1, 2, 42])
   173  
   174  # list.remove
   175  def remove(v):
   176    x = [3, 1, 4, 1]
   177    x.remove(v)
   178    return x
   179  assert.eq(remove(3), [1, 4, 1])
   180  assert.eq(remove(1), [3, 4, 1])
   181  assert.eq(remove(4), [3, 1, 1])
   182  assert.fails(lambda: [3, 1, 4, 1].remove(42), "remove: element not found")
   183  
   184  # list.index
   185  bananas = list("bananas".elems())
   186  assert.eq(bananas.index('a'), 1) # bAnanas
   187  assert.fails(lambda: bananas.index('d'), "value not in list")
   188  # start
   189  assert.eq(bananas.index('a', -1000), 1) # bAnanas
   190  assert.eq(bananas.index('a', 0), 1)     # bAnanas
   191  assert.eq(bananas.index('a', 1), 1)     # bAnanas
   192  assert.eq(bananas.index('a', 2), 3)     # banAnas
   193  assert.eq(bananas.index('a', 3), 3)     # banAnas
   194  assert.eq(bananas.index('b', 0), 0)     # Bananas
   195  assert.eq(bananas.index('n', -3), 4)    # banaNas
   196  assert.fails(lambda: bananas.index('n', -2), "value not in list")
   197  assert.eq(bananas.index('s', -2), 6)    # bananaS
   198  assert.fails(lambda: bananas.index('b', 1), "value not in list")
   199  # start, end
   200  assert.eq(bananas.index('s', -1000, 7), 6) # bananaS
   201  assert.fails(lambda: bananas.index('s', -1000, 6), "value not in list")
   202  assert.fails(lambda: bananas.index('d', -1000, 1000), "value not in list")
   203  
   204  # slicing, x[i:j:k]
   205  assert.eq(bananas[6::-2], list("snnb".elems()))
   206  assert.eq(bananas[5::-2], list("aaa".elems()))
   207  assert.eq(bananas[4::-2], list("nnb".elems()))
   208  assert.eq(bananas[99::-2], list("snnb".elems()))
   209  assert.eq(bananas[100::-2], list("snnb".elems()))
   210  # TODO(adonovan): many more tests
   211  
   212  # iterator invalidation
   213  def iterator1():
   214    list = [0, 1, 2]
   215    for x in list:
   216      list[x] = 2 * x
   217    return list
   218  assert.eq(iterator1(), [0, 2, 4]) # element updates are allowed
   219  
   220  def iterator2():
   221    list = [0, 1, 2]
   222    for x in list:
   223      list.remove(x)
   224  assert.fails(iterator2, "remove.*during iteration")
   225  
   226  def iterator3():
   227    list = [0, 1, 2]
   228    for x in list:
   229      list.append(3)
   230  assert.fails(iterator3, "append.*during iteration")
   231  
   232  def iterator4():
   233    list = [0, 1, 2]
   234    for x in list:
   235      list.extend([3, 4])
   236  assert.fails(iterator4, "extend.*during iteration")
   237  
   238  def iterator5():
   239    def f(x):
   240      x.append(4)
   241    list = [1, 2, 3]
   242    _ = [f(list) for x in list]
   243  assert.fails(iterator5, "append.*during iteration")