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