...

Text file src/go.starlark.net/starlark/testdata/assign.star

Documentation: go.starlark.net/starlark/testdata

     1# Tests of Starlark assignment.
     2
     3# This is a "chunked" file: each "---" effectively starts a new file.
     4
     5# tuple assignment
     6load("assert.star", "assert")
     7
     8() = () # empty ok
     9
    10a, b, c = 1, 2, 3
    11assert.eq(a, 1)
    12assert.eq(b, 2)
    13assert.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
    34load("assert.star", "assert")
    35
    36[] = [] # empty ok
    37
    38[a, b, c] = [1, 2, 3]
    39assert.eq(a, 1)
    40assert.eq(b, 2)
    41assert.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
    62load("assert.star", "assert")
    63
    64# empty ok
    65[] = ()
    66() = []
    67
    68[a, b, c] = (1, 2, 3)
    69assert.eq(a, 1)
    70assert.eq(b, 2)
    71assert.eq(c, 3)
    72
    73[a2, b2, c2] = 1, 2, 3 # bare tuple ok
    74
    75(d, e, f) = [1, 2, 3]
    76assert.eq(d, 1)
    77assert.eq(e, 2)
    78assert.eq(f, 3)
    79
    80[g, h, (i, j)] = (1, 2, [3, 4])
    81assert.eq(g, 1)
    82assert.eq(h, 2)
    83assert.eq(i, 3)
    84assert.eq(j, 4)
    85
    86(k, l, [m, n]) = [1, 2, (3, 4)]
    87assert.eq(k, 1)
    88assert.eq(l, 2)
    89assert.eq(m, 3)
    90assert.eq(n, 4)
    91
    92---
    93# misc assignment
    94load("assert.star", "assert")
    95
    96def 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
   110assignment()
   111
   112---
   113# augmented assignment
   114
   115load("assert.star", "assert")
   116
   117def f():
   118  x = 1
   119  x += 1
   120  assert.eq(x, 2)
   121  x *= 3
   122  assert.eq(x, 6)
   123f()
   124
   125---
   126# effects of evaluating LHS occur only once
   127
   128load("assert.star", "assert")
   129
   130count = [0] # count[0] is the number of calls to f
   131
   132def f():
   133  count[0] += 1
   134  return count[0]
   135
   136x = [1, 2, 3]
   137x[f()] += 1
   138
   139assert.eq(x, [1, 3, 3]) # sole call to f returned 1
   140assert.eq(count[0], 1) # f was called only once
   141
   142---
   143# Order of evaluation.
   144
   145load("assert.star", "assert")
   146
   147calls = []
   148
   149def f(name, result):
   150  calls.append(name)
   151  return result
   152
   153# The right side is evaluated before the left in an ordinary assignment.
   154calls.clear()
   155f("array", [0])[f("index", 0)] = f("rhs", 0)
   156assert.eq(calls, ["rhs", "array", "index"])
   157
   158calls.clear()
   159f("lhs1", [0])[0], f("lhs2", [0])[0] = f("rhs1", 0), f("rhs2", 0)
   160assert.eq(calls, ["rhs1", "rhs2", "lhs1", "lhs2"])
   161
   162# Left side is evaluated first (and only once) in an augmented assignment.
   163calls.clear()
   164f("array", [0])[f("index", 0)] += f("addend", 1)
   165assert.eq(calls, ["array", "index", "addend"])
   166
   167---
   168# global referenced before assignment
   169
   170def f():
   171   return g ### "global variable g referenced before assignment"
   172
   173f()
   174
   175g = 1
   176
   177---
   178# Free variables are captured by reference, so this is ok.
   179load("assert.star", "assert")
   180
   181def f():
   182   def g():
   183     return outer
   184   outer = 1
   185   return g()
   186
   187assert.eq(f(), 1)
   188
   189---
   190load("assert.star", "assert")
   191
   192printok = [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.
   198def use_before_def():
   199  print(x) # dynamic error: local var referenced before assignment
   200  printok[0] = True
   201  x = 1  # makes 'x' local
   202
   203assert.fails(use_before_def, 'local variable x referenced before assignment')
   204assert.true(not printok[0]) # execution of print statement failed
   205
   206---
   207x = [1]
   208x.extend([2]) # ok
   209
   210def f():
   211   x += [4] ### "local variable x referenced before assignment"
   212
   213f()
   214
   215---
   216
   217z += 3 ### "global variable z referenced before assignment"
   218
   219---
   220load("assert.star", "assert")
   221
   222# It's ok to define a global that shadows a built-in...
   223list = []
   224assert.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.
   229assert.fails(lambda: tuple, "global variable tuple referenced before assignment")
   230tuple = ()
   231
   232---
   233# option:set
   234# Same as above, but set is dialect-specific;
   235# we shouldn't notice any difference.
   236load("assert.star", "assert")
   237
   238set = [1, 2, 3]
   239assert.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.
   245x = [[1, 2]]
   246assert.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.
   252x = [1, 2]
   253_ = [x for _ in [3] for x in x] ### "local variable x referenced before assignment"
   254
   255---
   256load("assert.star", "assert")
   257
   258# assign singleton sequence to 1-tuple
   259(x,) = (1,)
   260assert.eq(x, 1)
   261(y,) = [1]
   262assert.eq(y, 1)
   263
   264# assign 1-tuple to variable
   265z = (1,)
   266assert.eq(type(z), "tuple")
   267assert.eq(len(z), 1)
   268assert.eq(z[0], 1)
   269
   270# assign value to parenthesized variable
   271(a) = 1
   272assert.eq(a, 1)
   273
   274---
   275# assignment to/from fields.
   276load("assert.star", "assert", "freeze")
   277
   278hf = hasfields()
   279hf.x = 1
   280assert.eq(hf.x, 1)
   281hf.x = [1, 2]
   282hf.x += [3, 4]
   283assert.eq(hf.x, [1, 2, 3, 4])
   284freeze(hf)
   285def setX(hf):
   286  hf.x = 2
   287def setY(hf):
   288  hf.y = 3
   289assert.fails(lambda: setX(hf), "cannot set field on a frozen hasfields")
   290assert.fails(lambda: setY(hf), "cannot set field on a frozen hasfields")
   291
   292---
   293# destucturing assignment in a for loop.
   294load("assert.star", "assert")
   295
   296def f():
   297  res = []
   298  for (x, y), z in [(["a", "b"], 3), (["c", "d"], 4)]:
   299    res.append((x, y, z))
   300  return res
   301assert.eq(f(), [("a", "b", 3), ("c", "d", 4)])
   302
   303def g():
   304  a = {}
   305  for i, a[i] in [("one", 1), ("two", 2)]:
   306    pass
   307  return a
   308assert.eq(g(), {"one": 1, "two": 2})
   309
   310---
   311# parenthesized LHS in augmented assignment (success)
   312# option:globalreassign
   313load("assert.star", "assert")
   314
   315a = 5
   316(a) += 3
   317assert.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
   326load("assert.star", "assert")
   327assert = 1
   328load("assert.star", "assert")
   329
   330---
   331# option:globalreassign option:loadbindsglobally
   332load("assert.star", "assert")
   333assert = 1
   334load("assert.star", "assert")
   335
   336---
   337# option:loadbindsglobally
   338_ = assert ### "global variable assert referenced before assignment"
   339load("assert.star", "assert")
   340
   341---
   342_ = assert ### "local variable assert referenced before assignment"
   343load("assert.star", "assert")
   344
   345---
   346def f(): assert.eq(1, 1) # forward ref OK
   347load("assert.star", "assert")
   348f()
   349
   350---
   351# option:loadbindsglobally
   352def f(): assert.eq(1, 1) # forward ref OK
   353load("assert.star", "assert")
   354f()

View as plain text