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