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_index()
229  # list of list
230  var l1: list<number>
231  l1[0] = 123
232  assert_equal([123], l1)
233
234  var l2: list<list<number>>
235  l2[0] = []
236  l2[0][0] = 123
237  assert_equal([[123]], l2)
238
239  var l3: list<list<list<number>>>
240  l3[0] = []
241  l3[0][0] = []
242  l3[0][0][0] = 123
243  assert_equal([[[123]]], l3)
244
245  var lines =<< trim END
246      var l3: list<list<number>>
247      l3[0] = []
248      l3[0][0] = []
249  END
250  CheckDefFailure(lines, 'E1012: Type mismatch; expected number but got list<unknown>', 3)
251
252  # dict of dict
253  var d1: dict<number>
254  d1.one = 1
255  assert_equal({one: 1}, d1)
256
257  var d2: dict<dict<number>>
258  d2.one = {}
259  d2.one.two = 123
260  assert_equal({one: {two: 123}}, d2)
261
262  var d3: dict<dict<dict<number>>>
263  d3.one = {}
264  d3.one.two = {}
265  d3.one.two.three = 123
266  assert_equal({one: {two: {three: 123}}}, d3)
267
268  lines =<< trim END
269      var d3: dict<dict<number>>
270      d3.one = {}
271      d3.one.two = {}
272  END
273  CheckDefFailure(lines, 'E1012: Type mismatch; expected number but got dict<unknown>', 3)
274
275  # list of dict
276  var ld: list<dict<number>>
277  ld[0] = {}
278  ld[0].one = 123
279  assert_equal([{one: 123}], ld)
280
281  lines =<< trim END
282      var ld: list<dict<number>>
283      ld[0] = []
284  END
285  CheckDefFailure(lines, 'E1012: Type mismatch; expected dict<number> but got list<unknown>', 2)
286
287  # dict of list
288  var dl: dict<list<number>>
289  dl.one = []
290  dl.one[0] = 123
291  assert_equal({one: [123]}, dl)
292
293  lines =<< trim END
294      var dl: dict<list<number>>
295      dl.one = {}
296  END
297  CheckDefFailure(lines, 'E1012: Type mismatch; expected list<number> but got dict<unknown>', 2)
298enddef
299
300def Test_extend_list()
301  var lines =<< trim END
302      vim9script
303      var l: list<number>
304      l += [123]
305      assert_equal([123], l)
306  END
307  CheckScriptSuccess(lines)
308
309  lines =<< trim END
310      vim9script
311      var list: list<string>
312      extend(list, ['x'])
313      assert_equal(['x'], list)
314  END
315  CheckScriptSuccess(lines)
316
317  # appending to NULL list from a function
318  lines =<< trim END
319      vim9script
320      var list: list<string>
321      def Func()
322        list += ['a', 'b']
323      enddef
324      Func()
325      assert_equal(['a', 'b'], list)
326  END
327  CheckScriptSuccess(lines)
328
329  lines =<< trim END
330      vim9script
331      var l: list<string> = test_null_list()
332      extend(l, ['x'])
333      assert_equal(['x'], l)
334  END
335  CheckScriptSuccess(lines)
336
337  lines =<< trim END
338      vim9script
339      extend(test_null_list(), ['x'])
340  END
341  CheckScriptFailure(lines, 'E1134:', 2)
342enddef
343
344def Test_extend_dict()
345  var lines =<< trim END
346      vim9script
347      var d: dict<number>
348      extend(d, #{a: 1})
349      assert_equal(#{a: 1}, d)
350
351      var d2: dict<number>
352      d2['one'] = 1
353      assert_equal(#{one: 1}, d2)
354  END
355  CheckScriptSuccess(lines)
356
357  lines =<< trim END
358      vim9script
359      var d: dict<string> = test_null_dict()
360      extend(d, #{a: 'x'})
361      assert_equal(#{a: 'x'}, d)
362  END
363  CheckScriptSuccess(lines)
364
365  lines =<< trim END
366      vim9script
367      extend(test_null_dict(), #{a: 'x'})
368  END
369  CheckScriptFailure(lines, 'E1133:', 2)
370enddef
371
372def Test_single_letter_vars()
373  # single letter variables
374  var a: number = 123
375  a = 123
376  assert_equal(123, a)
377  var b: number
378  b = 123
379  assert_equal(123, b)
380  var g: number
381  g = 123
382  assert_equal(123, g)
383  var s: number
384  s = 123
385  assert_equal(123, s)
386  var t: number
387  t = 123
388  assert_equal(123, t)
389  var v: number
390  v = 123
391  assert_equal(123, v)
392  var w: number
393  w = 123
394  assert_equal(123, w)
395enddef
396
397def Test_vim9_single_char_vars()
398  var lines =<< trim END
399      vim9script
400
401      # single character variable declarations work
402      var a: string
403      var b: number
404      var l: list<any>
405      var s: string
406      var t: number
407      var v: number
408      var w: number
409
410      # script-local variables can be used without s: prefix
411      a = 'script-a'
412      b = 111
413      l = [1, 2, 3]
414      s = 'script-s'
415      t = 222
416      v = 333
417      w = 444
418
419      assert_equal('script-a', a)
420      assert_equal(111, b)
421      assert_equal([1, 2, 3], l)
422      assert_equal('script-s', s)
423      assert_equal(222, t)
424      assert_equal(333, v)
425      assert_equal(444, w)
426  END
427  writefile(lines, 'Xsinglechar')
428  source Xsinglechar
429  delete('Xsinglechar')
430enddef
431
432def Test_assignment_list()
433  var list1: list<bool> = [false, true, false]
434  var list2: list<number> = [1, 2, 3]
435  var list3: list<string> = ['sdf', 'asdf']
436  var list4: list<any> = ['yes', true, 1234]
437  var list5: list<blob> = [0z01, 0z02]
438
439  var listS: list<string> = []
440  var listN: list<number> = []
441
442  assert_equal([1, 2, 3], list2)
443  list2[-1] = 99
444  assert_equal([1, 2, 99], list2)
445  list2[-2] = 88
446  assert_equal([1, 88, 99], list2)
447  list2[-3] = 77
448  assert_equal([77, 88, 99], list2)
449  list2 += [100]
450  assert_equal([77, 88, 99, 100], list2)
451
452  list3 += ['end']
453  assert_equal(['sdf', 'asdf', 'end'], list3)
454
455  CheckDefExecFailure(['var ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
456  CheckDefExecFailure(['var [v1, v2] = [1, 2]'], 'E1092:')
457
458  # type becomes list<any>
459  var somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
460enddef
461
462def Test_assignment_list_vim9script()
463  var lines =<< trim END
464    vim9script
465    var v1: number
466    var v2: number
467    var v3: number
468    [v1, v2, v3] = [1, 2, 3]
469    assert_equal([1, 2, 3], [v1, v2, v3])
470  END
471  CheckScriptSuccess(lines)
472enddef
473
474def Test_assignment_dict()
475  var dict1: dict<bool> = #{one: false, two: true}
476  var dict2: dict<number> = #{one: 1, two: 2}
477  var dict3: dict<string> = #{key: 'value'}
478  var dict4: dict<any> = #{one: 1, two: '2'}
479  var dict5: dict<blob> = #{one: 0z01, two: 0z02}
480
481  # overwrite
482  dict3['key'] = 'another'
483  assert_equal(dict3, #{key: 'another'})
484  dict3.key = 'yet another'
485  assert_equal(dict3, #{key: 'yet another'})
486
487  var lines =<< trim END
488    var dd = #{one: 1}
489    dd.one) = 2
490  END
491  CheckDefFailure(lines, 'E15:', 2)
492
493  # empty key can be used
494  var dd = {}
495  dd[""] = 6
496  assert_equal({'': 6}, dd)
497
498  # type becomes dict<any>
499  var somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
500
501  # assignment to script-local dict
502  lines =<< trim END
503    vim9script
504    var test: dict<any> = {}
505    def FillDict(): dict<any>
506      test['a'] = 43
507      return test
508    enddef
509    assert_equal(#{a: 43}, FillDict())
510  END
511  CheckScriptSuccess(lines)
512
513  lines =<< trim END
514    vim9script
515    var test: dict<any>
516    def FillDict(): dict<any>
517      test['a'] = 43
518      return test
519    enddef
520    FillDict()
521  END
522  CheckScriptFailure(lines, 'E1103:')
523
524  # assignment to global dict
525  lines =<< trim END
526    vim9script
527    g:test = {}
528    def FillDict(): dict<any>
529      g:test['a'] = 43
530      return g:test
531    enddef
532    assert_equal(#{a: 43}, FillDict())
533  END
534  CheckScriptSuccess(lines)
535
536  # assignment to buffer dict
537  lines =<< trim END
538    vim9script
539    b:test = {}
540    def FillDict(): dict<any>
541      b:test['a'] = 43
542      return b:test
543    enddef
544    assert_equal(#{a: 43}, FillDict())
545  END
546  CheckScriptSuccess(lines)
547enddef
548
549def Test_assignment_local()
550  # Test in a separated file in order not to the current buffer/window/tab is
551  # changed.
552  var script_lines: list<string> =<< trim END
553    let b:existing = 'yes'
554    let w:existing = 'yes'
555    let t:existing = 'yes'
556
557    def Test_assignment_local_internal()
558      b:newvar = 'new'
559      assert_equal('new', b:newvar)
560      assert_equal('yes', b:existing)
561      b:existing = 'no'
562      assert_equal('no', b:existing)
563      b:existing ..= 'NO'
564      assert_equal('noNO', b:existing)
565
566      w:newvar = 'new'
567      assert_equal('new', w:newvar)
568      assert_equal('yes', w:existing)
569      w:existing = 'no'
570      assert_equal('no', w:existing)
571      w:existing ..= 'NO'
572      assert_equal('noNO', w:existing)
573
574      t:newvar = 'new'
575      assert_equal('new', t:newvar)
576      assert_equal('yes', t:existing)
577      t:existing = 'no'
578      assert_equal('no', t:existing)
579      t:existing ..= 'NO'
580      assert_equal('noNO', t:existing)
581    enddef
582    call Test_assignment_local_internal()
583  END
584  CheckScriptSuccess(script_lines)
585enddef
586
587def Test_assignment_default()
588  # Test default values.
589  var thebool: bool
590  assert_equal(v:false, thebool)
591
592  var thenumber: number
593  assert_equal(0, thenumber)
594
595  if has('float')
596    var thefloat: float
597    assert_equal(0.0, thefloat)
598  endif
599
600  var thestring: string
601  assert_equal('', thestring)
602
603  var theblob: blob
604  assert_equal(0z, theblob)
605
606  var Thefunc: func
607  assert_equal(test_null_function(), Thefunc)
608
609  var thelist: list<any>
610  assert_equal([], thelist)
611
612  var thedict: dict<any>
613  assert_equal({}, thedict)
614
615  if has('channel')
616    var thejob: job
617    assert_equal(test_null_job(), thejob)
618
619    var thechannel: channel
620    assert_equal(test_null_channel(), thechannel)
621
622    if has('unix') && executable('cat')
623      # check with non-null job and channel, types must match
624      thejob = job_start("cat ", #{})
625      thechannel = job_getchannel(thejob)
626      job_stop(thejob, 'kill')
627    endif
628  endif
629
630  var nr = 1234 | nr = 5678
631  assert_equal(5678, nr)
632enddef
633
634def Test_assignment_var_list()
635  var v1: string
636  var v2: string
637  var vrem: list<string>
638  [v1] = ['aaa']
639  assert_equal('aaa', v1)
640
641  [v1, v2] = ['one', 'two']
642  assert_equal('one', v1)
643  assert_equal('two', v2)
644
645  [v1, v2; vrem] = ['one', 'two']
646  assert_equal('one', v1)
647  assert_equal('two', v2)
648  assert_equal([], vrem)
649
650  [v1, v2; vrem] = ['one', 'two', 'three']
651  assert_equal('one', v1)
652  assert_equal('two', v2)
653  assert_equal(['three'], vrem)
654
655  [&ts, &sw] = [3, 4]
656  assert_equal(3, &ts)
657  assert_equal(4, &sw)
658  set ts=8 sw=4
659enddef
660
661def Test_assignment_vim9script()
662  var lines =<< trim END
663    vim9script
664    def Func(): list<number>
665      return [1, 2]
666    enddef
667    var name1: number
668    var name2: number
669    [name1, name2] =
670          Func()
671    assert_equal(1, name1)
672    assert_equal(2, name2)
673    var ll =
674          Func()
675    assert_equal([1, 2], ll)
676
677    @/ = 'text'
678    assert_equal('text', @/)
679    @0 = 'zero'
680    assert_equal('zero', @0)
681    @1 = 'one'
682    assert_equal('one', @1)
683    @9 = 'nine'
684    assert_equal('nine', @9)
685    @- = 'minus'
686    assert_equal('minus', @-)
687    if has('clipboard_working')
688      @* = 'star'
689      assert_equal('star', @*)
690      @+ = 'plus'
691      assert_equal('plus', @+)
692    endif
693
694    var a: number = 123
695    assert_equal(123, a)
696    var s: string = 'yes'
697    assert_equal('yes', s)
698    var b: number = 42
699    assert_equal(42, b)
700    var w: number = 43
701    assert_equal(43, w)
702    var t: number = 44
703    assert_equal(44, t)
704
705    var to_var = 0
706    to_var = 3
707    assert_equal(3, to_var)
708  END
709  CheckScriptSuccess(lines)
710
711  lines =<< trim END
712      vim9script
713      var n: number
714      def Func()
715        n = 'string'
716      enddef
717      defcompile
718  END
719  CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
720enddef
721
722def Mess(): string
723  v:foldstart = 123
724  return 'xxx'
725enddef
726
727def Test_assignment_failure()
728  CheckDefFailure(['var name=234'], 'E1004:')
729  CheckDefFailure(['var name =234'], 'E1004:')
730  CheckDefFailure(['var name= 234'], 'E1004:')
731
732  CheckScriptFailure(['vim9script', 'var name=234'], 'E1004:')
733  CheckScriptFailure(['vim9script', 'var name=234'], "before and after '='")
734  CheckScriptFailure(['vim9script', 'var name =234'], 'E1004:')
735  CheckScriptFailure(['vim9script', 'var name= 234'], 'E1004:')
736  CheckScriptFailure(['vim9script', 'var name = 234', 'name+=234'], 'E1004:')
737  CheckScriptFailure(['vim9script', 'var name = 234', 'name+=234'], "before and after '+='")
738  CheckScriptFailure(['vim9script', 'var name = "x"', 'name..="y"'], 'E1004:')
739  CheckScriptFailure(['vim9script', 'var name = "x"', 'name..="y"'], "before and after '..='")
740
741  CheckDefFailure(['var true = 1'], 'E1034:')
742  CheckDefFailure(['var false = 1'], 'E1034:')
743
744  CheckDefFailure(['[a; b; c] = g:list'], 'E452:')
745  CheckDefExecFailure(['var a: number',
746                       '[a] = test_null_list()'], 'E1093:')
747  CheckDefExecFailure(['var a: number',
748                       '[a] = []'], 'E1093:')
749  CheckDefExecFailure(['var x: number',
750                       'var y: number',
751                       '[x, y] = [1]'], 'E1093:')
752  CheckDefExecFailure(['var x: string',
753                       'var y: string',
754                       '[x, y] = ["x"]'], 'E1093:')
755  CheckDefExecFailure(['var x: number',
756                       'var y: number',
757                       'var z: list<number>',
758                       '[x, y; z] = [1]'], 'E1093:')
759
760  CheckDefFailure(['var somevar'], "E1022:")
761  CheckDefFailure(['var &tabstop = 4'], 'E1052:')
762  CheckDefFailure(['&g:option = 5'], 'E113:')
763  CheckScriptFailure(['vim9script', 'var &tabstop = 4'], 'E1052:')
764
765  CheckDefFailure(['var $VAR = 5'], 'E1016: Cannot declare an environment variable:')
766  CheckScriptFailure(['vim9script', 'var $ENV = "xxx"'], 'E1016:')
767
768  if has('dnd')
769    CheckDefFailure(['var @~ = 5'], 'E1066:')
770  else
771    CheckDefFailure(['var @~ = 5'], 'E354:')
772    CheckDefFailure(['@~ = 5'], 'E354:')
773  endif
774  CheckDefFailure(['var @a = 5'], 'E1066:')
775  CheckDefFailure(['var @/ = "x"'], 'E1066:')
776  CheckScriptFailure(['vim9script', 'var @a = "abc"'], 'E1066:')
777
778  CheckDefFailure(['var g:var = 5'], 'E1016: Cannot declare a global variable:')
779  CheckDefFailure(['var w:var = 5'], 'E1016: Cannot declare a window variable:')
780  CheckDefFailure(['var b:var = 5'], 'E1016: Cannot declare a buffer variable:')
781  CheckDefFailure(['var t:var = 5'], 'E1016: Cannot declare a tab variable:')
782
783  CheckDefFailure(['var anr = 4', 'anr ..= "text"'], 'E1019:')
784  CheckDefFailure(['var xnr += 4'], 'E1020:', 1)
785  CheckScriptFailure(['vim9script', 'var xnr += 4'], 'E1020:')
786  CheckDefFailure(["var xnr = xnr + 1"], 'E1001:', 1)
787  CheckScriptFailure(['vim9script', 'var xnr = xnr + 4'], 'E121:')
788
789  CheckScriptFailure(['vim9script', 'def Func()', 'var dummy = s:notfound', 'enddef', 'defcompile'], 'E1108:')
790
791  CheckDefFailure(['var name: list<string> = [123]'], 'expected list<string> but got list<number>')
792  CheckDefFailure(['var name: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
793
794  CheckDefFailure(['var name: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
795  CheckDefFailure(['var name: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
796
797  CheckDefFailure(['var name = feedkeys("0")'], 'E1031:')
798  CheckDefFailure(['var name: number = feedkeys("0")'], 'expected number but got void')
799
800  CheckDefFailure(['var name: dict <number>'], 'E1068:')
801  CheckDefFailure(['var name: dict<number'], 'E1009:')
802
803  assert_fails('s/^/\=Mess()/n', 'E794:')
804  CheckDefFailure(['var name: dict<number'], 'E1009:')
805
806  CheckDefFailure(['w:foo: number = 10'],
807                  'E488: Trailing characters: : number = 1')
808  CheckDefFailure(['t:foo: bool = true'],
809                  'E488: Trailing characters: : bool = true')
810  CheckDefFailure(['b:foo: string = "x"'],
811                  'E488: Trailing characters: : string = "x"')
812  CheckDefFailure(['g:foo: number = 123'],
813                  'E488: Trailing characters: : number = 123')
814enddef
815
816def Test_assign_list()
817  var l: list<string> = []
818  l[0] = 'value'
819  assert_equal('value', l[0])
820
821  l[1] = 'asdf'
822  assert_equal('value', l[0])
823  assert_equal('asdf', l[1])
824  assert_equal('asdf', l[-1])
825  assert_equal('value', l[-2])
826
827  var nrl: list<number> = []
828  for i in range(5)
829    nrl[i] = i
830  endfor
831  assert_equal([0, 1, 2, 3, 4], nrl)
832
833  CheckDefFailure(["var l: list<number> = ['', true]"], 'E1012: Type mismatch; expected list<number> but got list<any>', 1)
834  CheckDefFailure(["var l: list<list<number>> = [['', true]]"], 'E1012: Type mismatch; expected list<list<number>> but got list<list<any>>', 1)
835enddef
836
837def Test_assign_dict()
838  var d: dict<string> = {}
839  d['key'] = 'value'
840  assert_equal('value', d['key'])
841
842  d[123] = 'qwerty'
843  assert_equal('qwerty', d[123])
844  assert_equal('qwerty', d['123'])
845
846  var nrd: dict<number> = {}
847  for i in range(3)
848    nrd[i] = i
849  endfor
850  assert_equal({'0': 0, '1': 1, '2': 2}, nrd)
851
852  CheckDefFailure(["var d: dict<number> = #{a: '', b: true}"], 'E1012: Type mismatch; expected dict<number> but got dict<any>', 1)
853  CheckDefFailure(["var d: dict<dict<number>> = #{x: #{a: '', b: true}}"], 'E1012: Type mismatch; expected dict<dict<number>> but got dict<dict<any>>', 1)
854enddef
855
856def Test_assign_dict_unknown_type()
857  var lines =<< trim END
858      vim9script
859      var mylist = []
860      mylist += [#{one: 'one'}]
861      def Func()
862        var dd = mylist[0]
863        assert_equal('one', dd.one)
864      enddef
865      Func()
866  END
867  CheckScriptSuccess(lines)
868
869  lines =<< trim END
870      vim9script
871      var mylist = [[]]
872      mylist[0] += [#{one: 'one'}]
873      def Func()
874        var dd = mylist[0][0]
875        assert_equal('one', dd.one)
876      enddef
877      Func()
878  END
879  CheckScriptSuccess(lines)
880enddef
881
882def Test_assign_lambda()
883  # check if assign a lambda to a variable which type is func or any.
884  var lines =<< trim END
885      vim9script
886      var FuncRef = {->123}
887      assert_equal(123, FuncRef())
888      var FuncRef_Func: func = {->123}
889      assert_equal(123, FuncRef_Func())
890      var FuncRef_Any: any = {->123}
891      assert_equal(123, FuncRef_Any())
892  END
893  CheckScriptSuccess(lines)
894enddef
895
896def Test_heredoc()
897  var lines =<< trim END # comment
898    text
899  END
900  assert_equal(['text'], lines)
901
902  CheckDefFailure(['var lines =<< trim END X', 'END'], 'E488:')
903  CheckDefFailure(['var lines =<< trim END " comment', 'END'], 'E488:')
904
905  lines =<< trim [END]
906      def Func()
907        var&lines =<< trim END
908        x
909        x
910        x
911        x
912        x
913        x
914        x
915        x
916      enddef
917      call Func()
918  [END]
919  CheckScriptFailure(lines, 'E990:')
920enddef
921
922def Test_let_func_call()
923  var lines =<< trim END
924    vim9script
925    func GetValue()
926      if exists('g:count')
927        let g:count += 1
928      else
929        let g:count = 1
930      endif
931      return 'this'
932    endfunc
933    var val: string = GetValue()
934    # env var is always a string
935    var env = $TERM
936  END
937  writefile(lines, 'Xfinished')
938  source Xfinished
939  # GetValue() is not called during discovery phase
940  assert_equal(1, g:count)
941
942  unlet g:count
943  delete('Xfinished')
944enddef
945
946def Test_let_missing_type()
947  var lines =<< trim END
948    vim9script
949    var name = g:unknown
950  END
951  CheckScriptFailure(lines, 'E121:')
952
953  lines =<< trim END
954    vim9script
955    var nr: number = 123
956    var name = nr
957  END
958  CheckScriptSuccess(lines)
959enddef
960
961def Test_let_declaration()
962  var lines =<< trim END
963    vim9script
964    var name: string
965    g:var_uninit = name
966    name = 'text'
967    g:var_test = name
968    # prefixing s: is optional
969    s:name = 'prefixed'
970    g:var_prefixed = s:name
971
972    var s:other: number
973    other = 1234
974    g:other_var = other
975
976    # type is inferred
977    s:dict = {'a': 222}
978    def GetDictVal(key: any)
979      g:dict_val = s:dict[key]
980    enddef
981    GetDictVal('a')
982  END
983  CheckScriptSuccess(lines)
984  assert_equal('', g:var_uninit)
985  assert_equal('text', g:var_test)
986  assert_equal('prefixed', g:var_prefixed)
987  assert_equal(1234, g:other_var)
988  assert_equal(222, g:dict_val)
989
990  unlet g:var_uninit
991  unlet g:var_test
992  unlet g:var_prefixed
993  unlet g:other_var
994enddef
995
996def Test_let_declaration_fails()
997  var lines =<< trim END
998    vim9script
999    final var: string
1000  END
1001  CheckScriptFailure(lines, 'E1125:')
1002
1003  lines =<< trim END
1004    vim9script
1005    const var: string
1006  END
1007  CheckScriptFailure(lines, 'E1021:')
1008
1009  lines =<< trim END
1010    vim9script
1011    var 9var: string
1012  END
1013  CheckScriptFailure(lines, 'E475:')
1014enddef
1015
1016def Test_let_type_check()
1017  var lines =<< trim END
1018    vim9script
1019    var name: string
1020    name = 1234
1021  END
1022  CheckScriptFailure(lines, 'E1012:')
1023
1024  lines =<< trim END
1025    vim9script
1026    var name:string
1027  END
1028  CheckScriptFailure(lines, 'E1069:')
1029
1030  lines =<< trim END
1031    vim9script
1032    var name: asdf
1033  END
1034  CheckScriptFailure(lines, 'E1010:')
1035
1036  lines =<< trim END
1037    vim9script
1038    var s:l: list<number>
1039    s:l = []
1040  END
1041  CheckScriptSuccess(lines)
1042
1043  lines =<< trim END
1044    vim9script
1045    var s:d: dict<number>
1046    s:d = {}
1047  END
1048  CheckScriptSuccess(lines)
1049enddef
1050
1051let g:dict_number = #{one: 1, two: 2}
1052
1053def Test_let_list_dict_type()
1054  var ll: list<number>
1055  ll = [1, 2, 2, 3, 3, 3]->uniq()
1056  ll->assert_equal([1, 2, 3])
1057
1058  var dd: dict<number>
1059  dd = g:dict_number
1060  dd->assert_equal(g:dict_number)
1061
1062  var lines =<< trim END
1063      var ll: list<number>
1064      ll = [1, 2, 3]->map('"one"')
1065  END
1066  CheckDefExecFailure(lines, 'E1012: Type mismatch; expected list<number> but got list<string>')
1067enddef
1068
1069def Test_unlet()
1070  g:somevar = 'yes'
1071  assert_true(exists('g:somevar'))
1072  unlet g:somevar
1073  assert_false(exists('g:somevar'))
1074  unlet! g:somevar
1075
1076  # also works for script-local variable in legacy Vim script
1077  s:somevar = 'legacy'
1078  assert_true(exists('s:somevar'))
1079  unlet s:somevar
1080  assert_false(exists('s:somevar'))
1081  unlet! s:somevar
1082
1083  CheckScriptFailure([
1084   'vim9script',
1085   'var svar = 123',
1086   'unlet svar',
1087   ], 'E1081:')
1088  CheckScriptFailure([
1089   'vim9script',
1090   'var svar = 123',
1091   'unlet s:svar',
1092   ], 'E1081:')
1093  CheckScriptFailure([
1094   'vim9script',
1095   'var svar = 123',
1096   'def Func()',
1097   '  unlet svar',
1098   'enddef',
1099   'defcompile',
1100   ], 'E1081:')
1101  CheckScriptFailure([
1102   'vim9script',
1103   'var svar = 123',
1104   'def Func()',
1105   '  unlet s:svar',
1106   'enddef',
1107   'defcompile',
1108   ], 'E1081:')
1109
1110  $ENVVAR = 'foobar'
1111  assert_equal('foobar', $ENVVAR)
1112  unlet $ENVVAR
1113  assert_equal('', $ENVVAR)
1114enddef
1115
1116
1117" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1118