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