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