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