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:adict = #{a: 1}
13let g:astring = 'text'
14
15def Test_assignment_bool()
16  var bool1: bool = true
17  assert_equal(v:true, bool1)
18  var bool2: bool = false
19  assert_equal(v:false, bool2)
20
21  var bool3: bool = 0
22  assert_equal(false, bool3)
23  var bool4: bool = 1
24  assert_equal(true, bool4)
25
26  var bool5: bool = 1 && true
27  assert_equal(true, bool5)
28  var bool6: bool = 0 && 1
29  assert_equal(false, bool6)
30  var bool7: bool = 0 || 1 && true
31  assert_equal(true, bool7)
32
33  var lines =<< trim END
34    vim9script
35    def GetFlag(): bool
36      var flag: bool = 1
37      return flag
38    enddef
39    var flag: bool = GetFlag()
40    assert_equal(true, flag)
41    flag = 0
42    assert_equal(false, flag)
43    flag = 1
44    assert_equal(true, flag)
45    flag = 1 || true
46    assert_equal(true, flag)
47    flag = 1 && false
48    assert_equal(false, flag)
49
50    var cp: bool = &cp
51    var fen: bool = &l:fen
52  END
53  CheckScriptSuccess(lines)
54  CheckDefAndScriptFailure(['var x: bool = 2'], 'E1012:')
55  CheckDefAndScriptFailure(['var x: bool = -1'], 'E1012:')
56  CheckDefAndScriptFailure(['var x: bool = [1]'], 'E1012:')
57  CheckDefAndScriptFailure(['var x: bool = {}'], 'E1012:')
58  CheckDefAndScriptFailure(['var x: bool = "x"'], 'E1012:')
59
60  CheckDefAndScriptFailure(['var x: bool = "x"', '', 'eval 0'], 'E1012:', 1)
61enddef
62
63def Test_syntax()
64  var name = 234
65  var other: list<string> = ['asdf']
66enddef
67
68def Test_assignment()
69  CheckDefFailure(['var x:string'], 'E1069:')
70  CheckDefFailure(['var x:string = "x"'], 'E1069:')
71  CheckDefFailure(['var a:string = "x"'], 'E1069:')
72  CheckDefFailure(['var lambda = () => "lambda"'], 'E704:')
73  CheckScriptFailure(['var x = "x"'], 'E1124:')
74
75  # lower case name is OK for a list
76  var lambdaLines =<< trim END
77      var lambdaList: list<func> = [Test_syntax]
78      lambdaList[0] = () => "lambda"
79  END
80  CheckDefAndScriptSuccess(lambdaLines)
81
82  var nr: number = 1234
83  CheckDefFailure(['var nr: number = "asdf"'], 'E1012:')
84
85  var a: number = 6 #comment
86  assert_equal(6, a)
87
88  if has('channel')
89    var chan1: channel
90    assert_equal('fail', ch_status(chan1))
91
92    var job1: job
93    assert_equal('fail', job_status(job1))
94
95    # calling job_start() is in test_vim9_fails.vim, it causes leak reports
96  endif
97  if has('float')
98    var float1: float = 3.4
99  endif
100  var Funky1: func
101  var Funky2: func = function('len')
102  var Party2: func = funcref('g:Test_syntax')
103
104  g:newvar = 'new'  #comment
105  assert_equal('new', g:newvar)
106
107  assert_equal('yes', g:existing)
108  g:existing = 'no'
109  assert_equal('no', g:existing)
110
111  v:char = 'abc'
112  assert_equal('abc', v:char)
113
114  $ENVVAR = 'foobar'
115  assert_equal('foobar', $ENVVAR)
116  $ENVVAR = ''
117
118  var lines =<< trim END
119    vim9script
120    $ENVVAR = 'barfoo'
121    assert_equal('barfoo', $ENVVAR)
122    $ENVVAR = ''
123  END
124  CheckScriptSuccess(lines)
125
126  s:appendToMe ..= 'yyy'
127  assert_equal('xxxyyy', s:appendToMe)
128  s:addToMe += 222
129  assert_equal(333, s:addToMe)
130  s:newVar = 'new'
131  assert_equal('new', s:newVar)
132
133  set ts=7
134  var ts: number = &ts
135  assert_equal(7, ts)
136  &ts += 1
137  assert_equal(8, &ts)
138  &ts -= 3
139  assert_equal(5, &ts)
140  &ts *= 2
141  assert_equal(10, &ts)
142  &ts /= 3
143  assert_equal(3, &ts)
144  set ts=10
145  &ts %= 4
146  assert_equal(2, &ts)
147
148  if has('float')
149    var f100: float = 100.0
150    f100 /= 5
151    assert_equal(20.0, f100)
152
153    var f200: float = 200.0
154    f200 /= 5.0
155    assert_equal(40.0, f200)
156
157    CheckDefFailure(['var nr: number = 200', 'nr /= 5.0'], 'E1012:')
158  endif
159
160  lines =<< trim END
161    &ts = 6
162    &ts += 3
163    assert_equal(9, &ts)
164
165    &l:ts = 6
166    assert_equal(6, &ts)
167    &l:ts += 2
168    assert_equal(8, &ts)
169
170    &g:ts = 6
171    assert_equal(6, &g:ts)
172    &g:ts += 2
173    assert_equal(8, &g:ts)
174
175    &number = true
176    assert_equal(true, &number)
177    &number = 0
178    assert_equal(false, &number)
179    &number = 1
180    assert_equal(true, &number)
181    &number = false
182    assert_equal(false, &number)
183  END
184  CheckDefAndScriptSuccess(lines)
185
186  CheckDefFailure(['&notex += 3'], 'E113:')
187  CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
188  CheckDefFailure(['&ts = [7]'], 'E1012:')
189  CheckDefExecFailure(['&ts = g:alist'], 'E1012: Type mismatch; expected number but got list<number>')
190  CheckDefFailure(['&ts = "xx"'], 'E1012:')
191  CheckDefExecFailure(['&ts = g:astring'], 'E1012: Type mismatch; expected number but got string')
192  CheckDefFailure(['&path += 3'], 'E1012:')
193  CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
194  # test freeing ISN_STOREOPT
195  CheckDefFailure(['&ts = 3', 'var asdf'], 'E1022:')
196  &ts = 8
197
198  lines =<< trim END
199    var save_TI = &t_TI
200    &t_TI = ''
201    assert_equal('', &t_TI)
202    &t_TI = 'xxx'
203    assert_equal('xxx', &t_TI)
204    &t_TI = save_TI
205  END
206  CheckDefAndScriptSuccess(lines)
207
208  CheckDefFailure(['&t_TI = 123'], 'E1012:')
209  CheckScriptFailure(['vim9script', '&t_TI = 123'], 'E928:')
210
211  CheckDefFailure(['var s:var = 123'], 'E1101:')
212  CheckDefFailure(['var s:var: number'], 'E1101:')
213
214  lines =<< trim END
215    vim9script
216    def SomeFunc()
217      s:var = 123
218    enddef
219    defcompile
220  END
221  CheckScriptFailure(lines, 'E1089:')
222
223  g:inc_counter += 1
224  assert_equal(2, g:inc_counter)
225
226  $SOME_ENV_VAR ..= 'more'
227  assert_equal('somemore', $SOME_ENV_VAR)
228  CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1051:')
229  CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1012:')
230
231  lines =<< trim END
232    @c = 'areg'
233    @c ..= 'add'
234    assert_equal('aregadd', @c)
235  END
236  CheckDefAndScriptSuccess(lines)
237
238  CheckDefFailure(['@a += "more"'], 'E1051:')
239  CheckDefFailure(['@a += 123'], 'E1012:')
240
241  v:errmsg = 'none'
242  v:errmsg ..= 'again'
243  assert_equal('noneagain', v:errmsg)
244  CheckDefFailure(['v:errmsg += "more"'], 'E1051:')
245  CheckDefFailure(['v:errmsg += 123'], 'E1012:')
246
247  var text =<< trim END
248    some text
249  END
250enddef
251
252def Test_reserved_name()
253  for name in ['true', 'false', 'null']
254    CheckDefExecAndScriptFailure(['var ' .. name .. ' =  0'], 'E1034:')
255    CheckDefExecAndScriptFailure(['var ' .. name .. ': bool'], 'E1034:')
256  endfor
257enddef
258
259def Test_skipped_assignment()
260  var lines =<< trim END
261      for x in []
262        var i: number = 1
263        while false
264          i += 1
265        endwhile
266      endfor
267  END
268  CheckDefAndScriptSuccess(lines)
269enddef
270
271def Test_assign_unpack()
272  var lines =<< trim END
273    var v1: number
274    var v2: number
275    [v1, v2] = [1, 2]
276    assert_equal(1, v1)
277    assert_equal(2, v2)
278
279    [v1, _, v2, _] = [1, 99, 2, 77]
280    assert_equal(1, v1)
281    assert_equal(2, v2)
282
283    [v1, v2; _] = [1, 2, 3, 4, 5]
284    assert_equal(1, v1)
285    assert_equal(2, v2)
286
287    var a = 1
288    var b = 3
289    [a, b] += [2, 4]
290    assert_equal(3, a)
291    assert_equal(7, b)
292
293    [a, b] -= [1, 2]
294    assert_equal(2, a)
295    assert_equal(5, b)
296
297    [a, b] *= [3, 2]
298    assert_equal(6, a)
299    assert_equal(10, b)
300
301    [a, b] /= [2, 4]
302    assert_equal(3, a)
303    assert_equal(2, b)
304
305    [a, b] = [17, 15]
306    [a, b] %= [5, 3]
307    assert_equal(2, a)
308    assert_equal(0, b)
309  END
310  CheckDefAndScriptSuccess(lines)
311
312  lines =<< trim END
313      var v1: number
314      var v2: number
315      [v1, v2] =
316  END
317  CheckDefFailure(lines, 'E1097:', 5)
318
319  lines =<< trim END
320      var v1: number
321      var v2: number
322      [v1, v2] = xxx
323  END
324  CheckDefFailure(lines, 'E1001:', 3)
325
326  lines =<< trim END
327      var v1: number
328      var v2: number
329      [v1, v2] = popup_clear()
330  END
331  CheckDefFailure(lines, 'E1031:', 3)
332
333  lines =<< trim END
334      [v1, v2] = [1, 2]
335  END
336  CheckDefFailure(lines, 'E1089', 1)
337  CheckScriptFailure(['vim9script'] + lines, 'E1089', 2)
338
339  lines =<< trim END
340      var v1: number
341      var v2: number
342      [v1, v2] = ''
343  END
344  CheckDefFailure(lines, 'E1012: Type mismatch; expected list<any> but got string', 3)
345
346  lines =<< trim END
347    g:values = [false, 0]
348    var x: bool
349    var y: string
350    [x, y] = g:values
351  END
352  CheckDefExecAndScriptFailure(lines, 'E1163: Variable 2: type mismatch, expected string but got number')
353enddef
354
355def Test_assign_linebreak()
356  var nr: number
357  nr =
358      123
359  assert_equal(123, nr)
360
361  var n2: number
362  [nr, n2] =
363     [12, 34]
364  assert_equal(12, nr)
365  assert_equal(34, n2)
366
367  CheckDefFailure(["var x = #"], 'E1097:', 3)
368
369  var lines =<< trim END
370      var x: list<string> = ['a']
371      var y: list<number> = x
372          ->copy()
373          ->copy()
374  END
375  CheckDefFailure(lines, 'E1012:', 2)
376enddef
377
378def Test_assign_index()
379  # list of list
380  var l1: list<number>
381  l1[0] = 123
382  assert_equal([123], l1)
383
384  var l2: list<list<number>>
385  l2[0] = []
386  l2[0][0] = 123
387  assert_equal([[123]], l2)
388
389  var l3: list<list<list<number>>>
390  l3[0] = []
391  l3[0][0] = []
392  l3[0][0][0] = 123
393  assert_equal([[[123]]], l3)
394
395  var lines =<< trim END
396      var l3: list<list<number>>
397      l3[0] = []
398      l3[0][0] = []
399  END
400  CheckDefFailure(lines, 'E1012: Type mismatch; expected number but got list<unknown>', 3)
401
402  # dict of dict
403  var d1: dict<number>
404  d1.one = 1
405  assert_equal({one: 1}, d1)
406
407  var d2: dict<dict<number>>
408  d2.one = {}
409  d2.one.two = 123
410  assert_equal({one: {two: 123}}, d2)
411
412  var d3: dict<dict<dict<number>>>
413  d3.one = {}
414  d3.one.two = {}
415  d3.one.two.three = 123
416  assert_equal({one: {two: {three: 123}}}, d3)
417
418  lines =<< trim END
419      var d3: dict<dict<number>>
420      d3.one = {}
421      d3.one.two = {}
422  END
423  CheckDefFailure(lines, 'E1012: Type mismatch; expected number but got dict<unknown>', 3)
424
425  lines =<< trim END
426    var lines: list<string>
427    lines['a'] = 'asdf'
428  END
429  CheckDefFailure(lines, 'E1012:', 2)
430
431  lines =<< trim END
432    var lines: string
433    lines[9] = 'asdf'
434  END
435  CheckDefFailure(lines, 'E1141:', 2)
436
437  # list of dict
438  var ld: list<dict<number>>
439  ld[0] = {}
440  ld[0].one = 123
441  assert_equal([{one: 123}], ld)
442
443  lines =<< trim END
444      var ld: list<dict<number>>
445      ld[0] = []
446  END
447  CheckDefFailure(lines, 'E1012: Type mismatch; expected dict<number> but got list<unknown>', 2)
448
449  # dict of list
450  var dl: dict<list<number>>
451  dl.one = []
452  dl.one[0] = 123
453  assert_equal({one: [123]}, dl)
454
455  lines =<< trim END
456      var dl: dict<list<number>>
457      dl.one = {}
458  END
459  CheckDefFailure(lines, 'E1012: Type mismatch; expected list<number> but got dict<unknown>', 2)
460enddef
461
462def Test_extend_list()
463  var lines =<< trim END
464      vim9script
465      var l: list<number>
466      l += [123]
467      assert_equal([123], l)
468  END
469  CheckScriptSuccess(lines)
470
471  lines =<< trim END
472      vim9script
473      var list: list<string>
474      extend(list, ['x'])
475      assert_equal(['x'], list)
476  END
477  CheckScriptSuccess(lines)
478
479  # appending to NULL list from a function
480  lines =<< trim END
481      vim9script
482      var list: list<string>
483      def Func()
484        list += ['a', 'b']
485      enddef
486      Func()
487      assert_equal(['a', 'b'], list)
488  END
489  CheckScriptSuccess(lines)
490  lines =<< trim END
491      vim9script
492      var list: list<string>
493      def Func()
494        extend(list, ['x', 'b'])
495      enddef
496      Func()
497      assert_equal(['x', 'b'], list)
498  END
499  CheckScriptSuccess(lines)
500
501  lines =<< trim END
502      vim9script
503      var l: list<string> = test_null_list()
504      extend(l, ['x'])
505      assert_equal(['x'], l)
506  END
507  CheckScriptSuccess(lines)
508
509  lines =<< trim END
510      vim9script
511      extend(test_null_list(), ['x'])
512  END
513  CheckScriptFailure(lines, 'E1134:', 2)
514enddef
515
516def Test_extend_dict()
517  var lines =<< trim END
518      vim9script
519      var d: dict<number>
520      extend(d, {a: 1})
521      assert_equal({a: 1}, d)
522
523      var d2: dict<number>
524      d2['one'] = 1
525      assert_equal({one: 1}, d2)
526  END
527  CheckScriptSuccess(lines)
528
529  lines =<< trim END
530      vim9script
531      var d: dict<string> = test_null_dict()
532      extend(d, {a: 'x'})
533      assert_equal({a: 'x'}, d)
534  END
535  CheckScriptSuccess(lines)
536
537  lines =<< trim END
538      vim9script
539      extend(test_null_dict(), {a: 'x'})
540  END
541  CheckScriptFailure(lines, 'E1133:', 2)
542enddef
543
544def Test_single_letter_vars()
545  # single letter variables
546  var a: number = 123
547  a = 123
548  assert_equal(123, a)
549  var b: number
550  b = 123
551  assert_equal(123, b)
552  var g: number
553  g = 123
554  assert_equal(123, g)
555  var s: number
556  s = 123
557  assert_equal(123, s)
558  var t: number
559  t = 123
560  assert_equal(123, t)
561  var v: number
562  v = 123
563  assert_equal(123, v)
564  var w: number
565  w = 123
566  assert_equal(123, w)
567enddef
568
569def Test_vim9_single_char_vars()
570  var lines =<< trim END
571      vim9script
572
573      # single character variable declarations work
574      var a: string
575      var b: number
576      var l: list<any>
577      var s: string
578      var t: number
579      var v: number
580      var w: number
581
582      # script-local variables can be used without s: prefix
583      a = 'script-a'
584      b = 111
585      l = [1, 2, 3]
586      s = 'script-s'
587      t = 222
588      v = 333
589      w = 444
590
591      assert_equal('script-a', a)
592      assert_equal(111, b)
593      assert_equal([1, 2, 3], l)
594      assert_equal('script-s', s)
595      assert_equal(222, t)
596      assert_equal(333, v)
597      assert_equal(444, w)
598  END
599  writefile(lines, 'Xsinglechar')
600  source Xsinglechar
601  delete('Xsinglechar')
602enddef
603
604def Test_assignment_list()
605  var list1: list<bool> = [false, true, false]
606  var list2: list<number> = [1, 2, 3]
607  var list3: list<string> = ['sdf', 'asdf']
608  var list4: list<any> = ['yes', true, 1234]
609  var list5: list<blob> = [0z01, 0z02]
610
611  var listS: list<string> = []
612  var listN: list<number> = []
613
614  assert_equal([1, 2, 3], list2)
615  list2[-1] = 99
616  assert_equal([1, 2, 99], list2)
617  list2[-2] = 88
618  assert_equal([1, 88, 99], list2)
619  list2[-3] = 77
620  assert_equal([77, 88, 99], list2)
621  list2 += [100]
622  assert_equal([77, 88, 99, 100], list2)
623
624  list3 += ['end']
625  assert_equal(['sdf', 'asdf', 'end'], list3)
626
627  CheckDefExecFailure(['var ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
628  CheckDefExecFailure(['var [v1, v2] = [1, 2]'], 'E1092:')
629
630  # type becomes list<any>
631  var somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
632
633  var lines =<< trim END
634    var d = {dd: test_null_list()}
635    d.dd[0] = 0
636  END
637  CheckDefExecFailure(lines, 'E1147:', 2)
638enddef
639
640def Test_assignment_list_any_index()
641   var l: list<number> = [1, 2]
642  for  [x, y, _]
643  in  [[0, 1, ''], [1, 3, '']]
644      l[x] = l[x] + y
645  endfor
646  assert_equal([2, 5], l)
647enddef
648
649def Test_assignment_list_vim9script()
650  var lines =<< trim END
651    vim9script
652    var v1: number
653    var v2: number
654    var v3: number
655    [v1, v2, v3] = [1, 2, 3]
656    assert_equal([1, 2, 3], [v1, v2, v3])
657  END
658  CheckScriptSuccess(lines)
659enddef
660
661def Test_assignment_dict()
662  var dict1: dict<bool> = {one: false, two: true}
663  var dict2: dict<number> = {one: 1, two: 2}
664  var dict3: dict<string> = {key: 'value'}
665  var dict4: dict<any> = {one: 1, two: '2'}
666  var dict5: dict<blob> = {one: 0z01, two: 0z02}
667
668  # overwrite
669  dict3['key'] = 'another'
670  assert_equal(dict3, {key: 'another'})
671  dict3.key = 'yet another'
672  assert_equal(dict3, {key: 'yet another'})
673
674  # member "any" can also be a dict and assigned to
675  var anydict: dict<any> = {nest: {}, nr: 0}
676  anydict.nest['this'] = 123
677  anydict.nest.that = 456
678  assert_equal({nest: {this: 123, that: 456}, nr: 0}, anydict)
679
680  var lines =<< trim END
681    var dd = {}
682    dd.two = 2
683    assert_equal({two: 2}, dd)
684  END
685  CheckDefAndScriptSuccess(lines)
686
687  lines =<< trim END
688    var d = {dd: {}}
689    d.dd[0] = 2
690    d.dd['x'] = 3
691    d.dd.y = 4
692    assert_equal({dd: {0: 2, x: 3, y: 4}}, d)
693  END
694  CheckDefAndScriptSuccess(lines)
695
696  lines =<< trim END
697    var dd = {one: 1}
698    dd.one) = 2
699  END
700  CheckDefFailure(lines, 'E488:', 2)
701
702  lines =<< trim END
703    var dd = {one: 1}
704    var dd.one = 2
705  END
706  CheckDefAndScriptFailure(lines, 'E1017:', 2)
707
708  # empty key can be used
709  var dd = {}
710  dd[""] = 6
711  assert_equal({['']: 6}, dd)
712
713  # type becomes dict<any>
714  var somedict = rand() > 0 ? {a: 1, b: 2} : {a: 'a', b: 'b'}
715
716  # assignment to script-local dict
717  lines =<< trim END
718    vim9script
719    var test: dict<any> = {}
720    def FillDict(): dict<any>
721      test['a'] = 43
722      return test
723    enddef
724    assert_equal({a: 43}, FillDict())
725  END
726  CheckScriptSuccess(lines)
727
728  lines =<< trim END
729    vim9script
730    var test: dict<any>
731    def FillDict(): dict<any>
732      test['a'] = 43
733      return test
734    enddef
735    FillDict()
736    assert_equal({a: 43}, test)
737  END
738  CheckScriptSuccess(lines)
739
740  # assignment to global dict
741  lines =<< trim END
742    vim9script
743    g:test = {}
744    def FillDict(): dict<any>
745      g:test['a'] = 43
746      return g:test
747    enddef
748    assert_equal({a: 43}, FillDict())
749  END
750  CheckScriptSuccess(lines)
751
752  # assignment to buffer dict
753  lines =<< trim END
754    vim9script
755    b:test = {}
756    def FillDict(): dict<any>
757      b:test['a'] = 43
758      return b:test
759    enddef
760    assert_equal({a: 43}, FillDict())
761  END
762  CheckScriptSuccess(lines)
763
764  lines =<< trim END
765    var d = {dd: test_null_dict()}
766    d.dd[0] = 0
767  END
768  CheckDefExecFailure(lines, 'E1103:', 2)
769
770  lines =<< trim END
771    var d = {dd: 'string'}
772    d.dd[0] = 0
773  END
774  CheckDefExecFailure(lines, 'E1148:', 2)
775enddef
776
777def Test_assignment_local()
778  # Test in a separated file in order not to the current buffer/window/tab is
779  # changed.
780  var script_lines: list<string> =<< trim END
781    let b:existing = 'yes'
782    let w:existing = 'yes'
783    let t:existing = 'yes'
784
785    def Test_assignment_local_internal()
786      b:newvar = 'new'
787      assert_equal('new', b:newvar)
788      assert_equal('yes', b:existing)
789      b:existing = 'no'
790      assert_equal('no', b:existing)
791      b:existing ..= 'NO'
792      assert_equal('noNO', b:existing)
793
794      w:newvar = 'new'
795      assert_equal('new', w:newvar)
796      assert_equal('yes', w:existing)
797      w:existing = 'no'
798      assert_equal('no', w:existing)
799      w:existing ..= 'NO'
800      assert_equal('noNO', w:existing)
801
802      t:newvar = 'new'
803      assert_equal('new', t:newvar)
804      assert_equal('yes', t:existing)
805      t:existing = 'no'
806      assert_equal('no', t:existing)
807      t:existing ..= 'NO'
808      assert_equal('noNO', t:existing)
809    enddef
810    call Test_assignment_local_internal()
811  END
812  CheckScriptSuccess(script_lines)
813enddef
814
815def Test_assignment_default()
816  # Test default values.
817  var thebool: bool
818  assert_equal(v:false, thebool)
819
820  var thenumber: number
821  assert_equal(0, thenumber)
822
823  if has('float')
824    var thefloat: float
825    assert_equal(0.0, thefloat)
826  endif
827
828  var thestring: string
829  assert_equal('', thestring)
830
831  var theblob: blob
832  assert_equal(0z, theblob)
833
834  var Thefunc: func
835  assert_equal(test_null_function(), Thefunc)
836
837  var thelist: list<any>
838  assert_equal([], thelist)
839
840  var thedict: dict<any>
841  assert_equal({}, thedict)
842
843  if has('channel')
844    var thejob: job
845    assert_equal(test_null_job(), thejob)
846
847    var thechannel: channel
848    assert_equal(test_null_channel(), thechannel)
849
850    if has('unix') && executable('cat')
851      # check with non-null job and channel, types must match
852      thejob = job_start("cat ", {})
853      thechannel = job_getchannel(thejob)
854      job_stop(thejob, 'kill')
855    endif
856  endif
857
858  var nr = 1234 | nr = 5678
859  assert_equal(5678, nr)
860enddef
861
862let scriptvar = 'init'
863
864def Test_assignment_var_list()
865  var lines =<< trim END
866      var v1: string
867      var v2: string
868      var vrem: list<string>
869      [v1] = ['aaa']
870      assert_equal('aaa', v1)
871
872      [v1, v2] = ['one', 'two']
873      assert_equal('one', v1)
874      assert_equal('two', v2)
875
876      [v1, v2; vrem] = ['one', 'two']
877      assert_equal('one', v1)
878      assert_equal('two', v2)
879      assert_equal([], vrem)
880
881      [v1, v2; vrem] = ['one', 'two', 'three']
882      assert_equal('one', v1)
883      assert_equal('two', v2)
884      assert_equal(['three'], vrem)
885
886      [&ts, &sw] = [3, 4]
887      assert_equal(3, &ts)
888      assert_equal(4, &sw)
889      set ts=8 sw=4
890
891      [@a, @z] = ['aa', 'zz']
892      assert_equal('aa', @a)
893      assert_equal('zz', @z)
894
895      [$SOME_VAR, $OTHER_VAR] = ['some', 'other']
896      assert_equal('some', $SOME_VAR)
897      assert_equal('other', $OTHER_VAR)
898
899      [g:globalvar, b:bufvar, w:winvar, t:tabvar, v:errmsg] =
900            ['global', 'buf', 'win', 'tab', 'error']
901      assert_equal('global', g:globalvar)
902      assert_equal('buf', b:bufvar)
903      assert_equal('win', w:winvar)
904      assert_equal('tab', t:tabvar)
905      assert_equal('error', v:errmsg)
906      unlet g:globalvar
907  END
908  CheckDefAndScriptSuccess(lines)
909
910  [g:globalvar, s:scriptvar, b:bufvar] = ['global', 'script', 'buf']
911  assert_equal('global', g:globalvar)
912  assert_equal('script', s:scriptvar)
913  assert_equal('buf', b:bufvar)
914
915  lines =<< trim END
916      vim9script
917      var s:scriptvar = 'init'
918      [g:globalvar, s:scriptvar, w:winvar] = ['global', 'script', 'win']
919      assert_equal('global', g:globalvar)
920      assert_equal('script', s:scriptvar)
921      assert_equal('win', w:winvar)
922  END
923  CheckScriptSuccess(lines)
924enddef
925
926def Test_assignment_vim9script()
927  var lines =<< trim END
928    vim9script
929    def Func(): list<number>
930      return [1, 2]
931    enddef
932    var name1: number
933    var name2: number
934    [name1, name2] =
935          Func()
936    assert_equal(1, name1)
937    assert_equal(2, name2)
938    var ll =
939          Func()
940    assert_equal([1, 2], ll)
941
942    @/ = 'text'
943    assert_equal('text', @/)
944    @0 = 'zero'
945    assert_equal('zero', @0)
946    @1 = 'one'
947    assert_equal('one', @1)
948    @9 = 'nine'
949    assert_equal('nine', @9)
950    @- = 'minus'
951    assert_equal('minus', @-)
952    if has('clipboard_working')
953      @* = 'star'
954      assert_equal('star', @*)
955      @+ = 'plus'
956      assert_equal('plus', @+)
957    endif
958
959    var a: number = 123
960    assert_equal(123, a)
961    var s: string = 'yes'
962    assert_equal('yes', s)
963    var b: number = 42
964    assert_equal(42, b)
965    var w: number = 43
966    assert_equal(43, w)
967    var t: number = 44
968    assert_equal(44, t)
969
970    var to_var = 0
971    to_var = 3
972    assert_equal(3, to_var)
973  END
974  CheckScriptSuccess(lines)
975
976  lines =<< trim END
977      vim9script
978      var n: number
979      def Func()
980        n = 'string'
981      enddef
982      defcompile
983  END
984  CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
985enddef
986
987def Mess(): string
988  v:foldstart = 123
989  return 'xxx'
990enddef
991
992def Test_assignment_failure()
993  CheckDefFailure(['var name=234'], 'E1004:')
994  CheckDefFailure(['var name =234'], 'E1004:')
995  CheckDefFailure(['var name= 234'], 'E1004:')
996
997  CheckScriptFailure(['vim9script', 'var name=234'], 'E1004:')
998  CheckScriptFailure(['vim9script', 'var name=234'], "before and after '='")
999  CheckScriptFailure(['vim9script', 'var name =234'], 'E1004:')
1000  CheckScriptFailure(['vim9script', 'var name= 234'], 'E1004:')
1001  CheckScriptFailure(['vim9script', 'var name = 234', 'name+=234'], 'E1004:')
1002  CheckScriptFailure(['vim9script', 'var name = 234', 'name+=234'], "before and after '+='")
1003  CheckScriptFailure(['vim9script', 'var name = "x"', 'name..="y"'], 'E1004:')
1004  CheckScriptFailure(['vim9script', 'var name = "x"', 'name..="y"'], "before and after '..='")
1005
1006  CheckDefFailure(['var true = 1'], 'E1034:')
1007  CheckDefFailure(['var false = 1'], 'E1034:')
1008  CheckDefFailure(['var null = 1'], 'E1034:')
1009  CheckDefFailure(['var this = 1'], 'E1034:')
1010
1011  CheckDefFailure(['[a; b; c] = g:list'], 'E452:')
1012  CheckDefExecFailure(['var a: number',
1013                       '[a] = test_null_list()'], 'E1093:')
1014  CheckDefExecFailure(['var a: number',
1015                       '[a] = []'], 'E1093:')
1016  CheckDefExecFailure(['var x: number',
1017                       'var y: number',
1018                       '[x, y] = [1]'], 'E1093:')
1019  CheckDefExecFailure(['var x: string',
1020                       'var y: string',
1021                       '[x, y] = ["x"]'], 'E1093:')
1022  CheckDefExecFailure(['var x: number',
1023                       'var y: number',
1024                       'var z: list<number>',
1025                       '[x, y; z] = [1]'], 'E1093:')
1026
1027  CheckDefFailure(['var somevar'], "E1022:")
1028  CheckDefFailure(['var &tabstop = 4'], 'E1052:')
1029  CheckDefFailure(['&g:option = 5'], 'E113:')
1030  CheckScriptFailure(['vim9script', 'var &tabstop = 4'], 'E1052:')
1031
1032  CheckDefFailure(['var $VAR = 5'], 'E1016: Cannot declare an environment variable:')
1033  CheckScriptFailure(['vim9script', 'var $ENV = "xxx"'], 'E1016:')
1034
1035  if has('dnd')
1036    CheckDefFailure(['var @~ = 5'], 'E1066:')
1037  else
1038    CheckDefFailure(['var @~ = 5'], 'E354:')
1039    CheckDefFailure(['@~ = 5'], 'E354:')
1040  endif
1041  CheckDefFailure(['var @a = 5'], 'E1066:')
1042  CheckDefFailure(['var @/ = "x"'], 'E1066:')
1043  CheckScriptFailure(['vim9script', 'var @a = "abc"'], 'E1066:')
1044
1045  CheckDefFailure(['var g:var = 5'], 'E1016: Cannot declare a global variable:')
1046  CheckDefFailure(['var w:var = 5'], 'E1016: Cannot declare a window variable:')
1047  CheckDefFailure(['var b:var = 5'], 'E1016: Cannot declare a buffer variable:')
1048  CheckDefFailure(['var t:var = 5'], 'E1016: Cannot declare a tab variable:')
1049
1050  CheckDefFailure(['var anr = 4', 'anr ..= "text"'], 'E1019:')
1051  CheckDefFailure(['var xnr += 4'], 'E1020:', 1)
1052  CheckScriptFailure(['vim9script', 'var xnr += 4'], 'E1020:')
1053  CheckDefFailure(["var xnr = xnr + 1"], 'E1001:', 1)
1054  CheckScriptFailure(['vim9script', 'var xnr = xnr + 4'], 'E121:')
1055
1056  CheckScriptFailure(['vim9script', 'def Func()', 'var dummy = s:notfound', 'enddef', 'defcompile'], 'E1108:')
1057
1058  CheckDefFailure(['var name: list<string> = [123]'], 'expected list<string> but got list<number>')
1059  CheckDefFailure(['var name: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
1060
1061  CheckDefFailure(['var name: dict<string> = {key: 123}'], 'expected dict<string> but got dict<number>')
1062  CheckDefFailure(['var name: dict<number> = {key: "xx"}'], 'expected dict<number> but got dict<string>')
1063
1064  CheckDefFailure(['var name = feedkeys("0")'], 'E1031:')
1065  CheckDefFailure(['var name: number = feedkeys("0")'], 'expected number but got void')
1066
1067  CheckDefFailure(['var name: dict <number>'], 'E1068:')
1068  CheckDefFailure(['var name: dict<number'], 'E1009:')
1069
1070  assert_fails('s/^/\=Mess()/n', 'E794:')
1071  CheckDefFailure(['var name: dict<number'], 'E1009:')
1072
1073  CheckDefFailure(['w:foo: number = 10'],
1074                  'E488: Trailing characters: : number = 1')
1075  CheckDefFailure(['t:foo: bool = true'],
1076                  'E488: Trailing characters: : bool = true')
1077  CheckDefFailure(['b:foo: string = "x"'],
1078                  'E488: Trailing characters: : string = "x"')
1079  CheckDefFailure(['g:foo: number = 123'],
1080                  'E488: Trailing characters: : number = 123')
1081enddef
1082
1083def Test_assign_list()
1084  var l: list<string> = []
1085  l[0] = 'value'
1086  assert_equal('value', l[0])
1087
1088  l[1] = 'asdf'
1089  assert_equal('value', l[0])
1090  assert_equal('asdf', l[1])
1091  assert_equal('asdf', l[-1])
1092  assert_equal('value', l[-2])
1093
1094  var nrl: list<number> = []
1095  for i in range(5)
1096    nrl[i] = i
1097  endfor
1098  assert_equal([0, 1, 2, 3, 4], nrl)
1099
1100  CheckDefFailure(["var l: list<number> = ['', true]"], 'E1012: Type mismatch; expected list<number> but got list<any>', 1)
1101  CheckDefFailure(["var l: list<list<number>> = [['', true]]"], 'E1012: Type mismatch; expected list<list<number>> but got list<list<any>>', 1)
1102enddef
1103
1104def Test_assign_dict()
1105  var lines =<< trim END
1106      var d: dict<string> = {}
1107      d['key'] = 'value'
1108      assert_equal('value', d['key'])
1109
1110      d[123] = 'qwerty'
1111      assert_equal('qwerty', d[123])
1112      assert_equal('qwerty', d['123'])
1113
1114      var nrd: dict<number> = {}
1115      for i in range(3)
1116        nrd[i] = i
1117      endfor
1118      assert_equal({0: 0, 1: 1, 2: 2}, nrd)
1119
1120      d.somekey = 'someval'
1121      assert_equal({key: 'value', '123': 'qwerty', somekey: 'someval'}, d)
1122      # unlet d.somekey
1123      # assert_equal({key: 'value', '123': 'qwerty'}, d)
1124  END
1125  CheckDefAndScriptSuccess(lines)
1126
1127  # TODO: move to above once "unlet d.somekey" in :def is implemented
1128  lines =<< trim END
1129      vim9script
1130      var d: dict<string> = {}
1131      d['key'] = 'value'
1132      d.somekey = 'someval'
1133      assert_equal({key: 'value', somekey: 'someval'}, d)
1134      unlet d.somekey
1135      assert_equal({key: 'value'}, d)
1136  END
1137  CheckScriptSuccess(lines)
1138
1139  CheckDefFailure(["var d: dict<number> = {a: '', b: true}"], 'E1012: Type mismatch; expected dict<number> but got dict<any>', 1)
1140  CheckDefFailure(["var d: dict<dict<number>> = {x: {a: '', b: true}}"], 'E1012: Type mismatch; expected dict<dict<number>> but got dict<dict<any>>', 1)
1141enddef
1142
1143def Test_assign_dict_unknown_type()
1144  var lines =<< trim END
1145      vim9script
1146      var mylist = []
1147      mylist += [{one: 'one'}]
1148      def Func()
1149        var dd = mylist[0]
1150        assert_equal('one', dd.one)
1151      enddef
1152      Func()
1153  END
1154  CheckScriptSuccess(lines)
1155
1156  lines =<< trim END
1157      vim9script
1158      var mylist = [[]]
1159      mylist[0] += [{one: 'one'}]
1160      def Func()
1161        var dd = mylist[0][0]
1162        assert_equal('one', dd.one)
1163      enddef
1164      Func()
1165  END
1166  CheckScriptSuccess(lines)
1167enddef
1168
1169def Test_assign_dict_with_op()
1170  var lines =<< trim END
1171    var ds: dict<string> = {a: 'x'}
1172    ds['a'] ..= 'y'
1173    ds.a ..= 'z'
1174    assert_equal('xyz', ds.a)
1175
1176    var dn: dict<number> = {a: 9}
1177    dn['a'] += 2
1178    assert_equal(11, dn.a)
1179    dn.a += 2
1180    assert_equal(13, dn.a)
1181
1182    dn['a'] -= 3
1183    assert_equal(10, dn.a)
1184    dn.a -= 2
1185    assert_equal(8, dn.a)
1186
1187    dn['a'] *= 2
1188    assert_equal(16, dn.a)
1189    dn.a *= 2
1190    assert_equal(32, dn.a)
1191
1192    dn['a'] /= 3
1193    assert_equal(10, dn.a)
1194    dn.a /= 2
1195    assert_equal(5, dn.a)
1196
1197    dn['a'] %= 3
1198    assert_equal(2, dn.a)
1199    dn.a %= 6
1200    assert_equal(2, dn.a)
1201
1202    var dd: dict<dict<list<any>>>
1203    dd.a = {}
1204    dd.a.b = [0]
1205    dd.a.b += [1]
1206    assert_equal({a: {b: [0, 1]}}, dd)
1207
1208    var dab = {a: ['b']}
1209    dab.a[0] ..= 'c'
1210    assert_equal({a: ['bc']}, dab)
1211  END
1212  CheckDefAndScriptSuccess(lines)
1213enddef
1214
1215def Test_assign_list_with_op()
1216  var lines =<< trim END
1217    var ls: list<string> = ['x']
1218    ls[0] ..= 'y'
1219    assert_equal('xy', ls[0])
1220
1221    var ln: list<number> = [9]
1222    ln[0] += 2
1223    assert_equal(11, ln[0])
1224
1225    ln[0] -= 3
1226    assert_equal(8, ln[0])
1227
1228    ln[0] *= 2
1229    assert_equal(16, ln[0])
1230
1231    ln[0] /= 3
1232    assert_equal(5, ln[0])
1233
1234    ln[0] %= 3
1235    assert_equal(2, ln[0])
1236  END
1237  CheckDefAndScriptSuccess(lines)
1238enddef
1239
1240def Test_assign_with_op_fails()
1241  var lines =<< trim END
1242      var s = 'abc'
1243      s[1] += 'x'
1244  END
1245  CheckDefAndScriptFailure2(lines, 'E1141:', 'E689:', 2)
1246
1247  lines =<< trim END
1248      var s = 'abc'
1249      s[1] ..= 'x'
1250  END
1251  CheckDefAndScriptFailure2(lines, 'E1141:', 'E689:', 2)
1252
1253  lines =<< trim END
1254      var dd: dict<dict<list<any>>>
1255      dd.a = {}
1256      dd.a.b += [1]
1257  END
1258  CheckDefExecAndScriptFailure(lines, 'E716:', 3)
1259enddef
1260
1261def Test_assign_lambda()
1262  # check if assign a lambda to a variable which type is func or any.
1263  var lines =<< trim END
1264      vim9script
1265      var FuncRef = () => 123
1266      assert_equal(123, FuncRef())
1267      var FuncRef_Func: func = () => 123
1268      assert_equal(123, FuncRef_Func())
1269      var FuncRef_Any: any = () => 123
1270      assert_equal(123, FuncRef_Any())
1271      var FuncRef_Number: func(): number = () => 321
1272      assert_equal(321, FuncRef_Number())
1273  END
1274  CheckScriptSuccess(lines)
1275
1276  lines =<< trim END
1277      var Ref: func(number)
1278      Ref = (j) => !j
1279  END
1280  CheckDefAndScriptFailure(lines, 'E1012: Type mismatch; expected func(number) but got func(any): bool')
1281
1282  lines =<< trim END
1283      echo filter([1, 2, 3], (_, v: string) => v + 1)
1284  END
1285  CheckDefAndScriptFailure(lines, 'E1051:')
1286enddef
1287
1288def Test_heredoc()
1289  var lines =<< trim END # comment
1290    text
1291  END
1292  assert_equal(['text'], lines)
1293
1294  CheckDefFailure(['var lines =<< trim END X', 'END'], 'E488:')
1295  CheckDefFailure(['var lines =<< trim END " comment', 'END'], 'E488:')
1296
1297  lines =<< trim [END]
1298      def Func()
1299        var&lines =<< trim END
1300        x
1301        x
1302      enddef
1303      defcompile
1304  [END]
1305  CheckScriptFailure(lines, 'E1145: Missing heredoc end marker: END')
1306  delfunc! g:Func
1307
1308  lines =<< trim [END]
1309      def Func()
1310        var lines =<< trim END
1311        x
1312        x
1313        x
1314        x
1315        x
1316        x
1317        x
1318        x
1319      enddef
1320      call Func()
1321  [END]
1322  CheckScriptFailure(lines, 'E1145: Missing heredoc end marker: END')
1323  delfunc! g:Func
1324enddef
1325
1326def Test_var_func_call()
1327  var lines =<< trim END
1328    vim9script
1329    func GetValue()
1330      if exists('g:count')
1331        let g:count += 1
1332      else
1333        let g:count = 1
1334      endif
1335      return 'this'
1336    endfunc
1337    var val: string = GetValue()
1338    # env var is always a string
1339    var env = $TERM
1340  END
1341  writefile(lines, 'Xfinished')
1342  source Xfinished
1343  # GetValue() is not called during discovery phase
1344  assert_equal(1, g:count)
1345
1346  unlet g:count
1347  delete('Xfinished')
1348enddef
1349
1350def Test_var_missing_type()
1351  var lines =<< trim END
1352    vim9script
1353    var name = g:unknown
1354  END
1355  CheckScriptFailure(lines, 'E121:')
1356
1357  lines =<< trim END
1358    vim9script
1359    var nr: number = 123
1360    var name = nr
1361  END
1362  CheckScriptSuccess(lines)
1363enddef
1364
1365def Test_var_declaration()
1366  var lines =<< trim END
1367    vim9script
1368    var name: string
1369    g:var_uninit = name
1370    name = 'text'
1371    g:var_test = name
1372    # prefixing s: is optional
1373    s:name = 'prefixed'
1374    g:var_prefixed = s:name
1375
1376    const FOO: number = 123
1377    assert_equal(123, FOO)
1378    const FOOS = 'foos'
1379    assert_equal('foos', FOOS)
1380    final FLIST = [1]
1381    assert_equal([1], FLIST)
1382    FLIST[0] = 11
1383    assert_equal([11], FLIST)
1384
1385    const g:FOO: number = 321
1386    assert_equal(321, g:FOO)
1387    const g:FOOS = 'gfoos'
1388    assert_equal('gfoos', g:FOOS)
1389    final g:FLIST = [2]
1390    assert_equal([2], g:FLIST)
1391    g:FLIST[0] = 22
1392    assert_equal([22], g:FLIST)
1393
1394    def SetGlobalConst()
1395      const g:globConst = 123
1396    enddef
1397    SetGlobalConst()
1398    assert_equal(123, g:globConst)
1399    assert_true(islocked('g:globConst'))
1400
1401    const w:FOO: number = 46
1402    assert_equal(46, w:FOO)
1403    const w:FOOS = 'wfoos'
1404    assert_equal('wfoos', w:FOOS)
1405    final w:FLIST = [3]
1406    assert_equal([3], w:FLIST)
1407    w:FLIST[0] = 33
1408    assert_equal([33], w:FLIST)
1409
1410    var s:other: number
1411    other = 1234
1412    g:other_var = other
1413
1414    var xyz: string  # comment
1415
1416    # type is inferred
1417    var s:dict = {['a']: 222}
1418    def GetDictVal(key: any)
1419      g:dict_val = s:dict[key]
1420    enddef
1421    GetDictVal('a')
1422
1423    final adict: dict<string> = {}
1424    def ChangeAdict()
1425      adict.foo = 'foo'
1426    enddef
1427    ChangeAdict()
1428  END
1429  CheckScriptSuccess(lines)
1430  assert_equal('', g:var_uninit)
1431  assert_equal('text', g:var_test)
1432  assert_equal('prefixed', g:var_prefixed)
1433  assert_equal(1234, g:other_var)
1434  assert_equal(222, g:dict_val)
1435
1436  unlet g:var_uninit
1437  unlet g:var_test
1438  unlet g:var_prefixed
1439  unlet g:other_var
1440  unlet g:globConst
1441  unlet g:FOO
1442  unlet g:FOOS
1443  unlet g:FLIST
1444  unlet w:FOO
1445  unlet w:FOOS
1446  unlet w:FLIST
1447enddef
1448
1449def Test_var_declaration_fails()
1450  var lines =<< trim END
1451    vim9script
1452    final var: string
1453  END
1454  CheckScriptFailure(lines, 'E1125:')
1455
1456  lines =<< trim END
1457    vim9script
1458    const g:constvar = 'string'
1459    g:constvar = 'xx'
1460  END
1461  CheckScriptFailure(lines, 'E741:')
1462  unlet g:constvar
1463
1464  lines =<< trim END
1465    vim9script
1466    var name = 'one'
1467    lockvar name
1468    def SetLocked()
1469      name = 'two'
1470    enddef
1471    SetLocked()
1472  END
1473  CheckScriptFailure(lines, 'E741: Value is locked: name', 1)
1474
1475  lines =<< trim END
1476    let s:legacy = 'one'
1477    lockvar s:legacy
1478    def SetLocked()
1479      s:legacy = 'two'
1480    enddef
1481    call SetLocked()
1482  END
1483  CheckScriptFailure(lines, 'E741: Value is locked: s:legacy', 1)
1484
1485  lines =<< trim END
1486    vim9script
1487    def SetGlobalConst()
1488      const g:globConst = 123
1489    enddef
1490    SetGlobalConst()
1491    g:globConst = 234
1492  END
1493  CheckScriptFailure(lines, 'E741: Value is locked: g:globConst', 6)
1494  unlet g:globConst
1495
1496  lines =<< trim END
1497    vim9script
1498    const cdict: dict<string> = {}
1499    def Change()
1500      cdict.foo = 'foo'
1501    enddef
1502    defcompile
1503  END
1504  CheckScriptFailure(lines, 'E46:')
1505
1506  lines =<< trim END
1507    vim9script
1508    final w:finalvar = [9]
1509    w:finalvar = [8]
1510  END
1511  CheckScriptFailure(lines, 'E1122:')
1512  unlet w:finalvar
1513
1514  lines =<< trim END
1515    vim9script
1516    const var: string
1517  END
1518  CheckScriptFailure(lines, 'E1021:')
1519
1520  lines =<< trim END
1521    vim9script
1522    var 9var: string
1523  END
1524  CheckScriptFailure(lines, 'E488:')
1525
1526  CheckDefFailure(['var foo.bar = 2'], 'E1087:')
1527  CheckDefFailure(['var foo[3] = 2'], 'E1087:')
1528  CheckDefFailure(['const foo: number'], 'E1021:')
1529enddef
1530
1531def Test_script_local_in_legacy()
1532  # OK to define script-local later when prefixed with s:
1533  var lines =<< trim END
1534    def SetLater()
1535      s:legvar = 'two'
1536    enddef
1537    defcompile
1538    let s:legvar = 'one'
1539    call SetLater()
1540    call assert_equal('two', s:legvar)
1541  END
1542  CheckScriptSuccess(lines)
1543
1544  # OK to leave out s: prefix when script-local already defined
1545  lines =<< trim END
1546    let s:legvar = 'one'
1547    def SetNoPrefix()
1548      legvar = 'two'
1549    enddef
1550    call SetNoPrefix()
1551    call assert_equal('two', s:legvar)
1552  END
1553  CheckScriptSuccess(lines)
1554
1555  # Not OK to leave out s: prefix when script-local defined later
1556  lines =<< trim END
1557    def SetLaterNoPrefix()
1558      legvar = 'two'
1559    enddef
1560    defcompile
1561    let s:legvar = 'one'
1562  END
1563  CheckScriptFailure(lines, 'E476:', 1)
1564enddef
1565
1566def Test_var_type_check()
1567  var lines =<< trim END
1568    vim9script
1569    var name: string
1570    name = 1234
1571  END
1572  CheckScriptFailure(lines, 'E1012:')
1573
1574  lines =<< trim END
1575    vim9script
1576    var name:string
1577  END
1578  CheckScriptFailure(lines, 'E1069:')
1579
1580  lines =<< trim END
1581    vim9script
1582    var name: asdf
1583  END
1584  CheckScriptFailure(lines, 'E1010:')
1585
1586  lines =<< trim END
1587    vim9script
1588    var s:l: list<number>
1589    s:l = []
1590  END
1591  CheckScriptSuccess(lines)
1592
1593  lines =<< trim END
1594    vim9script
1595    var s:d: dict<number>
1596    s:d = {}
1597  END
1598  CheckScriptSuccess(lines)
1599enddef
1600
1601let g:dict_number = #{one: 1, two: 2}
1602
1603def Test_var_list_dict_type()
1604  var ll: list<number>
1605  ll = [1, 2, 2, 3, 3, 3]->uniq()
1606  ll->assert_equal([1, 2, 3])
1607
1608  var dd: dict<number>
1609  dd = g:dict_number
1610  dd->assert_equal(g:dict_number)
1611
1612  var lines =<< trim END
1613      var ll: list<number>
1614      ll = [1, 2, 3]->map('"one"')
1615  END
1616  CheckDefExecFailure(lines, 'E1012: Type mismatch; expected number but got string')
1617enddef
1618
1619def Test_cannot_use_let()
1620  CheckDefAndScriptFailure(['let a = 34'], 'E1126:', 1)
1621enddef
1622
1623def Test_unlet()
1624  g:somevar = 'yes'
1625  assert_true(exists('g:somevar'))
1626  unlet g:somevar
1627  assert_false(exists('g:somevar'))
1628  unlet! g:somevar
1629
1630  # also works for script-local variable in legacy Vim script
1631  s:somevar = 'legacy'
1632  assert_true(exists('s:somevar'))
1633  unlet s:somevar
1634  assert_false(exists('s:somevar'))
1635  unlet! s:somevar
1636
1637  CheckDefExecFailure([
1638    'var dd = 111',
1639    'unlet dd',
1640    ], 'E1081:', 2)
1641
1642  # dict unlet
1643  var dd = {a: 1, b: 2, c: 3}
1644  unlet dd['a']
1645  unlet dd.c
1646  assert_equal({b: 2}, dd)
1647
1648  # list unlet
1649  var ll = [1, 2, 3, 4]
1650  unlet ll[1]
1651  unlet ll[-1]
1652  assert_equal([1, 3], ll)
1653
1654  ll = [1, 2, 3, 4]
1655  unlet ll[0 : 1]
1656  assert_equal([3, 4], ll)
1657
1658  ll = [1, 2, 3, 4]
1659  unlet ll[2 : 8]
1660  assert_equal([1, 2], ll)
1661
1662  ll = [1, 2, 3, 4]
1663  unlet ll[-2 : -1]
1664  assert_equal([1, 2], ll)
1665
1666  CheckDefFailure([
1667    'var ll = [1, 2]',
1668    'll[1 : 2] = 7',
1669    ], 'E1165:', 2)
1670  CheckDefFailure([
1671    'var dd = {a: 1}',
1672    'unlet dd["a" : "a"]',
1673    ], 'E1166:', 2)
1674  CheckDefExecFailure([
1675    'unlet g:adict[0 : 1]',
1676    ], 'E1148:', 1)
1677  CheckDefFailure([
1678    'var ll = [1, 2]',
1679    'unlet ll[0:1]',
1680    ], 'E1004:', 2)
1681  CheckDefFailure([
1682    'var ll = [1, 2]',
1683    'unlet ll[0 :1]',
1684    ], 'E1004:', 2)
1685  CheckDefFailure([
1686    'var ll = [1, 2]',
1687    'unlet ll[0: 1]',
1688    ], 'E1004:', 2)
1689
1690  CheckDefFailure([
1691    'var ll = [1, 2]',
1692    'unlet ll["x" : 1]',
1693    ], 'E1012:', 2)
1694  CheckDefFailure([
1695    'var ll = [1, 2]',
1696    'unlet ll[0 : "x"]',
1697    ], 'E1012:', 2)
1698
1699  # list of dict unlet
1700  var dl = [{a: 1, b: 2}, {c: 3}]
1701  unlet dl[0]['b']
1702  assert_equal([{a: 1}, {c: 3}], dl)
1703
1704  CheckDefExecFailure([
1705    'var ll = test_null_list()',
1706    'unlet ll[0]',
1707    ], 'E684:', 2)
1708  CheckDefExecFailure([
1709    'var ll = [1]',
1710    'unlet ll[2]',
1711    ], 'E684:', 2)
1712  CheckDefExecFailure([
1713    'var ll = [1]',
1714    'unlet ll[g:astring]',
1715    ], 'E1012:', 2)
1716  CheckDefExecFailure([
1717    'var dd = test_null_dict()',
1718    'unlet dd["a"]',
1719    ], 'E716:', 2)
1720  CheckDefExecFailure([
1721    'var dd = {a: 1}',
1722    'unlet dd["b"]',
1723    ], 'E716:', 2)
1724  CheckDefExecFailure([
1725    'var dd = {a: 1}',
1726    'unlet dd[g:alist]',
1727    ], 'E1105:', 2)
1728
1729  # can compile unlet before variable exists
1730  g:someDict = {key: 'val'}
1731  var k = 'key'
1732  unlet g:someDict[k]
1733  assert_equal({}, g:someDict)
1734  unlet g:someDict
1735  assert_false(exists('g:someDict'))
1736
1737  CheckScriptFailure([
1738   'vim9script',
1739   'var svar = 123',
1740   'unlet svar',
1741   ], 'E1081:')
1742  CheckScriptFailure([
1743   'vim9script',
1744   'var svar = 123',
1745   'unlet s:svar',
1746   ], 'E1081:')
1747  CheckScriptFailure([
1748   'vim9script',
1749   'var svar = 123',
1750   'def Func()',
1751   '  unlet svar',
1752   'enddef',
1753   'defcompile',
1754   ], 'E1081:')
1755  CheckScriptFailure([
1756   'vim9script',
1757   'var svar = 123',
1758   'func Func()',
1759   '  unlet s:svar',
1760   'endfunc',
1761   'Func()',
1762   ], 'E1081:')
1763  CheckScriptFailure([
1764   'vim9script',
1765   'var svar = 123',
1766   'def Func()',
1767   '  unlet s:svar',
1768   'enddef',
1769   'defcompile',
1770   ], 'E1081:')
1771
1772  writefile(['vim9script', 'export var svar = 1234'], 'XunletExport.vim')
1773  var lines =<< trim END
1774    vim9script
1775    import svar from './XunletExport.vim'
1776    def UnletSvar()
1777      unlet svar
1778    enddef
1779    defcompile
1780  END
1781  CheckScriptFailure(lines, 'E1081:', 1)
1782  delete('XunletExport.vim')
1783
1784  $ENVVAR = 'foobar'
1785  assert_equal('foobar', $ENVVAR)
1786  unlet $ENVVAR
1787  assert_equal('', $ENVVAR)
1788enddef
1789
1790def Test_expr_error_no_assign()
1791  var lines =<< trim END
1792      vim9script
1793      var x = invalid
1794      echo x
1795  END
1796  CheckScriptFailureList(lines, ['E121:', 'E121:'])
1797
1798  lines =<< trim END
1799      vim9script
1800      var x = 1 / 0
1801      echo x
1802  END
1803  CheckScriptFailure(lines, 'E1154:')
1804
1805  lines =<< trim END
1806      vim9script
1807      var x = 1 % 0
1808      echo x
1809  END
1810  CheckScriptFailure(lines, 'E1154:')
1811
1812  lines =<< trim END
1813      var x: string  'string'
1814  END
1815  CheckDefAndScriptFailure(lines, 'E488:')
1816enddef
1817
1818
1819def Test_assign_command_modifier()
1820  var lines =<< trim END
1821      var verbose = 0
1822      verbose = 1
1823      assert_equal(1, verbose)
1824      silent verbose = 2
1825      assert_equal(2, verbose)
1826      silent verbose += 2
1827      assert_equal(4, verbose)
1828      silent verbose -= 1
1829      assert_equal(3, verbose)
1830
1831      var topleft = {one: 1}
1832      sandbox topleft.one = 3
1833      assert_equal({one: 3}, topleft)
1834      leftabove topleft[' '] = 4
1835      assert_equal({one: 3, ' ': 4}, topleft)
1836
1837      var x: number
1838      var y: number
1839      silent [x, y] = [1, 2]
1840      assert_equal(1, x)
1841      assert_equal(2, y)
1842  END
1843  CheckDefAndScriptSuccess(lines)
1844enddef
1845
1846def Test_assign_alt_buf_register()
1847  var lines =<< trim END
1848      edit 'file_b1'
1849      var b1 = bufnr()
1850      edit 'file_b2'
1851      var b2 = bufnr()
1852      assert_equal(b1, bufnr('#'))
1853      @# = b2
1854      assert_equal(b2, bufnr('#'))
1855  END
1856  CheckDefAndScriptSuccess(lines)
1857enddef
1858
1859def Test_script_funcref_case()
1860  var lines =<< trim END
1861      var Len = (s: string): number => len(s) + 1
1862      assert_equal(5, Len('asdf'))
1863  END
1864  CheckDefAndScriptSuccess(lines)
1865
1866  lines =<< trim END
1867      var len = (s: string): number => len(s) + 1
1868  END
1869  CheckDefAndScriptFailure(lines, 'E704:')
1870
1871  lines =<< trim END
1872      vim9script
1873      var s:Len = (s: string): number => len(s) + 2
1874      assert_equal(6, Len('asdf'))
1875  END
1876  CheckScriptSuccess(lines)
1877
1878  lines =<< trim END
1879      vim9script
1880      var s:len = (s: string): number => len(s) + 1
1881  END
1882  CheckScriptFailure(lines, 'E704:')
1883enddef
1884
1885def Test_inc_dec()
1886  var lines =<< trim END
1887      var nr = 7
1888      ++nr
1889      assert_equal(8, nr)
1890      --nr
1891      assert_equal(7, nr)
1892
1893      var ll = [1, 2]
1894      --ll[0]
1895      ++ll[1]
1896      assert_equal([0, 3], ll)
1897
1898      g:count = 1
1899      ++g:count
1900      --g:count
1901      assert_equal(1, g:count)
1902      unlet g:count
1903  END
1904  CheckDefAndScriptSuccess(lines)
1905enddef
1906
1907
1908" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1909