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