1" Test Vim9 assignments
2
3source check.vim
4source vim9.vim
5
6let s:appendToMe = 'xxx'
7let s:addToMe = 111
8let g:existing = 'yes'
9let g:inc_counter = 1
10let $SOME_ENV_VAR = 'some'
11let g:alist = [7]
12let g:adict = #{a: 1}
13let g:astring = 'text'
14
15def Test_assignment_bool()
16  var bool1: bool = true
17  assert_equal(v:true, bool1)
18  var bool2: bool = false
19  assert_equal(v:false, bool2)
20
21  var bool3: bool = 0
22  assert_equal(false, bool3)
23  var bool4: bool = 1
24  assert_equal(true, bool4)
25
26  var bool5: bool = 1 && true
27  assert_equal(true, bool5)
28  var bool6: bool = 0 && 1
29  assert_equal(false, bool6)
30  var bool7: bool = 0 || 1 && true
31  assert_equal(true, bool7)
32
33  var lines =<< trim END
34    vim9script
35    def GetFlag(): bool
36      var flag: bool = 1
37      return flag
38    enddef
39    var flag: bool = GetFlag()
40    assert_equal(true, flag)
41    flag = 0
42    assert_equal(false, flag)
43    flag = 1
44    assert_equal(true, flag)
45    flag = 1 || true
46    assert_equal(true, flag)
47    flag = 1 && false
48    assert_equal(false, flag)
49
50    var cp: bool = &cp
51    var fen: bool = &l:fen
52  END
53  CheckScriptSuccess(lines)
54  CheckDefAndScriptFailure(['var x: bool = 2'], 'E1012:')
55  CheckDefAndScriptFailure(['var x: bool = -1'], 'E1012:')
56  CheckDefAndScriptFailure(['var x: bool = [1]'], 'E1012:')
57  CheckDefAndScriptFailure(['var x: bool = {}'], 'E1012:')
58  CheckDefAndScriptFailure(['var x: bool = "x"'], 'E1012:')
59
60  CheckDefAndScriptFailure(['var x: bool = "x"', '', 'eval 0'], 'E1012:', 1)
61enddef
62
63def Test_syntax()
64  var name = 234
65  var other: list<string> = ['asdf']
66enddef
67
68def Test_assignment()
69  CheckDefFailure(['var x:string'], 'E1069:')
70  CheckDefFailure(['var x:string = "x"'], 'E1069:')
71  CheckDefFailure(['var a:string = "x"'], 'E1069:')
72  CheckDefFailure(['var lambda = () => "lambda"'], 'E704:')
73  CheckScriptFailure(['var x = "x"'], 'E1124:')
74
75  # lower case name is OK for a list
76  var lambdaLines =<< trim END
77      var lambdaList: list<func> = [Test_syntax]
78      lambdaList[0] = () => "lambda"
79  END
80  CheckDefAndScriptSuccess(lambdaLines)
81
82  var nr: number = 1234
83  CheckDefFailure(['var nr: number = "asdf"'], 'E1012:')
84
85  var a: number = 6 #comment
86  assert_equal(6, a)
87
88  if has('channel')
89    var chan1: channel
90    assert_equal('fail', ch_status(chan1))
91
92    var job1: job
93    assert_equal('fail', job_status(job1))
94
95    # calling job_start() is in test_vim9_fails.vim, it causes leak reports
96  endif
97  if has('float')
98    var float1: float = 3.4
99  endif
100  var Funky1: func
101  var Funky2: func = function('len')
102  var Party2: func = funcref('g:Test_syntax')
103
104  g:newvar = 'new'  #comment
105  assert_equal('new', g:newvar)
106
107  assert_equal('yes', g:existing)
108  g:existing = 'no'
109  assert_equal('no', g:existing)
110
111  v:char = 'abc'
112  assert_equal('abc', v:char)
113
114  $ENVVAR = 'foobar'
115  assert_equal('foobar', $ENVVAR)
116  $ENVVAR = ''
117
118  var lines =<< trim END
119    vim9script
120    $ENVVAR = 'barfoo'
121    assert_equal('barfoo', $ENVVAR)
122    $ENVVAR = ''
123  END
124  CheckScriptSuccess(lines)
125
126  s:appendToMe ..= 'yyy'
127  assert_equal('xxxyyy', s:appendToMe)
128  s:addToMe += 222
129  assert_equal(333, s:addToMe)
130  s:newVar = 'new'
131  assert_equal('new', s:newVar)
132
133  set ts=7
134  var ts: number = &ts
135  assert_equal(7, ts)
136  &ts += 1
137  assert_equal(8, &ts)
138  &ts -= 3
139  assert_equal(5, &ts)
140  &ts *= 2
141  assert_equal(10, &ts)
142  &ts /= 3
143  assert_equal(3, &ts)
144  set ts=10
145  &ts %= 4
146  assert_equal(2, &ts)
147
148  if has('float')
149    var f100: float = 100.0
150    f100 /= 5
151    assert_equal(20.0, f100)
152
153    var f200: float = 200.0
154    f200 /= 5.0
155    assert_equal(40.0, f200)
156
157    CheckDefFailure(['var nr: number = 200', 'nr /= 5.0'], 'E1012:')
158  endif
159
160  lines =<< trim END
161    &ts = 6
162    &ts += 3
163    assert_equal(9, &ts)
164
165    &l:ts = 6
166    assert_equal(6, &ts)
167    &l:ts += 2
168    assert_equal(8, &ts)
169
170    &g:ts = 6
171    assert_equal(6, &g:ts)
172    &g:ts += 2
173    assert_equal(8, &g:ts)
174
175    &number = true
176    assert_equal(true, &number)
177    &number = 0
178    assert_equal(false, &number)
179    &number = 1
180    assert_equal(true, &number)
181    &number = false
182    assert_equal(false, &number)
183  END
184  CheckDefAndScriptSuccess(lines)
185
186  CheckDefFailure(['&notex += 3'], 'E113:')
187  CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
188  CheckDefFailure(['&ts = [7]'], 'E1012:')
189  CheckDefExecFailure(['&ts = g:alist'], 'E1012: Type mismatch; expected number but got list<number>')
190  CheckDefFailure(['&ts = "xx"'], 'E1012:')
191  CheckDefExecFailure(['&ts = g:astring'], 'E1012: Type mismatch; expected number but got string')
192  CheckDefFailure(['&path += 3'], 'E1012:')
193  CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
194  # test freeing ISN_STOREOPT
195  CheckDefFailure(['&ts = 3', 'var asdf'], 'E1022:')
196  &ts = 8
197
198  lines =<< trim END
199    var save_TI = &t_TI
200    &t_TI = ''
201    assert_equal('', &t_TI)
202    &t_TI = 'xxx'
203    assert_equal('xxx', &t_TI)
204    &t_TI = save_TI
205  END
206  CheckDefAndScriptSuccess(lines)
207
208  CheckDefFailure(['&t_TI = 123'], 'E1012:')
209  CheckScriptFailure(['vim9script', '&t_TI = 123'], 'E928:')
210
211  CheckDefFailure(['var s:var = 123'], 'E1101:')
212  CheckDefFailure(['var s:var: number'], 'E1101:')
213
214  lines =<< trim END
215    vim9script
216    def SomeFunc()
217      s:var = 123
218    enddef
219    defcompile
220  END
221  CheckScriptFailure(lines, 'E1089:')
222
223  g:inc_counter += 1
224  assert_equal(2, g:inc_counter)
225
226  $SOME_ENV_VAR ..= 'more'
227  assert_equal('somemore', $SOME_ENV_VAR)
228  CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1051:')
229  CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1012:')
230
231  lines =<< trim END
232    @c = 'areg'
233    @c ..= 'add'
234    assert_equal('aregadd', @c)
235  END
236  CheckDefAndScriptSuccess(lines)
237
238  CheckDefFailure(['@a += "more"'], 'E1051:')
239  CheckDefFailure(['@a += 123'], 'E1012:')
240
241  v:errmsg = 'none'
242  v:errmsg ..= 'again'
243  assert_equal('noneagain', v:errmsg)
244  CheckDefFailure(['v:errmsg += "more"'], 'E1051:')
245  CheckDefFailure(['v:errmsg += 123'], 'E1012:')
246
247  var text =<< trim END
248    some text
249  END
250enddef
251
252def Test_assign_unpack()
253  var lines =<< trim END
254    var v1: number
255    var v2: number
256    [v1, v2] = [1, 2]
257    assert_equal(1, v1)
258    assert_equal(2, v2)
259  END
260  CheckDefAndScriptSuccess(lines)
261
262  lines =<< trim END
263      var v1: number
264      var v2: number
265      [v1, v2] =
266  END
267  CheckDefFailure(lines, 'E1097:', 5)
268
269  lines =<< trim END
270      var v1: number
271      var v2: number
272      [v1, v2] = xxx
273  END
274  CheckDefFailure(lines, 'E1001:', 3)
275
276  lines =<< trim END
277      var v1: number
278      var v2: number
279      [v1, v2] = popup_clear()
280  END
281  CheckDefFailure(lines, 'E1031:', 3)
282
283  lines =<< trim END
284      [v1, v2] = [1, 2]
285  END
286  CheckDefFailure(lines, 'E1089', 1)
287  CheckScriptFailure(['vim9script'] + lines, 'E1089', 2)
288
289  lines =<< trim END
290      var v1: number
291      var v2: number
292      [v1, v2] = ''
293  END
294  CheckDefFailure(lines, 'E1012: Type mismatch; expected list<any> but got string', 3)
295
296  lines =<< trim END
297    g:values = [false, 0]
298    var x: bool
299    var y: string
300    [x, y] = g:values
301  END
302  CheckDefExecAndScriptFailure(lines, 'E1163: Variable 2: type mismatch, expected string but got number')
303enddef
304
305def Test_assign_linebreak()
306  var nr: number
307  nr =
308      123
309  assert_equal(123, nr)
310
311  var n2: number
312  [nr, n2] =
313     [12, 34]
314  assert_equal(12, nr)
315  assert_equal(34, n2)
316
317  CheckDefFailure(["var x = #"], 'E1097:', 3)
318enddef
319
320def Test_assign_index()
321  # list of list
322  var l1: list<number>
323  l1[0] = 123
324  assert_equal([123], l1)
325
326  var l2: list<list<number>>
327  l2[0] = []
328  l2[0][0] = 123
329  assert_equal([[123]], l2)
330
331  var l3: list<list<list<number>>>
332  l3[0] = []
333  l3[0][0] = []
334  l3[0][0][0] = 123
335  assert_equal([[[123]]], l3)
336
337  var lines =<< trim END
338      var l3: list<list<number>>
339      l3[0] = []
340      l3[0][0] = []
341  END
342  CheckDefFailure(lines, 'E1012: Type mismatch; expected number but got list<unknown>', 3)
343
344  # dict of dict
345  var d1: dict<number>
346  d1.one = 1
347  assert_equal({one: 1}, d1)
348
349  var d2: dict<dict<number>>
350  d2.one = {}
351  d2.one.two = 123
352  assert_equal({one: {two: 123}}, d2)
353
354  var d3: dict<dict<dict<number>>>
355  d3.one = {}
356  d3.one.two = {}
357  d3.one.two.three = 123
358  assert_equal({one: {two: {three: 123}}}, d3)
359
360  lines =<< trim END
361      var d3: dict<dict<number>>
362      d3.one = {}
363      d3.one.two = {}
364  END
365  CheckDefFailure(lines, 'E1012: Type mismatch; expected number but got dict<unknown>', 3)
366
367  lines =<< trim END
368    var lines: list<string>
369    lines['a'] = 'asdf'
370  END
371  CheckDefFailure(lines, 'E1012:', 2)
372
373  lines =<< trim END
374    var lines: string
375    lines[9] = 'asdf'
376  END
377  CheckDefFailure(lines, 'E1141:', 2)
378
379  # list of dict
380  var ld: list<dict<number>>
381  ld[0] = {}
382  ld[0].one = 123
383  assert_equal([{one: 123}], ld)
384
385  lines =<< trim END
386      var ld: list<dict<number>>
387      ld[0] = []
388  END
389  CheckDefFailure(lines, 'E1012: Type mismatch; expected dict<number> but got list<unknown>', 2)
390
391  # dict of list
392  var dl: dict<list<number>>
393  dl.one = []
394  dl.one[0] = 123
395  assert_equal({one: [123]}, dl)
396
397  lines =<< trim END
398      var dl: dict<list<number>>
399      dl.one = {}
400  END
401  CheckDefFailure(lines, 'E1012: Type mismatch; expected list<number> but got dict<unknown>', 2)
402enddef
403
404def Test_extend_list()
405  var lines =<< trim END
406      vim9script
407      var l: list<number>
408      l += [123]
409      assert_equal([123], l)
410  END
411  CheckScriptSuccess(lines)
412
413  lines =<< trim END
414      vim9script
415      var list: list<string>
416      extend(list, ['x'])
417      assert_equal(['x'], list)
418  END
419  CheckScriptSuccess(lines)
420
421  # appending to NULL list from a function
422  lines =<< trim END
423      vim9script
424      var list: list<string>
425      def Func()
426        list += ['a', 'b']
427      enddef
428      Func()
429      assert_equal(['a', 'b'], list)
430  END
431  CheckScriptSuccess(lines)
432  lines =<< trim END
433      vim9script
434      var list: list<string>
435      def Func()
436        extend(list, ['x', 'b'])
437      enddef
438      Func()
439      assert_equal(['x', 'b'], list)
440  END
441  CheckScriptSuccess(lines)
442
443  lines =<< trim END
444      vim9script
445      var l: list<string> = test_null_list()
446      extend(l, ['x'])
447      assert_equal(['x'], l)
448  END
449  CheckScriptSuccess(lines)
450
451  lines =<< trim END
452      vim9script
453      extend(test_null_list(), ['x'])
454  END
455  CheckScriptFailure(lines, 'E1134:', 2)
456enddef
457
458def Test_extend_dict()
459  var lines =<< trim END
460      vim9script
461      var d: dict<number>
462      extend(d, {a: 1})
463      assert_equal({a: 1}, d)
464
465      var d2: dict<number>
466      d2['one'] = 1
467      assert_equal({one: 1}, d2)
468  END
469  CheckScriptSuccess(lines)
470
471  lines =<< trim END
472      vim9script
473      var d: dict<string> = test_null_dict()
474      extend(d, {a: 'x'})
475      assert_equal({a: 'x'}, d)
476  END
477  CheckScriptSuccess(lines)
478
479  lines =<< trim END
480      vim9script
481      extend(test_null_dict(), {a: 'x'})
482  END
483  CheckScriptFailure(lines, 'E1133:', 2)
484enddef
485
486def Test_single_letter_vars()
487  # single letter variables
488  var a: number = 123
489  a = 123
490  assert_equal(123, a)
491  var b: number
492  b = 123
493  assert_equal(123, b)
494  var g: number
495  g = 123
496  assert_equal(123, g)
497  var s: number
498  s = 123
499  assert_equal(123, s)
500  var t: number
501  t = 123
502  assert_equal(123, t)
503  var v: number
504  v = 123
505  assert_equal(123, v)
506  var w: number
507  w = 123
508  assert_equal(123, w)
509enddef
510
511def Test_vim9_single_char_vars()
512  var lines =<< trim END
513      vim9script
514
515      # single character variable declarations work
516      var a: string
517      var b: number
518      var l: list<any>
519      var s: string
520      var t: number
521      var v: number
522      var w: number
523
524      # script-local variables can be used without s: prefix
525      a = 'script-a'
526      b = 111
527      l = [1, 2, 3]
528      s = 'script-s'
529      t = 222
530      v = 333
531      w = 444
532
533      assert_equal('script-a', a)
534      assert_equal(111, b)
535      assert_equal([1, 2, 3], l)
536      assert_equal('script-s', s)
537      assert_equal(222, t)
538      assert_equal(333, v)
539      assert_equal(444, w)
540  END
541  writefile(lines, 'Xsinglechar')
542  source Xsinglechar
543  delete('Xsinglechar')
544enddef
545
546def Test_assignment_list()
547  var list1: list<bool> = [false, true, false]
548  var list2: list<number> = [1, 2, 3]
549  var list3: list<string> = ['sdf', 'asdf']
550  var list4: list<any> = ['yes', true, 1234]
551  var list5: list<blob> = [0z01, 0z02]
552
553  var listS: list<string> = []
554  var listN: list<number> = []
555
556  assert_equal([1, 2, 3], list2)
557  list2[-1] = 99
558  assert_equal([1, 2, 99], list2)
559  list2[-2] = 88
560  assert_equal([1, 88, 99], list2)
561  list2[-3] = 77
562  assert_equal([77, 88, 99], list2)
563  list2 += [100]
564  assert_equal([77, 88, 99, 100], list2)
565
566  list3 += ['end']
567  assert_equal(['sdf', 'asdf', 'end'], list3)
568
569  CheckDefExecFailure(['var ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
570  CheckDefExecFailure(['var [v1, v2] = [1, 2]'], 'E1092:')
571
572  # type becomes list<any>
573  var somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
574
575  var lines =<< trim END
576    var d = {dd: test_null_list()}
577    d.dd[0] = 0
578  END
579  CheckDefExecFailure(lines, 'E1147:', 2)
580enddef
581
582def Test_assignment_list_any_index()
583   var l: list<number> = [1, 2]
584  for  [x, y, _]
585  in  [[0, 1, ''], [1, 3, '']]
586      l[x] = l[x] + y
587  endfor
588  assert_equal([2, 5], l)
589enddef
590
591def Test_assignment_list_vim9script()
592  var lines =<< trim END
593    vim9script
594    var v1: number
595    var v2: number
596    var v3: number
597    [v1, v2, v3] = [1, 2, 3]
598    assert_equal([1, 2, 3], [v1, v2, v3])
599  END
600  CheckScriptSuccess(lines)
601enddef
602
603def Test_assignment_dict()
604  var dict1: dict<bool> = {one: false, two: true}
605  var dict2: dict<number> = {one: 1, two: 2}
606  var dict3: dict<string> = {key: 'value'}
607  var dict4: dict<any> = {one: 1, two: '2'}
608  var dict5: dict<blob> = {one: 0z01, two: 0z02}
609
610  # overwrite
611  dict3['key'] = 'another'
612  assert_equal(dict3, {key: 'another'})
613  dict3.key = 'yet another'
614  assert_equal(dict3, {key: 'yet another'})
615
616  # member "any" can also be a dict and assigned to
617  var anydict: dict<any> = {nest: {}, nr: 0}
618  anydict.nest['this'] = 123
619  anydict.nest.that = 456
620  assert_equal({nest: {this: 123, that: 456}, nr: 0}, anydict)
621
622  var lines =<< trim END
623    var dd = {}
624    dd.two = 2
625    assert_equal({two: 2}, dd)
626  END
627  CheckDefAndScriptSuccess(lines)
628
629  lines =<< trim END
630    var d = {dd: {}}
631    d.dd[0] = 2
632    d.dd['x'] = 3
633    d.dd.y = 4
634    assert_equal({dd: {0: 2, x: 3, y: 4}}, d)
635  END
636  CheckDefAndScriptSuccess(lines)
637
638  lines =<< trim END
639    var dd = {one: 1}
640    dd.one) = 2
641  END
642  CheckDefFailure(lines, 'E488:', 2)
643
644  lines =<< trim END
645    var dd = {one: 1}
646    var dd.one = 2
647  END
648  CheckDefAndScriptFailure(lines, 'E1017:', 2)
649
650  # empty key can be used
651  var dd = {}
652  dd[""] = 6
653  assert_equal({['']: 6}, dd)
654
655  # type becomes dict<any>
656  var somedict = rand() > 0 ? {a: 1, b: 2} : {a: 'a', b: 'b'}
657
658  # assignment to script-local dict
659  lines =<< trim END
660    vim9script
661    var test: dict<any> = {}
662    def FillDict(): dict<any>
663      test['a'] = 43
664      return test
665    enddef
666    assert_equal({a: 43}, FillDict())
667  END
668  CheckScriptSuccess(lines)
669
670  lines =<< trim END
671    vim9script
672    var test: dict<any>
673    def FillDict(): dict<any>
674      test['a'] = 43
675      return test
676    enddef
677    FillDict()
678    assert_equal({a: 43}, test)
679  END
680  CheckScriptSuccess(lines)
681
682  # assignment to global dict
683  lines =<< trim END
684    vim9script
685    g:test = {}
686    def FillDict(): dict<any>
687      g:test['a'] = 43
688      return g:test
689    enddef
690    assert_equal({a: 43}, FillDict())
691  END
692  CheckScriptSuccess(lines)
693
694  # assignment to buffer dict
695  lines =<< trim END
696    vim9script
697    b:test = {}
698    def FillDict(): dict<any>
699      b:test['a'] = 43
700      return b:test
701    enddef
702    assert_equal({a: 43}, FillDict())
703  END
704  CheckScriptSuccess(lines)
705
706  lines =<< trim END
707    var d = {dd: test_null_dict()}
708    d.dd[0] = 0
709  END
710  CheckDefExecFailure(lines, 'E1103:', 2)
711
712  lines =<< trim END
713    var d = {dd: 'string'}
714    d.dd[0] = 0
715  END
716  CheckDefExecFailure(lines, 'E1148:', 2)
717enddef
718
719def Test_assignment_local()
720  # Test in a separated file in order not to the current buffer/window/tab is
721  # changed.
722  var script_lines: list<string> =<< trim END
723    let b:existing = 'yes'
724    let w:existing = 'yes'
725    let t:existing = 'yes'
726
727    def Test_assignment_local_internal()
728      b:newvar = 'new'
729      assert_equal('new', b:newvar)
730      assert_equal('yes', b:existing)
731      b:existing = 'no'
732      assert_equal('no', b:existing)
733      b:existing ..= 'NO'
734      assert_equal('noNO', b:existing)
735
736      w:newvar = 'new'
737      assert_equal('new', w:newvar)
738      assert_equal('yes', w:existing)
739      w:existing = 'no'
740      assert_equal('no', w:existing)
741      w:existing ..= 'NO'
742      assert_equal('noNO', w:existing)
743
744      t:newvar = 'new'
745      assert_equal('new', t:newvar)
746      assert_equal('yes', t:existing)
747      t:existing = 'no'
748      assert_equal('no', t:existing)
749      t:existing ..= 'NO'
750      assert_equal('noNO', t:existing)
751    enddef
752    call Test_assignment_local_internal()
753  END
754  CheckScriptSuccess(script_lines)
755enddef
756
757def Test_assignment_default()
758  # Test default values.
759  var thebool: bool
760  assert_equal(v:false, thebool)
761
762  var thenumber: number
763  assert_equal(0, thenumber)
764
765  if has('float')
766    var thefloat: float
767    assert_equal(0.0, thefloat)
768  endif
769
770  var thestring: string
771  assert_equal('', thestring)
772
773  var theblob: blob
774  assert_equal(0z, theblob)
775
776  var Thefunc: func
777  assert_equal(test_null_function(), Thefunc)
778
779  var thelist: list<any>
780  assert_equal([], thelist)
781
782  var thedict: dict<any>
783  assert_equal({}, thedict)
784
785  if has('channel')
786    var thejob: job
787    assert_equal(test_null_job(), thejob)
788
789    var thechannel: channel
790    assert_equal(test_null_channel(), thechannel)
791
792    if has('unix') && executable('cat')
793      # check with non-null job and channel, types must match
794      thejob = job_start("cat ", {})
795      thechannel = job_getchannel(thejob)
796      job_stop(thejob, 'kill')
797    endif
798  endif
799
800  var nr = 1234 | nr = 5678
801  assert_equal(5678, nr)
802enddef
803
804let scriptvar = 'init'
805
806def Test_assignment_var_list()
807  var lines =<< trim END
808      var v1: string
809      var v2: string
810      var vrem: list<string>
811      [v1] = ['aaa']
812      assert_equal('aaa', v1)
813
814      [v1, v2] = ['one', 'two']
815      assert_equal('one', v1)
816      assert_equal('two', v2)
817
818      [v1, v2; vrem] = ['one', 'two']
819      assert_equal('one', v1)
820      assert_equal('two', v2)
821      assert_equal([], vrem)
822
823      [v1, v2; vrem] = ['one', 'two', 'three']
824      assert_equal('one', v1)
825      assert_equal('two', v2)
826      assert_equal(['three'], vrem)
827
828      [&ts, &sw] = [3, 4]
829      assert_equal(3, &ts)
830      assert_equal(4, &sw)
831      set ts=8 sw=4
832
833      [@a, @z] = ['aa', 'zz']
834      assert_equal('aa', @a)
835      assert_equal('zz', @z)
836
837      [$SOME_VAR, $OTHER_VAR] = ['some', 'other']
838      assert_equal('some', $SOME_VAR)
839      assert_equal('other', $OTHER_VAR)
840
841      [g:globalvar, b:bufvar, w:winvar, t:tabvar, v:errmsg] =
842            ['global', 'buf', 'win', 'tab', 'error']
843      assert_equal('global', g:globalvar)
844      assert_equal('buf', b:bufvar)
845      assert_equal('win', w:winvar)
846      assert_equal('tab', t:tabvar)
847      assert_equal('error', v:errmsg)
848      unlet g:globalvar
849  END
850  CheckDefAndScriptSuccess(lines)
851
852  [g:globalvar, s:scriptvar, b:bufvar] = ['global', 'script', 'buf']
853  assert_equal('global', g:globalvar)
854  assert_equal('script', s:scriptvar)
855  assert_equal('buf', b:bufvar)
856
857  lines =<< trim END
858      vim9script
859      var s:scriptvar = 'init'
860      [g:globalvar, s:scriptvar, w:winvar] = ['global', 'script', 'win']
861      assert_equal('global', g:globalvar)
862      assert_equal('script', s:scriptvar)
863      assert_equal('win', w:winvar)
864  END
865  CheckScriptSuccess(lines)
866enddef
867
868def Test_assignment_vim9script()
869  var lines =<< trim END
870    vim9script
871    def Func(): list<number>
872      return [1, 2]
873    enddef
874    var name1: number
875    var name2: number
876    [name1, name2] =
877          Func()
878    assert_equal(1, name1)
879    assert_equal(2, name2)
880    var ll =
881          Func()
882    assert_equal([1, 2], ll)
883
884    @/ = 'text'
885    assert_equal('text', @/)
886    @0 = 'zero'
887    assert_equal('zero', @0)
888    @1 = 'one'
889    assert_equal('one', @1)
890    @9 = 'nine'
891    assert_equal('nine', @9)
892    @- = 'minus'
893    assert_equal('minus', @-)
894    if has('clipboard_working')
895      @* = 'star'
896      assert_equal('star', @*)
897      @+ = 'plus'
898      assert_equal('plus', @+)
899    endif
900
901    var a: number = 123
902    assert_equal(123, a)
903    var s: string = 'yes'
904    assert_equal('yes', s)
905    var b: number = 42
906    assert_equal(42, b)
907    var w: number = 43
908    assert_equal(43, w)
909    var t: number = 44
910    assert_equal(44, t)
911
912    var to_var = 0
913    to_var = 3
914    assert_equal(3, to_var)
915  END
916  CheckScriptSuccess(lines)
917
918  lines =<< trim END
919      vim9script
920      var n: number
921      def Func()
922        n = 'string'
923      enddef
924      defcompile
925  END
926  CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
927enddef
928
929def Mess(): string
930  v:foldstart = 123
931  return 'xxx'
932enddef
933
934def Test_assignment_failure()
935  CheckDefFailure(['var name=234'], 'E1004:')
936  CheckDefFailure(['var name =234'], 'E1004:')
937  CheckDefFailure(['var name= 234'], 'E1004:')
938
939  CheckScriptFailure(['vim9script', 'var name=234'], 'E1004:')
940  CheckScriptFailure(['vim9script', 'var name=234'], "before and after '='")
941  CheckScriptFailure(['vim9script', 'var name =234'], 'E1004:')
942  CheckScriptFailure(['vim9script', 'var name= 234'], 'E1004:')
943  CheckScriptFailure(['vim9script', 'var name = 234', 'name+=234'], 'E1004:')
944  CheckScriptFailure(['vim9script', 'var name = 234', 'name+=234'], "before and after '+='")
945  CheckScriptFailure(['vim9script', 'var name = "x"', 'name..="y"'], 'E1004:')
946  CheckScriptFailure(['vim9script', 'var name = "x"', 'name..="y"'], "before and after '..='")
947
948  CheckDefFailure(['var true = 1'], 'E1034:')
949  CheckDefFailure(['var false = 1'], 'E1034:')
950
951  CheckDefFailure(['[a; b; c] = g:list'], 'E452:')
952  CheckDefExecFailure(['var a: number',
953                       '[a] = test_null_list()'], 'E1093:')
954  CheckDefExecFailure(['var a: number',
955                       '[a] = []'], 'E1093:')
956  CheckDefExecFailure(['var x: number',
957                       'var y: number',
958                       '[x, y] = [1]'], 'E1093:')
959  CheckDefExecFailure(['var x: string',
960                       'var y: string',
961                       '[x, y] = ["x"]'], 'E1093:')
962  CheckDefExecFailure(['var x: number',
963                       'var y: number',
964                       'var z: list<number>',
965                       '[x, y; z] = [1]'], 'E1093:')
966
967  CheckDefFailure(['var somevar'], "E1022:")
968  CheckDefFailure(['var &tabstop = 4'], 'E1052:')
969  CheckDefFailure(['&g:option = 5'], 'E113:')
970  CheckScriptFailure(['vim9script', 'var &tabstop = 4'], 'E1052:')
971
972  CheckDefFailure(['var $VAR = 5'], 'E1016: Cannot declare an environment variable:')
973  CheckScriptFailure(['vim9script', 'var $ENV = "xxx"'], 'E1016:')
974
975  if has('dnd')
976    CheckDefFailure(['var @~ = 5'], 'E1066:')
977  else
978    CheckDefFailure(['var @~ = 5'], 'E354:')
979    CheckDefFailure(['@~ = 5'], 'E354:')
980  endif
981  CheckDefFailure(['var @a = 5'], 'E1066:')
982  CheckDefFailure(['var @/ = "x"'], 'E1066:')
983  CheckScriptFailure(['vim9script', 'var @a = "abc"'], 'E1066:')
984
985  CheckDefFailure(['var g:var = 5'], 'E1016: Cannot declare a global variable:')
986  CheckDefFailure(['var w:var = 5'], 'E1016: Cannot declare a window variable:')
987  CheckDefFailure(['var b:var = 5'], 'E1016: Cannot declare a buffer variable:')
988  CheckDefFailure(['var t:var = 5'], 'E1016: Cannot declare a tab variable:')
989
990  CheckDefFailure(['var anr = 4', 'anr ..= "text"'], 'E1019:')
991  CheckDefFailure(['var xnr += 4'], 'E1020:', 1)
992  CheckScriptFailure(['vim9script', 'var xnr += 4'], 'E1020:')
993  CheckDefFailure(["var xnr = xnr + 1"], 'E1001:', 1)
994  CheckScriptFailure(['vim9script', 'var xnr = xnr + 4'], 'E121:')
995
996  CheckScriptFailure(['vim9script', 'def Func()', 'var dummy = s:notfound', 'enddef', 'defcompile'], 'E1108:')
997
998  CheckDefFailure(['var name: list<string> = [123]'], 'expected list<string> but got list<number>')
999  CheckDefFailure(['var name: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
1000
1001  CheckDefFailure(['var name: dict<string> = {key: 123}'], 'expected dict<string> but got dict<number>')
1002  CheckDefFailure(['var name: dict<number> = {key: "xx"}'], 'expected dict<number> but got dict<string>')
1003
1004  CheckDefFailure(['var name = feedkeys("0")'], 'E1031:')
1005  CheckDefFailure(['var name: number = feedkeys("0")'], 'expected number but got void')
1006
1007  CheckDefFailure(['var name: dict <number>'], 'E1068:')
1008  CheckDefFailure(['var name: dict<number'], 'E1009:')
1009
1010  assert_fails('s/^/\=Mess()/n', 'E794:')
1011  CheckDefFailure(['var name: dict<number'], 'E1009:')
1012
1013  CheckDefFailure(['w:foo: number = 10'],
1014                  'E488: Trailing characters: : number = 1')
1015  CheckDefFailure(['t:foo: bool = true'],
1016                  'E488: Trailing characters: : bool = true')
1017  CheckDefFailure(['b:foo: string = "x"'],
1018                  'E488: Trailing characters: : string = "x"')
1019  CheckDefFailure(['g:foo: number = 123'],
1020                  'E488: Trailing characters: : number = 123')
1021enddef
1022
1023def Test_assign_list()
1024  var l: list<string> = []
1025  l[0] = 'value'
1026  assert_equal('value', l[0])
1027
1028  l[1] = 'asdf'
1029  assert_equal('value', l[0])
1030  assert_equal('asdf', l[1])
1031  assert_equal('asdf', l[-1])
1032  assert_equal('value', l[-2])
1033
1034  var nrl: list<number> = []
1035  for i in range(5)
1036    nrl[i] = i
1037  endfor
1038  assert_equal([0, 1, 2, 3, 4], nrl)
1039
1040  CheckDefFailure(["var l: list<number> = ['', true]"], 'E1012: Type mismatch; expected list<number> but got list<any>', 1)
1041  CheckDefFailure(["var l: list<list<number>> = [['', true]]"], 'E1012: Type mismatch; expected list<list<number>> but got list<list<any>>', 1)
1042enddef
1043
1044def Test_assign_dict()
1045  var lines =<< trim END
1046      var d: dict<string> = {}
1047      d['key'] = 'value'
1048      assert_equal('value', d['key'])
1049
1050      d[123] = 'qwerty'
1051      assert_equal('qwerty', d[123])
1052      assert_equal('qwerty', d['123'])
1053
1054      var nrd: dict<number> = {}
1055      for i in range(3)
1056        nrd[i] = i
1057      endfor
1058      assert_equal({0: 0, 1: 1, 2: 2}, nrd)
1059
1060      d.somekey = 'someval'
1061      assert_equal({key: 'value', '123': 'qwerty', somekey: 'someval'}, d)
1062      # unlet d.somekey
1063      # assert_equal({key: 'value', '123': 'qwerty'}, d)
1064  END
1065  CheckDefAndScriptSuccess(lines)
1066
1067  # TODO: move to above once "unlet d.somekey" in :def is implemented
1068  lines =<< trim END
1069      vim9script
1070      var d: dict<string> = {}
1071      d['key'] = 'value'
1072      d.somekey = 'someval'
1073      assert_equal({key: 'value', somekey: 'someval'}, d)
1074      unlet d.somekey
1075      assert_equal({key: 'value'}, d)
1076  END
1077  CheckScriptSuccess(lines)
1078
1079  CheckDefFailure(["var d: dict<number> = {a: '', b: true}"], 'E1012: Type mismatch; expected dict<number> but got dict<any>', 1)
1080  CheckDefFailure(["var d: dict<dict<number>> = {x: {a: '', b: true}}"], 'E1012: Type mismatch; expected dict<dict<number>> but got dict<dict<any>>', 1)
1081enddef
1082
1083def Test_assign_dict_unknown_type()
1084  var lines =<< trim END
1085      vim9script
1086      var mylist = []
1087      mylist += [{one: 'one'}]
1088      def Func()
1089        var dd = mylist[0]
1090        assert_equal('one', dd.one)
1091      enddef
1092      Func()
1093  END
1094  CheckScriptSuccess(lines)
1095
1096  lines =<< trim END
1097      vim9script
1098      var mylist = [[]]
1099      mylist[0] += [{one: 'one'}]
1100      def Func()
1101        var dd = mylist[0][0]
1102        assert_equal('one', dd.one)
1103      enddef
1104      Func()
1105  END
1106  CheckScriptSuccess(lines)
1107enddef
1108
1109def Test_assign_dict_with_op()
1110  var lines =<< trim END
1111    vim9script
1112    var ds: dict<string> = {a: 'x'}
1113    ds['a'] ..= 'y'
1114    ds.a ..= 'z'
1115    assert_equal('xyz', ds.a)
1116
1117    var dn: dict<number> = {a: 9}
1118    dn['a'] += 2
1119    assert_equal(11, dn.a)
1120    dn.a += 2
1121    assert_equal(13, dn.a)
1122
1123    dn['a'] -= 3
1124    assert_equal(10, dn.a)
1125    dn.a -= 2
1126    assert_equal(8, dn.a)
1127
1128    dn['a'] *= 2
1129    assert_equal(16, dn.a)
1130    dn.a *= 2
1131    assert_equal(32, dn.a)
1132
1133    dn['a'] /= 3
1134    assert_equal(10, dn.a)
1135    dn.a /= 2
1136    assert_equal(5, dn.a)
1137
1138    dn['a'] %= 3
1139    assert_equal(2, dn.a)
1140    dn.a %= 6
1141    assert_equal(2, dn.a)
1142  END
1143  # TODO: this should also work with a :def function
1144  CheckScriptSuccess(lines)
1145enddef
1146
1147def Test_assign_lambda()
1148  # check if assign a lambda to a variable which type is func or any.
1149  var lines =<< trim END
1150      vim9script
1151      var FuncRef = () => 123
1152      assert_equal(123, FuncRef())
1153      var FuncRef_Func: func = () => 123
1154      assert_equal(123, FuncRef_Func())
1155      var FuncRef_Any: any = () => 123
1156      assert_equal(123, FuncRef_Any())
1157      var FuncRef_Number: func(): number = () => 321
1158      assert_equal(321, FuncRef_Number())
1159  END
1160  CheckScriptSuccess(lines)
1161
1162  lines =<< trim END
1163      var Ref: func(number)
1164      Ref = (j) => !j
1165  END
1166  CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected func(number) but got func(any): bool')
1167
1168  lines =<< trim END
1169      echo filter([1, 2, 3], (_, v: string) => v + 1)
1170  END
1171  CheckDefAndScriptFailure(lines, 'E1051:')
1172enddef
1173
1174def Test_heredoc()
1175  var lines =<< trim END # comment
1176    text
1177  END
1178  assert_equal(['text'], lines)
1179
1180  CheckDefFailure(['var lines =<< trim END X', 'END'], 'E488:')
1181  CheckDefFailure(['var lines =<< trim END " comment', 'END'], 'E488:')
1182
1183  lines =<< trim [END]
1184      def Func()
1185        var&lines =<< trim END
1186        x
1187        x
1188      enddef
1189      defcompile
1190  [END]
1191  CheckScriptFailure(lines, 'E1145: Missing heredoc end marker: END')
1192  delfunc! g:Func
1193
1194  lines =<< trim [END]
1195      def Func()
1196        var lines =<< trim END
1197        x
1198        x
1199        x
1200        x
1201        x
1202        x
1203        x
1204        x
1205      enddef
1206      call Func()
1207  [END]
1208  CheckScriptFailure(lines, 'E1145: Missing heredoc end marker: END')
1209  delfunc! g:Func
1210enddef
1211
1212def Test_var_func_call()
1213  var lines =<< trim END
1214    vim9script
1215    func GetValue()
1216      if exists('g:count')
1217        let g:count += 1
1218      else
1219        let g:count = 1
1220      endif
1221      return 'this'
1222    endfunc
1223    var val: string = GetValue()
1224    # env var is always a string
1225    var env = $TERM
1226  END
1227  writefile(lines, 'Xfinished')
1228  source Xfinished
1229  # GetValue() is not called during discovery phase
1230  assert_equal(1, g:count)
1231
1232  unlet g:count
1233  delete('Xfinished')
1234enddef
1235
1236def Test_var_missing_type()
1237  var lines =<< trim END
1238    vim9script
1239    var name = g:unknown
1240  END
1241  CheckScriptFailure(lines, 'E121:')
1242
1243  lines =<< trim END
1244    vim9script
1245    var nr: number = 123
1246    var name = nr
1247  END
1248  CheckScriptSuccess(lines)
1249enddef
1250
1251def Test_var_declaration()
1252  var lines =<< trim END
1253    vim9script
1254    var name: string
1255    g:var_uninit = name
1256    name = 'text'
1257    g:var_test = name
1258    # prefixing s: is optional
1259    s:name = 'prefixed'
1260    g:var_prefixed = s:name
1261
1262    const FOO: number = 123
1263    assert_equal(123, FOO)
1264    const FOOS = 'foos'
1265    assert_equal('foos', FOOS)
1266    final FLIST = [1]
1267    assert_equal([1], FLIST)
1268    FLIST[0] = 11
1269    assert_equal([11], FLIST)
1270
1271    const g:FOO: number = 321
1272    assert_equal(321, g:FOO)
1273    const g:FOOS = 'gfoos'
1274    assert_equal('gfoos', g:FOOS)
1275    final g:FLIST = [2]
1276    assert_equal([2], g:FLIST)
1277    g:FLIST[0] = 22
1278    assert_equal([22], g:FLIST)
1279
1280    def SetGlobalConst()
1281      const g:globConst = 123
1282    enddef
1283    SetGlobalConst()
1284    assert_equal(123, g:globConst)
1285    assert_true(islocked('g:globConst'))
1286
1287    const w:FOO: number = 46
1288    assert_equal(46, w:FOO)
1289    const w:FOOS = 'wfoos'
1290    assert_equal('wfoos', w:FOOS)
1291    final w:FLIST = [3]
1292    assert_equal([3], w:FLIST)
1293    w:FLIST[0] = 33
1294    assert_equal([33], w:FLIST)
1295
1296    var s:other: number
1297    other = 1234
1298    g:other_var = other
1299
1300    var xyz: string  # comment
1301
1302    # type is inferred
1303    var s:dict = {['a']: 222}
1304    def GetDictVal(key: any)
1305      g:dict_val = s:dict[key]
1306    enddef
1307    GetDictVal('a')
1308
1309    final adict: dict<string> = {}
1310    def ChangeAdict()
1311      adict.foo = 'foo'
1312    enddef
1313    ChangeAdict()
1314  END
1315  CheckScriptSuccess(lines)
1316  assert_equal('', g:var_uninit)
1317  assert_equal('text', g:var_test)
1318  assert_equal('prefixed', g:var_prefixed)
1319  assert_equal(1234, g:other_var)
1320  assert_equal(222, g:dict_val)
1321
1322  unlet g:var_uninit
1323  unlet g:var_test
1324  unlet g:var_prefixed
1325  unlet g:other_var
1326  unlet g:FOO
1327  unlet g:FOOS
1328  unlet g:FLIST
1329  unlet w:FOO
1330  unlet w:FOOS
1331  unlet w:FLIST
1332enddef
1333
1334def Test_var_declaration_fails()
1335  var lines =<< trim END
1336    vim9script
1337    final var: string
1338  END
1339  CheckScriptFailure(lines, 'E1125:')
1340
1341  lines =<< trim END
1342    vim9script
1343    const g:constvar = 'string'
1344    g:constvar = 'xx'
1345  END
1346  CheckScriptFailure(lines, 'E741:')
1347  unlet g:constvar
1348
1349  lines =<< trim END
1350    vim9script
1351    var name = 'one'
1352    lockvar name
1353    def SetLocked()
1354      name = 'two'
1355    enddef
1356    SetLocked()
1357  END
1358  CheckScriptFailure(lines, 'E741: Value is locked: name', 1)
1359
1360  lines =<< trim END
1361    let s:legacy = 'one'
1362    lockvar s:legacy
1363    def SetLocked()
1364      s:legacy = 'two'
1365    enddef
1366    call SetLocked()
1367  END
1368  CheckScriptFailure(lines, 'E741: Value is locked: s:legacy', 1)
1369
1370  lines =<< trim END
1371    vim9script
1372    def SetGlobalConst()
1373      const g:globConst = 123
1374    enddef
1375    SetGlobalConst()
1376    g:globConst = 234
1377  END
1378  CheckScriptFailure(lines, 'E741: Value is locked: globConst', 1)
1379  unlet g:globConst
1380
1381  lines =<< trim END
1382    vim9script
1383    const cdict: dict<string> = {}
1384    def Change()
1385      cdict.foo = 'foo'
1386    enddef
1387    defcompile
1388  END
1389  CheckScriptFailure(lines, 'E46:')
1390
1391  lines =<< trim END
1392    vim9script
1393    final w:finalvar = [9]
1394    w:finalvar = [8]
1395  END
1396  CheckScriptFailure(lines, 'E1122:')
1397  unlet w:finalvar
1398
1399  lines =<< trim END
1400    vim9script
1401    const var: string
1402  END
1403  CheckScriptFailure(lines, 'E1021:')
1404
1405  lines =<< trim END
1406    vim9script
1407    var 9var: string
1408  END
1409  CheckScriptFailure(lines, 'E488:')
1410
1411  CheckDefFailure(['var foo.bar = 2'], 'E1087:')
1412  CheckDefFailure(['var foo[3] = 2'], 'E1087:')
1413  CheckDefFailure(['const foo: number'], 'E1021:')
1414enddef
1415
1416def Test_var_type_check()
1417  var lines =<< trim END
1418    vim9script
1419    var name: string
1420    name = 1234
1421  END
1422  CheckScriptFailure(lines, 'E1012:')
1423
1424  lines =<< trim END
1425    vim9script
1426    var name:string
1427  END
1428  CheckScriptFailure(lines, 'E1069:')
1429
1430  lines =<< trim END
1431    vim9script
1432    var name: asdf
1433  END
1434  CheckScriptFailure(lines, 'E1010:')
1435
1436  lines =<< trim END
1437    vim9script
1438    var s:l: list<number>
1439    s:l = []
1440  END
1441  CheckScriptSuccess(lines)
1442
1443  lines =<< trim END
1444    vim9script
1445    var s:d: dict<number>
1446    s:d = {}
1447  END
1448  CheckScriptSuccess(lines)
1449enddef
1450
1451let g:dict_number = #{one: 1, two: 2}
1452
1453def Test_var_list_dict_type()
1454  var ll: list<number>
1455  ll = [1, 2, 2, 3, 3, 3]->uniq()
1456  ll->assert_equal([1, 2, 3])
1457
1458  var dd: dict<number>
1459  dd = g:dict_number
1460  dd->assert_equal(g:dict_number)
1461
1462  var lines =<< trim END
1463      var ll: list<number>
1464      ll = [1, 2, 3]->map('"one"')
1465  END
1466  CheckDefExecFailure(lines, 'E1012: Type mismatch; expected number but got string')
1467enddef
1468
1469def Test_cannot_use_let()
1470  CheckDefAndScriptFailure(['let a = 34'], 'E1126:', 1)
1471enddef
1472
1473def Test_unlet()
1474  g:somevar = 'yes'
1475  assert_true(exists('g:somevar'))
1476  unlet g:somevar
1477  assert_false(exists('g:somevar'))
1478  unlet! g:somevar
1479
1480  # also works for script-local variable in legacy Vim script
1481  s:somevar = 'legacy'
1482  assert_true(exists('s:somevar'))
1483  unlet s:somevar
1484  assert_false(exists('s:somevar'))
1485  unlet! s:somevar
1486
1487  CheckDefExecFailure([
1488    'var dd = 111',
1489    'unlet dd',
1490    ], 'E1081:', 2)
1491
1492  # dict unlet
1493  var dd = {a: 1, b: 2, c: 3}
1494  unlet dd['a']
1495  unlet dd.c
1496  assert_equal({b: 2}, dd)
1497
1498  # list unlet
1499  var ll = [1, 2, 3, 4]
1500  unlet ll[1]
1501  unlet ll[-1]
1502  assert_equal([1, 3], ll)
1503
1504  ll = [1, 2, 3, 4]
1505  unlet ll[0 : 1]
1506  assert_equal([3, 4], ll)
1507
1508  ll = [1, 2, 3, 4]
1509  unlet ll[2 : 8]
1510  assert_equal([1, 2], ll)
1511
1512  ll = [1, 2, 3, 4]
1513  unlet ll[-2 : -1]
1514  assert_equal([1, 2], ll)
1515
1516  CheckDefFailure([
1517    'var ll = [1, 2]',
1518    'll[1 : 2] = 7',
1519    ], 'E1165:', 2)
1520  CheckDefFailure([
1521    'var dd = {a: 1}',
1522    'unlet dd["a" : "a"]',
1523    ], 'E1166:', 2)
1524  CheckDefExecFailure([
1525    'unlet g:adict[0 : 1]',
1526    ], 'E1148:', 1)
1527  CheckDefFailure([
1528    'var ll = [1, 2]',
1529    'unlet ll[0:1]',
1530    ], 'E1004:', 2)
1531  CheckDefFailure([
1532    'var ll = [1, 2]',
1533    'unlet ll[0 :1]',
1534    ], 'E1004:', 2)
1535  CheckDefFailure([
1536    'var ll = [1, 2]',
1537    'unlet ll[0: 1]',
1538    ], 'E1004:', 2)
1539
1540  CheckDefFailure([
1541    'var ll = [1, 2]',
1542    'unlet ll["x" : 1]',
1543    ], 'E1012:', 2)
1544  CheckDefFailure([
1545    'var ll = [1, 2]',
1546    'unlet ll[0 : "x"]',
1547    ], 'E1012:', 2)
1548
1549  # list of dict unlet
1550  var dl = [{a: 1, b: 2}, {c: 3}]
1551  unlet dl[0]['b']
1552  assert_equal([{a: 1}, {c: 3}], dl)
1553
1554  CheckDefExecFailure([
1555    'var ll = test_null_list()',
1556    'unlet ll[0]',
1557    ], 'E684:', 2)
1558  CheckDefExecFailure([
1559    'var ll = [1]',
1560    'unlet ll[2]',
1561    ], 'E684:', 2)
1562  CheckDefExecFailure([
1563    'var ll = [1]',
1564    'unlet ll[g:astring]',
1565    ], 'E1012:', 2)
1566  CheckDefExecFailure([
1567    'var dd = test_null_dict()',
1568    'unlet dd["a"]',
1569    ], 'E716:', 2)
1570  CheckDefExecFailure([
1571    'var dd = {a: 1}',
1572    'unlet dd["b"]',
1573    ], 'E716:', 2)
1574  CheckDefExecFailure([
1575    'var dd = {a: 1}',
1576    'unlet dd[g:alist]',
1577    ], 'E1105:', 2)
1578
1579  # can compile unlet before variable exists
1580  g:someDict = {key: 'val'}
1581  var k = 'key'
1582  unlet g:someDict[k]
1583  assert_equal({}, g:someDict)
1584  unlet g:someDict
1585  assert_false(exists('g:someDict'))
1586
1587  CheckScriptFailure([
1588   'vim9script',
1589   'var svar = 123',
1590   'unlet svar',
1591   ], 'E1081:')
1592  CheckScriptFailure([
1593   'vim9script',
1594   'var svar = 123',
1595   'unlet s:svar',
1596   ], 'E1081:')
1597  CheckScriptFailure([
1598   'vim9script',
1599   'var svar = 123',
1600   'def Func()',
1601   '  unlet svar',
1602   'enddef',
1603   'defcompile',
1604   ], 'E1081:')
1605  CheckScriptFailure([
1606   'vim9script',
1607   'var svar = 123',
1608   'func Func()',
1609   '  unlet s:svar',
1610   'endfunc',
1611   'Func()',
1612   ], 'E1081:')
1613  CheckScriptFailure([
1614   'vim9script',
1615   'var svar = 123',
1616   'def Func()',
1617   '  unlet s:svar',
1618   'enddef',
1619   'defcompile',
1620   ], 'E1081:')
1621
1622  writefile(['vim9script', 'export var svar = 1234'], 'XunletExport.vim')
1623  var lines =<< trim END
1624    vim9script
1625    import svar from './XunletExport.vim'
1626    def UnletSvar()
1627      unlet svar
1628    enddef
1629    defcompile
1630  END
1631  CheckScriptFailure(lines, 'E1081:', 1)
1632  delete('XunletExport.vim')
1633
1634  $ENVVAR = 'foobar'
1635  assert_equal('foobar', $ENVVAR)
1636  unlet $ENVVAR
1637  assert_equal('', $ENVVAR)
1638enddef
1639
1640def Test_expr_error_no_assign()
1641  var lines =<< trim END
1642      vim9script
1643      var x = invalid
1644      echo x
1645  END
1646  CheckScriptFailureList(lines, ['E121:', 'E121:'])
1647
1648  lines =<< trim END
1649      vim9script
1650      var x = 1 / 0
1651      echo x
1652  END
1653  CheckScriptFailureList(lines, ['E1154:', 'E121:'])
1654
1655  lines =<< trim END
1656      vim9script
1657      var x = 1 % 0
1658      echo x
1659  END
1660  CheckScriptFailureList(lines, ['E1154:', 'E121:'])
1661
1662  lines =<< trim END
1663      var x: string  'string'
1664  END
1665  CheckDefAndScriptFailure(lines, 'E488:')
1666enddef
1667
1668
1669def Test_assign_command_modifier()
1670  var lines =<< trim END
1671      var verbose = 0
1672      verbose = 1
1673      assert_equal(1, verbose)
1674      silent verbose = 2
1675      assert_equal(2, verbose)
1676      silent verbose += 2
1677      assert_equal(4, verbose)
1678      silent verbose -= 1
1679      assert_equal(3, verbose)
1680
1681      var topleft = {one: 1}
1682      sandbox topleft.one = 3
1683      assert_equal({one: 3}, topleft)
1684      leftabove topleft[' '] = 4
1685      assert_equal({one: 3, ' ': 4}, topleft)
1686
1687      var x: number
1688      var y: number
1689      silent [x, y] = [1, 2]
1690      assert_equal(1, x)
1691      assert_equal(2, y)
1692  END
1693  CheckDefAndScriptSuccess(lines)
1694enddef
1695
1696def Test_script_funcref_case()
1697  var lines =<< trim END
1698      var Len = (s: string): number => len(s) + 1
1699      assert_equal(5, Len('asdf'))
1700  END
1701  CheckDefAndScriptSuccess(lines)
1702
1703  lines =<< trim END
1704      var len = (s: string): number => len(s) + 1
1705  END
1706  CheckDefAndScriptFailure(lines, 'E704:')
1707
1708  lines =<< trim END
1709      vim9script
1710      var s:Len = (s: string): number => len(s) + 2
1711      assert_equal(6, Len('asdf'))
1712  END
1713  CheckScriptSuccess(lines)
1714
1715  lines =<< trim END
1716      vim9script
1717      var s:len = (s: string): number => len(s) + 1
1718  END
1719  CheckScriptFailure(lines, 'E704:')
1720enddef
1721
1722
1723" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1724