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