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