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:astring = 'text'
13
14def Test_assignment_bool()
15  var bool1: bool = true
16  assert_equal(v:true, bool1)
17  var bool2: bool = false
18  assert_equal(v:false, bool2)
19
20  var bool3: bool = 0
21  assert_equal(false, bool3)
22  var bool4: bool = 1
23  assert_equal(true, bool4)
24
25  var bool5: bool = 'yes' && 'no'
26  assert_equal(true, bool5)
27  var bool6: bool = [] && 99
28  assert_equal(false, bool6)
29  var bool7: bool = [] || #{a: 1} && 99
30  assert_equal(true, bool7)
31
32  var lines =<< trim END
33    vim9script
34    def GetFlag(): bool
35      var flag: bool = 1
36      return flag
37    enddef
38    var flag: bool = GetFlag()
39    assert_equal(true, flag)
40    flag = 0
41    assert_equal(false, flag)
42    flag = 1
43    assert_equal(true, flag)
44    flag = 99 || 123
45    assert_equal(true, flag)
46    flag = 'yes' && []
47    assert_equal(false, flag)
48  END
49  CheckScriptSuccess(lines)
50  CheckDefAndScriptFailure(['var x: bool = 2'], 'E1012:')
51  CheckDefAndScriptFailure(['var x: bool = -1'], 'E1012:')
52  CheckDefAndScriptFailure(['var x: bool = [1]'], 'E1012:')
53  CheckDefAndScriptFailure(['var x: bool = {}'], 'E1012:')
54  CheckDefAndScriptFailure(['var x: bool = "x"'], 'E1012:')
55enddef
56
57def Test_syntax()
58  var name = 234
59  var other: list<string> = ['asdf']
60enddef
61
62def Test_assignment()
63  CheckDefFailure(['var x:string'], 'E1069:')
64  CheckDefFailure(['var x:string = "x"'], 'E1069:')
65  CheckDefFailure(['var a:string = "x"'], 'E1069:')
66  CheckDefFailure(['var lambda = {-> "lambda"}'], 'E704:')
67  CheckScriptFailure(['var x = "x"'], 'E1124:')
68
69  var nr: number = 1234
70  CheckDefFailure(['var nr: number = "asdf"'], 'E1012:')
71
72  var a: number = 6 #comment
73  assert_equal(6, a)
74
75  if has('channel')
76    var chan1: channel
77    var job1: job
78    var job2: job = job_start('willfail')
79  endif
80  if has('float')
81    var float1: float = 3.4
82  endif
83  var Funky1: func
84  var Funky2: func = function('len')
85  var Party2: func = funcref('g:Test_syntax')
86
87  g:newvar = 'new'  #comment
88  assert_equal('new', g:newvar)
89
90  assert_equal('yes', g:existing)
91  g:existing = 'no'
92  assert_equal('no', g:existing)
93
94  v:char = 'abc'
95  assert_equal('abc', v:char)
96
97  $ENVVAR = 'foobar'
98  assert_equal('foobar', $ENVVAR)
99  $ENVVAR = ''
100
101  var lines =<< trim END
102    vim9script
103    $ENVVAR = 'barfoo'
104    assert_equal('barfoo', $ENVVAR)
105    $ENVVAR = ''
106  END
107  CheckScriptSuccess(lines)
108
109  s:appendToMe ..= 'yyy'
110  assert_equal('xxxyyy', s:appendToMe)
111  s:addToMe += 222
112  assert_equal(333, s:addToMe)
113  s:newVar = 'new'
114  assert_equal('new', s:newVar)
115
116  set ts=7
117  &ts += 1
118  assert_equal(8, &ts)
119  &ts -= 3
120  assert_equal(5, &ts)
121  &ts *= 2
122  assert_equal(10, &ts)
123  &ts /= 3
124  assert_equal(3, &ts)
125  set ts=10
126  &ts %= 4
127  assert_equal(2, &ts)
128
129  if has('float')
130    var f100: float = 100.0
131    f100 /= 5
132    assert_equal(20.0, f100)
133
134    var f200: float = 200.0
135    f200 /= 5.0
136    assert_equal(40.0, f200)
137
138    CheckDefFailure(['var nr: number = 200', 'nr /= 5.0'], 'E1012:')
139  endif
140
141  lines =<< trim END
142    &ts = 6
143    &ts += 3
144    assert_equal(9, &ts)
145
146    &l:ts = 6
147    assert_equal(6, &ts)
148    &l:ts += 2
149    assert_equal(8, &ts)
150
151    &g:ts = 6
152    assert_equal(6, &g:ts)
153    &g:ts += 2
154    assert_equal(8, &g:ts)
155  END
156  CheckDefAndScriptSuccess(lines)
157
158  CheckDefFailure(['&notex += 3'], 'E113:')
159  CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
160  CheckDefFailure(['&ts = [7]'], 'E1012:')
161  CheckDefExecFailure(['&ts = g:alist'], 'E1012: Type mismatch; expected number but got list<number>')
162  CheckDefFailure(['&ts = "xx"'], 'E1012:')
163  CheckDefExecFailure(['&ts = g:astring'], 'E1012: Type mismatch; expected number but got string')
164  CheckDefFailure(['&path += 3'], 'E1012:')
165  CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
166  # test freeing ISN_STOREOPT
167  CheckDefFailure(['&ts = 3', 'var asdf'], 'E1022:')
168  &ts = 8
169
170  lines =<< trim END
171    var save_TI = &t_TI
172    &t_TI = ''
173    assert_equal('', &t_TI)
174    &t_TI = 'xxx'
175    assert_equal('xxx', &t_TI)
176    &t_TI = save_TI
177  END
178  CheckDefAndScriptSuccess(lines)
179
180  CheckDefFailure(['&t_TI = 123'], 'E1012:')
181  CheckScriptFailure(['vim9script', '&t_TI = 123'], 'E928:')
182
183  CheckDefFailure(['var s:var = 123'], 'E1101:')
184  CheckDefFailure(['var s:var: number'], 'E1101:')
185
186  lines =<< trim END
187    vim9script
188    def SomeFunc()
189      s:var = 123
190    enddef
191    defcompile
192  END
193  CheckScriptFailure(lines, 'E1089:')
194
195  g:inc_counter += 1
196  assert_equal(2, g:inc_counter)
197
198  $SOME_ENV_VAR ..= 'more'
199  assert_equal('somemore', $SOME_ENV_VAR)
200  CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1051:')
201  CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1012:')
202
203  lines =<< trim END
204    @c = 'areg'
205    @c ..= 'add'
206    assert_equal('aregadd', @c)
207  END
208  CheckDefAndScriptSuccess(lines)
209
210  CheckDefFailure(['@a += "more"'], 'E1051:')
211  CheckDefFailure(['@a += 123'], 'E1012:')
212
213  v:errmsg = 'none'
214  v:errmsg ..= 'again'
215  assert_equal('noneagain', v:errmsg)
216  CheckDefFailure(['v:errmsg += "more"'], 'E1051:')
217  CheckDefFailure(['v:errmsg += 123'], 'E1012:')
218
219  # this should not leak
220  if 0
221    var text =<< trim END
222      some text
223    END
224  endif
225enddef
226
227def Test_extend_list()
228  var lines =<< trim END
229      vim9script
230      var l: list<number>
231      l += [123]
232      assert_equal([123], l)
233
234      var d: dict<number>
235      d['one'] = 1
236      assert_equal(#{one: 1}, d)
237  END
238  CheckScriptSuccess(lines)
239enddef
240
241def Test_single_letter_vars()
242  # single letter variables
243  var a: number = 123
244  a = 123
245  assert_equal(123, a)
246  var b: number
247  b = 123
248  assert_equal(123, b)
249  var g: number
250  g = 123
251  assert_equal(123, g)
252  var s: number
253  s = 123
254  assert_equal(123, s)
255  var t: number
256  t = 123
257  assert_equal(123, t)
258  var v: number
259  v = 123
260  assert_equal(123, v)
261  var w: number
262  w = 123
263  assert_equal(123, w)
264enddef
265
266def Test_vim9_single_char_vars()
267  var lines =<< trim END
268      vim9script
269
270      # single character variable declarations work
271      var a: string
272      var b: number
273      var l: list<any>
274      var s: string
275      var t: number
276      var v: number
277      var w: number
278
279      # script-local variables can be used without s: prefix
280      a = 'script-a'
281      b = 111
282      l = [1, 2, 3]
283      s = 'script-s'
284      t = 222
285      v = 333
286      w = 444
287
288      assert_equal('script-a', a)
289      assert_equal(111, b)
290      assert_equal([1, 2, 3], l)
291      assert_equal('script-s', s)
292      assert_equal(222, t)
293      assert_equal(333, v)
294      assert_equal(444, w)
295  END
296  writefile(lines, 'Xsinglechar')
297  source Xsinglechar
298  delete('Xsinglechar')
299enddef
300
301def Test_assignment_list()
302  var list1: list<bool> = [false, true, false]
303  var list2: list<number> = [1, 2, 3]
304  var list3: list<string> = ['sdf', 'asdf']
305  var list4: list<any> = ['yes', true, 1234]
306  var list5: list<blob> = [0z01, 0z02]
307
308  var listS: list<string> = []
309  var listN: list<number> = []
310
311  assert_equal([1, 2, 3], list2)
312  list2[-1] = 99
313  assert_equal([1, 2, 99], list2)
314  list2[-2] = 88
315  assert_equal([1, 88, 99], list2)
316  list2[-3] = 77
317  assert_equal([77, 88, 99], list2)
318  list2 += [100]
319  assert_equal([77, 88, 99, 100], list2)
320
321  list3 += ['end']
322  assert_equal(['sdf', 'asdf', 'end'], list3)
323
324  CheckDefExecFailure(['var ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
325  CheckDefExecFailure(['var [v1, v2] = [1, 2]'], 'E1092:')
326
327  # type becomes list<any>
328  var somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
329enddef
330
331def Test_assignment_list_vim9script()
332  var lines =<< trim END
333    vim9script
334    var v1: number
335    var v2: number
336    var v3: number
337    [v1, v2, v3] = [1, 2, 3]
338    assert_equal([1, 2, 3], [v1, v2, v3])
339  END
340  CheckScriptSuccess(lines)
341enddef
342
343def Test_assignment_dict()
344  var dict1: dict<bool> = #{one: false, two: true}
345  var dict2: dict<number> = #{one: 1, two: 2}
346  var dict3: dict<string> = #{key: 'value'}
347  var dict4: dict<any> = #{one: 1, two: '2'}
348  var dict5: dict<blob> = #{one: 0z01, two: 0z02}
349
350  # overwrite
351  dict3['key'] = 'another'
352
353  # empty key can be used
354  var dd = {}
355  dd[""] = 6
356  assert_equal({'': 6}, dd)
357
358  # type becomes dict<any>
359  var somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
360
361  # assignment to script-local dict
362  var lines =<< trim END
363    vim9script
364    var test: dict<any> = {}
365    def FillDict(): dict<any>
366      test['a'] = 43
367      return test
368    enddef
369    assert_equal(#{a: 43}, FillDict())
370  END
371  CheckScriptSuccess(lines)
372
373  lines =<< trim END
374    vim9script
375    var test: dict<any>
376    def FillDict(): dict<any>
377      test['a'] = 43
378      return test
379    enddef
380    FillDict()
381  END
382  CheckScriptFailure(lines, 'E1103:')
383
384  # assignment to global dict
385  lines =<< trim END
386    vim9script
387    g:test = {}
388    def FillDict(): dict<any>
389      g:test['a'] = 43
390      return g:test
391    enddef
392    assert_equal(#{a: 43}, FillDict())
393  END
394  CheckScriptSuccess(lines)
395
396  # assignment to buffer dict
397  lines =<< trim END
398    vim9script
399    b:test = {}
400    def FillDict(): dict<any>
401      b:test['a'] = 43
402      return b:test
403    enddef
404    assert_equal(#{a: 43}, FillDict())
405  END
406  CheckScriptSuccess(lines)
407enddef
408
409def Test_assignment_local()
410  # Test in a separated file in order not to the current buffer/window/tab is
411  # changed.
412  var script_lines: list<string> =<< trim END
413    let b:existing = 'yes'
414    let w:existing = 'yes'
415    let t:existing = 'yes'
416
417    def Test_assignment_local_internal()
418      b:newvar = 'new'
419      assert_equal('new', b:newvar)
420      assert_equal('yes', b:existing)
421      b:existing = 'no'
422      assert_equal('no', b:existing)
423      b:existing ..= 'NO'
424      assert_equal('noNO', b:existing)
425
426      w:newvar = 'new'
427      assert_equal('new', w:newvar)
428      assert_equal('yes', w:existing)
429      w:existing = 'no'
430      assert_equal('no', w:existing)
431      w:existing ..= 'NO'
432      assert_equal('noNO', w:existing)
433
434      t:newvar = 'new'
435      assert_equal('new', t:newvar)
436      assert_equal('yes', t:existing)
437      t:existing = 'no'
438      assert_equal('no', t:existing)
439      t:existing ..= 'NO'
440      assert_equal('noNO', t:existing)
441    enddef
442    call Test_assignment_local_internal()
443  END
444  CheckScriptSuccess(script_lines)
445enddef
446
447def Test_assignment_default()
448
449  # Test default values.
450  var thebool: bool
451  assert_equal(v:false, thebool)
452
453  var thenumber: number
454  assert_equal(0, thenumber)
455
456  if has('float')
457    var thefloat: float
458    assert_equal(0.0, thefloat)
459  endif
460
461  var thestring: string
462  assert_equal('', thestring)
463
464  var theblob: blob
465  assert_equal(0z, theblob)
466
467  var Thefunc: func
468  assert_equal(test_null_function(), Thefunc)
469
470  var thelist: list<any>
471  assert_equal([], thelist)
472
473  var thedict: dict<any>
474  assert_equal({}, thedict)
475
476  if has('channel')
477    var thejob: job
478    assert_equal(test_null_job(), thejob)
479
480    var thechannel: channel
481    assert_equal(test_null_channel(), thechannel)
482
483    if has('unix') && executable('cat')
484      # check with non-null job and channel, types must match
485      thejob = job_start("cat ", #{})
486      thechannel = job_getchannel(thejob)
487      job_stop(thejob, 'kill')
488    endif
489  endif
490
491  var nr = 1234 | nr = 5678
492  assert_equal(5678, nr)
493enddef
494
495def Test_assignment_var_list()
496  var v1: string
497  var v2: string
498  var vrem: list<string>
499  [v1] = ['aaa']
500  assert_equal('aaa', v1)
501
502  [v1, v2] = ['one', 'two']
503  assert_equal('one', v1)
504  assert_equal('two', v2)
505
506  [v1, v2; vrem] = ['one', 'two']
507  assert_equal('one', v1)
508  assert_equal('two', v2)
509  assert_equal([], vrem)
510
511  [v1, v2; vrem] = ['one', 'two', 'three']
512  assert_equal('one', v1)
513  assert_equal('two', v2)
514  assert_equal(['three'], vrem)
515
516  [&ts, &sw] = [3, 4]
517  assert_equal(3, &ts)
518  assert_equal(4, &sw)
519  set ts=8 sw=4
520enddef
521
522def Test_assignment_vim9script()
523  var lines =<< trim END
524    vim9script
525    def Func(): list<number>
526      return [1, 2]
527    enddef
528    var name1: number
529    var name2: number
530    [name1, name2] =
531          Func()
532    assert_equal(1, name1)
533    assert_equal(2, name2)
534    var ll =
535          Func()
536    assert_equal([1, 2], ll)
537
538    @/ = 'text'
539    assert_equal('text', @/)
540    @0 = 'zero'
541    assert_equal('zero', @0)
542    @1 = 'one'
543    assert_equal('one', @1)
544    @9 = 'nine'
545    assert_equal('nine', @9)
546    @- = 'minus'
547    assert_equal('minus', @-)
548    if has('clipboard_working')
549      @* = 'star'
550      assert_equal('star', @*)
551      @+ = 'plus'
552      assert_equal('plus', @+)
553    endif
554
555    var a: number = 123
556    assert_equal(123, a)
557    var s: string = 'yes'
558    assert_equal('yes', s)
559    var b: number = 42
560    assert_equal(42, b)
561    var w: number = 43
562    assert_equal(43, w)
563    var t: number = 44
564    assert_equal(44, t)
565  END
566  CheckScriptSuccess(lines)
567
568  lines =<< trim END
569      vim9script
570      var n: number
571      def Func()
572        n = 'string'
573      enddef
574      defcompile
575  END
576  CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
577enddef
578
579def Mess(): string
580  v:foldstart = 123
581  return 'xxx'
582enddef
583
584def Test_assignment_failure()
585  CheckDefFailure(['var name=234'], 'E1004:')
586  CheckDefFailure(['var name =234'], 'E1004:')
587  CheckDefFailure(['var name= 234'], 'E1004:')
588
589  CheckScriptFailure(['vim9script', 'var name=234'], 'E1004:')
590  CheckScriptFailure(['vim9script', 'var name=234'], "before and after '='")
591  CheckScriptFailure(['vim9script', 'var name =234'], 'E1004:')
592  CheckScriptFailure(['vim9script', 'var name= 234'], 'E1004:')
593  CheckScriptFailure(['vim9script', 'var name = 234', 'name+=234'], 'E1004:')
594  CheckScriptFailure(['vim9script', 'var name = 234', 'name+=234'], "before and after '+='")
595  CheckScriptFailure(['vim9script', 'var name = "x"', 'name..="y"'], 'E1004:')
596  CheckScriptFailure(['vim9script', 'var name = "x"', 'name..="y"'], "before and after '..='")
597
598  CheckDefFailure(['var true = 1'], 'E1034:')
599  CheckDefFailure(['var false = 1'], 'E1034:')
600
601  CheckDefFailure(['[a; b; c] = g:list'], 'E452:')
602  CheckDefExecFailure(['var a: number',
603                       '[a] = test_null_list()'], 'E1093:')
604  CheckDefExecFailure(['var a: number',
605                       '[a] = []'], 'E1093:')
606  CheckDefExecFailure(['var x: number',
607                       'var y: number',
608                       '[x, y] = [1]'], 'E1093:')
609  CheckDefExecFailure(['var x: number',
610                       'var y: number',
611                       'var z: list<number>',
612                       '[x, y; z] = [1]'], 'E1093:')
613
614  CheckDefFailure(['var somevar'], "E1022:")
615  CheckDefFailure(['var &tabstop = 4'], 'E1052:')
616  CheckDefFailure(['&g:option = 5'], 'E113:')
617  CheckScriptFailure(['vim9script', 'var &tabstop = 4'], 'E1052:')
618
619  CheckDefFailure(['var $VAR = 5'], 'E1016: Cannot declare an environment variable:')
620  CheckScriptFailure(['vim9script', 'var $ENV = "xxx"'], 'E1016:')
621
622  if has('dnd')
623    CheckDefFailure(['var @~ = 5'], 'E1066:')
624  else
625    CheckDefFailure(['var @~ = 5'], 'E354:')
626    CheckDefFailure(['@~ = 5'], 'E354:')
627  endif
628  CheckDefFailure(['var @a = 5'], 'E1066:')
629  CheckDefFailure(['var @/ = "x"'], 'E1066:')
630  CheckScriptFailure(['vim9script', 'var @a = "abc"'], 'E1066:')
631
632  CheckDefFailure(['var g:var = 5'], 'E1016: Cannot declare a global variable:')
633  CheckDefFailure(['var w:var = 5'], 'E1016: Cannot declare a window variable:')
634  CheckDefFailure(['var b:var = 5'], 'E1016: Cannot declare a buffer variable:')
635  CheckDefFailure(['var t:var = 5'], 'E1016: Cannot declare a tab variable:')
636
637  CheckDefFailure(['var anr = 4', 'anr ..= "text"'], 'E1019:')
638  CheckDefFailure(['var xnr += 4'], 'E1020:', 1)
639  CheckScriptFailure(['vim9script', 'var xnr += 4'], 'E1020:')
640  CheckDefFailure(["var xnr = xnr + 1"], 'E1001:', 1)
641  CheckScriptFailure(['vim9script', 'var xnr = xnr + 4'], 'E121:')
642
643  CheckScriptFailure(['vim9script', 'def Func()', 'var dummy = s:notfound', 'enddef', 'defcompile'], 'E1108:')
644
645  CheckDefFailure(['var name: list<string> = [123]'], 'expected list<string> but got list<number>')
646  CheckDefFailure(['var name: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
647
648  CheckDefFailure(['var name: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
649  CheckDefFailure(['var name: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
650
651  CheckDefFailure(['var name = feedkeys("0")'], 'E1031:')
652  CheckDefFailure(['var name: number = feedkeys("0")'], 'expected number but got void')
653
654  CheckDefFailure(['var name: dict <number>'], 'E1068:')
655  CheckDefFailure(['var name: dict<number'], 'E1009:')
656
657  assert_fails('s/^/\=Mess()/n', 'E794:')
658  CheckDefFailure(['var name: dict<number'], 'E1009:')
659
660  CheckDefFailure(['w:foo: number = 10'],
661                  'E488: Trailing characters: : number = 1')
662  CheckDefFailure(['t:foo: bool = true'],
663                  'E488: Trailing characters: : bool = true')
664  CheckDefFailure(['b:foo: string = "x"'],
665                  'E488: Trailing characters: : string = "x"')
666  CheckDefFailure(['g:foo: number = 123'],
667                  'E488: Trailing characters: : number = 123')
668enddef
669
670def Test_assign_list()
671  var l: list<string> = []
672  l[0] = 'value'
673  assert_equal('value', l[0])
674
675  l[1] = 'asdf'
676  assert_equal('value', l[0])
677  assert_equal('asdf', l[1])
678  assert_equal('asdf', l[-1])
679  assert_equal('value', l[-2])
680
681  var nrl: list<number> = []
682  for i in range(5)
683    nrl[i] = i
684  endfor
685  assert_equal([0, 1, 2, 3, 4], nrl)
686enddef
687
688def Test_assign_dict()
689  var d: dict<string> = {}
690  d['key'] = 'value'
691  assert_equal('value', d['key'])
692
693  d[123] = 'qwerty'
694  assert_equal('qwerty', d[123])
695  assert_equal('qwerty', d['123'])
696
697  var nrd: dict<number> = {}
698  for i in range(3)
699    nrd[i] = i
700  endfor
701  assert_equal({'0': 0, '1': 1, '2': 2}, nrd)
702enddef
703
704def Test_assign_dict_unknown_type()
705  var lines =<< trim END
706      vim9script
707      var mylist = []
708      mylist += [#{one: 'one'}]
709      def Func()
710        var dd = mylist[0]
711        assert_equal('one', dd.one)
712      enddef
713      Func()
714  END
715  CheckScriptSuccess(lines)
716
717  # doesn't work yet
718  #lines =<< trim END
719  #    vim9script
720  #    var mylist = [[]]
721  #    mylist[0] += [#{one: 'one'}]
722  #    def Func()
723  #      var dd = mylist[0][0]
724  #      assert_equal('one', dd.one)
725  #    enddef
726  #    Func()
727  #END
728  #CheckScriptSuccess(lines)
729enddef
730
731def Test_assign_lambda()
732  # check if assign a lambda to a variable which type is func or any.
733  var lines =<< trim END
734      vim9script
735      var FuncRef = {->123}
736      assert_equal(123, FuncRef())
737      var FuncRef_Func: func = {->123}
738      assert_equal(123, FuncRef_Func())
739      var FuncRef_Any: any = {->123}
740      assert_equal(123, FuncRef_Any())
741  END
742  CheckScriptSuccess(lines)
743enddef
744
745def Test_heredoc()
746  var lines =<< trim END # comment
747    text
748  END
749  assert_equal(['text'], lines)
750
751  CheckDefFailure(['var lines =<< trim END X', 'END'], 'E488:')
752  CheckDefFailure(['var lines =<< trim END " comment', 'END'], 'E488:')
753
754  lines =<< trim [END]
755      def Func()
756        var&lines =<< trim END
757        x
758        x
759        x
760        x
761        x
762        x
763        x
764        x
765      enddef
766      call Func()
767  [END]
768  CheckScriptFailure(lines, 'E990:')
769enddef
770
771def Test_let_func_call()
772  var lines =<< trim END
773    vim9script
774    func GetValue()
775      if exists('g:count')
776        let g:count += 1
777      else
778        let g:count = 1
779      endif
780      return 'this'
781    endfunc
782    var val: string = GetValue()
783    # env var is always a string
784    var env = $TERM
785  END
786  writefile(lines, 'Xfinished')
787  source Xfinished
788  # GetValue() is not called during discovery phase
789  assert_equal(1, g:count)
790
791  unlet g:count
792  delete('Xfinished')
793enddef
794
795def Test_let_missing_type()
796  var lines =<< trim END
797    vim9script
798    var name = g:unknown
799  END
800  CheckScriptFailure(lines, 'E121:')
801
802  lines =<< trim END
803    vim9script
804    var nr: number = 123
805    var name = nr
806  END
807  CheckScriptSuccess(lines)
808enddef
809
810def Test_let_declaration()
811  var lines =<< trim END
812    vim9script
813    var name: string
814    g:var_uninit = name
815    name = 'text'
816    g:var_test = name
817    # prefixing s: is optional
818    s:name = 'prefixed'
819    g:var_prefixed = s:name
820
821    var s:other: number
822    other = 1234
823    g:other_var = other
824
825    # type is inferred
826    s:dict = {'a': 222}
827    def GetDictVal(key: any)
828      g:dict_val = s:dict[key]
829    enddef
830    GetDictVal('a')
831  END
832  CheckScriptSuccess(lines)
833  assert_equal('', g:var_uninit)
834  assert_equal('text', g:var_test)
835  assert_equal('prefixed', g:var_prefixed)
836  assert_equal(1234, g:other_var)
837  assert_equal(222, g:dict_val)
838
839  unlet g:var_uninit
840  unlet g:var_test
841  unlet g:var_prefixed
842  unlet g:other_var
843enddef
844
845def Test_let_declaration_fails()
846  var lines =<< trim END
847    vim9script
848    final var: string
849  END
850  CheckScriptFailure(lines, 'E1125:')
851
852  lines =<< trim END
853    vim9script
854    const var: string
855  END
856  CheckScriptFailure(lines, 'E1021:')
857
858  lines =<< trim END
859    vim9script
860    var 9var: string
861  END
862  CheckScriptFailure(lines, 'E475:')
863enddef
864
865def Test_let_type_check()
866  var lines =<< trim END
867    vim9script
868    var name: string
869    name = 1234
870  END
871  CheckScriptFailure(lines, 'E1012:')
872
873  lines =<< trim END
874    vim9script
875    var name:string
876  END
877  CheckScriptFailure(lines, 'E1069:')
878
879  lines =<< trim END
880    vim9script
881    var name: asdf
882  END
883  CheckScriptFailure(lines, 'E1010:')
884
885  lines =<< trim END
886    vim9script
887    var s:l: list<number>
888    s:l = []
889  END
890  CheckScriptSuccess(lines)
891
892  lines =<< trim END
893    vim9script
894    var s:d: dict<number>
895    s:d = {}
896  END
897  CheckScriptSuccess(lines)
898enddef
899
900let g:dict_number = #{one: 1, two: 2}
901
902def Test_let_list_dict_type()
903  var ll: list<number>
904  ll = [1, 2, 2, 3, 3, 3]->uniq()
905  ll->assert_equal([1, 2, 3])
906
907  var dd: dict<number>
908  dd = g:dict_number
909  dd->assert_equal(g:dict_number)
910
911  var lines =<< trim END
912      var ll: list<number>
913      ll = [1, 2, 3]->map('"one"')
914  END
915  CheckDefExecFailure(lines, 'E1012: Type mismatch; expected list<number> but got list<string>')
916enddef
917
918def Test_unlet()
919  g:somevar = 'yes'
920  assert_true(exists('g:somevar'))
921  unlet g:somevar
922  assert_false(exists('g:somevar'))
923  unlet! g:somevar
924
925  # also works for script-local variable in legacy Vim script
926  s:somevar = 'legacy'
927  assert_true(exists('s:somevar'))
928  unlet s:somevar
929  assert_false(exists('s:somevar'))
930  unlet! s:somevar
931
932  CheckScriptFailure([
933   'vim9script',
934   'var svar = 123',
935   'unlet svar',
936   ], 'E1081:')
937  CheckScriptFailure([
938   'vim9script',
939   'var svar = 123',
940   'unlet s:svar',
941   ], 'E1081:')
942  CheckScriptFailure([
943   'vim9script',
944   'var svar = 123',
945   'def Func()',
946   '  unlet svar',
947   'enddef',
948   'defcompile',
949   ], 'E1081:')
950  CheckScriptFailure([
951   'vim9script',
952   'var svar = 123',
953   'def Func()',
954   '  unlet s:svar',
955   'enddef',
956   'defcompile',
957   ], 'E1081:')
958
959  $ENVVAR = 'foobar'
960  assert_equal('foobar', $ENVVAR)
961  unlet $ENVVAR
962  assert_equal('', $ENVVAR)
963enddef
964
965
966" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
967