1" Tests for Vim9 script expressions
2
3source check.vim
4source vim9.vim
5
6let g:cond = v:false
7def FuncOne(arg: number): string
8  return 'yes'
9enddef
10def FuncTwo(arg: number): number
11  return 123
12enddef
13
14" test cond ? expr : expr
15def Test_expr1_trinary()
16  var lines =<< trim END
17      assert_equal('one', true ? 'one' : 'two')
18      assert_equal('one', 1 ?
19                            'one' :
20                            'two')
21      if has('float')
22        assert_equal('one', !!0.1 ? 'one' : 'two')
23      endif
24      assert_equal('one', !!'x' ? 'one' : 'two')
25      assert_equal('one', !!'x'
26                            ? 'one'
27                            : 'two')
28      assert_equal('one', !!0z1234 ? 'one' : 'two')
29      assert_equal('one', !![0] ? 'one' : 'two')
30      assert_equal('one', !!#{x: 0} ? 'one' : 'two')
31      var name = 1
32      assert_equal('one', name ? 'one' : 'two')
33
34      assert_equal('two', false ? 'one' : 'two')
35      assert_equal('two', 0 ? 'one' : 'two')
36      if has('float')
37        assert_equal('two', !!0.0 ? 'one' : 'two')
38      endif
39      assert_equal('two', !!'' ? 'one' : 'two')
40      assert_equal('two', !!0z ? 'one' : 'two')
41      assert_equal('two', !![] ? 'one' : 'two')
42      assert_equal('two', !!{} ? 'one' : 'two')
43      name = 0
44      assert_equal('two', name ? 'one' : 'two')
45
46      # with constant condition expression is not evaluated
47      assert_equal('one', 1 ? 'one' : xxx)
48
49      var Some: func = function('len')
50      var Other: func = function('winnr')
51      var Res: func = g:atrue ? Some : Other
52      assert_equal(function('len'), Res)
53
54      var RetOne: func(string): number = function('len')
55      var RetTwo: func(string): number = function('winnr')
56      var RetThat: func = g:atrue ? RetOne : RetTwo
57      assert_equal(function('len'), RetThat)
58
59      var X = FuncOne
60      var Y = FuncTwo
61      var Z = g:cond ? FuncOne : FuncTwo
62      assert_equal(123, Z(3))
63  END
64  CheckDefAndScriptSuccess(lines)
65enddef
66
67def Test_expr1_trinary_vimscript()
68  # check line continuation
69  var lines =<< trim END
70      vim9script
71      var name = 1
72      		? 'yes'
73		: 'no'
74      assert_equal('yes', name)
75  END
76  CheckScriptSuccess(lines)
77
78  lines =<< trim END
79      vim9script
80      var name = v:false
81      		? 'yes'
82		: 'no'
83      assert_equal('no', name)
84  END
85  CheckScriptSuccess(lines)
86
87  lines =<< trim END
88      vim9script
89      var name = v:false ?
90      		'yes' :
91		'no'
92      assert_equal('no', name)
93  END
94  CheckScriptSuccess(lines)
95
96  lines =<< trim END
97      vim9script
98      var name = v:false ?  # comment
99      		'yes' :
100                # comment
101		'no' # comment
102      assert_equal('no', name)
103  END
104  CheckScriptSuccess(lines)
105
106  # check white space
107  lines =<< trim END
108      vim9script
109      var name = v:true?1:2
110  END
111  CheckScriptFailure(lines, 'E1004:', 2)
112  lines =<< trim END
113      vim9script
114      var name = v:true? 1 : 2
115  END
116  CheckScriptFailure(lines, 'E1004:', 2)
117  lines =<< trim END
118      vim9script
119      var name = v:true ?1 : 2
120  END
121  CheckScriptFailure(lines, 'E1004:', 2)
122  lines =<< trim END
123      vim9script
124      var name = v:true ? 1: 2
125  END
126  CheckScriptFailure(lines, 'E1004:', 2)
127  lines =<< trim END
128      vim9script
129      var name = v:true ? 1 :2
130  END
131  CheckScriptFailure(lines, 'E1004:', 2)
132
133  lines =<< trim END
134      vim9script
135      var name = 'x' ? 1 : 2
136  END
137  CheckScriptFailure(lines, 'E1135:', 2)
138
139  lines =<< trim END
140      vim9script
141      var name = [] ? 1 : 2
142  END
143  CheckScriptFailure(lines, 'E745:', 2)
144
145  lines =<< trim END
146      vim9script
147      var name = {} ? 1 : 2
148  END
149  CheckScriptFailure(lines, 'E728:', 2)
150
151  # check after failure eval_flags is reset
152  lines =<< trim END
153      vim9script
154      try
155        eval('0 ? 1: 2')
156      catch
157      endtry
158      assert_equal(v:true, eval(string(v:true)))
159  END
160  CheckScriptSuccess(lines)
161
162  lines =<< trim END
163      vim9script
164      try
165        eval('0 ? 1 :2')
166      catch
167      endtry
168      assert_equal(v:true, eval(string(v:true)))
169  END
170  CheckScriptSuccess(lines)
171enddef
172
173func Test_expr1_trinary_fails()
174  call CheckDefFailure(["var x = 1 ? 'one'"], "Missing ':' after '?'", 1)
175
176  let msg = "White space required before and after '?'"
177  call CheckDefFailure(["var x = 1? 'one' : 'two'"], msg, 1)
178  call CheckDefFailure(["var x = 1 ?'one' : 'two'"], msg, 1)
179  call CheckDefFailure(["var x = 1?'one' : 'two'"], msg, 1)
180
181  let msg = "White space required before and after ':'"
182  call CheckDefFailure(["var x = 1 ? 'one': 'two'"], msg, 1)
183  call CheckDefFailure(["var x = 1 ? 'one' :'two'"], msg, 1)
184  call CheckDefFailure(["var x = 1 ? 'one':'two'"], msg, 1)
185
186  call CheckDefFailure(["var x = 'x' ? 'one' : 'two'"], 'E1135:', 1)
187  call CheckDefFailure(["var x = 0z1234 ? 'one' : 'two'"], 'E974:', 1)
188  call CheckDefExecFailure(["var x = [] ? 'one' : 'two'"], 'E745:', 1)
189  call CheckDefExecFailure(["var x = {} ? 'one' : 'two'"], 'E728:', 1)
190
191  if has('float')
192    call CheckDefFailure(["var x = 0.1 ? 'one' : 'two'"], 'E805:', 1)
193  endif
194
195  " missing argument detected even when common type is used
196  call CheckDefFailure([
197	\ 'var X = FuncOne',
198	\ 'var Y = FuncTwo',
199	\ 'var Z = g:cond ? FuncOne : FuncTwo',
200	\ 'Z()'], 'E119:', 4)
201endfunc
202
203def Test_expr1_falsy()
204  var lines =<< trim END
205      assert_equal(v:true, v:true ?? 456)
206      assert_equal(123, 123 ?? 456)
207      assert_equal('yes', 'yes' ?? 456)
208      assert_equal([1], [1] ?? 456)
209      assert_equal(#{one: 1}, #{one: 1} ?? 456)
210      if has('float')
211        assert_equal(0.1, 0.1 ?? 456)
212      endif
213
214      assert_equal(456, v:false ?? 456)
215      assert_equal(456, 0 ?? 456)
216      assert_equal(456, '' ?? 456)
217      assert_equal(456, [] ?? 456)
218      assert_equal(456, {} ?? 456)
219      if has('float')
220        assert_equal(456, 0.0 ?? 456)
221      endif
222  END
223  CheckDefAndScriptSuccess(lines)
224
225  var msg = "White space required before and after '??'"
226  call CheckDefFailure(["var x = 1?? 'one' : 'two'"], msg, 1)
227  call CheckDefFailure(["var x = 1 ??'one' : 'two'"], msg, 1)
228  call CheckDefFailure(["var x = 1??'one' : 'two'"], msg, 1)
229enddef
230
231def Record(val: any): any
232  g:vals->add(val)
233  return val
234enddef
235
236" test ||
237def Test_expr2()
238  var lines =<< trim END
239      assert_equal(true, 1 || 0)
240      assert_equal(true, 0 ||
241                        0 ||
242                        1)
243      assert_equal(true, 0 ||
244			0 ||
245			!!7)
246      assert_equal(false, 0 || 0)
247      assert_equal(false, 0
248                        || 0)
249      assert_equal(false, 0 || false)
250
251      g:vals = []
252      assert_equal(true, Record(1) || Record(3))
253      assert_equal([1], g:vals)
254
255      g:vals = []
256      assert_equal(true, Record(0) || Record(1))
257      assert_equal([0, 1], g:vals)
258
259      g:vals = []
260      assert_equal(true, Record(0) || Record(true))
261      assert_equal([0, true], g:vals)
262
263      g:vals = []
264      assert_equal(true, Record(0)
265                          || Record(1)
266                          || Record(0))
267      assert_equal([0, 1], g:vals)
268
269      g:vals = []
270      assert_equal(true, Record(0)
271			  || Record(true)
272			  || Record(0))
273      assert_equal([0, true], g:vals)
274
275      g:vals = []
276      assert_equal(true, Record(true) || Record(false))
277      assert_equal([true], g:vals)
278
279      g:vals = []
280      assert_equal(false, Record(0) || Record(false) || Record(0))
281      assert_equal([0, false, 0], g:vals)
282  END
283  CheckDefAndScriptSuccess(lines)
284enddef
285
286def Test_expr2_vimscript()
287  # check line continuation
288  var lines =<< trim END
289      vim9script
290      var name = 0
291      		|| 1
292      assert_equal(true, name)
293  END
294  CheckScriptSuccess(lines)
295
296  lines =<< trim END
297      vim9script
298      var name = v:false
299      		|| v:true
300      		|| v:false
301      assert_equal(v:true, name)
302  END
303  CheckScriptSuccess(lines)
304
305  lines =<< trim END
306      vim9script
307      var name = v:false ||
308      		v:true ||
309		v:false
310      assert_equal(v:true, name)
311  END
312  CheckScriptSuccess(lines)
313
314  lines =<< trim END
315      vim9script
316      var name = v:false || # comment
317                # comment
318      		v:true ||
319                # comment
320		v:false # comment
321      assert_equal(v:true, name)
322  END
323  CheckScriptSuccess(lines)
324
325  # check white space
326  lines =<< trim END
327      vim9script
328      var name = v:true||v:true
329  END
330  CheckScriptFailure(lines, 'E1004:', 2)
331  lines =<< trim END
332      vim9script
333      var name = v:true ||v:true
334  END
335  CheckScriptFailure(lines, 'E1004:', 2)
336  lines =<< trim END
337      vim9script
338      var name = v:true|| v:true
339  END
340  CheckScriptFailure(lines, 'E1004:', 2)
341enddef
342
343def Test_expr2_fails()
344  var msg = "White space required before and after '||'"
345  call CheckDefFailure(["var x = 1||2"], msg, 1)
346  call CheckDefFailure(["var x = 1 ||2"], msg, 1)
347  call CheckDefFailure(["var x = 1|| 2"], msg, 1)
348
349  call CheckDefFailure(["var x = 1 || xxx"], 'E1001:', 1)
350  call CheckDefFailure(["var x = [] || false"], 'E1012:', 1)
351  call CheckDefFailure(["if 'yes' || 0", 'echo 0', 'endif'], 'E1012: Type mismatch; expected bool but got string', 1)
352
353  # TODO: should fail at compile time
354  call CheckDefExecFailure(["var x = 3 || 7"], 'E1023:', 1)
355  call CheckScriptFailure(["vim9script", "var x = 3 || 7"], 'E1023:', 2)
356  call CheckScriptFailure(["vim9script", "var x = [] || false"], 'E745:', 2)
357enddef
358
359" test &&
360def Test_expr3()
361  var lines =<< trim END
362      assert_equal(false, 1 && 0)
363      assert_equal(false, 0 &&
364                    0 &&
365                    1)
366      assert_equal(true, 1
367                        && true
368                        && 1)
369      assert_equal(false, 0 && 0)
370      assert_equal(false, 0 && false)
371      assert_equal(true, 1 && true)
372
373      g:vals = []
374      assert_equal(true, Record(true) && Record(1))
375      assert_equal([true, 1], g:vals)
376
377      g:vals = []
378      assert_equal(true, Record(1) && Record(true))
379      assert_equal([1, true], g:vals)
380
381      g:vals = []
382      assert_equal(false, Record(0) && Record(1))
383      assert_equal([0], g:vals)
384
385      g:vals = []
386      assert_equal(false, Record(0) && Record(1) && Record(0))
387      assert_equal([0], g:vals)
388
389      g:vals = []
390      assert_equal(false, Record(0) && Record(4) && Record(0))
391      assert_equal([0], g:vals)
392
393      g:vals = []
394      assert_equal(false, Record(1) && Record(true) && Record(0))
395      assert_equal([1, true, 0], g:vals)
396  END
397  CheckDefAndScriptSuccess(lines)
398enddef
399
400def Test_expr3_vimscript()
401  # check line continuation
402  var lines =<< trim END
403      vim9script
404      var name = 0
405      		&& 1
406      assert_equal(false, name)
407  END
408  CheckScriptSuccess(lines)
409
410  lines =<< trim END
411      vim9script
412      var name = v:true
413      		&& v:true
414      		&& v:true
415      assert_equal(v:true, name)
416  END
417  CheckScriptSuccess(lines)
418
419  lines =<< trim END
420      vim9script
421      var name = v:true &&
422      		v:true &&
423      		v:true
424      assert_equal(v:true, name)
425  END
426  CheckScriptSuccess(lines)
427
428  lines =<< trim END
429      vim9script
430      var name = v:true &&  # comment
431                # comment
432      		v:true &&
433                # comment
434      		v:true
435      assert_equal(v:true, name)
436  END
437  CheckScriptSuccess(lines)
438
439  # check white space
440  lines =<< trim END
441      vim9script
442      var name = v:true&&v:true
443  END
444  CheckScriptFailure(lines, 'E1004:', 2)
445  lines =<< trim END
446      vim9script
447      var name = v:true &&v:true
448  END
449  CheckScriptFailure(lines, 'E1004:', 2)
450  lines =<< trim END
451      vim9script
452      var name = v:true&& v:true
453  END
454  CheckScriptFailure(lines, 'E1004:', 2)
455enddef
456
457func Test_expr3_fails()
458  let msg = "White space required before and after '&&'"
459  call CheckDefFailure(["var x = 1&&2"], msg, 1)
460  call CheckDefFailure(["var x = 1 &&2"], msg, 1)
461  call CheckDefFailure(["var x = 1&& 2"], msg, 1)
462
463  call CheckDefFailure(["if 'yes' && 0", 'echo 0', 'endif'], 'E1012: Type mismatch; expected bool but got string', 1)
464
465  call CheckDefExecFailure(['assert_equal(false, Record(1) && Record(4) && Record(0))'], 'E1023: Using a Number as a Bool: 4', 1)
466endfunc
467
468" global variables to use for tests with the "any" type
469let atrue = v:true
470let afalse = v:false
471let anone = v:none
472let anull = v:null
473let anint = 10
474let theone = 1
475let thefour = 4
476if has('float')
477  let afloat = 0.1
478endif
479let astring = 'asdf'
480let ablob = 0z01ab
481let alist = [2, 3, 4]
482let adict = #{aaa: 2, bbb: 8}
483
484" test == comperator
485def Test_expr4_equal()
486  var lines =<< trim END
487      var trueVar = true
488      var falseVar = false
489      assert_equal(true, true == true)
490      assert_equal(false, true ==
491                            false)
492      assert_equal(true, true
493                            == trueVar)
494      assert_equal(false, true == falseVar)
495      assert_equal(true, true == g:atrue)
496      assert_equal(false, g:atrue == false)
497
498      assert_equal(true, v:none == v:none)
499      assert_equal(false, v:none == v:null)
500      assert_equal(true, g:anone == v:none)
501      assert_equal(false, v:none == g:anull)
502
503      var nr0 = 0
504      var nr61 = 61
505      assert_equal(false, 2 == 0)
506      assert_equal(false, 2 == nr0)
507      assert_equal(true, 61 == 61)
508      assert_equal(true, 61 == nr61)
509      assert_equal(true, g:anint == 10)
510      assert_equal(false, 61 == g:anint)
511
512      if has('float')
513        var ff = 0.3
514        assert_equal(true, ff == 0.3)
515        assert_equal(false, 0.4 == ff)
516        assert_equal(true, 0.1 == g:afloat)
517        assert_equal(false, g:afloat == 0.3)
518
519        ff = 3.0
520        assert_equal(true, ff == 3)
521        assert_equal(true, 3 == ff)
522        ff = 3.1
523        assert_equal(false, ff == 3)
524        assert_equal(false, 3 == ff)
525      endif
526
527      assert_equal(true, 'abc' == 'abc')
528      assert_equal(false, 'xyz' == 'abc')
529      assert_equal(true, g:astring == 'asdf')
530      assert_equal(false, 'xyz' == g:astring)
531
532      assert_equal(false, 'abc' == 'aBc')
533      assert_equal(false, 'abc' ==# 'aBc')
534      assert_equal(true, 'abc' ==? 'aBc')
535
536      assert_equal(false, 'abc' == 'ABC')
537      set ignorecase
538      assert_equal(false, 'abc' == 'ABC')
539      assert_equal(false, 'abc' ==# 'ABC')
540      assert_equal(true, 'abc' ==? 'ABC')
541      set noignorecase
542
543      var bb = 0z3f
544      assert_equal(true, 0z3f == bb)
545      assert_equal(false, bb == 0z4f)
546      assert_equal(true, g:ablob == 0z01ab)
547      assert_equal(false, 0z3f == g:ablob)
548
549      assert_equal(true, [1, 2, 3] == [1, 2, 3])
550      assert_equal(false, [1, 2, 3] == [2, 3, 1])
551      assert_equal(true, [2, 3, 4] == g:alist)
552      assert_equal(false, g:alist == [2, 3, 1])
553      assert_equal(false, [1, 2, 3] == [])
554      assert_equal(false, [1, 2, 3] == ['1', '2', '3'])
555
556      assert_equal(true, #{one: 1, two: 2} == #{one: 1, two: 2})
557      assert_equal(false, #{one: 1, two: 2} == #{one: 2, two: 2})
558      assert_equal(false, #{one: 1, two: 2} == #{two: 2})
559      assert_equal(false, #{one: 1, two: 2} == #{})
560      assert_equal(true, g:adict == #{bbb: 8, aaa: 2})
561      assert_equal(false, #{ccc: 9, aaa: 2} == g:adict)
562
563      assert_equal(true, function('g:Test_expr4_equal') == function('g:Test_expr4_equal'))
564      assert_equal(false, function('g:Test_expr4_equal') == function('g:Test_expr4_is'))
565
566      assert_equal(true, function('g:Test_expr4_equal', [123]) == function('g:Test_expr4_equal', [123]))
567      assert_equal(false, function('g:Test_expr4_equal', [123]) == function('g:Test_expr4_is', [123]))
568      assert_equal(false, function('g:Test_expr4_equal', [123]) == function('g:Test_expr4_equal', [999]))
569
570      # TODO: this unexpectedly sometimes fails on Appveyor
571      if !has('win32')
572        var OneFunc: func
573        var TwoFunc: func
574        OneFunc = function('len')
575        TwoFunc = function('len')
576        assert_equal(true, OneFunc('abc') == TwoFunc('123'))
577      endif
578  END
579  CheckDefAndScriptSuccess(lines)
580
581  CheckDefFailure(["var x = 'a' == xxx"], 'E1001:', 1)
582  CheckDefExecFailure(['var items: any', 'eval 1', 'eval 2', 'if items == []', 'endif'], 'E691:', 4)
583enddef
584
585" test != comperator
586def Test_expr4_notequal()
587  var lines =<< trim END
588      var trueVar = true
589      var falseVar = false
590      assert_equal(false, true != true)
591      assert_equal(true, true !=
592                            false)
593      assert_equal(false, true
594                            != trueVar)
595      assert_equal(true, true != falseVar)
596      assert_equal(false, true != g:atrue)
597      assert_equal(true, g:atrue != false)
598
599      assert_equal(false, v:none != v:none)
600      assert_equal(true, v:none != v:null)
601      assert_equal(false, g:anone != v:none)
602      assert_equal(true, v:none != g:anull)
603
604      var nr55 = 55
605      var nr0 = 55
606      assert_equal(true, 2 != 0)
607      assert_equal(true, 2 != nr0)
608      assert_equal(false, 55 != 55)
609      assert_equal(false, 55 != nr55)
610      assert_equal(false, g:anint != 10)
611      assert_equal(true, 61 != g:anint)
612
613      if has('float')
614        var ff = 0.3
615        assert_equal(false, 0.3 != ff)
616        assert_equal(true, 0.4 != ff)
617        assert_equal(false, 0.1 != g:afloat)
618        assert_equal(true, g:afloat != 0.3)
619
620        ff = 3.0
621        assert_equal(false, ff != 3)
622        assert_equal(false, 3 != ff)
623        ff = 3.1
624        assert_equal(true, ff != 3)
625        assert_equal(true, 3 != ff)
626      endif
627
628      assert_equal(false, 'abc' != 'abc')
629      assert_equal(true, 'xyz' != 'abc')
630      assert_equal(false, g:astring != 'asdf')
631      assert_equal(true, 'xyz' != g:astring)
632
633      assert_equal(true, 'abc' != 'ABC')
634      set ignorecase
635      assert_equal(true, 'abc' != 'ABC')
636      assert_equal(true, 'abc' !=# 'ABC')
637      assert_equal(false, 'abc' !=? 'ABC')
638      set noignorecase
639
640      var bb = 0z3f
641      assert_equal(false, 0z3f != bb)
642      assert_equal(true, bb != 0z4f)
643      assert_equal(false, g:ablob != 0z01ab)
644      assert_equal(true, 0z3f != g:ablob)
645
646      assert_equal(false, [1, 2, 3] != [1, 2, 3])
647      assert_equal(true, [1, 2, 3] != [2, 3, 1])
648      assert_equal(false, [2, 3, 4] != g:alist)
649      assert_equal(true, g:alist != [2, 3, 1])
650      assert_equal(true, [1, 2, 3] != [])
651      assert_equal(true, [1, 2, 3] != ['1', '2', '3'])
652
653      assert_equal(false, #{one: 1, two: 2} != #{one: 1, two: 2})
654      assert_equal(true, #{one: 1, two: 2} != #{one: 2, two: 2})
655      assert_equal(true, #{one: 1, two: 2} != #{two: 2})
656      assert_equal(true, #{one: 1, two: 2} != #{})
657      assert_equal(false, g:adict != #{bbb: 8, aaa: 2})
658      assert_equal(true, #{ccc: 9, aaa: 2} != g:adict)
659
660      assert_equal(false, function('g:Test_expr4_equal') != function('g:Test_expr4_equal'))
661      assert_equal(true, function('g:Test_expr4_equal') != function('g:Test_expr4_is'))
662
663      assert_equal(false, function('g:Test_expr4_equal', [123]) != function('g:Test_expr4_equal', [123]))
664      assert_equal(true, function('g:Test_expr4_equal', [123]) != function('g:Test_expr4_is', [123]))
665      assert_equal(true, function('g:Test_expr4_equal', [123]) != function('g:Test_expr4_equal', [999]))
666  END
667  CheckDefAndScriptSuccess(lines)
668enddef
669
670" test > comperator
671def Test_expr4_greater()
672  var lines =<< trim END
673      assert_true(2 > 0)
674      assert_true(2 >
675                    1)
676      assert_false(2 > 2)
677      assert_false(2 > 3)
678      var nr2 = 2
679      assert_true(nr2 > 0)
680      assert_true(nr2 >
681                    1)
682      assert_false(nr2 > 2)
683      assert_false(nr2
684                        > 3)
685      if has('float')
686        var ff = 2.0
687        assert_true(ff > 0.0)
688        assert_true(ff > 1.0)
689        assert_false(ff > 2.0)
690        assert_false(ff > 3.0)
691      endif
692  END
693  CheckDefAndScriptSuccess(lines)
694enddef
695
696" test >= comperator
697def Test_expr4_greaterequal()
698  var lines =<< trim END
699      assert_true(2 >= 0)
700      assert_true(2 >=
701                            2)
702      assert_false(2 >= 3)
703      var nr2 = 2
704      assert_true(nr2 >= 0)
705      assert_true(nr2 >= 2)
706      assert_false(nr2 >= 3)
707      if has('float')
708        var ff = 2.0
709        assert_true(ff >= 0.0)
710        assert_true(ff >= 2.0)
711        assert_false(ff >= 3.0)
712      endif
713  END
714  CheckDefAndScriptSuccess(lines)
715enddef
716
717" test < comperator
718def Test_expr4_smaller()
719  var lines =<< trim END
720      assert_false(2 < 0)
721      assert_false(2 <
722                            2)
723      assert_true(2
724                    < 3)
725      var nr2 = 2
726      assert_false(nr2 < 0)
727      assert_false(nr2 < 2)
728      assert_true(nr2 < 3)
729      if has('float')
730        var ff = 2.0
731        assert_false(ff < 0.0)
732        assert_false(ff < 2.0)
733        assert_true(ff < 3.0)
734      endif
735  END
736  CheckDefAndScriptSuccess(lines)
737enddef
738
739" test <= comperator
740def Test_expr4_smallerequal()
741  var lines =<< trim END
742      assert_false(2 <= 0)
743      assert_false(2 <=
744                            1)
745      assert_true(2
746                    <= 2)
747      assert_true(2 <= 3)
748      var nr2 = 2
749      assert_false(nr2 <= 0)
750      assert_false(nr2 <= 1)
751      assert_true(nr2 <= 2)
752      assert_true(nr2 <= 3)
753      if has('float')
754        var ff = 2.0
755        assert_false(ff <= 0.0)
756        assert_false(ff <= 1.0)
757        assert_true(ff <= 2.0)
758        assert_true(ff <= 3.0)
759      endif
760  END
761  CheckDefAndScriptSuccess(lines)
762enddef
763
764" test =~ comperator
765def Test_expr4_match()
766  var lines =<< trim END
767      assert_equal(false, '2' =~ '0')
768      assert_equal(false, ''
769                             =~ '0')
770      assert_equal(true, '2' =~
771                            '[0-9]')
772      set ignorecase
773      assert_equal(false, 'abc' =~ 'ABC')
774      assert_equal(false, 'abc' =~# 'ABC')
775      assert_equal(true, 'abc' =~? 'ABC')
776      set noignorecase
777  END
778  CheckDefAndScriptSuccess(lines)
779enddef
780
781" test !~ comperator
782def Test_expr4_nomatch()
783  var lines =<< trim END
784      assert_equal(true, '2' !~ '0')
785      assert_equal(true, ''
786                            !~ '0')
787      assert_equal(false, '2' !~
788                            '[0-9]')
789  END
790  CheckDefAndScriptSuccess(lines)
791enddef
792
793" test is comperator
794def Test_expr4_is()
795  var lines =<< trim END
796      var mylist = [2]
797      assert_false(mylist is [2])
798      var other = mylist
799      assert_true(mylist is
800                    other)
801
802      var myblob = 0z1234
803      assert_false(myblob
804                            is 0z1234)
805      var otherblob = myblob
806      assert_true(myblob is otherblob)
807  END
808  CheckDefAndScriptSuccess(lines)
809enddef
810
811" test isnot comperator
812def Test_expr4_isnot()
813  var lines =<< trim END
814      var mylist = [2]
815      assert_true('2' isnot '0')
816      assert_true(mylist isnot [2])
817      var other = mylist
818      assert_false(mylist isnot
819                            other)
820
821      var myblob = 0z1234
822      assert_true(myblob
823                    isnot 0z1234)
824      var otherblob = myblob
825      assert_false(myblob isnot otherblob)
826  END
827  CheckDefAndScriptSuccess(lines)
828enddef
829
830def RetVoid()
831  var x = 1
832enddef
833
834def Test_expr4_vim9script()
835  # check line continuation
836  var lines =<< trim END
837      vim9script
838      var name = 0
839      		< 1
840      assert_equal(true, name)
841  END
842  CheckScriptSuccess(lines)
843
844  lines =<< trim END
845      vim9script
846      var name = 123
847                # comment
848      		!= 123
849      assert_equal(false, name)
850  END
851  CheckScriptSuccess(lines)
852
853  lines =<< trim END
854      vim9script
855      var name = 123 ==
856      			123
857      assert_equal(true, name)
858  END
859  CheckScriptSuccess(lines)
860
861  lines =<< trim END
862      vim9script
863      var list = [1, 2, 3]
864      var name = list
865      		is list
866      assert_equal(true, name)
867  END
868  CheckScriptSuccess(lines)
869
870  lines =<< trim END
871      vim9script
872      var list = [1, 2, 3]
873      var name = list # comment
874                 # comment
875      		is list
876      assert_equal(true, name)
877  END
878  CheckScriptSuccess(lines)
879
880  lines =<< trim END
881      vim9script
882      var myblob = 0z1234
883      var name = myblob
884      		isnot 0z11
885      assert_equal(true, name)
886  END
887  CheckScriptSuccess(lines)
888
889  # spot check mismatching types
890  lines =<< trim END
891      vim9script
892      echo '' == 0
893  END
894  CheckScriptFailure(lines, 'E1072:', 2)
895
896  lines =<< trim END
897      vim9script
898      echo v:true > v:false
899  END
900  CheckScriptFailure(lines, 'Cannot compare bool with bool', 2)
901
902  lines =<< trim END
903      vim9script
904      echo 123 is 123
905  END
906  CheckScriptFailure(lines, 'Cannot use "is" with number', 2)
907
908  # check missing white space
909  lines =<< trim END
910    vim9script
911    echo 2>3
912  END
913  CheckScriptFailure(lines, 'E1004:', 2)
914  lines =<< trim END
915    vim9script
916    echo 2 >3
917  END
918  CheckScriptFailure(lines, 'E1004:', 2)
919  lines =<< trim END
920    vim9script
921    echo 2> 3
922  END
923  CheckScriptFailure(lines, 'E1004:', 2)
924  lines =<< trim END
925    vim9script
926    echo 2!=3
927  END
928  CheckScriptFailure(lines, 'E1004:', 2)
929  lines =<< trim END
930    vim9script
931    echo 2 !=3
932  END
933  CheckScriptFailure(lines, 'E1004:', 2)
934  lines =<< trim END
935    vim9script
936    echo 2!= 3
937  END
938  CheckScriptFailure(lines, 'E1004:', 2)
939
940  lines =<< trim END
941    vim9script
942    echo len('xxx') == 3
943  END
944  CheckScriptSuccess(lines)
945
946  lines =<< trim END
947    vim9script
948    var line = 'abc'
949    echo line[1] =~ '\w'
950  END
951  CheckScriptSuccess(lines)
952enddef
953
954func Test_expr4_fails()
955  let msg = "White space required before and after '>'"
956  call CheckDefFailure(["var x = 1>2"], msg, 1)
957  call CheckDefFailure(["var x = 1 >2"], msg, 1)
958  call CheckDefFailure(["var x = 1> 2"], msg, 1)
959
960  let msg = "White space required before and after '=='"
961  call CheckDefFailure(["var x = 1==2"], msg, 1)
962  call CheckDefFailure(["var x = 1 ==2"], msg, 1)
963  call CheckDefFailure(["var x = 1== 2"], msg, 1)
964
965  let msg = "White space required before and after 'is'"
966  call CheckDefFailure(["var x = '1'is'2'"], msg, 1)
967  call CheckDefFailure(["var x = '1' is'2'"], msg, 1)
968  call CheckDefFailure(["var x = '1'is '2'"], msg, 1)
969
970  let msg = "White space required before and after 'isnot'"
971  call CheckDefFailure(["var x = '1'isnot'2'"], msg, 1)
972  call CheckDefFailure(["var x = '1' isnot'2'"], msg, 1)
973  call CheckDefFailure(["var x = '1'isnot '2'"], msg, 1)
974
975  call CheckDefFailure(["var x = 1 is# 2"], 'E15:', 1)
976  call CheckDefFailure(["var x = 1 is? 2"], 'E15:', 1)
977  call CheckDefFailure(["var x = 1 isnot# 2"], 'E15:', 1)
978  call CheckDefFailure(["var x = 1 isnot? 2"], 'E15:', 1)
979
980  call CheckDefFailure(["var x = 1 == '2'"], 'Cannot compare number with string', 1)
981  call CheckDefFailure(["var x = '1' == 2"], 'Cannot compare string with number', 1)
982  call CheckDefFailure(["var x = 1 == RetVoid()"], 'Cannot compare number with void', 1)
983  call CheckDefFailure(["var x = RetVoid() == 1"], 'Cannot compare void with number', 1)
984
985  call CheckDefFailure(["var x = true > false"], 'Cannot compare bool with bool', 1)
986  call CheckDefFailure(["var x = true >= false"], 'Cannot compare bool with bool', 1)
987  call CheckDefFailure(["var x = true < false"], 'Cannot compare bool with bool', 1)
988  call CheckDefFailure(["var x = true <= false"], 'Cannot compare bool with bool', 1)
989  call CheckDefFailure(["var x = true =~ false"], 'Cannot compare bool with bool', 1)
990  call CheckDefFailure(["var x = true !~ false"], 'Cannot compare bool with bool', 1)
991  call CheckDefFailure(["var x = true is false"], 'Cannot use "is" with bool', 1)
992  call CheckDefFailure(["var x = true isnot false"], 'Cannot use "isnot" with bool', 1)
993
994  call CheckDefFailure(["var x = v:none is v:null"], 'Cannot use "is" with special', 1)
995  call CheckDefFailure(["var x = v:none isnot v:null"], 'Cannot use "isnot" with special', 1)
996  call CheckDefFailure(["var x = 123 is 123"], 'Cannot use "is" with number', 1)
997  call CheckDefFailure(["var x = 123 isnot 123"], 'Cannot use "isnot" with number', 1)
998  if has('float')
999    call CheckDefFailure(["var x = 1.3 is 1.3"], 'Cannot use "is" with float', 1)
1000    call CheckDefFailure(["var x = 1.3 isnot 1.3"], 'Cannot use "isnot" with float', 1)
1001  endif
1002
1003  call CheckDefFailure(["var x = 0za1 > 0z34"], 'Cannot compare blob with blob', 1)
1004  call CheckDefFailure(["var x = 0za1 >= 0z34"], 'Cannot compare blob with blob', 1)
1005  call CheckDefFailure(["var x = 0za1 < 0z34"], 'Cannot compare blob with blob', 1)
1006  call CheckDefFailure(["var x = 0za1 <= 0z34"], 'Cannot compare blob with blob', 1)
1007  call CheckDefFailure(["var x = 0za1 =~ 0z34"], 'Cannot compare blob with blob', 1)
1008  call CheckDefFailure(["var x = 0za1 !~ 0z34"], 'Cannot compare blob with blob', 1)
1009
1010  call CheckDefFailure(["var x = [13] > [88]"], 'Cannot compare list with list', 1)
1011  call CheckDefFailure(["var x = [13] >= [88]"], 'Cannot compare list with list', 1)
1012  call CheckDefFailure(["var x = [13] < [88]"], 'Cannot compare list with list', 1)
1013  call CheckDefFailure(["var x = [13] <= [88]"], 'Cannot compare list with list', 1)
1014  call CheckDefFailure(["var x = [13] =~ [88]"], 'Cannot compare list with list', 1)
1015  call CheckDefFailure(["var x = [13] !~ [88]"], 'Cannot compare list with list', 1)
1016
1017  call CheckDefFailure(['var j: job', 'var chan: channel', 'var r = j == chan'], 'Cannot compare job with channel', 3)
1018  call CheckDefFailure(['var j: job', 'var x: list<any>', 'var r = j == x'], 'Cannot compare job with list', 3)
1019  call CheckDefFailure(['var j: job', 'var Xx: func', 'var r = j == Xx'], 'Cannot compare job with func', 3)
1020  call CheckDefFailure(['var j: job', 'var Xx: func', 'var r = j == Xx'], 'Cannot compare job with func', 3)
1021endfunc
1022
1023" test addition, subtraction, concatenation
1024def Test_expr5()
1025  var lines =<< trim END
1026      assert_equal(66, 60 + 6)
1027      assert_equal(70, 60 +
1028                            g:anint)
1029      assert_equal(9, g:thefour
1030                            + 5)
1031      assert_equal(14, g:thefour + g:anint)
1032      assert_equal([1, 2, 3, 4], [1] + g:alist)
1033
1034      assert_equal(54, 60 - 6)
1035      assert_equal(50, 60 -
1036                        g:anint)
1037      assert_equal(-1, g:thefour
1038                            - 5)
1039      assert_equal(-6, g:thefour - g:anint)
1040
1041      assert_equal('hello', 'hel' .. 'lo')
1042      assert_equal('hello 123', 'hello ' ..
1043                                            123)
1044      assert_equal('hello 123', 'hello '
1045                                    ..  123)
1046      assert_equal('123 hello', 123 .. ' hello')
1047      assert_equal('123456', 123 .. 456)
1048
1049      assert_equal('av:true', 'a' .. true)
1050      assert_equal('av:false', 'a' .. false)
1051      assert_equal('av:null', 'a' .. v:null)
1052      assert_equal('av:none', 'a' .. v:none)
1053      if has('float')
1054        assert_equal('a0.123', 'a' .. 0.123)
1055      endif
1056
1057      assert_equal([1, 2, 3, 4], [1, 2] + [3, 4])
1058      assert_equal(0z11223344, 0z1122 + 0z3344)
1059      assert_equal(0z112201ab, 0z1122
1060                                    + g:ablob)
1061      assert_equal(0z01ab3344, g:ablob + 0z3344)
1062      assert_equal(0z01ab01ab, g:ablob + g:ablob)
1063
1064      # concatenate non-constant to constant
1065      var save_path = &path
1066      &path = 'b'
1067      assert_equal('ab', 'a' .. &path)
1068      &path = save_path
1069
1070      @b = 'b'
1071      assert_equal('ab', 'a' .. @b)
1072
1073      $ENVVAR = 'env'
1074      assert_equal('aenv', 'a' .. $ENVVAR)
1075  END
1076  CheckDefAndScriptSuccess(lines)
1077enddef
1078
1079def Test_expr5_vim9script()
1080  # check line continuation
1081  var lines =<< trim END
1082      vim9script
1083      var name = 11
1084      		+ 77
1085		- 22
1086      assert_equal(66, name)
1087  END
1088  CheckScriptSuccess(lines)
1089
1090  lines =<< trim END
1091      vim9script
1092      var name = 11 +
1093		  77 -
1094		  22
1095      assert_equal(66, name)
1096  END
1097  CheckScriptSuccess(lines)
1098
1099  lines =<< trim END
1100      vim9script
1101      var name = 11 +  # comment
1102		  77 -
1103                  # comment
1104		  22
1105      assert_equal(66, name)
1106  END
1107  CheckScriptSuccess(lines)
1108
1109  lines =<< trim END
1110      vim9script
1111      var name = 'one'
1112      		.. 'two'
1113      assert_equal('onetwo', name)
1114  END
1115  CheckScriptSuccess(lines)
1116
1117  lines =<< trim END
1118      vim9script
1119      echo 'abc' is# 'abc'
1120  END
1121  CheckScriptFailure(lines, 'E15:', 2)
1122
1123  lines =<< trim END
1124      vim9script
1125      echo {} - 22
1126  END
1127  CheckScriptFailure(lines, 'E728:', 2)
1128
1129  lines =<< trim END
1130      vim9script
1131      echo [] - 33
1132  END
1133  CheckScriptFailure(lines, 'E745:', 2)
1134
1135  lines =<< trim END
1136      vim9script
1137      echo 0z1234 - 44
1138  END
1139  CheckScriptFailure(lines, 'E974:', 2)
1140
1141  lines =<< trim END
1142      vim9script
1143      echo 'abc' is? 'abc'
1144  END
1145  CheckScriptFailure(lines, 'E15:', 2)
1146
1147  lines =<< trim END
1148      vim9script
1149      echo 'abc' isnot# 'abc'
1150  END
1151  CheckScriptFailure(lines, 'E15:', 2)
1152
1153  lines =<< trim END
1154      vim9script
1155      echo 'abc' isnot? 'abc'
1156  END
1157  CheckScriptFailure(lines, 'E15:', 2)
1158
1159  # check white space
1160  lines =<< trim END
1161      vim9script
1162      echo 5+6
1163  END
1164  CheckScriptFailure(lines, 'E1004:', 2)
1165  lines =<< trim END
1166      vim9script
1167      echo 5 +6
1168  END
1169  CheckScriptFailure(lines, 'E1004:', 2)
1170  lines =<< trim END
1171      vim9script
1172      echo 5+ 6
1173  END
1174  CheckScriptFailure(lines, 'E1004:', 2)
1175
1176  lines =<< trim END
1177      vim9script
1178      echo 'a'..'b'
1179  END
1180  CheckScriptFailure(lines, 'E1004:', 2)
1181  lines =<< trim END
1182      vim9script
1183      echo 'a' ..'b'
1184  END
1185  CheckScriptFailure(lines, 'E1004:', 2)
1186  lines =<< trim END
1187      vim9script
1188      echo 'a'.. 'b'
1189  END
1190  CheckScriptFailure(lines, 'E1004:', 2)
1191
1192  # check invalid string concatenation
1193  lines =<< trim END
1194      vim9script
1195      echo 'a' .. [1]
1196  END
1197  CheckScriptFailure(lines, 'E730:', 2)
1198  lines =<< trim END
1199      vim9script
1200      echo 'a' .. #{a: 1}
1201  END
1202  CheckScriptFailure(lines, 'E731:', 2)
1203  lines =<< trim END
1204      vim9script
1205      echo 'a' .. test_void()
1206  END
1207  CheckScriptFailure(lines, 'E908:', 2)
1208  lines =<< trim END
1209      vim9script
1210      echo 'a' .. 0z33
1211  END
1212  CheckScriptFailure(lines, 'E976:', 2)
1213  lines =<< trim END
1214      vim9script
1215      echo 'a' .. function('len')
1216  END
1217  CheckScriptFailure(lines, 'E729:', 2)
1218enddef
1219
1220def Test_expr5_vim9script_channel()
1221  if !has('channel')
1222    MissingFeature 'float'
1223  else
1224    var lines =<< trim END
1225        vim9script
1226        echo 'a' .. test_null_job()
1227    END
1228    CheckScriptFailure(lines, 'E908:', 2)
1229    lines =<< trim END
1230        vim9script
1231        echo 'a' .. test_null_channel()
1232    END
1233    CheckScriptFailure(lines, 'E908:', 2)
1234  endif
1235enddef
1236
1237def Test_expr5_float()
1238  if !has('float')
1239    MissingFeature 'float'
1240  else
1241    var lines =<< trim END
1242        assert_equal(66.0, 60.0 + 6.0)
1243        assert_equal(66.0, 60.0 + 6)
1244        assert_equal(66.0, 60 +
1245                             6.0)
1246        assert_equal(5.1, g:afloat
1247                            + 5)
1248        assert_equal(8.1, 8 + g:afloat)
1249        assert_equal(10.1, g:anint + g:afloat)
1250        assert_equal(10.1, g:afloat + g:anint)
1251
1252        assert_equal(54.0, 60.0 - 6.0)
1253        assert_equal(54.0, 60.0
1254                                - 6)
1255        assert_equal(54.0, 60 - 6.0)
1256        assert_equal(-4.9, g:afloat - 5)
1257        assert_equal(7.9, 8 - g:afloat)
1258        assert_equal(9.9, g:anint - g:afloat)
1259        assert_equal(-9.9, g:afloat - g:anint)
1260    END
1261    CheckDefAndScriptSuccess(lines)
1262  endif
1263enddef
1264
1265func Test_expr5_fails()
1266  let msg = "White space required before and after '+'"
1267  call CheckDefFailure(["var x = 1+2"], msg, 1)
1268  call CheckDefFailure(["var x = 1 +2"], msg, 1)
1269  call CheckDefFailure(["var x = 1+ 2"], msg, 1)
1270
1271  let msg = "White space required before and after '-'"
1272  call CheckDefFailure(["var x = 1-2"], msg, 1)
1273  call CheckDefFailure(["var x = 1 -2"], msg, 1)
1274  call CheckDefFailure(["var x = 1- 2"], msg, 1)
1275
1276  let msg = "White space required before and after '..'"
1277  call CheckDefFailure(["var x = '1'..'2'"], msg, 1)
1278  call CheckDefFailure(["var x = '1' ..'2'"], msg, 1)
1279  call CheckDefFailure(["var x = '1'.. '2'"], msg, 1)
1280
1281  call CheckDefFailure(["var x = 0z1122 + 33"], 'E1051:', 1)
1282  call CheckDefFailure(["var x = 0z1122 + [3]"], 'E1051:', 1)
1283  call CheckDefFailure(["var x = 0z1122 + 'asd'"], 'E1051:', 1)
1284  call CheckDefFailure(["var x = 33 + 0z1122"], 'E1051:', 1)
1285  call CheckDefFailure(["var x = [3] + 0z1122"], 'E1051:', 1)
1286  call CheckDefFailure(["var x = 'asdf' + 0z1122"], 'E1051:', 1)
1287  call CheckDefFailure(["var x = 6 + xxx"], 'E1001:', 1)
1288
1289  call CheckDefFailure(["var x = 'a' .. [1]"], 'E1105:', 1)
1290  call CheckDefFailure(["var x = 'a' .. #{a: 1}"], 'E1105:', 1)
1291  call CheckDefFailure(["var x = 'a' .. test_void()"], 'E1105:', 1)
1292  call CheckDefFailure(["var x = 'a' .. 0z32"], 'E1105:', 1)
1293  call CheckDefFailure(["var x = 'a' .. function('len')"], 'E1105:', 1)
1294  call CheckDefFailure(["var x = 'a' .. function('len', ['a'])"], 'E1105:', 1)
1295endfunc
1296
1297func Test_expr5_fails_channel()
1298  CheckFeature channel
1299  call CheckDefFailure(["var x = 'a' .. test_null_job()"], 'E1105:', 1)
1300  call CheckDefFailure(["var x = 'a' .. test_null_channel()"], 'E1105:', 1)
1301endfunc
1302
1303" test multiply, divide, modulo
1304def Test_expr6()
1305  var lines =<< trim END
1306      assert_equal(36, 6 * 6)
1307      assert_equal(24, 6 *
1308                            g:thefour)
1309      assert_equal(24, g:thefour
1310                            * 6)
1311      assert_equal(40, g:anint * g:thefour)
1312
1313      assert_equal(10, 60 / 6)
1314      assert_equal(6, 60 /
1315                            g:anint)
1316      assert_equal(1, g:anint / 6)
1317      assert_equal(2, g:anint
1318                            / g:thefour)
1319
1320      assert_equal(5, 11 % 6)
1321      assert_equal(4, g:anint % 6)
1322      assert_equal(3, 13 %
1323                            g:anint)
1324      assert_equal(2, g:anint
1325                            % g:thefour)
1326
1327      assert_equal(4, 6 * 4 / 6)
1328
1329      var x = [2]
1330      var y = [3]
1331      assert_equal(5, x[0] + y[0])
1332      assert_equal(6, x[0] * y[0])
1333      if has('float')
1334        var xf = [2.0]
1335        var yf = [3.0]
1336        assert_equal(5.0, xf[0]
1337                            + yf[0])
1338        assert_equal(6.0, xf[0]
1339                            * yf[0])
1340      endif
1341  END
1342  CheckDefAndScriptSuccess(lines)
1343
1344  CheckDefFailure(["var x = 6 * xxx"], 'E1001:', 1)
1345enddef
1346
1347def Test_expr6_vim9script()
1348  # check line continuation
1349  var lines =<< trim END
1350      vim9script
1351      var name = 11
1352      		* 22
1353		/ 3
1354      assert_equal(80, name)
1355  END
1356  CheckScriptSuccess(lines)
1357
1358  lines =<< trim END
1359      vim9script
1360      var name = 25
1361      		% 10
1362      assert_equal(5, name)
1363  END
1364  CheckScriptSuccess(lines)
1365
1366  lines =<< trim END
1367      vim9script
1368      var name = 25
1369                # comment
1370
1371                # comment
1372      		% 10
1373      assert_equal(5, name)
1374  END
1375  CheckScriptSuccess(lines)
1376
1377  lines =<< trim END
1378      vim9script
1379      var name = 11 *
1380      		22 /
1381		3
1382      assert_equal(80, name)
1383  END
1384  CheckScriptSuccess(lines)
1385
1386  # check white space
1387  lines =<< trim END
1388      vim9script
1389      echo 5*6
1390  END
1391  CheckScriptFailure(lines, 'E1004:', 2)
1392  lines =<< trim END
1393      vim9script
1394      echo 5 *6
1395  END
1396  CheckScriptFailure(lines, 'E1004:', 2)
1397  lines =<< trim END
1398      vim9script
1399      echo 5* 6
1400  END
1401  CheckScriptFailure(lines, 'E1004:', 2)
1402enddef
1403
1404def Test_expr6_float()
1405  if !has('float')
1406    MissingFeature 'float'
1407  else
1408    var lines =<< trim END
1409        assert_equal(36.0, 6.0 * 6)
1410        assert_equal(36.0, 6 *
1411                               6.0)
1412        assert_equal(36.0, 6.0 * 6.0)
1413        assert_equal(1.0, g:afloat * g:anint)
1414
1415        assert_equal(10.0, 60 / 6.0)
1416        assert_equal(10.0, 60.0 /
1417                            6)
1418        assert_equal(10.0, 60.0 / 6.0)
1419        assert_equal(0.01, g:afloat / g:anint)
1420
1421        assert_equal(4.0, 6.0 * 4 / 6)
1422        assert_equal(4.0, 6 *
1423                            4.0 /
1424                            6)
1425        assert_equal(4.0, 6 * 4 / 6.0)
1426        assert_equal(4.0, 6.0 * 4.0 / 6)
1427        assert_equal(4.0, 6 * 4.0 / 6.0)
1428        assert_equal(4.0, 6.0 * 4 / 6.0)
1429        assert_equal(4.0, 6.0 * 4.0 / 6.0)
1430
1431        assert_equal(4.0, 6.0 * 4.0 / 6.0)
1432    END
1433    CheckDefAndScriptSuccess(lines)
1434  endif
1435enddef
1436
1437func Test_expr6_fails()
1438  let msg = "White space required before and after '*'"
1439  call CheckDefFailure(["var x = 1*2"], msg, 1)
1440  call CheckDefFailure(["var x = 1 *2"], msg, 1)
1441  call CheckDefFailure(["var x = 1* 2"], msg, 1)
1442
1443  let msg = "White space required before and after '/'"
1444  call CheckDefFailure(["var x = 1/2"], msg, 1)
1445  call CheckDefFailure(["var x = 1 /2"], msg, 1)
1446  call CheckDefFailure(["var x = 1/ 2"], msg, 1)
1447
1448  let msg = "White space required before and after '%'"
1449  call CheckDefFailure(["var x = 1%2"], msg, 1)
1450  call CheckDefFailure(["var x = 1 %2"], msg, 1)
1451  call CheckDefFailure(["var x = 1% 2"], msg, 1)
1452
1453  call CheckDefFailure(["var x = '1' * '2'"], 'E1036:', 1)
1454  call CheckDefFailure(["var x = '1' / '2'"], 'E1036:', 1)
1455  call CheckDefFailure(["var x = '1' % '2'"], 'E1035:', 1)
1456
1457  call CheckDefFailure(["var x = 0z01 * 0z12"], 'E1036:', 1)
1458  call CheckDefFailure(["var x = 0z01 / 0z12"], 'E1036:', 1)
1459  call CheckDefFailure(["var x = 0z01 % 0z12"], 'E1035:', 1)
1460
1461  call CheckDefFailure(["var x = [1] * [2]"], 'E1036:', 1)
1462  call CheckDefFailure(["var x = [1] / [2]"], 'E1036:', 1)
1463  call CheckDefFailure(["var x = [1] % [2]"], 'E1035:', 1)
1464
1465  call CheckDefFailure(["var x = #{one: 1} * #{two: 2}"], 'E1036:', 1)
1466  call CheckDefFailure(["var x = #{one: 1} / #{two: 2}"], 'E1036:', 1)
1467  call CheckDefFailure(["var x = #{one: 1} % #{two: 2}"], 'E1035:', 1)
1468
1469  call CheckDefFailure(["var x = 0xff[1]"], 'E1107:', 1)
1470  if has('float')
1471    call CheckDefFailure(["var x = 0.7[1]"], 'E1107:', 1)
1472  endif
1473endfunc
1474
1475func Test_expr6_float_fails()
1476  CheckFeature float
1477  call CheckDefFailure(["var x = 1.0 % 2"], 'E1035:', 1)
1478endfunc
1479
1480" define here to use old style parsing
1481if has('float')
1482  let g:float_zero = 0.0
1483  let g:float_neg = -9.8
1484  let g:float_big = 9.9e99
1485endif
1486let g:blob_empty = 0z
1487let g:blob_one = 0z01
1488let g:blob_long = 0z0102.0304
1489
1490let g:string_empty = ''
1491let g:string_short = 'x'
1492let g:string_long = 'abcdefghijklm'
1493let g:string_special = "ab\ncd\ref\ekk"
1494
1495let g:special_true = v:true
1496let g:special_false = v:false
1497let g:special_null = v:null
1498let g:special_none = v:none
1499
1500let g:list_empty = []
1501let g:list_mixed = [1, 'b', v:false]
1502
1503let g:dict_empty = {}
1504let g:dict_one = #{one: 1}
1505
1506let $TESTVAR = 'testvar'
1507
1508" type casts
1509def Test_expr7t()
1510  var ls: list<string> = ['a', <string>g:string_empty]
1511  var ln: list<number> = [<number>g:anint, <number>g:thefour]
1512  var nr = <number>234
1513  assert_equal(234, nr)
1514
1515  CheckDefFailure(["var x = <nr>123"], 'E1010:', 1)
1516  CheckDefFailure(["var x = <number >123"], 'E1068:', 1)
1517  CheckDefFailure(["var x = <number 123"], 'E1104:', 1)
1518enddef
1519
1520" test low level expression
1521def Test_expr7_number()
1522  # number constant
1523  var lines =<< trim END
1524      assert_equal(0, 0)
1525      assert_equal(654, 0654)
1526
1527      assert_equal(6, 0x6)
1528      assert_equal(15, 0xf)
1529      assert_equal(255, 0xff)
1530  END
1531  CheckDefAndScriptSuccess(lines)
1532enddef
1533
1534def Test_expr7_float()
1535  # float constant
1536  if !has('float')
1537    MissingFeature 'float'
1538  else
1539    var lines =<< trim END
1540        assert_equal(g:float_zero, .0)
1541        assert_equal(g:float_zero, 0.0)
1542        assert_equal(g:float_neg, -9.8)
1543        assert_equal(g:float_big, 9.9e99)
1544    END
1545    CheckDefAndScriptSuccess(lines)
1546  endif
1547enddef
1548
1549def Test_expr7_blob()
1550  # blob constant
1551  var lines =<< trim END
1552      assert_equal(g:blob_empty, 0z)
1553      assert_equal(g:blob_one, 0z01)
1554      assert_equal(g:blob_long, 0z0102.0304)
1555  END
1556  CheckDefAndScriptSuccess(lines)
1557
1558  CheckDefFailure(["var x = 0z123"], 'E973:', 1)
1559enddef
1560
1561def Test_expr7_string()
1562  # string constant
1563  var lines =<< trim END
1564      assert_equal(g:string_empty, '')
1565      assert_equal(g:string_empty, "")
1566      assert_equal(g:string_short, 'x')
1567      assert_equal(g:string_short, "x")
1568      assert_equal(g:string_long, 'abcdefghijklm')
1569      assert_equal(g:string_long, "abcdefghijklm")
1570      assert_equal(g:string_special, "ab\ncd\ref\ekk")
1571  END
1572  CheckDefAndScriptSuccess(lines)
1573
1574  CheckDefFailure(['var x = "abc'], 'E114:', 1)
1575  CheckDefFailure(["var x = 'abc"], 'E115:', 1)
1576enddef
1577
1578def Test_expr7_vimvar()
1579  var old: list<string> = v:oldfiles
1580  var compl: dict<any> = v:completed_item
1581
1582  CheckDefFailure(["var old: list<number> = v:oldfiles"], 'E1012: Type mismatch; expected list<number> but got list<string>', 1)
1583  new
1584  exec "normal! afoo fo\<C-N>\<Esc>"
1585  CheckDefExecFailure(["var old: dict<number> = v:completed_item"], 'E1012: Type mismatch; expected dict<number> but got dict<string>', 1)
1586  bwipe!
1587enddef
1588
1589def Test_expr7_special()
1590  # special constant
1591  var lines =<< trim END
1592      assert_equal(g:special_true, true)
1593      assert_equal(g:special_false, false)
1594      assert_equal(g:special_true, v:true)
1595      assert_equal(g:special_false, v:false)
1596      assert_equal(v:true, true)
1597      assert_equal(v:false, false)
1598
1599      assert_equal(true, !false)
1600      assert_equal(false, !true)
1601      assert_equal(true, !0)
1602      assert_equal(false, !1)
1603      assert_equal(false, !!false)
1604      assert_equal(true, !!true)
1605      assert_equal(false, !!0)
1606      assert_equal(true, !!1)
1607
1608      var t = true
1609      var f = false
1610      assert_equal(true, t)
1611      assert_equal(false, f)
1612
1613      assert_equal(g:special_null, v:null)
1614      assert_equal(g:special_none, v:none)
1615  END
1616  CheckDefAndScriptSuccess(lines)
1617
1618  CheckDefFailure(['v:true = true'], 'E46:', 1)
1619  CheckDefFailure(['v:true = false'], 'E46:', 1)
1620  CheckDefFailure(['v:false = true'], 'E46:', 1)
1621  CheckDefFailure(['v:null = 11'], 'E46:', 1)
1622  CheckDefFailure(['v:none = 22'], 'E46:', 1)
1623enddef
1624
1625def Test_expr7_list()
1626  # list
1627  var lines =<< trim END
1628      assert_equal(g:list_empty, [])
1629      assert_equal(g:list_empty, [  ])
1630
1631      var numbers: list<number> = [1, 2, 3]
1632      numbers = [1]
1633      numbers = []
1634
1635      var strings: list<string> = ['a', 'b', 'c']
1636      strings = ['x']
1637      strings = []
1638
1639      var mixed: list<any> = [1, 'b', false,]
1640      assert_equal(g:list_mixed, mixed)
1641      assert_equal('b', mixed[1])
1642
1643      echo [1,
1644            2] [3,
1645                    4]
1646
1647      var llstring: list<list<string>> = [['text'], []]
1648      llstring = [[], ['text']]
1649      llstring = [[], []]
1650  END
1651  CheckDefAndScriptSuccess(lines)
1652
1653  var rangelist: list<number> = range(3)
1654  g:rangelist = range(3)
1655  CheckDefExecFailure(["var x: list<string> = g:rangelist"], 'E1012: Type mismatch; expected list<string> but got list<number>', 1)
1656
1657  CheckDefFailure(["var x = 1234[3]"], 'E1107:', 1)
1658  CheckDefExecFailure(["var x = g:anint[3]"], 'E1062:', 1)
1659
1660  CheckDefFailure(["var x = g:list_mixed[xxx]"], 'E1001:', 1)
1661
1662  CheckDefFailure(["var x = [1,2,3]"], 'E1069:', 1)
1663  CheckDefFailure(["var x = [1 ,2, 3]"], 'E1068:', 1)
1664
1665  CheckDefExecFailure(["echo 1", "var x = [][0]", "echo 3"], 'E684:', 2)
1666
1667  CheckDefExecFailure(["var x = g:list_mixed['xx']"], 'E1012:', 1)
1668  CheckDefFailure(["var x = g:list_mixed["], 'E1097:', 2)
1669  CheckDefFailure(["var x = g:list_mixed[0"], 'E1097:', 2)
1670  CheckDefExecFailure(["var x = g:list_empty[3]"], 'E684:', 1)
1671  CheckDefExecFailure(["var l: list<number> = [234, 'x']"], 'E1012:', 1)
1672  CheckDefExecFailure(["var l: list<number> = ['x', 234]"], 'E1012:', 1)
1673  CheckDefExecFailure(["var l: list<string> = [234, 'x']"], 'E1012:', 1)
1674  CheckDefExecFailure(["var l: list<string> = ['x', 123]"], 'E1012:', 1)
1675
1676  lines =<< trim END
1677      vim9script
1678      var datalist: list<string>
1679      def Main()
1680        datalist += ['x'.
1681      enddef
1682      Main()
1683  END
1684  CheckScriptFailure(lines, 'E1127:')
1685enddef
1686
1687def Test_expr7_list_vim9script()
1688  var lines =<< trim END
1689      vim9script
1690      var l = [
1691		11,
1692		22,
1693		]
1694      assert_equal([11, 22], l)
1695
1696      echo [1,
1697	    2] [3,
1698		    4]
1699
1700      echo [1, # comment
1701            # comment
1702	    2] [3,
1703            # comment
1704		    4]
1705  END
1706  CheckScriptSuccess(lines)
1707
1708  lines =<< trim END
1709      vim9script
1710      var l = [11,
1711		22]
1712      assert_equal([11, 22], l)
1713  END
1714  CheckScriptSuccess(lines)
1715
1716  lines =<< trim END
1717      vim9script
1718      var l = [11,22]
1719  END
1720  CheckScriptFailure(lines, 'E1069:', 2)
1721
1722  lines =<< trim END
1723      vim9script
1724      var l = [11 , 22]
1725  END
1726  CheckScriptFailure(lines, 'E1068:', 2)
1727
1728  lines =<< trim END
1729    vim9script
1730    var l: list<number> = [234, 'x']
1731  END
1732  CheckScriptFailure(lines, 'E1012:', 2)
1733  lines =<< trim END
1734    vim9script
1735    var l: list<number> = ['x', 234]
1736  END
1737  CheckScriptFailure(lines, 'E1012:', 2)
1738  lines =<< trim END
1739    vim9script
1740    var l: list<string> = ['x', 234]
1741  END
1742  CheckScriptFailure(lines, 'E1012:', 2)
1743  lines =<< trim END
1744    vim9script
1745    var l: list<string> = [234, 'x']
1746  END
1747  CheckScriptFailure(lines, 'E1012:', 2)
1748
1749  lines =<< trim END
1750      vim9script
1751      def Failing()
1752        job_stop()
1753      enddef
1754      var list = [Failing]
1755  END
1756  if has('channel')
1757    CheckScriptFailure(lines, 'E119:', 1)
1758  else
1759    CheckScriptFailure(lines, 'E117:', 1)
1760  endif
1761enddef
1762
1763def LambdaWithComments(): func
1764  return {x ->
1765            # some comment
1766            x == 1
1767            # some comment
1768            ||
1769            x == 2
1770        }
1771enddef
1772
1773def LambdaUsingArg(x: number): func
1774  return {->
1775            # some comment
1776            x == 1
1777            # some comment
1778            ||
1779            x == 2
1780        }
1781enddef
1782
1783def Test_expr7_lambda()
1784  var lines =<< trim END
1785      var La = { -> 'result'}
1786      assert_equal('result', La())
1787      assert_equal([1, 3, 5], [1, 2, 3]->map({key, val -> key + val}))
1788
1789      # line continuation inside lambda with "cond ? expr : expr" works
1790      var ll = range(3)
1791      map(ll, {k, v -> v % 2 ? {
1792                '111': 111 } : {}
1793            })
1794      assert_equal([{}, {'111': 111}, {}], ll)
1795
1796      ll = range(3)
1797      map(ll, {k, v -> v == 8 || v
1798                    == 9
1799                    || v % 2 ? 111 : 222
1800            })
1801      assert_equal([222, 111, 222], ll)
1802
1803      ll = range(3)
1804      map(ll, {k, v -> v != 8 && v
1805                    != 9
1806                    && v % 2 == 0 ? 111 : 222
1807            })
1808      assert_equal([111, 222, 111], ll)
1809
1810      var dl = [{'key': 0}, {'key': 22}]->filter({ _, v -> v['key'] })
1811      assert_equal([{'key': 22}], dl)
1812
1813      dl = [{'key': 12}, {'foo': 34}]
1814      assert_equal([{'key': 12}], filter(dl,
1815            {_, v -> has_key(v, 'key') ? v['key'] == 12 : 0}))
1816
1817      assert_equal(false, LambdaWithComments()(0))
1818      assert_equal(true, LambdaWithComments()(1))
1819      assert_equal(true, LambdaWithComments()(2))
1820      assert_equal(false, LambdaWithComments()(3))
1821
1822      assert_equal(false, LambdaUsingArg(0)())
1823      assert_equal(true, LambdaUsingArg(1)())
1824  END
1825  CheckDefAndScriptSuccess(lines)
1826
1827  CheckDefFailure(["filter([1, 2], {k,v -> 1})"], 'E1069:', 1)
1828  # error is in first line of the lambda
1829  CheckDefFailure(["var L = {a -> a + b}"], 'E1001:', 0)
1830
1831  assert_equal('xxxyyy', 'xxx'->{a, b -> a .. b}('yyy'))
1832
1833  CheckDefExecFailure(["var s = 'asdf'->{a -> a}('x')"],
1834        'E1106: One argument too many')
1835  CheckDefExecFailure(["var s = 'asdf'->{a -> a}('x', 'y')"],
1836        'E1106: 2 arguments too many')
1837  CheckDefFailure(["echo 'asdf'->{a -> a}(x)"], 'E1001:', 1)
1838
1839  CheckDefSuccess(['var Fx = {a -> #{k1: 0,', ' k2: 1}}'])
1840  CheckDefFailure(['var Fx = {a -> #{k1: 0', ' k2: 1}}'], 'E722:', 2)
1841  CheckDefFailure(['var Fx = {a -> #{k1: 0,', ' k2 1}}'], 'E720:', 2)
1842
1843  CheckDefSuccess(['var Fx = {a -> [0,', ' 1]}'])
1844  CheckDefFailure(['var Fx = {a -> [0', ' 1]}'], 'E696:', 2)
1845enddef
1846
1847def Test_expr7_lambda_vim9script()
1848  var lines =<< trim END
1849      vim9script
1850      var v = 10->{a ->
1851	    a
1852	      + 2
1853	  }()
1854      assert_equal(12, v)
1855  END
1856  CheckScriptSuccess(lines)
1857
1858  # nested lambda with line breaks
1859  lines =<< trim END
1860      vim9script
1861      search('"', 'cW', 0, 0, {->
1862	synstack('.', col('.'))
1863	->map({_, v -> synIDattr(v, 'name')})->len()})
1864  END
1865  CheckScriptSuccess(lines)
1866enddef
1867
1868def Test_epxr7_funcref()
1869  var lines =<< trim END
1870      def RetNumber(): number
1871        return 123
1872      enddef
1873      var FuncRef = RetNumber
1874      assert_equal(123, FuncRef())
1875  END
1876  CheckDefAndScriptSuccess(lines)
1877enddef
1878
1879def Test_expr7_dict()
1880  # dictionary
1881  var lines =<< trim END
1882      assert_equal(g:dict_empty, {})
1883      assert_equal(g:dict_empty, {  })
1884      assert_equal(g:dict_one, {'one': 1})
1885      var key = 'one'
1886      var val = 1
1887      assert_equal(g:dict_one, {key: val})
1888
1889      var numbers: dict<number> = #{a: 1, b: 2, c: 3}
1890      numbers = #{a: 1}
1891      numbers = #{}
1892
1893      var strings: dict<string> = #{a: 'a', b: 'b', c: 'c'}
1894      strings = #{a: 'x'}
1895      strings = #{}
1896
1897      var mixed: dict<any> = #{a: 'a', b: 42}
1898      mixed = #{a: 'x'}
1899      mixed = #{a: 234}
1900      mixed = #{}
1901
1902      var dictlist: dict<list<string>> = #{absent: [], present: ['hi']}
1903      dictlist = #{absent: ['hi'], present: []}
1904      dictlist = #{absent: [], present: []}
1905
1906      var dictdict: dict<dict<string>> = #{one: #{a: 'text'}, two: #{}}
1907      dictdict = #{one: #{}, two: #{a: 'text'}}
1908      dictdict = #{one: #{}, two: #{}}
1909
1910      assert_equal({'': 0}, {matchstr('string', 'wont match'): 0})
1911  END
1912  CheckDefAndScriptSuccess(lines)
1913
1914  CheckDefFailure(["var x = #{a:8}"], 'E1069:', 1)
1915  CheckDefFailure(["var x = #{a : 8}"], 'E1068:', 1)
1916  CheckDefFailure(["var x = #{a :8}"], 'E1068:', 1)
1917  CheckDefFailure(["var x = #{a: 8 , b: 9}"], 'E1068:', 1)
1918  CheckDefFailure(["var x = #{a: 1,b: 2}"], 'E1069:', 1)
1919
1920  CheckDefFailure(["var x = #{8: 8}"], 'E1014:', 1)
1921  CheckDefFailure(["var x = #{xxx}"], 'E720:', 1)
1922  CheckDefFailure(["var x = #{xxx: 1", "var y = 2"], 'E722:', 2)
1923  CheckDefFailure(["var x = #{xxx: 1,"], 'E723:', 2)
1924  CheckDefFailure(["var x = {'a': xxx}"], 'E1001:', 1)
1925  CheckDefFailure(["var x = {xxx: 8}"], 'E1001:', 1)
1926  CheckDefFailure(["var x = #{a: 1, a: 2}"], 'E721:', 1)
1927  CheckDefFailure(["var x = #"], 'E1015:', 1)
1928  CheckDefExecFailure(["var x = g:anint.member"], 'E715:', 1)
1929  CheckDefExecFailure(["var x = g:dict_empty.member"], 'E716:', 1)
1930
1931  CheckDefExecFailure(['var x: dict<number> = #{a: 234, b: "1"}'], 'E1012:', 1)
1932  CheckDefExecFailure(['var x: dict<number> = #{a: "x", b: 134}'], 'E1012:', 1)
1933  CheckDefExecFailure(['var x: dict<string> = #{a: 234, b: "1"}'], 'E1012:', 1)
1934  CheckDefExecFailure(['var x: dict<string> = #{a: "x", b: 134}'], 'E1012:', 1)
1935
1936  CheckDefFailure(['var x = ({'], 'E723:', 2)
1937  CheckDefExecFailure(['{}[getftype("")]'], 'E716: Key not present in Dictionary: ""', 1)
1938enddef
1939
1940def Test_expr7_dict_vim9script()
1941  var lines =<< trim END
1942      vim9script
1943      var d = {
1944		'one':
1945		   1,
1946		'two': 2,
1947		   }
1948      assert_equal({'one': 1, 'two': 2}, d)
1949
1950      d = {  # comment
1951		'one':
1952                # comment
1953
1954		   1,
1955                # comment
1956                # comment
1957		'two': 2,
1958		   }
1959      assert_equal({'one': 1, 'two': 2}, d)
1960  END
1961  CheckScriptSuccess(lines)
1962
1963  lines =<< trim END
1964      vim9script
1965      var d = { "one": "one", "two": "two", }
1966      assert_equal({'one': 'one', 'two': 'two'}, d)
1967  END
1968  CheckScriptSuccess(lines)
1969
1970  lines =<< trim END
1971      vim9script
1972      var d = #{one: 1,
1973		two: 2,
1974	       }
1975      assert_equal({'one': 1, 'two': 2}, d)
1976  END
1977  CheckScriptSuccess(lines)
1978
1979  lines =<< trim END
1980      vim9script
1981      var d = #{one:1, two: 2}
1982  END
1983  CheckScriptFailure(lines, 'E1069:', 2)
1984
1985  lines =<< trim END
1986      vim9script
1987      var d = #{one: 1,two: 2}
1988  END
1989  CheckScriptFailure(lines, 'E1069:', 2)
1990
1991  lines =<< trim END
1992      vim9script
1993      var d = #{one : 1}
1994  END
1995  CheckScriptFailure(lines, 'E1068:', 2)
1996
1997  lines =<< trim END
1998      vim9script
1999      var d = #{one:1}
2000  END
2001  CheckScriptFailure(lines, 'E1069:', 2)
2002
2003  lines =<< trim END
2004      vim9script
2005      var d = #{one: 1 , two: 2}
2006  END
2007  CheckScriptFailure(lines, 'E1068:', 2)
2008
2009  lines =<< trim END
2010    vim9script
2011    var l: dict<number> = #{a: 234, b: 'x'}
2012  END
2013  CheckScriptFailure(lines, 'E1012:', 2)
2014  lines =<< trim END
2015    vim9script
2016    var l: dict<number> = #{a: 'x', b: 234}
2017  END
2018  CheckScriptFailure(lines, 'E1012:', 2)
2019  lines =<< trim END
2020    vim9script
2021    var l: dict<string> = #{a: 'x', b: 234}
2022  END
2023  CheckScriptFailure(lines, 'E1012:', 2)
2024  lines =<< trim END
2025    vim9script
2026    var l: dict<string> = #{a: 234, b: 'x'}
2027  END
2028  CheckScriptFailure(lines, 'E1012:', 2)
2029
2030  lines =<< trim END
2031      vim9script
2032      def Failing()
2033        job_stop()
2034      enddef
2035      var dict = #{name: Failing}
2036  END
2037  if has('channel')
2038    CheckScriptFailure(lines, 'E119:', 1)
2039  else
2040    CheckScriptFailure(lines, 'E117:', 1)
2041  endif
2042enddef
2043
2044let g:oneString = 'one'
2045
2046def Test_expr_member()
2047  assert_equal(1, g:dict_one.one)
2048  var d: dict<number> = g:dict_one
2049  assert_equal(1, d['one'])
2050  assert_equal(1, d[
2051		  'one'
2052		  ])
2053  assert_equal(1, d
2054  	.one)
2055  d = {'1': 1, '_': 2}
2056  assert_equal(1, d
2057  	.1)
2058  assert_equal(2, d
2059  	._)
2060
2061  # getting the one member should clear the dict after getting the item
2062  assert_equal('one', #{one: 'one'}.one)
2063  assert_equal('one', #{one: 'one'}[g:oneString])
2064
2065  CheckDefFailure(["var x = g:dict_one.#$!"], 'E1002:', 1)
2066  CheckDefExecFailure(["var d: dict<any>", "echo d['a']"], 'E716:', 2)
2067  CheckDefExecFailure(["var d: dict<number>", "d = g:list_empty"], 'E1012: Type mismatch; expected dict<number> but got list<unknown>', 2)
2068enddef
2069
2070def Test_expr7_any_index_slice()
2071  var lines =<< trim END
2072    # getting the one member should clear the list only after getting the item
2073    assert_equal('bbb', ['aaa', 'bbb', 'ccc'][1])
2074
2075    # string is permissive, index out of range accepted
2076    g:teststring = 'abcdef'
2077    assert_equal('b', g:teststring[1])
2078    assert_equal('', g:teststring[-1])
2079    assert_equal('', g:teststring[99])
2080
2081    assert_equal('b', g:teststring[1:1])
2082    assert_equal('bcdef', g:teststring[1:])
2083    assert_equal('abcd', g:teststring[:3])
2084    assert_equal('cdef', g:teststring[-4:])
2085    assert_equal('abcdef', g:teststring[-9:])
2086    assert_equal('abcd', g:teststring[:-3])
2087    assert_equal('', g:teststring[:-9])
2088
2089    # blob index cannot be out of range
2090    g:testblob = 0z01ab
2091    assert_equal(0x01, g:testblob[0])
2092    assert_equal(0xab, g:testblob[1])
2093    assert_equal(0xab, g:testblob[-1])
2094    assert_equal(0x01, g:testblob[-2])
2095
2096    # blob slice accepts out of range
2097    assert_equal(0z01ab, g:testblob[0:1])
2098    assert_equal(0z01, g:testblob[0:0])
2099    assert_equal(0z01, g:testblob[-2:-2])
2100    assert_equal(0zab, g:testblob[1:1])
2101    assert_equal(0zab, g:testblob[-1:-1])
2102    assert_equal(0z, g:testblob[2:2])
2103    assert_equal(0z, g:testblob[0:-3])
2104
2105    # list index cannot be out of range
2106    g:testlist = [0, 1, 2, 3]
2107    assert_equal(0, g:testlist[0])
2108    assert_equal(1, g:testlist[1])
2109    assert_equal(3, g:testlist[3])
2110    assert_equal(3, g:testlist[-1])
2111    assert_equal(0, g:testlist[-4])
2112    assert_equal(1, g:testlist[g:theone])
2113
2114    # list slice accepts out of range
2115    assert_equal([0], g:testlist[0:0])
2116    assert_equal([3], g:testlist[3:3])
2117    assert_equal([0, 1], g:testlist[0:1])
2118    assert_equal([0, 1, 2, 3], g:testlist[0:3])
2119    assert_equal([0, 1, 2, 3], g:testlist[0:9])
2120    assert_equal([], g:testlist[-1:1])
2121    assert_equal([1], g:testlist[-3:1])
2122    assert_equal([0, 1], g:testlist[-4:1])
2123    assert_equal([0, 1], g:testlist[-9:1])
2124    assert_equal([1, 2, 3], g:testlist[1:-1])
2125    assert_equal([1], g:testlist[1:-3])
2126    assert_equal([], g:testlist[1:-4])
2127    assert_equal([], g:testlist[1:-9])
2128
2129    g:testdict = #{a: 1, b: 2}
2130    assert_equal(1, g:testdict['a'])
2131    assert_equal(2, g:testdict['b'])
2132  END
2133
2134  CheckDefSuccess(lines)
2135  CheckScriptSuccess(['vim9script'] + lines)
2136
2137  CheckDefExecFailure(['echo g:testblob[2]'], 'E979:', 1)
2138  CheckScriptFailure(['vim9script', 'echo g:testblob[2]'], 'E979:', 2)
2139  CheckDefExecFailure(['echo g:testblob[-3]'], 'E979:', 1)
2140  CheckScriptFailure(['vim9script', 'echo g:testblob[-3]'], 'E979:', 2)
2141
2142  CheckDefExecFailure(['echo g:testlist[4]'], 'E684:', 1)
2143  CheckScriptFailure(['vim9script', 'echo g:testlist[4]'], 'E684:', 2)
2144  CheckDefExecFailure(['echo g:testlist[-5]'], 'E684:', 1)
2145  CheckScriptFailure(['vim9script', 'echo g:testlist[-5]'], 'E684:', 2)
2146
2147  CheckDefExecFailure(['echo g:testdict["a":"b"]'], 'E719:', 1)
2148  CheckScriptFailure(['vim9script', 'echo g:testdict["a":"b"]'], 'E719:', 2)
2149  CheckDefExecFailure(['echo g:testdict[1]'], 'E716:', 1)
2150  CheckScriptFailure(['vim9script', 'echo g:testdict[1]'], 'E716:', 2)
2151
2152  unlet g:teststring
2153  unlet g:testblob
2154  unlet g:testlist
2155enddef
2156
2157def Test_expr_member_vim9script()
2158  var lines =<< trim END
2159      vim9script
2160      var d = #{one:
2161      		'one',
2162		two: 'two',
2163		1: 1,
2164		_: 2}
2165      assert_equal('one', d.one)
2166      assert_equal('one', d
2167                            .one)
2168      assert_equal(1, d
2169                            .1)
2170      assert_equal(2, d
2171                            ._)
2172      assert_equal('one', d[
2173			    'one'
2174			    ])
2175  END
2176  CheckScriptSuccess(lines)
2177
2178  lines =<< trim END
2179      vim9script
2180      var l = [1,
2181		  2,
2182		  3, 4
2183		  ]
2184      assert_equal(2, l[
2185			    1
2186			    ])
2187      assert_equal([2, 3], l[1 : 2])
2188      assert_equal([1, 2, 3], l[
2189				:
2190				2
2191				])
2192      assert_equal([3, 4], l[
2193				2
2194				:
2195				])
2196  END
2197  CheckScriptSuccess(lines)
2198enddef
2199
2200def Test_expr7_option()
2201  # option
2202  set ts=11
2203  assert_equal(11, &ts)
2204  &ts = 9
2205  assert_equal(9, &ts)
2206  set ts=8
2207  set grepprg=some\ text
2208  assert_equal('some text', &grepprg)
2209  &grepprg = test_null_string()
2210  assert_equal('', &grepprg)
2211  set grepprg&
2212enddef
2213
2214def Test_expr7_environment()
2215  # environment variable
2216  assert_equal('testvar', $TESTVAR)
2217  assert_equal('', $ASDF_ASD_XXX)
2218
2219  CheckDefFailure(["var x = $$$"], 'E1002:', 1)
2220enddef
2221
2222def Test_expr7_register()
2223  @a = 'register a'
2224  assert_equal('register a', @a)
2225
2226  var fname = expand('%')
2227  assert_equal(fname, @%)
2228
2229  feedkeys(":echo 'some'\<CR>", "xt")
2230  assert_equal("echo 'some'", @:)
2231
2232  normal axyz
2233  assert_equal("xyz", @.)
2234  CheckDefFailure(["@. = 'yes'"], 'E354:', 1)
2235
2236  @/ = 'slash'
2237  assert_equal('slash', @/)
2238
2239  @= = 'equal'
2240  assert_equal('equal', @=)
2241enddef
2242
2243def Test_expr7_namespace()
2244  g:some_var = 'some'
2245  assert_equal('some', get(g:, 'some_var'))
2246  assert_equal('some', get(g:, 'some_var', 'xxx'))
2247  assert_equal('xxx', get(g:, 'no_var', 'xxx'))
2248  unlet g:some_var
2249
2250  b:some_var = 'some'
2251  assert_equal('some', get(b:, 'some_var'))
2252  assert_equal('some', get(b:, 'some_var', 'xxx'))
2253  assert_equal('xxx', get(b:, 'no_var', 'xxx'))
2254  unlet b:some_var
2255
2256  w:some_var = 'some'
2257  assert_equal('some', get(w:, 'some_var'))
2258  assert_equal('some', get(w:, 'some_var', 'xxx'))
2259  assert_equal('xxx', get(w:, 'no_var', 'xxx'))
2260  unlet w:some_var
2261
2262  t:some_var = 'some'
2263  assert_equal('some', get(t:, 'some_var'))
2264  assert_equal('some', get(t:, 'some_var', 'xxx'))
2265  assert_equal('xxx', get(t:, 'no_var', 'xxx'))
2266  unlet t:some_var
2267enddef
2268
2269def Test_expr7_parens()
2270  # (expr)
2271  assert_equal(4, (6 * 4) / 6)
2272  assert_equal(0, 6 * ( 4 / 6 ))
2273
2274  assert_equal(6, +6)
2275  assert_equal(-6, -6)
2276  assert_equal(6, --6)
2277  assert_equal(6, -+-6)
2278  assert_equal(-6, ---6)
2279  assert_equal(false, !-3)
2280  assert_equal(true, !+-+0)
2281enddef
2282
2283def Test_expr7_parens_vim9script()
2284  var lines =<< trim END
2285      vim9script
2286      var s = (
2287		'one'
2288		..
2289		'two'
2290		)
2291      assert_equal('onetwo', s)
2292  END
2293  CheckScriptSuccess(lines)
2294enddef
2295
2296def Test_expr7_negate()
2297  assert_equal(-99, -99)
2298  assert_equal(99, --99)
2299  var nr = 88
2300  assert_equal(-88, -nr)
2301  assert_equal(88, --nr)
2302enddef
2303
2304def Echo(arg: any): string
2305  return arg
2306enddef
2307
2308def s:Echo4Arg(arg: any): string
2309  return arg
2310enddef
2311
2312def Test_expr7_call()
2313  var lines =<< trim END
2314      assert_equal('yes', 'yes'->Echo())
2315      assert_equal(true, !range(5)->empty())
2316      assert_equal([0, 1, 2], --3->range())
2317  END
2318  CheckDefAndScriptSuccess(lines)
2319
2320  assert_equal('yes', 'yes'
2321                        ->s:Echo4Arg())
2322
2323  CheckDefFailure(["var x = 'yes'->Echo"], 'E107:', 1)
2324  CheckScriptFailure([
2325   "vim9script",
2326   "var x = substitute ('x', 'x', 'x', 'x')"
2327   ], 'E121:', 2)
2328  CheckDefFailure(["var Ref = function('len' [1, 2])"], 'E1123:', 1)
2329
2330  var auto_lines =<< trim END
2331      def g:some#func(): string
2332	return 'found'
2333      enddef
2334  END
2335  mkdir('Xruntime/autoload', 'p')
2336  writefile(auto_lines, 'Xruntime/autoload/some.vim')
2337  var save_rtp = &rtp
2338  &rtp = getcwd() .. '/Xruntime,' .. &rtp
2339  assert_equal('found', g:some#func())
2340  assert_equal('found', some#func())
2341
2342  &rtp = save_rtp
2343  delete('Xruntime', 'rf')
2344enddef
2345
2346
2347def Test_expr7_not()
2348  var lines =<< trim END
2349      assert_equal(true, !'')
2350      assert_equal(true, ![])
2351      assert_equal(false, !'asdf')
2352      assert_equal(false, ![2])
2353      assert_equal(true, !!'asdf')
2354      assert_equal(true, !![2])
2355
2356      assert_equal(true, ! false)
2357      assert_equal(true, !! true)
2358      assert_equal(true, ! ! true)
2359      assert_equal(true, !!! false)
2360      assert_equal(true, ! ! ! false)
2361
2362      g:true = true
2363      g:false = false
2364      assert_equal(true, ! g:false)
2365      assert_equal(true, !! g:true)
2366      assert_equal(true, ! ! g:true)
2367      assert_equal(true, !!! g:false)
2368      assert_equal(true, ! ! ! g:false)
2369      unlet g:true
2370      unlet g:false
2371
2372      assert_equal(true, !test_null_partial())
2373      assert_equal(false, !{-> 'yes'})
2374
2375      assert_equal(true, !test_null_dict())
2376      assert_equal(true, !{})
2377      assert_equal(false, !{'yes': 'no'})
2378
2379      if has('channel')
2380	assert_equal(true, !test_null_job())
2381	assert_equal(true, !test_null_channel())
2382      endif
2383
2384      assert_equal(true, !test_null_blob())
2385      assert_equal(true, !0z)
2386      assert_equal(false, !0z01)
2387
2388      assert_equal(true, !test_void())
2389      assert_equal(true, !test_unknown())
2390
2391      assert_equal(false, ![1, 2, 3]->reverse())
2392      assert_equal(true, ![]->reverse())
2393  END
2394  CheckDefAndScriptSuccess(lines)
2395enddef
2396
2397func Test_expr7_fails()
2398  call CheckDefFailure(["var x = (12"], "E110:", 1)
2399
2400  call CheckDefFailure(["var x = -'xx'"], "E1030:", 1)
2401  call CheckDefFailure(["var x = +'xx'"], "E1030:", 1)
2402  call CheckDefFailure(["var x = -0z12"], "E974:", 1)
2403  call CheckDefExecFailure(["var x = -[8]"], "E39:", 1)
2404  call CheckDefExecFailure(["var x = -{'a': 1}"], "E39:", 1)
2405
2406  call CheckDefFailure(["var x = @"], "E1002:", 1)
2407  call CheckDefFailure(["var x = @<"], "E354:", 1)
2408
2409  call CheckDefFailure(["var x = [1, 2"], "E697:", 2)
2410  call CheckDefFailure(["var x = [notfound]"], "E1001:", 1)
2411
2412  call CheckDefFailure(["var x = { -> 123) }"], "E451:", 1)
2413  call CheckDefFailure(["var x = 123->{x -> x + 5) }"], "E451:", 1)
2414
2415  call CheckDefFailure(["var x = &notexist"], 'E113:', 1)
2416  call CheckDefFailure(["&grepprg = [343]"], 'E1012:', 1)
2417
2418  call CheckDefExecFailure(["echo s:doesnt_exist"], 'E121:', 1)
2419  call CheckDefExecFailure(["echo g:doesnt_exist"], 'E121:', 1)
2420
2421  call CheckDefFailure(["echo a:somevar"], 'E1075:', 1)
2422  call CheckDefFailure(["echo l:somevar"], 'E1075:', 1)
2423  call CheckDefFailure(["echo x:somevar"], 'E1075:', 1)
2424
2425  call CheckDefExecFailure(["var x = +g:astring"], 'E1030:', 1)
2426  call CheckDefExecFailure(["var x = +g:ablob"], 'E974:', 1)
2427  call CheckDefExecFailure(["var x = +g:alist"], 'E745:', 1)
2428  call CheckDefExecFailure(["var x = +g:adict"], 'E728:', 1)
2429
2430  call CheckDefFailure(["var x = ''", "var y = x.memb"], 'E715:', 2)
2431
2432  call CheckDefFailure(["'yes'->", "Echo()"], 'E488: Trailing characters: ->', 1)
2433
2434  call CheckDefExecFailure(["[1, 2->len()"], 'E697:', 2)
2435  call CheckDefExecFailure(["#{a: 1->len()"], 'E722:', 1)
2436  call CheckDefExecFailure(["{'a': 1->len()"], 'E723:', 2)
2437endfunc
2438
2439let g:Funcrefs = [function('add')]
2440
2441func CallMe(arg)
2442  return a:arg
2443endfunc
2444
2445func CallMe2(one, two)
2446  return a:one .. a:two
2447endfunc
2448
2449def Test_expr7_trailing()
2450  # user function call
2451  assert_equal(123, g:CallMe(123))
2452  assert_equal(123, g:CallMe(  123))
2453  assert_equal(123, g:CallMe(123  ))
2454  assert_equal('yesno', g:CallMe2('yes', 'no'))
2455  assert_equal('yesno', g:CallMe2( 'yes', 'no' ))
2456  assert_equal('nothing', g:CallMe('nothing'))
2457
2458  # partial call
2459  var Part = function('g:CallMe')
2460  assert_equal('yes', Part('yes'))
2461
2462  # funcref call, using list index
2463  var l = []
2464  g:Funcrefs[0](l, 2)
2465  assert_equal([2], l)
2466
2467  # method call
2468  l = [2, 5, 6]
2469  l->map({k, v -> k + v})
2470  assert_equal([2, 6, 8], l)
2471
2472  # lambda method call
2473  l = [2, 5]
2474  l->{l -> add(l, 8)}()
2475  assert_equal([2, 5, 8], l)
2476
2477  # dict member
2478  var d = #{key: 123}
2479  assert_equal(123, d.key)
2480enddef
2481
2482def Test_expr7_string_subscript()
2483  var lines =<< trim END
2484    var text = 'abcdef'
2485    assert_equal('', text[-1])
2486    assert_equal('a', text[0])
2487    assert_equal('e', text[4])
2488    assert_equal('f', text[5])
2489    assert_equal('', text[6])
2490
2491    text = 'ábçdëf'
2492    assert_equal('', text[-999])
2493    assert_equal('', text[-1])
2494    assert_equal('á', text[0])
2495    assert_equal('b', text[1])
2496    assert_equal('ç', text[2])
2497    assert_equal('d', text[3])
2498    assert_equal('ë', text[4])
2499    assert_equal('f', text[5])
2500    assert_equal('', text[6])
2501    assert_equal('', text[999])
2502
2503    assert_equal('ábçdëf', text[0:-1])
2504    assert_equal('ábçdëf', text[0 :-1])
2505    assert_equal('ábçdëf', text[0: -1])
2506    assert_equal('ábçdëf', text[0 : -1])
2507    assert_equal('ábçdëf', text[0
2508                  :-1])
2509    assert_equal('ábçdëf', text[0:
2510                  -1])
2511    assert_equal('ábçdëf', text[0 : -1
2512                  ])
2513    assert_equal('bçdëf', text[1:-1])
2514    assert_equal('çdëf', text[2:-1])
2515    assert_equal('dëf', text[3:-1])
2516    assert_equal('ëf', text[4:-1])
2517    assert_equal('f', text[5:-1])
2518    assert_equal('', text[6:-1])
2519    assert_equal('', text[999:-1])
2520
2521    assert_equal('ábçd', text[:3])
2522    assert_equal('bçdëf', text[1:])
2523    assert_equal('ábçdëf', text[:])
2524  END
2525  CheckDefSuccess(lines)
2526  CheckScriptSuccess(['vim9script'] + lines)
2527enddef
2528
2529def Test_expr7_list_subscript()
2530  var lines =<< trim END
2531    var list = [0, 1, 2, 3, 4]
2532    assert_equal(0, list[0])
2533    assert_equal(4, list[4])
2534    assert_equal(4, list[-1])
2535    assert_equal(0, list[-5])
2536
2537    assert_equal([0, 1, 2, 3, 4], list[0:4])
2538    assert_equal([0, 1, 2, 3, 4], list[:])
2539    assert_equal([1, 2, 3, 4], list[1:])
2540    assert_equal([2, 3, 4], list[2:-1])
2541    assert_equal([4], list[4:-1])
2542    assert_equal([], list[5:-1])
2543    assert_equal([], list[999:-1])
2544    assert_equal([1, 2, 3, 4], list[g:theone:g:thefour])
2545
2546    assert_equal([0, 1, 2, 3], list[0:3])
2547    assert_equal([0], list[0:0])
2548    assert_equal([0, 1, 2, 3, 4], list[0:-1])
2549    assert_equal([0, 1, 2], list[0:-3])
2550    assert_equal([0], list[0:-5])
2551    assert_equal([], list[0:-6])
2552    assert_equal([], list[0:-99])
2553  END
2554  CheckDefSuccess(lines)
2555  CheckScriptSuccess(['vim9script'] + lines)
2556
2557  lines = ['var l = [0, 1, 2]', 'echo l[g:astring : g:theone]']
2558  CheckDefExecFailure(lines, 'E1012:')
2559  CheckScriptFailure(['vim9script'] + lines, 'E1030:', 3)
2560enddef
2561
2562def Test_expr7_dict_subscript()
2563  var lines =<< trim END
2564      vim9script
2565      var l = [#{lnum: 2}, #{lnum: 1}]
2566      var res = l[0].lnum > l[1].lnum
2567      assert_true(res)
2568  END
2569  CheckScriptSuccess(lines)
2570enddef
2571
2572def Test_expr7_subscript_linebreak()
2573  var range = range(
2574  		3)
2575  var l = range
2576	->map('string(v:key)')
2577  assert_equal(['0', '1', '2'], l)
2578
2579  l = range
2580  	->map('string(v:key)')
2581  assert_equal(['0', '1', '2'], l)
2582
2583  l = range # comment
2584  	->map('string(v:key)')
2585  assert_equal(['0', '1', '2'], l)
2586
2587  l = range
2588
2589  	->map('string(v:key)')
2590  assert_equal(['0', '1', '2'], l)
2591
2592  l = range
2593	# comment
2594  	->map('string(v:key)')
2595  assert_equal(['0', '1', '2'], l)
2596
2597  assert_equal('1', l[
2598	1])
2599
2600  var d = #{one: 33}
2601  assert_equal(33, d.
2602	one)
2603enddef
2604
2605def Test_expr7_method_call()
2606  new
2607  setline(1, ['first', 'last'])
2608  'second'->append(1)
2609  "third"->append(2)
2610  assert_equal(['first', 'second', 'third', 'last'], getline(1, '$'))
2611  bwipe!
2612
2613  var bufnr = bufnr()
2614  var loclist = [#{bufnr: bufnr, lnum: 42, col: 17, text: 'wrong'}]
2615  loclist->setloclist(0)
2616  assert_equal([#{bufnr: bufnr,
2617  		lnum: 42,
2618		col: 17,
2619		text: 'wrong',
2620		pattern: '',
2621		valid: 1,
2622		vcol: 0,
2623		nr: 0,
2624		type: '',
2625		module: ''}
2626		], getloclist(0))
2627
2628  var result: bool = get(#{n: 0}, 'n', 0)
2629  assert_equal(false, result)
2630enddef
2631
2632func Test_expr7_trailing_fails()
2633  call CheckDefFailure(['var l = [2]', 'l->{l -> add(l, 8)}'], 'E107:', 2)
2634  call CheckDefFailure(['var l = [2]', 'l->{l -> add(l, 8)} ()'], 'E274:', 2)
2635endfunc
2636
2637func Test_expr_fails()
2638  call CheckDefFailure(["var x = '1'is2"], 'E488:', 1)
2639  call CheckDefFailure(["var x = '1'isnot2"], 'E488:', 1)
2640
2641  call CheckDefFailure(["CallMe ('yes')"], 'E476:', 1)
2642  call CheckScriptFailure(["CallMe ('yes')"], 'E492:', 1)
2643  call CheckDefAndScriptFailure(["CallMe2('yes','no')"], 'E1069:', 1)
2644  call CheckDefFailure(["CallMe2('yes' , 'no')"], 'E1068:', 1)
2645
2646  call CheckDefFailure(["v:nosuch += 3"], 'E1001:', 1)
2647  call CheckDefFailure(["var v:statusmsg = ''"], 'E1016: Cannot declare a v: variable:', 1)
2648  call CheckDefFailure(["var asdf = v:nosuch"], 'E1001:', 1)
2649
2650  call CheckDefFailure(["echo len('asdf'"], 'E110:', 2)
2651  call CheckDefFailure(["echo Func0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789()"], 'E1011:', 1)
2652  call CheckDefFailure(["echo doesnotexist()"], 'E117:', 1)
2653endfunc
2654
2655" vim: shiftwidth=2 sts=2 expandtab
2656