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