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