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