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