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