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