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