go.starlark.net@v0.0.0-20231101134539-556fd59b42f6/starlark/testdata/assign.star (about) 1 # Tests of Starlark assignment. 2 3 # This is a "chunked" file: each "---" effectively starts a new file. 4 5 # tuple assignment 6 load("assert.star", "assert") 7 8 () = () # empty ok 9 10 a, b, c = 1, 2, 3 11 assert.eq(a, 1) 12 assert.eq(b, 2) 13 assert.eq(c, 3) 14 15 (d, e, f,) = (1, 2, 3) # trailing comma ok 16 --- 17 (a, b, c) = 1 ### "got int in sequence assignment" 18 --- 19 (a, b) = () ### "too few values to unpack" 20 --- 21 (a, b) = (1,) ### "too few values to unpack" 22 --- 23 (a, b, c) = (1, 2) ### "too few values to unpack" 24 --- 25 (a, b) = (1, 2, 3) ### "too many values to unpack" 26 --- 27 () = 1 ### "got int in sequence assignment" 28 --- 29 () = (1,) ### "too many values to unpack" 30 --- 31 () = (1, 2) ### "too many values to unpack" 32 --- 33 # list assignment 34 load("assert.star", "assert") 35 36 [] = [] # empty ok 37 38 [a, b, c] = [1, 2, 3] 39 assert.eq(a, 1) 40 assert.eq(b, 2) 41 assert.eq(c, 3) 42 43 [d, e, f,] = [1, 2, 3] # trailing comma ok 44 --- 45 [a, b, c] = 1 ### "got int in sequence assignment" 46 --- 47 [a, b] = [] ### "too few values to unpack" 48 --- 49 [a, b] = [1] ### "too few values to unpack" 50 --- 51 [a, b, c] = [1, 2] ### "too few values to unpack" 52 --- 53 [a, b] = [1, 2, 3] ### "too many values to unpack" 54 --- 55 [] = 1 ### "got int in sequence assignment" 56 --- 57 [] = [1] ### "too many values to unpack" 58 --- 59 [] = [1, 2] ### "too many values to unpack" 60 --- 61 # list-tuple assignment 62 load("assert.star", "assert") 63 64 # empty ok 65 [] = () 66 () = [] 67 68 [a, b, c] = (1, 2, 3) 69 assert.eq(a, 1) 70 assert.eq(b, 2) 71 assert.eq(c, 3) 72 73 [a2, b2, c2] = 1, 2, 3 # bare tuple ok 74 75 (d, e, f) = [1, 2, 3] 76 assert.eq(d, 1) 77 assert.eq(e, 2) 78 assert.eq(f, 3) 79 80 [g, h, (i, j)] = (1, 2, [3, 4]) 81 assert.eq(g, 1) 82 assert.eq(h, 2) 83 assert.eq(i, 3) 84 assert.eq(j, 4) 85 86 (k, l, [m, n]) = [1, 2, (3, 4)] 87 assert.eq(k, 1) 88 assert.eq(l, 2) 89 assert.eq(m, 3) 90 assert.eq(n, 4) 91 92 --- 93 # misc assignment 94 load("assert.star", "assert") 95 96 def assignment(): 97 a = [1, 2, 3] 98 a[1] = 5 99 assert.eq(a, [1, 5, 3]) 100 a[-2] = 2 101 assert.eq(a, [1, 2, 3]) 102 assert.eq("%d %d" % (5, 7), "5 7") 103 x={} 104 x[1] = 2 105 x[1] += 3 106 assert.eq(x[1], 5) 107 def f12(): x[(1, "abc", {})] = 1 108 assert.fails(f12, "unhashable type: dict") 109 110 assignment() 111 112 --- 113 # augmented assignment 114 115 load("assert.star", "assert") 116 117 def f(): 118 x = 1 119 x += 1 120 assert.eq(x, 2) 121 x *= 3 122 assert.eq(x, 6) 123 f() 124 125 --- 126 # effects of evaluating LHS occur only once 127 128 load("assert.star", "assert") 129 130 count = [0] # count[0] is the number of calls to f 131 132 def f(): 133 count[0] += 1 134 return count[0] 135 136 x = [1, 2, 3] 137 x[f()] += 1 138 139 assert.eq(x, [1, 3, 3]) # sole call to f returned 1 140 assert.eq(count[0], 1) # f was called only once 141 142 --- 143 # Order of evaluation. 144 145 load("assert.star", "assert") 146 147 calls = [] 148 149 def f(name, result): 150 calls.append(name) 151 return result 152 153 # The right side is evaluated before the left in an ordinary assignment. 154 calls.clear() 155 f("array", [0])[f("index", 0)] = f("rhs", 0) 156 assert.eq(calls, ["rhs", "array", "index"]) 157 158 calls.clear() 159 f("lhs1", [0])[0], f("lhs2", [0])[0] = f("rhs1", 0), f("rhs2", 0) 160 assert.eq(calls, ["rhs1", "rhs2", "lhs1", "lhs2"]) 161 162 # Left side is evaluated first (and only once) in an augmented assignment. 163 calls.clear() 164 f("array", [0])[f("index", 0)] += f("addend", 1) 165 assert.eq(calls, ["array", "index", "addend"]) 166 167 --- 168 # global referenced before assignment 169 170 def f(): 171 return g ### "global variable g referenced before assignment" 172 173 f() 174 175 g = 1 176 177 --- 178 # Free variables are captured by reference, so this is ok. 179 load("assert.star", "assert") 180 181 def f(): 182 def g(): 183 return outer 184 outer = 1 185 return g() 186 187 assert.eq(f(), 1) 188 189 --- 190 load("assert.star", "assert") 191 192 printok = [False] 193 194 # This program should resolve successfully but fail dynamically. 195 # However, the Java implementation currently reports the dynamic 196 # error at the x=1 statement (b/33975425). I think we need to simplify 197 # the resolver algorithm to what we have implemented. 198 def use_before_def(): 199 print(x) # dynamic error: local var referenced before assignment 200 printok[0] = True 201 x = 1 # makes 'x' local 202 203 assert.fails(use_before_def, 'local variable x referenced before assignment') 204 assert.true(not printok[0]) # execution of print statement failed 205 206 --- 207 x = [1] 208 x.extend([2]) # ok 209 210 def f(): 211 x += [4] ### "local variable x referenced before assignment" 212 213 f() 214 215 --- 216 217 z += 3 ### "global variable z referenced before assignment" 218 219 --- 220 load("assert.star", "assert") 221 222 # It's ok to define a global that shadows a built-in... 223 list = [] 224 assert.eq(type(list), "list") 225 226 # ...but then all uses refer to the global, 227 # even if they occur before the binding use. 228 # See github.com/google/skylark/issues/116. 229 assert.fails(lambda: tuple, "global variable tuple referenced before assignment") 230 tuple = () 231 232 --- 233 # option:set 234 # Same as above, but set is dialect-specific; 235 # we shouldn't notice any difference. 236 load("assert.star", "assert") 237 238 set = [1, 2, 3] 239 assert.eq(type(set), "list") 240 241 # As in Python 2 and Python 3, 242 # all 'in x' expressions in a comprehension are evaluated 243 # in the comprehension's lexical block, except the first, 244 # which is resolved in the outer block. 245 x = [[1, 2]] 246 assert.eq([x for x in x for y in x], 247 [[1, 2], [1, 2]]) 248 249 --- 250 # A comprehension establishes a single new lexical block, 251 # not one per 'for' clause. 252 x = [1, 2] 253 _ = [x for _ in [3] for x in x] ### "local variable x referenced before assignment" 254 255 --- 256 load("assert.star", "assert") 257 258 # assign singleton sequence to 1-tuple 259 (x,) = (1,) 260 assert.eq(x, 1) 261 (y,) = [1] 262 assert.eq(y, 1) 263 264 # assign 1-tuple to variable 265 z = (1,) 266 assert.eq(type(z), "tuple") 267 assert.eq(len(z), 1) 268 assert.eq(z[0], 1) 269 270 # assign value to parenthesized variable 271 (a) = 1 272 assert.eq(a, 1) 273 274 --- 275 # assignment to/from fields. 276 load("assert.star", "assert", "freeze") 277 278 hf = hasfields() 279 hf.x = 1 280 assert.eq(hf.x, 1) 281 hf.x = [1, 2] 282 hf.x += [3, 4] 283 assert.eq(hf.x, [1, 2, 3, 4]) 284 freeze(hf) 285 def setX(hf): 286 hf.x = 2 287 def setY(hf): 288 hf.y = 3 289 assert.fails(lambda: setX(hf), "cannot set field on a frozen hasfields") 290 assert.fails(lambda: setY(hf), "cannot set field on a frozen hasfields") 291 292 --- 293 # destucturing assignment in a for loop. 294 load("assert.star", "assert") 295 296 def f(): 297 res = [] 298 for (x, y), z in [(["a", "b"], 3), (["c", "d"], 4)]: 299 res.append((x, y, z)) 300 return res 301 assert.eq(f(), [("a", "b", 3), ("c", "d", 4)]) 302 303 def g(): 304 a = {} 305 for i, a[i] in [("one", 1), ("two", 2)]: 306 pass 307 return a 308 assert.eq(g(), {"one": 1, "two": 2}) 309 310 --- 311 # parenthesized LHS in augmented assignment (success) 312 # option:globalreassign 313 load("assert.star", "assert") 314 315 a = 5 316 (a) += 3 317 assert.eq(a, 8) 318 319 --- 320 # parenthesized LHS in augmented assignment (error) 321 322 (a) += 5 ### "global variable a referenced before assignment" 323 324 --- 325 # option:globalreassign 326 load("assert.star", "assert") 327 assert = 1 328 load("assert.star", "assert") 329 330 --- 331 # option:globalreassign option:loadbindsglobally 332 load("assert.star", "assert") 333 assert = 1 334 load("assert.star", "assert") 335 336 --- 337 # option:loadbindsglobally 338 _ = assert ### "global variable assert referenced before assignment" 339 load("assert.star", "assert") 340 341 --- 342 _ = assert ### "local variable assert referenced before assignment" 343 load("assert.star", "assert") 344 345 --- 346 def f(): assert.eq(1, 1) # forward ref OK 347 load("assert.star", "assert") 348 f() 349 350 --- 351 # option:loadbindsglobally 352 def f(): assert.eq(1, 1) # forward ref OK 353 load("assert.star", "assert") 354 f()