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