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")