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