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
49    var cp: bool = &cp
50    var fen: bool = &l:fen
51  END
52  CheckScriptSuccess(lines)
53  CheckDefAndScriptFailure(['var x: bool = 2'], 'E1012:')
54  CheckDefAndScriptFailure(['var x: bool = -1'], 'E1012:')
55  CheckDefAndScriptFailure(['var x: bool = [1]'], 'E1012:')
56  CheckDefAndScriptFailure(['var x: bool = {}'], 'E1012:')
57  CheckDefAndScriptFailure(['var x: bool = "x"'], 'E1012:')
58
59  CheckDefAndScriptFailure(['var x: bool = "x"', '', 'eval 0'], 'E1012:', 1)
60enddef
61
62def Test_syntax()
63  var name = 234
64  var other: list<string> = ['asdf']
65enddef
66
67def Test_assignment()
68  CheckDefFailure(['var x:string'], 'E1069:')
69  CheckDefFailure(['var x:string = "x"'], 'E1069:')
70  CheckDefFailure(['var a:string = "x"'], 'E1069:')
71  CheckDefFailure(['var lambda = () => "lambda"'], 'E704:')
72  CheckScriptFailure(['var x = "x"'], 'E1124:')
73
74  var nr: number = 1234
75  CheckDefFailure(['var nr: number = "asdf"'], 'E1012:')
76
77  var a: number = 6 #comment
78  assert_equal(6, a)
79
80  if has('channel')
81    var chan1: channel
82    assert_equal('fail', ch_status(chan1))
83
84    var job1: job
85    assert_equal('fail', job_status(job1))
86
87    # calling job_start() is in test_vim9_fails.vim, it causes leak reports
88  endif
89  if has('float')
90    var float1: float = 3.4
91  endif
92  var Funky1: func
93  var Funky2: func = function('len')
94  var Party2: func = funcref('g:Test_syntax')
95
96  g:newvar = 'new'  #comment
97  assert_equal('new', g:newvar)
98
99  assert_equal('yes', g:existing)
100  g:existing = 'no'
101  assert_equal('no', g:existing)
102
103  v:char = 'abc'
104  assert_equal('abc', v:char)
105
106  $ENVVAR = 'foobar'
107  assert_equal('foobar', $ENVVAR)
108  $ENVVAR = ''
109
110  var lines =<< trim END
111    vim9script
112    $ENVVAR = 'barfoo'
113    assert_equal('barfoo', $ENVVAR)
114    $ENVVAR = ''
115  END
116  CheckScriptSuccess(lines)
117
118  s:appendToMe ..= 'yyy'
119  assert_equal('xxxyyy', s:appendToMe)
120  s:addToMe += 222
121  assert_equal(333, s:addToMe)
122  s:newVar = 'new'
123  assert_equal('new', s:newVar)
124
125  set ts=7
126  var ts: number = &ts
127  assert_equal(7, ts)
128  &ts += 1
129  assert_equal(8, &ts)
130  &ts -= 3
131  assert_equal(5, &ts)
132  &ts *= 2
133  assert_equal(10, &ts)
134  &ts /= 3
135  assert_equal(3, &ts)
136  set ts=10
137  &ts %= 4
138  assert_equal(2, &ts)
139
140  if has('float')
141    var f100: float = 100.0
142    f100 /= 5
143    assert_equal(20.0, f100)
144
145    var f200: float = 200.0
146    f200 /= 5.0
147    assert_equal(40.0, f200)
148
149    CheckDefFailure(['var nr: number = 200', 'nr /= 5.0'], 'E1012:')
150  endif
151
152  lines =<< trim END
153    &ts = 6
154    &ts += 3
155    assert_equal(9, &ts)
156
157    &l:ts = 6
158    assert_equal(6, &ts)
159    &l:ts += 2
160    assert_equal(8, &ts)
161
162    &g:ts = 6
163    assert_equal(6, &g:ts)
164    &g:ts += 2
165    assert_equal(8, &g:ts)
166
167    &number = true
168    assert_equal(true, &number)
169    &number = 0
170    assert_equal(false, &number)
171    &number = 1
172    assert_equal(true, &number)
173    &number = false
174    assert_equal(false, &number)
175  END
176  CheckDefAndScriptSuccess(lines)
177
178  CheckDefFailure(['&notex += 3'], 'E113:')
179  CheckDefFailure(['&ts ..= "xxx"'], 'E1019:')
180  CheckDefFailure(['&ts = [7]'], 'E1012:')
181  CheckDefExecFailure(['&ts = g:alist'], 'E1012: Type mismatch; expected number but got list<number>')
182  CheckDefFailure(['&ts = "xx"'], 'E1012:')
183  CheckDefExecFailure(['&ts = g:astring'], 'E1012: Type mismatch; expected number but got string')
184  CheckDefFailure(['&path += 3'], 'E1012:')
185  CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
186  # test freeing ISN_STOREOPT
187  CheckDefFailure(['&ts = 3', 'var asdf'], 'E1022:')
188  &ts = 8
189
190  lines =<< trim END
191    var save_TI = &t_TI
192    &t_TI = ''
193    assert_equal('', &t_TI)
194    &t_TI = 'xxx'
195    assert_equal('xxx', &t_TI)
196    &t_TI = save_TI
197  END
198  CheckDefAndScriptSuccess(lines)
199
200  CheckDefFailure(['&t_TI = 123'], 'E1012:')
201  CheckScriptFailure(['vim9script', '&t_TI = 123'], 'E928:')
202
203  CheckDefFailure(['var s:var = 123'], 'E1101:')
204  CheckDefFailure(['var s:var: number'], 'E1101:')
205
206  lines =<< trim END
207    vim9script
208    def SomeFunc()
209      s:var = 123
210    enddef
211    defcompile
212  END
213  CheckScriptFailure(lines, 'E1089:')
214
215  g:inc_counter += 1
216  assert_equal(2, g:inc_counter)
217
218  $SOME_ENV_VAR ..= 'more'
219  assert_equal('somemore', $SOME_ENV_VAR)
220  CheckDefFailure(['$SOME_ENV_VAR += "more"'], 'E1051:')
221  CheckDefFailure(['$SOME_ENV_VAR += 123'], 'E1012:')
222
223  lines =<< trim END
224    @c = 'areg'
225    @c ..= 'add'
226    assert_equal('aregadd', @c)
227  END
228  CheckDefAndScriptSuccess(lines)
229
230  CheckDefFailure(['@a += "more"'], 'E1051:')
231  CheckDefFailure(['@a += 123'], 'E1012:')
232
233  v:errmsg = 'none'
234  v:errmsg ..= 'again'
235  assert_equal('noneagain', v:errmsg)
236  CheckDefFailure(['v:errmsg += "more"'], 'E1051:')
237  CheckDefFailure(['v:errmsg += 123'], 'E1012:')
238
239  var text =<< trim END
240    some text
241  END
242enddef
243
244def Test_assign_unpack()
245  var lines =<< trim END
246    var v1: number
247    var v2: number
248    [v1, v2] = [1, 2]
249    assert_equal(1, v1)
250    assert_equal(2, v2)
251  END
252  CheckDefAndScriptSuccess(lines)
253
254  lines =<< trim END
255      var v1: number
256      var v2: number
257      [v1, v2] =
258  END
259  CheckDefFailure(lines, 'E1097:', 5)
260
261  lines =<< trim END
262      var v1: number
263      var v2: number
264      [v1, v2] = xxx
265  END
266  CheckDefFailure(lines, 'E1001:', 3)
267
268  lines =<< trim END
269      var v1: number
270      var v2: number
271      [v1, v2] = popup_clear()
272  END
273  CheckDefFailure(lines, 'E1031:', 3)
274
275  lines =<< trim END
276      [v1, v2] = [1, 2]
277  END
278  CheckDefFailure(lines, 'E1089', 1)
279  CheckScriptFailure(['vim9script'] + lines, 'E1089', 2)
280
281  lines =<< trim END
282      var v1: number
283      var v2: number
284      [v1, v2] = ''
285  END
286  CheckDefFailure(lines, 'E1012: Type mismatch; expected list<any> but got string', 3)
287
288  lines =<< trim END
289    g:values = [false, 0]
290    var x: bool
291    var y: string
292    [x, y] = g:values
293  END
294  CheckDefExecAndScriptFailure(lines, 'E1163: Variable 2: type mismatch, expected string but got number')
295enddef
296
297def Test_assign_linebreak()
298  var nr: number
299  nr =
300      123
301  assert_equal(123, nr)
302
303  var n2: number
304  [nr, n2] =
305     [12, 34]
306  assert_equal(12, nr)
307  assert_equal(34, n2)
308
309  CheckDefFailure(["var x = #"], 'E1097:', 3)
310enddef
311
312def Test_assign_index()
313  # list of list
314  var l1: list<number>
315  l1[0] = 123
316  assert_equal([123], l1)
317
318  var l2: list<list<number>>
319  l2[0] = []
320  l2[0][0] = 123
321  assert_equal([[123]], l2)
322
323  var l3: list<list<list<number>>>
324  l3[0] = []
325  l3[0][0] = []
326  l3[0][0][0] = 123
327  assert_equal([[[123]]], l3)
328
329  var lines =<< trim END
330      var l3: list<list<number>>
331      l3[0] = []
332      l3[0][0] = []
333  END
334  CheckDefFailure(lines, 'E1012: Type mismatch; expected number but got list<unknown>', 3)
335
336  # dict of dict
337  var d1: dict<number>
338  d1.one = 1
339  assert_equal({one: 1}, d1)
340
341  var d2: dict<dict<number>>
342  d2.one = {}
343  d2.one.two = 123
344  assert_equal({one: {two: 123}}, d2)
345
346  var d3: dict<dict<dict<number>>>
347  d3.one = {}
348  d3.one.two = {}
349  d3.one.two.three = 123
350  assert_equal({one: {two: {three: 123}}}, d3)
351
352  lines =<< trim END
353      var d3: dict<dict<number>>
354      d3.one = {}
355      d3.one.two = {}
356  END
357  CheckDefFailure(lines, 'E1012: Type mismatch; expected number but got dict<unknown>', 3)
358
359  lines =<< trim END
360    var lines: list<string>
361    lines['a'] = 'asdf'
362  END
363  CheckDefFailure(lines, 'E1012:', 2)
364
365  lines =<< trim END
366    var lines: string
367    lines[9] = 'asdf'
368  END
369  CheckDefFailure(lines, 'E1141:', 2)
370
371  # list of dict
372  var ld: list<dict<number>>
373  ld[0] = {}
374  ld[0].one = 123
375  assert_equal([{one: 123}], ld)
376
377  lines =<< trim END
378      var ld: list<dict<number>>
379      ld[0] = []
380  END
381  CheckDefFailure(lines, 'E1012: Type mismatch; expected dict<number> but got list<unknown>', 2)
382
383  # dict of list
384  var dl: dict<list<number>>
385  dl.one = []
386  dl.one[0] = 123
387  assert_equal({one: [123]}, dl)
388
389  lines =<< trim END
390      var dl: dict<list<number>>
391      dl.one = {}
392  END
393  CheckDefFailure(lines, 'E1012: Type mismatch; expected list<number> but got dict<unknown>', 2)
394enddef
395
396def Test_extend_list()
397  var lines =<< trim END
398      vim9script
399      var l: list<number>
400      l += [123]
401      assert_equal([123], l)
402  END
403  CheckScriptSuccess(lines)
404
405  lines =<< trim END
406      vim9script
407      var list: list<string>
408      extend(list, ['x'])
409      assert_equal(['x'], list)
410  END
411  CheckScriptSuccess(lines)
412
413  # appending to NULL list from a function
414  lines =<< trim END
415      vim9script
416      var list: list<string>
417      def Func()
418        list += ['a', 'b']
419      enddef
420      Func()
421      assert_equal(['a', 'b'], list)
422  END
423  CheckScriptSuccess(lines)
424  lines =<< trim END
425      vim9script
426      var list: list<string>
427      def Func()
428        extend(list, ['x', 'b'])
429      enddef
430      Func()
431      assert_equal(['x', 'b'], list)
432  END
433  CheckScriptSuccess(lines)
434
435  lines =<< trim END
436      vim9script
437      var l: list<string> = test_null_list()
438      extend(l, ['x'])
439      assert_equal(['x'], l)
440  END
441  CheckScriptSuccess(lines)
442
443  lines =<< trim END
444      vim9script
445      extend(test_null_list(), ['x'])
446  END
447  CheckScriptFailure(lines, 'E1134:', 2)
448enddef
449
450def Test_extend_dict()
451  var lines =<< trim END
452      vim9script
453      var d: dict<number>
454      extend(d, {a: 1})
455      assert_equal({a: 1}, d)
456
457      var d2: dict<number>
458      d2['one'] = 1
459      assert_equal({one: 1}, d2)
460  END
461  CheckScriptSuccess(lines)
462
463  lines =<< trim END
464      vim9script
465      var d: dict<string> = test_null_dict()
466      extend(d, {a: 'x'})
467      assert_equal({a: 'x'}, d)
468  END
469  CheckScriptSuccess(lines)
470
471  lines =<< trim END
472      vim9script
473      extend(test_null_dict(), {a: 'x'})
474  END
475  CheckScriptFailure(lines, 'E1133:', 2)
476enddef
477
478def Test_single_letter_vars()
479  # single letter variables
480  var a: number = 123
481  a = 123
482  assert_equal(123, a)
483  var b: number
484  b = 123
485  assert_equal(123, b)
486  var g: number
487  g = 123
488  assert_equal(123, g)
489  var s: number
490  s = 123
491  assert_equal(123, s)
492  var t: number
493  t = 123
494  assert_equal(123, t)
495  var v: number
496  v = 123
497  assert_equal(123, v)
498  var w: number
499  w = 123
500  assert_equal(123, w)
501enddef
502
503def Test_vim9_single_char_vars()
504  var lines =<< trim END
505      vim9script
506
507      # single character variable declarations work
508      var a: string
509      var b: number
510      var l: list<any>
511      var s: string
512      var t: number
513      var v: number
514      var w: number
515
516      # script-local variables can be used without s: prefix
517      a = 'script-a'
518      b = 111
519      l = [1, 2, 3]
520      s = 'script-s'
521      t = 222
522      v = 333
523      w = 444
524
525      assert_equal('script-a', a)
526      assert_equal(111, b)
527      assert_equal([1, 2, 3], l)
528      assert_equal('script-s', s)
529      assert_equal(222, t)
530      assert_equal(333, v)
531      assert_equal(444, w)
532  END
533  writefile(lines, 'Xsinglechar')
534  source Xsinglechar
535  delete('Xsinglechar')
536enddef
537
538def Test_assignment_list()
539  var list1: list<bool> = [false, true, false]
540  var list2: list<number> = [1, 2, 3]
541  var list3: list<string> = ['sdf', 'asdf']
542  var list4: list<any> = ['yes', true, 1234]
543  var list5: list<blob> = [0z01, 0z02]
544
545  var listS: list<string> = []
546  var listN: list<number> = []
547
548  assert_equal([1, 2, 3], list2)
549  list2[-1] = 99
550  assert_equal([1, 2, 99], list2)
551  list2[-2] = 88
552  assert_equal([1, 88, 99], list2)
553  list2[-3] = 77
554  assert_equal([77, 88, 99], list2)
555  list2 += [100]
556  assert_equal([77, 88, 99, 100], list2)
557
558  list3 += ['end']
559  assert_equal(['sdf', 'asdf', 'end'], list3)
560
561  CheckDefExecFailure(['var ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
562  CheckDefExecFailure(['var [v1, v2] = [1, 2]'], 'E1092:')
563
564  # type becomes list<any>
565  var somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
566
567  var lines =<< trim END
568    var d = {dd: test_null_list()}
569    d.dd[0] = 0
570  END
571  CheckDefExecFailure(lines, 'E1147:', 2)
572enddef
573
574def Test_assignment_list_any_index()
575   var l: list<number> = [1, 2]
576  for  [x, y, _]
577  in  [[0, 1, ''], [1, 3, '']]
578      l[x] = l[x] + y
579  endfor
580  assert_equal([2, 5], l)
581enddef
582
583def Test_assignment_list_vim9script()
584  var lines =<< trim END
585    vim9script
586    var v1: number
587    var v2: number
588    var v3: number
589    [v1, v2, v3] = [1, 2, 3]
590    assert_equal([1, 2, 3], [v1, v2, v3])
591  END
592  CheckScriptSuccess(lines)
593enddef
594
595def Test_assignment_dict()
596  var dict1: dict<bool> = {one: false, two: true}
597  var dict2: dict<number> = {one: 1, two: 2}
598  var dict3: dict<string> = {key: 'value'}
599  var dict4: dict<any> = {one: 1, two: '2'}
600  var dict5: dict<blob> = {one: 0z01, two: 0z02}
601
602  # overwrite
603  dict3['key'] = 'another'
604  assert_equal(dict3, {key: 'another'})
605  dict3.key = 'yet another'
606  assert_equal(dict3, {key: 'yet another'})
607
608  # member "any" can also be a dict and assigned to
609  var anydict: dict<any> = {nest: {}, nr: 0}
610  anydict.nest['this'] = 123
611  anydict.nest.that = 456
612  assert_equal({nest: {this: 123, that: 456}, nr: 0}, anydict)
613
614  var lines =<< trim END
615    var dd = {}
616    dd.two = 2
617    assert_equal({two: 2}, dd)
618  END
619  CheckDefAndScriptSuccess(lines)
620
621  lines =<< trim END
622    var d = {dd: {}}
623    d.dd[0] = 2
624    d.dd['x'] = 3
625    d.dd.y = 4
626    assert_equal({dd: {0: 2, x: 3, y: 4}}, d)
627  END
628  CheckDefAndScriptSuccess(lines)
629
630  lines =<< trim END
631    var dd = {one: 1}
632    dd.one) = 2
633  END
634  CheckDefFailure(lines, 'E488:', 2)
635
636  lines =<< trim END
637    var dd = {one: 1}
638    var dd.one = 2
639  END
640  CheckDefAndScriptFailure(lines, 'E1017:', 2)
641
642  # empty key can be used
643  var dd = {}
644  dd[""] = 6
645  assert_equal({['']: 6}, dd)
646
647  # type becomes dict<any>
648  var somedict = rand() > 0 ? {a: 1, b: 2} : {a: 'a', b: 'b'}
649
650  # assignment to script-local dict
651  lines =<< trim END
652    vim9script
653    var test: dict<any> = {}
654    def FillDict(): dict<any>
655      test['a'] = 43
656      return test
657    enddef
658    assert_equal({a: 43}, FillDict())
659  END
660  CheckScriptSuccess(lines)
661
662  lines =<< trim END
663    vim9script
664    var test: dict<any>
665    def FillDict(): dict<any>
666      test['a'] = 43
667      return test
668    enddef
669    FillDict()
670    assert_equal({a: 43}, test)
671  END
672  CheckScriptSuccess(lines)
673
674  # assignment to global dict
675  lines =<< trim END
676    vim9script
677    g:test = {}
678    def FillDict(): dict<any>
679      g:test['a'] = 43
680      return g:test
681    enddef
682    assert_equal({a: 43}, FillDict())
683  END
684  CheckScriptSuccess(lines)
685
686  # assignment to buffer dict
687  lines =<< trim END
688    vim9script
689    b:test = {}
690    def FillDict(): dict<any>
691      b:test['a'] = 43
692      return b:test
693    enddef
694    assert_equal({a: 43}, FillDict())
695  END
696  CheckScriptSuccess(lines)
697
698  lines =<< trim END
699    var d = {dd: test_null_dict()}
700    d.dd[0] = 0
701  END
702  CheckDefExecFailure(lines, 'E1103:', 2)
703
704  lines =<< trim END
705    var d = {dd: 'string'}
706    d.dd[0] = 0
707  END
708  CheckDefExecFailure(lines, 'E1148:', 2)
709enddef
710
711def Test_assignment_local()
712  # Test in a separated file in order not to the current buffer/window/tab is
713  # changed.
714  var script_lines: list<string> =<< trim END
715    let b:existing = 'yes'
716    let w:existing = 'yes'
717    let t:existing = 'yes'
718
719    def Test_assignment_local_internal()
720      b:newvar = 'new'
721      assert_equal('new', b:newvar)
722      assert_equal('yes', b:existing)
723      b:existing = 'no'
724      assert_equal('no', b:existing)
725      b:existing ..= 'NO'
726      assert_equal('noNO', b:existing)
727
728      w:newvar = 'new'
729      assert_equal('new', w:newvar)
730      assert_equal('yes', w:existing)
731      w:existing = 'no'
732      assert_equal('no', w:existing)
733      w:existing ..= 'NO'
734      assert_equal('noNO', w:existing)
735
736      t:newvar = 'new'
737      assert_equal('new', t:newvar)
738      assert_equal('yes', t:existing)
739      t:existing = 'no'
740      assert_equal('no', t:existing)
741      t:existing ..= 'NO'
742      assert_equal('noNO', t:existing)
743    enddef
744    call Test_assignment_local_internal()
745  END
746  CheckScriptSuccess(script_lines)
747enddef
748
749def Test_assignment_default()
750  # Test default values.
751  var thebool: bool
752  assert_equal(v:false, thebool)
753
754  var thenumber: number
755  assert_equal(0, thenumber)
756
757  if has('float')
758    var thefloat: float
759    assert_equal(0.0, thefloat)
760  endif
761
762  var thestring: string
763  assert_equal('', thestring)
764
765  var theblob: blob
766  assert_equal(0z, theblob)
767
768  var Thefunc: func
769  assert_equal(test_null_function(), Thefunc)
770
771  var thelist: list<any>
772  assert_equal([], thelist)
773
774  var thedict: dict<any>
775  assert_equal({}, thedict)
776
777  if has('channel')
778    var thejob: job
779    assert_equal(test_null_job(), thejob)
780
781    var thechannel: channel
782    assert_equal(test_null_channel(), thechannel)
783
784    if has('unix') && executable('cat')
785      # check with non-null job and channel, types must match
786      thejob = job_start("cat ", {})
787      thechannel = job_getchannel(thejob)
788      job_stop(thejob, 'kill')
789    endif
790  endif
791
792  var nr = 1234 | nr = 5678
793  assert_equal(5678, nr)
794enddef
795
796let scriptvar = 'init'
797
798def Test_assignment_var_list()
799  var lines =<< trim END
800      var v1: string
801      var v2: string
802      var vrem: list<string>
803      [v1] = ['aaa']
804      assert_equal('aaa', v1)
805
806      [v1, v2] = ['one', 'two']
807      assert_equal('one', v1)
808      assert_equal('two', v2)
809
810      [v1, v2; vrem] = ['one', 'two']
811      assert_equal('one', v1)
812      assert_equal('two', v2)
813      assert_equal([], vrem)
814
815      [v1, v2; vrem] = ['one', 'two', 'three']
816      assert_equal('one', v1)
817      assert_equal('two', v2)
818      assert_equal(['three'], vrem)
819
820      [&ts, &sw] = [3, 4]
821      assert_equal(3, &ts)
822      assert_equal(4, &sw)
823      set ts=8 sw=4
824
825      [@a, @z] = ['aa', 'zz']
826      assert_equal('aa', @a)
827      assert_equal('zz', @z)
828
829      [$SOME_VAR, $OTHER_VAR] = ['some', 'other']
830      assert_equal('some', $SOME_VAR)
831      assert_equal('other', $OTHER_VAR)
832
833      [g:globalvar, b:bufvar, w:winvar, t:tabvar, v:errmsg] =
834            ['global', 'buf', 'win', 'tab', 'error']
835      assert_equal('global', g:globalvar)
836      assert_equal('buf', b:bufvar)
837      assert_equal('win', w:winvar)
838      assert_equal('tab', t:tabvar)
839      assert_equal('error', v:errmsg)
840      unlet g:globalvar
841  END
842  CheckDefAndScriptSuccess(lines)
843
844  [g:globalvar, s:scriptvar, b:bufvar] = ['global', 'script', 'buf']
845  assert_equal('global', g:globalvar)
846  assert_equal('script', s:scriptvar)
847  assert_equal('buf', b:bufvar)
848
849  lines =<< trim END
850      vim9script
851      var s:scriptvar = 'init'
852      [g:globalvar, s:scriptvar, w:winvar] = ['global', 'script', 'win']
853      assert_equal('global', g:globalvar)
854      assert_equal('script', s:scriptvar)
855      assert_equal('win', w:winvar)
856  END
857  CheckScriptSuccess(lines)
858enddef
859
860def Test_assignment_vim9script()
861  var lines =<< trim END
862    vim9script
863    def Func(): list<number>
864      return [1, 2]
865    enddef
866    var name1: number
867    var name2: number
868    [name1, name2] =
869          Func()
870    assert_equal(1, name1)
871    assert_equal(2, name2)
872    var ll =
873          Func()
874    assert_equal([1, 2], ll)
875
876    @/ = 'text'
877    assert_equal('text', @/)
878    @0 = 'zero'
879    assert_equal('zero', @0)
880    @1 = 'one'
881    assert_equal('one', @1)
882    @9 = 'nine'
883    assert_equal('nine', @9)
884    @- = 'minus'
885    assert_equal('minus', @-)
886    if has('clipboard_working')
887      @* = 'star'
888      assert_equal('star', @*)
889      @+ = 'plus'
890      assert_equal('plus', @+)
891    endif
892
893    var a: number = 123
894    assert_equal(123, a)
895    var s: string = 'yes'
896    assert_equal('yes', s)
897    var b: number = 42
898    assert_equal(42, b)
899    var w: number = 43
900    assert_equal(43, w)
901    var t: number = 44
902    assert_equal(44, t)
903
904    var to_var = 0
905    to_var = 3
906    assert_equal(3, to_var)
907  END
908  CheckScriptSuccess(lines)
909
910  lines =<< trim END
911      vim9script
912      var n: number
913      def Func()
914        n = 'string'
915      enddef
916      defcompile
917  END
918  CheckScriptFailure(lines, 'E1012: Type mismatch; expected number but got string')
919enddef
920
921def Mess(): string
922  v:foldstart = 123
923  return 'xxx'
924enddef
925
926def Test_assignment_failure()
927  CheckDefFailure(['var name=234'], 'E1004:')
928  CheckDefFailure(['var name =234'], 'E1004:')
929  CheckDefFailure(['var name= 234'], 'E1004:')
930
931  CheckScriptFailure(['vim9script', 'var name=234'], 'E1004:')
932  CheckScriptFailure(['vim9script', 'var name=234'], "before and after '='")
933  CheckScriptFailure(['vim9script', 'var name =234'], 'E1004:')
934  CheckScriptFailure(['vim9script', 'var name= 234'], 'E1004:')
935  CheckScriptFailure(['vim9script', 'var name = 234', 'name+=234'], 'E1004:')
936  CheckScriptFailure(['vim9script', 'var name = 234', 'name+=234'], "before and after '+='")
937  CheckScriptFailure(['vim9script', 'var name = "x"', 'name..="y"'], 'E1004:')
938  CheckScriptFailure(['vim9script', 'var name = "x"', 'name..="y"'], "before and after '..='")
939
940  CheckDefFailure(['var true = 1'], 'E1034:')
941  CheckDefFailure(['var false = 1'], 'E1034:')
942
943  CheckDefFailure(['[a; b; c] = g:list'], 'E452:')
944  CheckDefExecFailure(['var a: number',
945                       '[a] = test_null_list()'], 'E1093:')
946  CheckDefExecFailure(['var a: number',
947                       '[a] = []'], 'E1093:')
948  CheckDefExecFailure(['var x: number',
949                       'var y: number',
950                       '[x, y] = [1]'], 'E1093:')
951  CheckDefExecFailure(['var x: string',
952                       'var y: string',
953                       '[x, y] = ["x"]'], 'E1093:')
954  CheckDefExecFailure(['var x: number',
955                       'var y: number',
956                       'var z: list<number>',
957                       '[x, y; z] = [1]'], 'E1093:')
958
959  CheckDefFailure(['var somevar'], "E1022:")
960  CheckDefFailure(['var &tabstop = 4'], 'E1052:')
961  CheckDefFailure(['&g:option = 5'], 'E113:')
962  CheckScriptFailure(['vim9script', 'var &tabstop = 4'], 'E1052:')
963
964  CheckDefFailure(['var $VAR = 5'], 'E1016: Cannot declare an environment variable:')
965  CheckScriptFailure(['vim9script', 'var $ENV = "xxx"'], 'E1016:')
966
967  if has('dnd')
968    CheckDefFailure(['var @~ = 5'], 'E1066:')
969  else
970    CheckDefFailure(['var @~ = 5'], 'E354:')
971    CheckDefFailure(['@~ = 5'], 'E354:')
972  endif
973  CheckDefFailure(['var @a = 5'], 'E1066:')
974  CheckDefFailure(['var @/ = "x"'], 'E1066:')
975  CheckScriptFailure(['vim9script', 'var @a = "abc"'], 'E1066:')
976
977  CheckDefFailure(['var g:var = 5'], 'E1016: Cannot declare a global variable:')
978  CheckDefFailure(['var w:var = 5'], 'E1016: Cannot declare a window variable:')
979  CheckDefFailure(['var b:var = 5'], 'E1016: Cannot declare a buffer variable:')
980  CheckDefFailure(['var t:var = 5'], 'E1016: Cannot declare a tab variable:')
981
982  CheckDefFailure(['var anr = 4', 'anr ..= "text"'], 'E1019:')
983  CheckDefFailure(['var xnr += 4'], 'E1020:', 1)
984  CheckScriptFailure(['vim9script', 'var xnr += 4'], 'E1020:')
985  CheckDefFailure(["var xnr = xnr + 1"], 'E1001:', 1)
986  CheckScriptFailure(['vim9script', 'var xnr = xnr + 4'], 'E121:')
987
988  CheckScriptFailure(['vim9script', 'def Func()', 'var dummy = s:notfound', 'enddef', 'defcompile'], 'E1108:')
989
990  CheckDefFailure(['var name: list<string> = [123]'], 'expected list<string> but got list<number>')
991  CheckDefFailure(['var name: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
992
993  CheckDefFailure(['var name: dict<string> = {key: 123}'], 'expected dict<string> but got dict<number>')
994  CheckDefFailure(['var name: dict<number> = {key: "xx"}'], 'expected dict<number> but got dict<string>')
995
996  CheckDefFailure(['var name = feedkeys("0")'], 'E1031:')
997  CheckDefFailure(['var name: number = feedkeys("0")'], 'expected number but got void')
998
999  CheckDefFailure(['var name: dict <number>'], 'E1068:')
1000  CheckDefFailure(['var name: dict<number'], 'E1009:')
1001
1002  assert_fails('s/^/\=Mess()/n', 'E794:')
1003  CheckDefFailure(['var name: dict<number'], 'E1009:')
1004
1005  CheckDefFailure(['w:foo: number = 10'],
1006                  'E488: Trailing characters: : number = 1')
1007  CheckDefFailure(['t:foo: bool = true'],
1008                  'E488: Trailing characters: : bool = true')
1009  CheckDefFailure(['b:foo: string = "x"'],
1010                  'E488: Trailing characters: : string = "x"')
1011  CheckDefFailure(['g:foo: number = 123'],
1012                  'E488: Trailing characters: : number = 123')
1013enddef
1014
1015def Test_assign_list()
1016  var l: list<string> = []
1017  l[0] = 'value'
1018  assert_equal('value', l[0])
1019
1020  l[1] = 'asdf'
1021  assert_equal('value', l[0])
1022  assert_equal('asdf', l[1])
1023  assert_equal('asdf', l[-1])
1024  assert_equal('value', l[-2])
1025
1026  var nrl: list<number> = []
1027  for i in range(5)
1028    nrl[i] = i
1029  endfor
1030  assert_equal([0, 1, 2, 3, 4], nrl)
1031
1032  CheckDefFailure(["var l: list<number> = ['', true]"], 'E1012: Type mismatch; expected list<number> but got list<any>', 1)
1033  CheckDefFailure(["var l: list<list<number>> = [['', true]]"], 'E1012: Type mismatch; expected list<list<number>> but got list<list<any>>', 1)
1034enddef
1035
1036def Test_assign_dict()
1037  var lines =<< trim END
1038      var d: dict<string> = {}
1039      d['key'] = 'value'
1040      assert_equal('value', d['key'])
1041
1042      d[123] = 'qwerty'
1043      assert_equal('qwerty', d[123])
1044      assert_equal('qwerty', d['123'])
1045
1046      var nrd: dict<number> = {}
1047      for i in range(3)
1048        nrd[i] = i
1049      endfor
1050      assert_equal({0: 0, 1: 1, 2: 2}, nrd)
1051
1052      d.somekey = 'someval'
1053      assert_equal({key: 'value', '123': 'qwerty', somekey: 'someval'}, d)
1054      # unlet d.somekey
1055      # assert_equal({key: 'value', '123': 'qwerty'}, d)
1056  END
1057  CheckDefAndScriptSuccess(lines)
1058
1059  # TODO: move to above once "unlet d.somekey" in :def is implemented
1060  lines =<< trim END
1061      vim9script
1062      var d: dict<string> = {}
1063      d['key'] = 'value'
1064      d.somekey = 'someval'
1065      assert_equal({key: 'value', somekey: 'someval'}, d)
1066      unlet d.somekey
1067      assert_equal({key: 'value'}, d)
1068  END
1069  CheckScriptSuccess(lines)
1070
1071  CheckDefFailure(["var d: dict<number> = {a: '', b: true}"], 'E1012: Type mismatch; expected dict<number> but got dict<any>', 1)
1072  CheckDefFailure(["var d: dict<dict<number>> = {x: {a: '', b: true}}"], 'E1012: Type mismatch; expected dict<dict<number>> but got dict<dict<any>>', 1)
1073enddef
1074
1075def Test_assign_dict_unknown_type()
1076  var lines =<< trim END
1077      vim9script
1078      var mylist = []
1079      mylist += [{one: 'one'}]
1080      def Func()
1081        var dd = mylist[0]
1082        assert_equal('one', dd.one)
1083      enddef
1084      Func()
1085  END
1086  CheckScriptSuccess(lines)
1087
1088  lines =<< trim END
1089      vim9script
1090      var mylist = [[]]
1091      mylist[0] += [{one: 'one'}]
1092      def Func()
1093        var dd = mylist[0][0]
1094        assert_equal('one', dd.one)
1095      enddef
1096      Func()
1097  END
1098  CheckScriptSuccess(lines)
1099enddef
1100
1101def Test_assign_lambda()
1102  # check if assign a lambda to a variable which type is func or any.
1103  var lines =<< trim END
1104      vim9script
1105      var FuncRef = () => 123
1106      assert_equal(123, FuncRef())
1107      var FuncRef_Func: func = () => 123
1108      assert_equal(123, FuncRef_Func())
1109      var FuncRef_Any: any = () => 123
1110      assert_equal(123, FuncRef_Any())
1111  END
1112  CheckScriptSuccess(lines)
1113
1114  lines =<< trim END
1115      var Ref: func(number)
1116      Ref = (j) => !j
1117  END
1118  CheckDefFailure(lines, 'E1012: Type mismatch; expected func(number) but got func(any): bool')
1119  CheckScriptFailure(['vim9script'] + lines, 'E1012: Type mismatch; expected func(number) but got func(any): any')
1120enddef
1121
1122def Test_heredoc()
1123  var lines =<< trim END # comment
1124    text
1125  END
1126  assert_equal(['text'], lines)
1127
1128  CheckDefFailure(['var lines =<< trim END X', 'END'], 'E488:')
1129  CheckDefFailure(['var lines =<< trim END " comment', 'END'], 'E488:')
1130
1131  lines =<< trim [END]
1132      def Func()
1133        var&lines =<< trim END
1134        x
1135        x
1136      enddef
1137      defcompile
1138  [END]
1139  CheckScriptFailure(lines, 'E1145: Missing heredoc end marker: END')
1140  delfunc! g:Func
1141
1142  lines =<< trim [END]
1143      def Func()
1144        var lines =<< trim END
1145        x
1146        x
1147        x
1148        x
1149        x
1150        x
1151        x
1152        x
1153      enddef
1154      call Func()
1155  [END]
1156  CheckScriptFailure(lines, 'E1145: Missing heredoc end marker: END')
1157  delfunc! g:Func
1158enddef
1159
1160def Test_var_func_call()
1161  var lines =<< trim END
1162    vim9script
1163    func GetValue()
1164      if exists('g:count')
1165        let g:count += 1
1166      else
1167        let g:count = 1
1168      endif
1169      return 'this'
1170    endfunc
1171    var val: string = GetValue()
1172    # env var is always a string
1173    var env = $TERM
1174  END
1175  writefile(lines, 'Xfinished')
1176  source Xfinished
1177  # GetValue() is not called during discovery phase
1178  assert_equal(1, g:count)
1179
1180  unlet g:count
1181  delete('Xfinished')
1182enddef
1183
1184def Test_var_missing_type()
1185  var lines =<< trim END
1186    vim9script
1187    var name = g:unknown
1188  END
1189  CheckScriptFailure(lines, 'E121:')
1190
1191  lines =<< trim END
1192    vim9script
1193    var nr: number = 123
1194    var name = nr
1195  END
1196  CheckScriptSuccess(lines)
1197enddef
1198
1199def Test_var_declaration()
1200  var lines =<< trim END
1201    vim9script
1202    var name: string
1203    g:var_uninit = name
1204    name = 'text'
1205    g:var_test = name
1206    # prefixing s: is optional
1207    s:name = 'prefixed'
1208    g:var_prefixed = s:name
1209
1210    const FOO: number = 123
1211    assert_equal(123, FOO)
1212    const FOOS = 'foos'
1213    assert_equal('foos', FOOS)
1214    final FLIST = [1]
1215    assert_equal([1], FLIST)
1216    FLIST[0] = 11
1217    assert_equal([11], FLIST)
1218
1219    const g:FOO: number = 321
1220    assert_equal(321, g:FOO)
1221    const g:FOOS = 'gfoos'
1222    assert_equal('gfoos', g:FOOS)
1223    final g:FLIST = [2]
1224    assert_equal([2], g:FLIST)
1225    g:FLIST[0] = 22
1226    assert_equal([22], g:FLIST)
1227
1228    const w:FOO: number = 46
1229    assert_equal(46, w:FOO)
1230    const w:FOOS = 'wfoos'
1231    assert_equal('wfoos', w:FOOS)
1232    final w:FLIST = [3]
1233    assert_equal([3], w:FLIST)
1234    w:FLIST[0] = 33
1235    assert_equal([33], w:FLIST)
1236
1237    var s:other: number
1238    other = 1234
1239    g:other_var = other
1240
1241    # type is inferred
1242    var s:dict = {['a']: 222}
1243    def GetDictVal(key: any)
1244      g:dict_val = s:dict[key]
1245    enddef
1246    GetDictVal('a')
1247
1248    final adict: dict<string> = {}
1249    def ChangeAdict()
1250      adict.foo = 'foo'
1251    enddef
1252    ChangeAdict()
1253  END
1254  CheckScriptSuccess(lines)
1255  assert_equal('', g:var_uninit)
1256  assert_equal('text', g:var_test)
1257  assert_equal('prefixed', g:var_prefixed)
1258  assert_equal(1234, g:other_var)
1259  assert_equal(222, g:dict_val)
1260
1261  unlet g:var_uninit
1262  unlet g:var_test
1263  unlet g:var_prefixed
1264  unlet g:other_var
1265  unlet g:FOO
1266  unlet g:FOOS
1267  unlet g:FLIST
1268  unlet w:FOO
1269  unlet w:FOOS
1270  unlet w:FLIST
1271enddef
1272
1273def Test_var_declaration_fails()
1274  var lines =<< trim END
1275    vim9script
1276    final var: string
1277  END
1278  CheckScriptFailure(lines, 'E1125:')
1279
1280  lines =<< trim END
1281    vim9script
1282    const g:constvar = 'string'
1283    g:constvar = 'xx'
1284  END
1285  CheckScriptFailure(lines, 'E741:')
1286  unlet g:constvar
1287
1288  lines =<< trim END
1289    vim9script
1290    const cdict: dict<string> = {}
1291    def Change()
1292      cdict.foo = 'foo'
1293    enddef
1294    defcompile
1295  END
1296  CheckScriptFailure(lines, 'E46:')
1297
1298  lines =<< trim END
1299    vim9script
1300    final w:finalvar = [9]
1301    w:finalvar = [8]
1302  END
1303  CheckScriptFailure(lines, 'E1122:')
1304  unlet w:finalvar
1305
1306  lines =<< trim END
1307    vim9script
1308    const var: string
1309  END
1310  CheckScriptFailure(lines, 'E1021:')
1311
1312  lines =<< trim END
1313    vim9script
1314    var 9var: string
1315  END
1316  CheckScriptFailure(lines, 'E475:')
1317
1318  CheckDefFailure(['var foo.bar = 2'], 'E1087:')
1319  CheckDefFailure(['var foo[3] = 2'], 'E1087:')
1320  CheckDefFailure(['const foo: number'], 'E1021:')
1321enddef
1322
1323def Test_var_type_check()
1324  var lines =<< trim END
1325    vim9script
1326    var name: string
1327    name = 1234
1328  END
1329  CheckScriptFailure(lines, 'E1012:')
1330
1331  lines =<< trim END
1332    vim9script
1333    var name:string
1334  END
1335  CheckScriptFailure(lines, 'E1069:')
1336
1337  lines =<< trim END
1338    vim9script
1339    var name: asdf
1340  END
1341  CheckScriptFailure(lines, 'E1010:')
1342
1343  lines =<< trim END
1344    vim9script
1345    var s:l: list<number>
1346    s:l = []
1347  END
1348  CheckScriptSuccess(lines)
1349
1350  lines =<< trim END
1351    vim9script
1352    var s:d: dict<number>
1353    s:d = {}
1354  END
1355  CheckScriptSuccess(lines)
1356enddef
1357
1358let g:dict_number = #{one: 1, two: 2}
1359
1360def Test_var_list_dict_type()
1361  var ll: list<number>
1362  ll = [1, 2, 2, 3, 3, 3]->uniq()
1363  ll->assert_equal([1, 2, 3])
1364
1365  var dd: dict<number>
1366  dd = g:dict_number
1367  dd->assert_equal(g:dict_number)
1368
1369  var lines =<< trim END
1370      var ll: list<number>
1371      ll = [1, 2, 3]->map('"one"')
1372  END
1373  CheckDefExecFailure(lines, 'E1012: Type mismatch; expected number but got string')
1374enddef
1375
1376def Test_cannot_use_let()
1377  CheckDefAndScriptFailure(['let a = 34'], 'E1126:', 1)
1378enddef
1379
1380def Test_unlet()
1381  g:somevar = 'yes'
1382  assert_true(exists('g:somevar'))
1383  unlet g:somevar
1384  assert_false(exists('g:somevar'))
1385  unlet! g:somevar
1386
1387  # also works for script-local variable in legacy Vim script
1388  s:somevar = 'legacy'
1389  assert_true(exists('s:somevar'))
1390  unlet s:somevar
1391  assert_false(exists('s:somevar'))
1392  unlet! s:somevar
1393
1394  CheckDefExecFailure([
1395    'var dd = 111',
1396    'unlet dd',
1397    ], 'E1081:', 2)
1398
1399  # dict unlet
1400  var dd = {a: 1, b: 2, c: 3}
1401  unlet dd['a']
1402  unlet dd.c
1403  assert_equal({b: 2}, dd)
1404
1405  # list unlet
1406  var ll = [1, 2, 3, 4]
1407  unlet ll[1]
1408  unlet ll[-1]
1409  assert_equal([1, 3], ll)
1410
1411  # list of dict unlet
1412  var dl = [{a: 1, b: 2}, {c: 3}]
1413  unlet dl[0]['b']
1414  assert_equal([{a: 1}, {c: 3}], dl)
1415
1416  CheckDefExecFailure([
1417    'var ll = test_null_list()',
1418    'unlet ll[0]',
1419    ], 'E684:', 2)
1420  CheckDefExecFailure([
1421    'var ll = [1]',
1422    'unlet ll[2]',
1423    ], 'E684:', 2)
1424  CheckDefExecFailure([
1425    'var ll = [1]',
1426    'unlet ll[g:astring]',
1427    ], 'E1012:', 2)
1428  CheckDefExecFailure([
1429    'var dd = test_null_dict()',
1430    'unlet dd["a"]',
1431    ], 'E716:', 2)
1432  CheckDefExecFailure([
1433    'var dd = {a: 1}',
1434    'unlet dd["b"]',
1435    ], 'E716:', 2)
1436  CheckDefExecFailure([
1437    'var dd = {a: 1}',
1438    'unlet dd[g:alist]',
1439    ], 'E1105:', 2)
1440
1441  # can compile unlet before variable exists
1442  g:someDict = {key: 'val'}
1443  var k = 'key'
1444  unlet g:someDict[k]
1445  assert_equal({}, g:someDict)
1446  unlet g:someDict
1447  assert_false(exists('g:someDict'))
1448
1449  CheckScriptFailure([
1450   'vim9script',
1451   'var svar = 123',
1452   'unlet svar',
1453   ], 'E1081:')
1454  CheckScriptFailure([
1455   'vim9script',
1456   'var svar = 123',
1457   'unlet s:svar',
1458   ], 'E1081:')
1459  CheckScriptFailure([
1460   'vim9script',
1461   'var svar = 123',
1462   'def Func()',
1463   '  unlet svar',
1464   'enddef',
1465   'defcompile',
1466   ], 'E1081:')
1467  CheckScriptFailure([
1468   'vim9script',
1469   'var svar = 123',
1470   'func Func()',
1471   '  unlet s:svar',
1472   'endfunc',
1473   'Func()',
1474   ], 'E1081:')
1475  CheckScriptFailure([
1476   'vim9script',
1477   'var svar = 123',
1478   'def Func()',
1479   '  unlet s:svar',
1480   'enddef',
1481   'defcompile',
1482   ], 'E1081:')
1483
1484  writefile(['vim9script', 'export var svar = 1234'], 'XunletExport.vim')
1485  var lines =<< trim END
1486    vim9script
1487    import svar from './XunletExport.vim'
1488    def UnletSvar()
1489      unlet svar
1490    enddef
1491    defcompile
1492  END
1493  CheckScriptFailure(lines, 'E1081:', 1)
1494  delete('XunletExport.vim')
1495
1496  $ENVVAR = 'foobar'
1497  assert_equal('foobar', $ENVVAR)
1498  unlet $ENVVAR
1499  assert_equal('', $ENVVAR)
1500enddef
1501
1502def Test_expr_error_no_assign()
1503  var lines =<< trim END
1504      vim9script
1505      var x = invalid
1506      echo x
1507  END
1508  CheckScriptFailureList(lines, ['E121:', 'E121:'])
1509
1510  lines =<< trim END
1511      vim9script
1512      var x = 1 / 0
1513      echo x
1514  END
1515  CheckScriptFailureList(lines, ['E1154:', 'E121:'])
1516
1517  lines =<< trim END
1518      vim9script
1519      var x = 1 % 0
1520      echo x
1521  END
1522  CheckScriptFailureList(lines, ['E1154:', 'E121:'])
1523enddef
1524
1525
1526def Test_assign_command_modifier()
1527  var lines =<< trim END
1528      var verbose = 0
1529      verbose = 1
1530      assert_equal(1, verbose)
1531      silent verbose = 2
1532      assert_equal(2, verbose)
1533      silent verbose += 2
1534      assert_equal(4, verbose)
1535      silent verbose -= 1
1536      assert_equal(3, verbose)
1537
1538      var topleft = {one: 1}
1539      sandbox topleft.one = 3
1540      assert_equal({one: 3}, topleft)
1541      leftabove topleft[' '] = 4
1542      assert_equal({one: 3, ' ': 4}, topleft)
1543
1544      var x: number
1545      var y: number
1546      silent [x, y] = [1, 2]
1547      assert_equal(1, x)
1548      assert_equal(2, y)
1549  END
1550  CheckDefAndScriptSuccess(lines)
1551enddef
1552
1553
1554" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1555