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