blob: fce52925c3a29542be16d8ee65ad9a69c485bbd7 [file] [log] [blame]
Yegappan Lakshmanan9cb865e2025-03-23 16:42:16 +01001" Tests for the Tuple types
2
3import './vim9.vim' as v9
4
5func TearDown()
6 " Run garbage collection after every test
7 call test_garbagecollect_now()
8endfunc
9
10" Tuple declaration
11func Test_tuple_declaration()
12 let lines =<< trim END
13 var Fn = function('min')
14 var t = (1, 'a', true, 3.1, 0z10, ['x'], {'a': []}, Fn)
15 assert_equal((1, 'a', true, 3.1, 0z10, ['x'], {'a': []}, Fn), t)
16 END
17 call v9.CheckSourceDefAndScriptSuccess(lines)
18
19 " Multiline tuple declaration
20 let lines =<< trim END
21 var t = (
22 'a',
23 'b',
24 )
25 assert_equal(('a', 'b'), t)
26 END
27 call v9.CheckSourceDefAndScriptSuccess(lines)
28
29 " Tuple declaration with comments
30 let lines =<< trim END
31 var t = ( # xxx
32 # xxx
33 'a', # xxx
34 # xxx
35 'b', # xxx
36 ) # xxx
37 assert_equal(('a', 'b'), t)
38 END
39 call v9.CheckSourceDefAndScriptSuccess(lines)
40
41 " Tuple declaration separated by '|'
42 let lines =<< trim END
43 VAR t1 = ('a', 'b') | VAR t2 = ('c', 'd')
44 call assert_equal(('a', 'b'), t1)
45 call assert_equal(('c', 'd'), t2)
46 END
47 call v9.CheckSourceLegacyAndVim9Success(lines)
48
49 " Space after and before parens
50 let lines =<< trim END
51 var t = ( 1, 2 )
52 assert_equal((1, 2), t)
53 END
54 call v9.CheckSourceDefAndScriptSuccess(lines)
55endfunc
56
57" Tuple declaration error
58func Test_tuple_declaration_error()
59 let lines =<< trim END
60 var t: tuple<> = ('a', 'b')
61 END
62 call v9.CheckSourceDefAndScriptFailure(lines, "E1008: Missing <type> after > = ('a', 'b')")
63
64 let lines =<< trim END
65 var t: tuple = ('a', 'b')
66 END
67 call v9.CheckSourceDefAndScriptFailure(lines, "E1008: Missing <type> after tuple")
68
69 let lines =<< trim END
70 var t: tuple<number> = ('a','b')
71 END
72 call v9.CheckSourceDefAndScriptFailure(lines, "E1069: White space required after ',': ,'b')")
73
74 let lines =<< trim END
75 var t: tuple<number> = ('a', 'b','c')
76 END
77 call v9.CheckSourceDefAndScriptFailure(lines, "E1069: White space required after ',': ,'c')")
78
79 let lines =<< trim END
80 var t: tuple <number> = ()
81 END
82 call v9.CheckSourceDefAndScriptFailure(lines, "E1068: No white space allowed before '<'")
83
84 let lines =<< trim END
85 var t: tuple<number,string>
86 END
87 call v9.CheckSourceDefAndScriptFailure(lines, "E1069: White space required after ','")
88
89 let lines =<< trim END
90 var t: tuple<number , string>
91 END
92 call v9.CheckSourceDefFailure(lines, "E1068: No white space allowed before ','")
93
94 let lines =<< trim END
95 var t = ('a', 'b' , 'c')
96 END
97 call v9.CheckSourceDefAndScriptFailure(lines, [
98 \ "E1068: No white space allowed before ','",
99 \ "E1068: No white space allowed before ','"])
100
101 let lines =<< trim END
102 VAR t = ('a', 'b' 'c')
103 END
104 call v9.CheckSourceLegacyAndVim9Failure(lines, [
105 \ "E1527: Missing comma in Tuple: 'c')",
106 \ "E1527: Missing comma in Tuple: 'c')",
107 \ "E1527: Missing comma in Tuple: 'c')"])
108
109 let lines =<< trim END
110 VAR t = ('a', 'b',
111 END
112 call v9.CheckSourceLegacyAndVim9Failure(lines, [
113 \ "E1526: Missing end of Tuple ')'",
114 \ "E1526: Missing end of Tuple ')'",
115 \ "E1526: Missing end of Tuple ')'"])
116
117 let lines =<< trim END
118 var t: tuple<number, ...> = (1, 2, 3)
119 END
120 call v9.CheckSourceDefAndScriptFailure(lines, [
121 \ 'E1010: Type not recognized: ',
122 \ 'E1010: Type not recognized: '])
123
124 let lines =<< trim END
125 var t: tuple<number, ...number> = (1, 2, 3)
126 END
127 call v9.CheckSourceDefAndScriptFailure(lines, [
128 \ 'E1539: Variadic tuple must end with a list type: number',
129 \ 'E1539: Variadic tuple must end with a list type: number'])
130
131 " Invalid expression in the tuple
132 let lines =<< trim END
133 def Foo()
134 var t = (1, 1*2, 2)
135 enddef
136 defcompile
137 END
138 call v9.CheckSourceDefFailure(lines, 'E1004: White space required before and after ''*'' at "*2, 2)"')
139
140 let lines =<< trim END
141 VAR t = ('a', , 'b',)
142 END
143 call v9.CheckSourceLegacyAndVim9Failure(lines, [
144 \ 'E15: Invalid expression: ", ''b'',)"',
145 \ "E1068: No white space allowed before ',': , 'b',)",
146 \ 'E15: Invalid expression: ", ''b'',)"'])
147
148 let lines =<< trim END
149 VAR t = ('a', 'b', ,)
150 END
151 call v9.CheckSourceLegacyAndVim9Failure(lines, [
152 \ 'E15: Invalid expression: ",)"',
153 \ "E1068: No white space allowed before ',': ,)",
154 \ 'E15: Invalid expression: ",)"'])
155
156 let lines =<< trim END
157 VAR t = (, 'a', 'b')
158 END
159 call v9.CheckSourceLegacyAndVim9Failure(lines, [
160 \ 'E15: Invalid expression: ", ''a'', ''b'')"',
161 \ "E1015: Name expected: , 'a', 'b')",
162 \ 'E15: Invalid expression: ", ''a'', ''b'')"'])
163
164 let lines =<< trim END
165 var t: tupel<number> = (1,)
166 END
167 call v9.CheckSourceDefAndScriptFailure(lines, 'E1010: Type not recognized: tupel<number>')
168
169 let lines =<< trim END
170 var t: tuple<number> = [1, 2]
171 END
172 call v9.CheckSourceDefAndScriptFailure(lines, 'E1012: Type mismatch; expected tuple<number> but got list<number>')
173endfunc
174
175" Test for indexing a tuple
176func Test_tuple_indexing()
177 let lines =<< trim END
178 VAR t = ('a', 'b', 'c')
179 call assert_equal(['a', 'b', 'c'], [t[0], t[1], t[2]])
180 call assert_equal(['c', 'b', 'a'], [t[-1], t[-2], t[-3]])
181 END
182 call v9.CheckSourceLegacyAndVim9Success(lines)
183
184 " Indexing a tuple passed as a function argument
185 let lines =<< trim END
186 vim9script
187 def Fn(t: any)
188 call assert_equal(['a', 'b', 'c'], [t[0], t[1], t[2]])
189 call assert_equal(['c', 'b', 'a'], [t[-1], t[-2], t[-3]])
190 enddef
191 Fn(('a', 'b', 'c'))
192 END
193 call v9.CheckSourceSuccess(lines)
194
195 let lines =<< trim END
196 var t: tuple<...list<number>> = (10, 20)
197 var x: number = t[0]
198 assert_equal(10, x)
199 END
200 call v9.CheckSourceDefAndScriptSuccess(lines)
201
202 let lines =<< trim END
203 var t: tuple<...list<list<number>>> = ([1, 2], [3, 4])
204 t[0][1] = 5
205 assert_equal(([1, 5], [3, 4]), t)
206 END
207 call v9.CheckSourceDefAndScriptSuccess(lines)
208
209 let lines =<< trim END
210 var t: tuple<list<number>> = ([2, 4],)
211 t[0][1] = 6
212 assert_equal(([2, 6],), t)
213 END
214 call v9.CheckSourceDefAndScriptSuccess(lines)
215endfunc
216
217" Indexing a tuple in a Dict
218func Test_tuple_in_a_dict_index()
219 let lines =<< trim END
220 vim9script
221 def Fn()
222 var d = {a: (1, 2)}
223 var x = d.a[0]
224 assert_equal('number', typename(x))
225 enddef
226 Fn()
227 END
228 call v9.CheckSourceSuccess(lines)
229endfunc
230
231func Test_tuple_index_error()
232 let lines =<< trim END
233 echo ('a', 'b', 'c')[3]
234 END
235 call v9.CheckSourceLegacyAndVim9Failure(lines, [
236 \ 'E1519: Tuple index out of range: 3',
237 \ 'E1519: Tuple index out of range: 3',
238 \ 'E1519: Tuple index out of range: 3'])
239
240 let lines =<< trim END
241 echo ('a', 'b', 'c')[-4]
242 END
243 call v9.CheckSourceLegacyAndVim9Failure(lines, [
244 \ 'E1519: Tuple index out of range: -4',
245 \ 'E1519: Tuple index out of range: -4',
246 \ 'E1519: Tuple index out of range: -4'])
247
248 let lines =<< trim END
249 vim9script
250 def Fn(t: any)
251 echo t[3]
252 enddef
253 Fn(('a', 'b', 'c'))
254 END
255 call v9.CheckSourceFailure(lines, 'E1519: Tuple index out of range: 3')
256
257 let lines =<< trim END
258 vim9script
259 def Fn(t: any)
260 echo t[-4]
261 enddef
262 Fn(('a', 'b', 'c'))
263 END
264 call v9.CheckSourceFailure(lines, 'E1519: Tuple index out of range: -4')
265
266 let lines =<< trim END
267 vim9script
268 def Fn(t: any)
269 var x = t[0]
270 enddef
271 Fn(())
272 END
273 call v9.CheckSourceFailure(lines, 'E1519: Tuple index out of range: 0')
274
275 " Index a null tuple
276 let lines =<< trim END
277 VAR t = test_null_tuple()
278 LET t[0][0] = 10
279 END
280 call v9.CheckSourceLegacyAndVim9Failure(lines, [
281 \ 'E1519: Tuple index out of range: 0',
282 \ 'E1519: Tuple index out of range: 0',
283 \ 'E1519: Tuple index out of range: 0'])
284
285 let lines =<< trim END
286 var x = null_tuple
287 x[0][0] = 10
288 END
289 call v9.CheckSourceDefExecAndScriptFailure(lines, [
290 \ 'E1519: Tuple index out of range: 0',
291 \ 'E1519: Tuple index out of range: 0'])
292
293 " Use a float as the index
294 let lines =<< trim END
295 VAR t = (1, 2)
296 VAR x = t[0.1]
297 END
298 call v9.CheckSourceLegacyAndVim9Failure(lines, [
299 \ 'E805: Using a Float as a Number',
300 \ 'E1012: Type mismatch; expected number but got float',
301 \ 'E805: Using a Float as a Number'])
302endfunc
303
304" Test for slicing a tuple
305func Test_tuple_slice()
306 let lines =<< trim END
307 VAR t = (1, 3, 5, 7, 9)
308 call assert_equal((3, 5), t[1 : 2])
309 call assert_equal((9,), t[4 : 4])
310 call assert_equal((7, 9), t[3 : 6])
311 call assert_equal((1, 3, 5), t[: 2])
312 call assert_equal((5, 7, 9), t[2 :])
313 call assert_equal((1, 3, 5, 7, 9), t[:])
314 call assert_equal((), test_null_tuple()[:])
315 END
316 call v9.CheckSourceLegacyAndVim9Success(lines)
317
318 let lines =<< trim END
319 call assert_equal(('b', 'c'), ('a', 'b', 'c')[1 : 5])
320 END
321 call v9.CheckSourceLegacyAndVim9Success(lines)
322endfunc
323
324" Test for concatenating tuples
325func Test_tuple_concatenate()
326 let lines =<< trim END
327 VAR t1 = ('a', 'b') + ('c', 'd')
328 call assert_equal(('a', 'b', 'c', 'd'), t1)
329
330 VAR t2 = ('a',) + ('b',)
331 call assert_equal(('a', 'b'), t2)
332
333 VAR t3 = ('a',) + ()
334 call assert_equal(('a',), t3)
335
336 VAR t4 = () + ('b',)
337 call assert_equal(('b',), t4)
338
339 VAR t5 = ('a', 'b') + test_null_tuple()
340 call assert_equal(('a', 'b'), t5)
341 call assert_equal('tuple<string, string>', typename(t5))
342
343 VAR t6 = test_null_tuple() + ('c', 'd')
344 call assert_equal(('c', 'd'), t6)
345 call assert_equal('tuple<string, string>', typename(t6))
346
347 VAR t7 = ('a', 'b') + (8, 9)
348 call assert_equal(('a', 'b', 8, 9), t7)
349 call assert_equal('tuple<string, string, number, number>', typename(t7))
350 END
351 call v9.CheckSourceLegacyAndVim9Success(lines)
352
353 let lines =<< trim END
354 var t1: tuple<...list<tuple<number, number>>> = ()
355 var t2: tuple<...list<tuple<number, number>>> = ()
356 var t: tuple<...list<tuple<number, number>>> = t1 + t2
357 assert_equal((), t)
358 END
359 call v9.CheckSourceDefAndScriptSuccess(lines)
360
361 let lines =<< trim END
362 var t: tuple<...list<number>> = (1, 2) + ('a', 'b')
363 END
364 call v9.CheckSourceDefExecAndScriptFailure(lines, [
365 \ 'E1012: Type mismatch; expected tuple<...list<number>> but got tuple<number, number, string, string>',
366 \ 'E1012: Type mismatch; expected tuple<...list<number>> but got tuple<number, number, string, string>'])
367
368 let lines =<< trim END
369 var a: tuple<...list<number>> = (1, 2)
370 var b: tuple<...list<string>> = ('a', 'b')
371 var t = a + b
372 END
373 call v9.CheckSourceDefExecAndScriptFailure(lines, [
374 \ 'E1540: Cannot use a variadic tuple in concatenation',
375 \ 'E1540: Cannot use a variadic tuple in concatenation'])
376
377 let lines =<< trim END
378 var a: tuple<...list<number>> = (1, 2)
379 var b: tuple<string, string> = ('a', 'b')
380 var t = a + b
381 END
382 call v9.CheckSourceDefExecAndScriptFailure(lines, [
383 \ 'E1540: Cannot use a variadic tuple in concatenation',
384 \ 'E1540: Cannot use a variadic tuple in concatenation'])
385
386 let lines =<< trim END
387 var a: tuple<number, ...list<string>> = (1, 'a', 'b')
388 var b: tuple<number, ...list<string>> = (2, 'c', 'd')
389 var t = a + b
390 END
391 call v9.CheckSourceDefExecAndScriptFailure(lines, [
392 \ 'E1540: Cannot use a variadic tuple in concatenation',
393 \ 'E1540: Cannot use a variadic tuple in concatenation'])
394
395 let lines =<< trim END
396 var a: tuple<number, ...list<string>> = (1, 'a', 'b')
397 var b: tuple<...list<string>> = ('c', 'd')
398 var t = a + b
399 END
400 call v9.CheckSourceDefExecAndScriptFailure(lines, [
401 \ 'E1540: Cannot use a variadic tuple in concatenation',
402 \ 'E1540: Cannot use a variadic tuple in concatenation'])
403
404 let lines =<< trim END
405 var a: tuple<...list<string>> = ('a', 'b')
406 var b: tuple<number, ...list<string>> = (2, 'c', 'd')
407 var t = a + b
408 END
409 call v9.CheckSourceDefExecAndScriptFailure(lines, [
410 \ 'E1540: Cannot use a variadic tuple in concatenation',
411 \ 'E1540: Cannot use a variadic tuple in concatenation'])
412
413 let lines =<< trim END
414 var t1: tuple<...list<tuple<number, number>>> = ()
415 var t2: tuple<...list<tuple<number, string>>> = ()
416 var t = t1 + t2
417 END
418 call v9.CheckSourceDefExecAndScriptFailure(lines, [
419 \ 'E1540: Cannot use a variadic tuple in concatenation',
420 \ 'E1540: Cannot use a variadic tuple in concatenation'])
421
422 " Make sure the correct line number is used in the error message
423 let lines =<< trim END
424 vim9script
425 var t1: tuple<...list<tuple<number, number>>> = ()
426 var t2: tuple<...list<tuple<number, string>>> = ()
427 var t = t1 + t2
428
429 END
430 call v9.CheckSourceFailure(lines, 'E1540: Cannot use a variadic tuple in concatenation', 4)
431
432 let lines =<< trim END
433 vim9script
434
435 def Fn()
436 var t1: tuple<...list<tuple<number, number>>> = ()
437 var t2: tuple<...list<tuple<number, string>>> = ()
438 var t = t1 + t2
439
440 enddef
441 Fn()
442 END
443 call v9.CheckSourceFailure(lines, 'E1540: Cannot use a variadic tuple in concatenation', 3)
444
445 " One or both the operands are variadic tuples
446 let lines =<< trim END
447 var a1: tuple<number, number> = (1, 2)
448 var b1: tuple<...list<string>> = ('a', 'b')
449 var t1 = a1 + b1
450 assert_equal((1, 2, 'a', 'b'), t1)
451
452 var a2: tuple<string, string> = ('a', 'b')
453 var b2: tuple<number, ...list<string>> = (1, 'c', 'd')
454 var t2 = a2 + b2
455 assert_equal(('a', 'b', 1, 'c', 'd'), t2)
456
457 var a3: tuple<...list<string>> = ('a', 'b')
458 var b3: tuple<...list<string>> = ('c', 'd')
459 var t3 = a3 + b3
460 assert_equal(('a', 'b', 'c', 'd'), t3)
461
462 var a4: tuple<...list<number>> = (1, 2)
463 var t4 = a4 + ()
464 assert_equal((1, 2), t4)
465
466 var b5: tuple<...list<number>> = (1, 2)
467 var t5 = () + b5
468 assert_equal((1, 2), t5)
469
470 var a6: tuple<...list<number>> = (1, 2)
471 var t6 = a6 + null_tuple
472 assert_equal((1, 2), t6)
473
474 var b7: tuple<...list<string>> = ('a', 'b')
475 var t7 = null_tuple + b7
476 assert_equal(('a', 'b'), t7)
477 END
478 call v9.CheckSourceDefAndScriptSuccess(lines)
479
480 let lines =<< trim END
481 VAR t = test_null_tuple() + test_null_tuple()
482 call assert_equal(test_null_tuple(), t)
483 END
484 call v9.CheckSourceLegacyAndVim9Success(lines)
485
486 let lines =<< trim END
487 vim9script
488 def Fn(x: any, y: any): any
489 return x + y
490 enddef
491 assert_equal((1, 2), Fn((1,), (2,)))
492 assert_equal((1, 'a'), Fn((1,), ('a',)))
493 assert_equal((1,), Fn((1,), null_tuple))
494 assert_equal(('a',), Fn(null_tuple, ('a',)))
495 assert_equal((), Fn(null_tuple, null_tuple))
496 END
497 call v9.CheckSourceScriptSuccess(lines)
498
499 " Test for concatenating to lists containing tuples
500 let lines =<< trim END
501 var x = [test_null_tuple()] + [test_null_tuple()]
502 assert_equal([(), ()], x)
503 var y = [()] + [()]
504 assert_equal([(), ()], y)
505 END
506 call v9.CheckSourceDefAndScriptSuccess(lines)
507endfunc
508
509" Test for comparing tuples
510func Test_tuple_compare()
511 let lines =<< trim END
512 call assert_false((1, 2) == (1, 3))
513 call assert_true((1, 2) == (1, 2))
514 call assert_true((1,) == (1,))
515 call assert_true(() == ())
516 call assert_false((1, 2) == (1, 2, 3))
517 call assert_false((1, 2) == test_null_tuple())
518 VAR t1 = (1, 2)
519 VAR t2 = t1
520 call assert_true(t1 == t2)
521 END
522 call v9.CheckSourceLegacyAndVim9Success(lines)
523
524 let lines =<< trim END
525 echo (1.0, ) == 1.0
526 END
527 call v9.CheckSourceLegacyAndVim9Failure(lines, [
528 \ 'E1517: Can only compare Tuple with Tuple',
529 \ 'E1072: Cannot compare tuple with float',
530 \ 'E1072: Cannot compare tuple with float'])
531
532 let lines =<< trim END
533 echo 1.0 == (1.0,)
534 END
535 call v9.CheckSourceLegacyAndVim9Failure(lines, [
536 \ 'E1517: Can only compare Tuple with Tuple',
537 \ 'E1072: Cannot compare float with tuple',
538 \ 'E1072: Cannot compare float with tuple'])
539
540 let lines =<< trim END
541 echo (1, 2) =~ []
542 END
543 call v9.CheckSourceLegacyAndVim9Failure(lines, [
544 \ 'E691: Can only compare List with List',
545 \ 'E1072: Cannot compare tuple with list',
546 \ 'E1072: Cannot compare tuple with list'])
547
548 let lines =<< trim END
549 echo (1, 2) =~ (1, 2)
550 END
551 call v9.CheckSourceLegacyAndVim9Failure(lines, [
552 \ 'E1518: Invalid operation for Tuple',
553 \ 'E1518: Invalid operation for Tuple',
554 \ 'E1518: Invalid operation for Tuple'])
555endfunc
556
557" Test for assigning multiple items from a tuple
558func Test_multi_assign_from_tuple()
559 let lines =<< trim END
560 VAR [v1, v2] = ('a', 'b')
561 call assert_equal(['a', 'b'], [v1, v2])
562
563 VAR [v3] = ('c',)
564 call assert_equal('c', v3)
565
566 VAR [v4; v5] = ('a', 'b', 'c')
567 call assert_equal('a', v4)
568 call assert_equal(('b', 'c'), v5)
569
570 VAR [v6; v7] = ('a',)
571 call assert_equal('a', v6)
572 call assert_equal((), v7)
573
574 VAR sum = 0
575 for [v8, v9] in ((2, 2), (2, 3))
576 LET sum += v8 * v9
577 endfor
578 call assert_equal(10, sum)
579
580 #" for: rest of the items in a List
581 LET sum = 0
582 for [v10; v11] in ((2, 1, 2, 5), (2, 1, 2, 10))
583 LET sum += v10 * max(v11)
584 endfor
585 call assert_equal(30, sum)
586
587 #" for: one item in the list
588 LET sum = 0
589 for [v12; v13] in ((2, 6), (2, 7))
590 LET sum += v12 * max(v13)
591 endfor
592 call assert_equal(26, sum)
593
594 #" for: zero items in the list
595 LET sum = 0
596 for [v14; v15] in ((4,), (5,))
597 LET sum += v14 + max(v15)
598 endfor
599 call assert_equal(9, sum)
600
601 #" A null tuple should be treated like an empty tuple
602 for [v16, v17] in test_null_tuple()
603 endfor
604 END
605 call v9.CheckSourceLegacyAndVim9Success(lines)
606
607 let lines =<< trim END
608 var t: tuple<...list<number>> = (4, 8)
609 var [x: number, y: number] = t
610 assert_equal([4, 8], [x, y])
611 END
612 call v9.CheckSourceDefAndScriptSuccess(lines)
613
614 " Test a mix lists and tuples with "any" type
615 let lines =<< trim END
616 vim9script
617 def Fn(x: any): string
618 var str = ''
619 for [a, b] in x
620 str ..= a .. b
621 endfor
622 return str
623 enddef
624 # List of lists
625 assert_equal('abcd', Fn([['a', 'b'], ['c', 'd']]))
626 # List of tuples
627 assert_equal('abcd', Fn([('a', 'b'), ('c', 'd')]))
628 # Tuple of lists
629 assert_equal('abcd', Fn((['a', 'b'], ['c', 'd'])))
630 # Tuple of tuples
631 assert_equal('abcd', Fn((('a', 'b'), ('c', 'd'))))
632 END
633 call v9.CheckSourceSuccess(lines)
634
635 let lines =<< trim END
636 VAR [v1, v2] = ('a', 'b', 'c')
637 END
638 call v9.CheckSourceLegacyAndVim9Failure(lines, [
639 \ 'E1537: Less targets than Tuple items',
640 \ 'E1093: Expected 2 items but got 3',
641 \ 'E1537: Less targets than Tuple items'])
642
643 let lines =<< trim END
644 VAR [v1, v2, v3] = ('a', 'b')
645 END
646 call v9.CheckSourceLegacyAndVim9Failure(lines, [
647 \ 'E1538: More targets than Tuple items',
648 \ 'E1093: Expected 3 items but got 2',
649 \ 'E1538: More targets than Tuple items'])
650
651 let lines =<< trim END
652 VAR [v1; v2] = test_null_tuple()
653 END
654 call v9.CheckSourceLegacyAndVim9Failure(lines, [
655 \ 'E1536: Tuple required',
656 \ 'E1093: Expected 1 items but got 0',
657 \ 'E1536: Tuple required'])
658
659 let lines =<< trim END
660 for [v1, v2] in (('a', 'b', 'c'),)
661 endfor
662 END
663 call v9.CheckSourceLegacyAndVim9Failure(lines, [
664 \ 'E1537: Less targets than Tuple items',
665 \ 'E1537: Less targets than Tuple items',
666 \ 'E1537: Less targets than Tuple items'])
667
668 let lines =<< trim END
669 for [v1, v2] in (('a',),)
670 endfor
671 END
672 call v9.CheckSourceLegacyAndVim9Failure(lines, [
673 \ 'E1538: More targets than Tuple items',
674 \ 'E1538: More targets than Tuple items',
675 \ 'E1538: More targets than Tuple items'])
676
677 let lines =<< trim END
678 for [v1, v2] in (test_null_tuple(),)
679 endfor
680 END
681 call v9.CheckSourceLegacyAndVim9Failure(lines, [
682 \ 'E1536: Tuple required',
683 \ 'E1538: More targets than Tuple items',
684 \ 'E1536: Tuple required'])
685
686 let lines =<< trim END
687 for [v1; v2] in (test_null_tuple(),)
688 endfor
689 END
690 call v9.CheckSourceLegacyAndVim9Failure(lines, [
691 \ 'E1536: Tuple required',
692 \ 'E1538: More targets than Tuple items',
693 \ 'E1536: Tuple required'])
694
695 " List assignment errors using a function tuple argument
696 let lines =<< trim END
697 vim9script
698 def Fn(x: tuple<...list<number>>)
699 var [a, b] = x
700 enddef
701 Fn((1, 2, 3))
702 END
703 call v9.CheckSourceFailure(lines, 'E1093: Expected 2 items but got 3')
704
705 let lines =<< trim END
706 vim9script
707 def Fn(x: tuple<number>)
708 var [a, b] = x
709 enddef
710 Fn((1,))
711 END
712 call v9.CheckSourceFailure(lines, 'E1093: Expected 2 items but got 1')
713
714 let lines =<< trim END
715 vim9script
716 def Fn(x: tuple<number>)
717 var [a, b] = x
718 enddef
719 Fn(null_tuple)
720 END
721 call v9.CheckSourceFailure(lines, 'E1093: Expected 2 items but got 0')
722endfunc
723
724" Test for performing an arithmetic operation on multiple variables using
725" items from a tuple
726func Test_multi_arithmetic_op_from_tuple()
727 let lines =<< trim END
728 VAR x = 10
729 VAR y = 10
730 LET [x, y] += (2, 4)
731 call assert_equal([12, 14], [x, y])
732 LET [x, y] -= (4, 2)
733 call assert_equal([8, 12], [x, y])
734 LET [x, y] *= (2, 3)
735 call assert_equal([16, 36], [x, y])
736 LET [x, y] /= (4, 2)
737 call assert_equal([4, 18], [x, y])
738 LET [x, y] %= (3, 5)
739 call assert_equal([1, 3], [x, y])
740 END
741 call v9.CheckSourceLegacyAndVim9Success(lines)
742
743 " The "." operator is supported only in Vim script
744 let lines =<< trim END
745 let x = 'a'
746 let y = 'b'
747 let [x, y] .= ('a', 'b')
748 call assert_equal(['aa', 'bb'], [x, y])
749 END
750 call v9.CheckSourceSuccess(lines)
751
752 let lines =<< trim END
753 VAR x = 'a'
754 VAR y = 'b'
755 LET [x, y] ..= ('a', 'b')
756 call assert_equal(('aa', 'bb'), (x, y))
757 END
758 call v9.CheckSourceLegacyAndVim9Success(lines)
759endfunc
760
761" Test for using a tuple in a for statement
762func Test_tuple_for()
763 let lines =<< trim END
764 VAR sum = 0
765 for v1 in (1, 3, 5)
766 LET sum += v1
767 endfor
768 call assert_equal(9, sum)
769
770 LET sum = 0
771 for v2 in ()
772 LET sum += v2
773 endfor
774 call assert_equal(0, sum)
775
776 LET sum = 0
777 for v2 in test_null_tuple()
778 LET sum += v2
779 endfor
780 call assert_equal(0, sum)
781 END
782 call v9.CheckSourceLegacyAndVim9Success(lines)
783
784 " ignoring the for loop assignment using '_'
785 let lines =<< trim END
786 vim9script
787 var count = 0
788 for _ in (1, 2, 3)
789 count += 1
790 endfor
791 assert_equal(3, count)
792 END
793 call v9.CheckSourceSuccess(lines)
794
795 let lines =<< trim END
796 var sum = 0
797 for v in null_tuple
798 sum += v
799 endfor
800 assert_equal(0, sum)
801 END
802 call v9.CheckSourceDefAndScriptSuccess(lines)
803
804 let lines =<< trim END
805 vim9script
806 def Foo()
807 for x in ((1, 2), (3, 4))
808 endfor
809 enddef
810 Foo()
811 END
812 call v9.CheckSourceSuccess(lines)
813
814 " Test for assigning multiple items from a tuple in a for loop
815 let lines =<< trim END
816 vim9script
817 def Fn()
818 for [x, y] in ([1, 2],)
819 assert_equal([1, 2], [x, y])
820 endfor
821 enddef
822 defcompile
823 Fn()
824 END
825 call v9.CheckSourceSuccess(lines)
826
827 " iterate over tuple<...list<number>
828 let lines =<< trim END
829 vim9script
830 def Fn()
831 var t: tuple<...list<number>> = (1, 2)
832 var sum = 0
833 for i: number in t
834 sum += i
835 endfor
836 assert_equal(3, sum)
837 enddef
838 Fn()
839 END
840 call v9.CheckSourceSuccess(lines)
841
842 " iterate over tuple<...list<list<number>>>
843 let lines =<< trim END
844 vim9script
845 def Fn()
846 var t: tuple<...list<list<number>>> = ([1, 2], [3, 4])
847 var sum = 0
848 for [x: number, y: number] in t
849 sum += x + y
850 endfor
851 assert_equal(10, sum)
852 enddef
853 Fn()
854 END
855 call v9.CheckSourceSuccess(lines)
856
857 " iterate over tuple<...list<tuple<...list<number>>>>
858 let lines =<< trim END
859 vim9script
860 def Fn()
861 var t: tuple<...list<tuple<...list<number>>>> = ((1, 2), (3, 4))
862 var sum = 0
863 for [x: number, y: number] in t
864 sum += x + y
865 endfor
866 assert_equal(10, sum)
867 enddef
868 Fn()
869 END
870 call v9.CheckSourceSuccess(lines)
871
872 " iterate over tuple<...list<list<number>>>
873 let lines =<< trim END
874 vim9script
875 def Fn()
876 var t: tuple<...list<list<number>>> = ([1, 2], [3, 4])
877 var sum = 0
878 for [x: number, y: number] in t
879 sum += x + y
880 endfor
881 assert_equal(10, sum)
882 enddef
883 Fn()
884 END
885 call v9.CheckSourceSuccess(lines)
886
887 " iterate over a tuple<...list<any>>
888 let lines =<< trim END
889 vim9script
890 def Fn()
891 var t: tuple<...list<any>> = (1, 'x', true, [], {}, ())
892 var str = ''
893 for v in t
894 str ..= string(v)
895 endfor
896 assert_equal("1'x'true[]{}()", str)
897 enddef
898 Fn()
899 END
900 call v9.CheckSourceSuccess(lines)
901
902 " use multiple variable assignment syntax with a tuple<...list<number>>
903 let lines =<< trim END
904 vim9script
905 def Fn()
906 var t: tuple<...list<number>> = (1, 2, 3)
907 for [i] in t
908 endfor
909 enddef
910 Fn()
911 END
912 call v9.CheckSourceFailure(lines, 'E1140: :for argument must be a sequence of lists or tuples', 2)
913endfunc
914
915" Test for checking the tuple type in assignment and return value
916func Test_tuple_type_check()
917 let lines =<< trim END
918 var t: tuple<...list<number>> = ('a', 'b')
919 END
920 call v9.CheckSourceDefFailure(lines, 'E1012: Type mismatch; expected tuple<...list<number>> but got tuple<string, string>', 1)
921
922 let lines =<< trim END
923 var t1: tuple<...list<string>> = ('a', 'b')
924 assert_equal(('a', 'b'), t1)
925 var t2 = (1, 2)
926 assert_equal((1, 2), t2)
927 var t = null_tuple
928 assert_equal(null_tuple, t)
929 t = test_null_tuple()
930 assert_equal(test_null_tuple(), t)
931 END
932 call v9.CheckSourceDefAndScriptSuccess(lines)
933
934 let lines =<< trim END
935 var t = ('a', 'b')
936 t = (1, 2)
937 END
938 call v9.CheckSourceDefFailure(lines, 'E1012: Type mismatch; expected tuple<string, string> but got tuple<number, number>', 2)
939
940 let lines =<< trim END
941 var t: tuple<number> = []
942 END
943 call v9.CheckSourceDefFailure(lines, 'E1012: Type mismatch; expected tuple<number> but got list<any>', 1)
944
945 let lines =<< trim END
946 var t: tuple<number> = {}
947 END
948 call v9.CheckSourceDefFailure(lines, 'E1012: Type mismatch; expected tuple<number> but got dict<any>', 1)
949
950 let lines =<< trim END
951 var l: list<number> = (1, 2)
952 END
953 call v9.CheckSourceDefFailure(lines, 'E1012: Type mismatch; expected list<number> but got tuple<number, number>', 1)
954
955 let lines =<< trim END
956 vim9script
957 def Fn(): tuple<...list<tuple<...list<string>>>>
958 return ((1, 2), (3, 4))
959 enddef
960 defcompile
961 END
962 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected tuple<...list<tuple<...list<string>>>> but got tuple<tuple<number, number>, tuple<number, number>>', 1)
963
964 let lines =<< trim END
965 var t: tuple<number> = ()
966 END
967 call v9.CheckSourceDefSuccess(lines)
968
969 let lines =<< trim END
970 vim9script
971 def Fn(): tuple<tuple<string>>
972 return ()
973 enddef
974 defcompile
975 END
976 call v9.CheckSourceSuccess(lines)
977
978 let lines =<< trim END
979 vim9script
980 def Fn(t: tuple<...list<number>>)
981 enddef
982 Fn(('a', 'b'))
983 END
984 call v9.CheckSourceFailure(lines, 'E1013: Argument 1: type mismatch, expected tuple<...list<number>> but got tuple<string, string>')
985
986 let lines =<< trim END
987 var t: any = (1, 2)
988 t = ('a', 'b')
989 END
990 call v9.CheckSourceDefSuccess(lines)
991
992 let lines =<< trim END
993 var t: tuple<...list<any>> = (1, 2)
994 t = ('a', 'b')
995 END
996 call v9.CheckSourceDefSuccess(lines)
997
998 let lines =<< trim END
999 var nll: tuple<list<number>> = ([1, 2],)
1000 nll->copy()[0]->extend(['x'])
1001 END
1002 call v9.CheckSourceDefAndScriptFailure(lines, [
1003 \ 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>',
1004 \ 'E1013: Argument 2: type mismatch, expected list<number> but got list<string> in extend()'])
1005
1006 let lines =<< trim END
1007 vim9script
1008 def Fn(y: tuple<number, ...list<bool>>)
1009 var x: tuple<number, ...list<string>>
1010 x = y
1011 enddef
1012
1013 var t: tuple<number, ...list<bool>> = (1, true, false)
1014 Fn(t)
1015 END
1016 call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected tuple<number, ...list<string>> but got tuple<number, ...list<bool>>')
1017endfunc
1018
1019" Test for setting the type of a script variable to tuple
1020func Test_tuple_scriptvar_type()
1021 " Uninitialized script variable should retain the type
1022 let lines =<< trim END
1023 vim9script
1024 var foobar: tuple<list<string>>
1025 def Foo()
1026 var x = foobar
1027 assert_equal('tuple<list<string>>', typename(x))
1028 enddef
1029 Foo()
1030 END
1031 call v9.CheckSourceScriptSuccess(lines)
1032
1033 " Initialized script variable should retain the type
1034 let lines =<< trim END
1035 vim9script
1036 var foobar: tuple<...list<string>> = ('a', 'b')
1037 def Foo()
1038 var x = foobar
1039 assert_equal('tuple<...list<string>>', typename(x))
1040 enddef
1041 Foo()
1042 END
1043 call v9.CheckSourceScriptSuccess(lines)
1044endfunc
1045
1046" Test for modifying a tuple
1047func Test_tuple_modify()
1048 let lines =<< trim END
1049 var t = (1, 2)
1050 t[0] = 3
1051 END
1052 call v9.CheckSourceDefAndScriptFailure(lines, ['E1532: Cannot modify a tuple', 'E1532: Cannot modify a tuple'])
1053endfunc
1054
1055def Test_using_null_tuple()
1056 var lines =<< trim END
1057 var x = null_tuple
1058 assert_true(x is null_tuple)
1059 var y = copy(x)
1060 assert_true(y is null_tuple)
1061 call assert_true((1, 2) != null_tuple)
1062 call assert_true(null_tuple != (1, 2))
1063 assert_equal(0, count(null_tuple, 'xx'))
1064 var z = deepcopy(x)
1065 assert_true(z is null_tuple)
1066 assert_equal(1, empty(x))
1067 assert_equal('xx', get(x, 0, 'xx'))
1068 assert_equal(-1, index(null_tuple, 10))
1069 assert_equal(-1, indexof(null_tuple, 'v:val == 2'))
1070 assert_equal('', join(null_tuple))
1071 assert_equal(0, len(x))
1072 assert_equal(0, min(null_tuple))
1073 assert_equal(0, max(null_tuple))
1074 assert_equal((), repeat(null_tuple, 3))
1075 assert_equal((), reverse(null_tuple))
1076 assert_equal((), slice(null_tuple, 0, 0))
1077 assert_equal('()', string(x))
1078 assert_equal('tuple<any>', typename(x))
1079 assert_equal(17, type(x))
1080 END
1081 v9.CheckSourceDefAndScriptSuccess(lines)
1082
1083 lines =<< trim END
1084 # An uninitialized tuple is not equal to null
1085 var t1: tuple<any>
1086 assert_true(t1 != null)
1087
1088 # An empty tuple is equal to null_tuple but not equal to null
1089 var t2: tuple<any> = ()
1090 assert_true(t2 == null_tuple)
1091 assert_true(t2 != null)
1092
1093 # null_tuple is equal to null
1094 assert_true(null_tuple == null)
1095 END
1096 v9.CheckSourceDefAndScriptSuccess(lines)
1097
1098 lines =<< trim END
1099 var x = null_tupel
1100 END
1101 v9.CheckSourceDefAndScriptFailure(lines, [
1102 \ 'E1001: Variable not found: null_tupel',
1103 \ 'E121: Undefined variable: null_tupel'])
1104enddef
1105
1106" Test for modifying a mutable item in a tuple
1107func Test_tuple_modify_mutable_item()
1108 let lines =<< trim END
1109 VAR t = ('a', ['b', 'c'], {'a': 10, 'b': 20})
1110 LET t[1][1] = 'x'
1111 LET t[2].a = 30
1112 call assert_equal(('a', ['b', 'x'], {'a': 30, 'b': 20}), t)
1113 END
1114 call v9.CheckSourceLegacyAndVim9Success(lines)
1115
1116 let lines =<< trim END
1117 VAR t = ('a', (['b'], 'c'))
1118 LET t[1][0][0] = 'x'
1119 call assert_equal(('a', (['x'], 'c')), t)
1120 END
1121 call v9.CheckSourceLegacyAndVim9Success(lines)
1122
1123 " Use a negative index
1124 let lines =<< trim END
1125 VAR t = ([1, 2], [3])
1126 LET t[-2][-2] = 5
1127 call assert_equal(([5, 2], [3]), t)
1128 END
1129 call v9.CheckSourceLegacyAndVim9Success(lines)
1130
1131 let lines =<< trim END
1132 VAR t = ('a', ('b', 'c'))
1133 LET t[1][0] = 'x'
1134 END
1135 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1136 \ 'E1532: Cannot modify a tuple',
1137 \ 'E1532: Cannot modify a tuple',
1138 \ 'E1532: Cannot modify a tuple'])
1139
1140 let lines =<< trim END
1141 VAR t = ['a', ('b', 'c')]
1142 LET t[1][0] = 'x'
1143 END
1144 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1145 \ 'E1532: Cannot modify a tuple',
1146 \ 'E1532: Cannot modify a tuple',
1147 \ 'E1532: Cannot modify a tuple'])
1148
1149 let lines =<< trim END
1150 VAR t = {'a': ('b', 'c')}
1151 LET t['a'][0] = 'x'
1152 END
1153 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1154 \ 'E1532: Cannot modify a tuple',
1155 \ 'E1532: Cannot modify a tuple',
1156 \ 'E1532: Cannot modify a tuple'])
1157
1158 let lines =<< trim END
1159 VAR t = {'a': ['b', ('c',)]}
1160 LET t['a'][1][0] = 'x'
1161 END
1162 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1163 \ 'E1532: Cannot modify a tuple',
1164 \ 'E1532: Cannot modify a tuple',
1165 \ 'E1532: Cannot modify a tuple'])
1166
1167 let lines =<< trim END
1168 let t = ('a', 'b', 'c', 'd')
1169 let t[1 : 2] = ('x', 'y')
1170 END
1171 call v9.CheckSourceFailure(lines, 'E1533: Cannot slice a tuple')
1172
1173 let lines =<< trim END
1174 var t: tuple<...list<string>> = ('a', 'b', 'c', 'd')
1175 t[1 : 2] = ('x', 'y')
1176 END
1177 call v9.CheckSourceDefAndScriptFailure(lines, [
1178 \ 'E1533: Cannot slice a tuple',
1179 \ 'E1533: Cannot slice a tuple'])
1180
1181 let lines =<< trim END
1182 var t: tuple<...list<string>> = ('a', 'b', 'c', 'd')
1183 t[ : 2] = ('x', 'y')
1184 END
1185 call v9.CheckSourceDefAndScriptFailure(lines, [
1186 \ 'E1533: Cannot slice a tuple',
1187 \ 'E1533: Cannot slice a tuple'])
1188
1189 let lines =<< trim END
1190 let t = ('a', 'b', 'c', 'd')
1191 let t[ : ] = ('x', 'y')
1192 END
1193 call v9.CheckSourceFailure(lines, 'E1533: Cannot slice a tuple')
1194
1195 let lines =<< trim END
1196 var t: tuple<...list<string>> = ('a', 'b', 'c', 'd')
1197 t[ : ] = ('x', 'y')
1198 END
1199 call v9.CheckSourceDefAndScriptFailure(lines, [
1200 \ 'E1533: Cannot slice a tuple',
1201 \ 'E1533: Cannot slice a tuple'])
1202
1203 let lines =<< trim END
1204 VAR t = ('abc',)
1205 LET t[0][1] = 'x'
1206 END
1207 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1208 \ "E689: Index not allowed after a string: t[0][1] = 'x'",
1209 \ 'E1148: Cannot index a string',
1210 \ "E689: Index not allowed after a string: t[0][1] = 'x'"])
1211
1212 " Out of range indexing
1213 let lines =<< trim END
1214 VAR t = ([1, 2], [3])
1215 LET t[2][0] = 5
1216 END
1217 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1218 \ 'E1519: Tuple index out of range: 2',
1219 \ 'E1519: Tuple index out of range: 2',
1220 \ 'E1519: Tuple index out of range: 2'])
1221
1222 let lines =<< trim END
1223 VAR t = ([1, 2], [3])
1224 LET t[-3][0] = 5
1225 END
1226 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1227 \ 'E1519: Tuple index out of range: -3',
1228 \ 'E1519: Tuple index out of range: -3',
1229 \ 'E1519: Tuple index out of range: -3'])
1230
1231 " Use a null tuple
1232 let lines =<< trim END
1233 VAR t = test_null_tuple()
1234 LET t[0][0] = 5
1235 END
1236 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1237 \ 'E1519: Tuple index out of range: 0',
1238 \ 'E1519: Tuple index out of range: 0',
1239 \ 'E1519: Tuple index out of range: 0'])
1240endfunc
1241
1242" Test for locking and unlocking a tuple variable
1243func Test_tuple_lock()
1244 let lines =<< trim END
1245 VAR t = ([0, 1],)
1246 call add(t[0], 2)
1247 call assert_equal(([0, 1, 2], ), t)
1248 END
1249 call v9.CheckSourceLegacyAndVim9Success(lines)
1250
1251 let lines =<< trim END
1252 VAR t = ([0, 1],)
1253 lockvar 2 t
1254 call add(t[0], 2)
1255 END
1256 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1257 \ 'E741: Value is locked: add() argument',
1258 \ 'E1178: Cannot lock or unlock a local variable',
1259 \ 'E741: Value is locked: add() argument'])
1260
1261 let lines =<< trim END
1262 LET g:t = ([0, 1],)
1263 lockvar 2 g:t
1264 unlockvar 2 g:t
1265 call add(g:t[0], 3)
1266 call assert_equal(([0, 1, 3], ), g:t)
1267 unlet g:t
1268 END
1269 call v9.CheckSourceLegacyAndVim9Success(lines)
1270
1271 let lines =<< trim END
1272 VAR t1 = (1, 2)
1273 const t2 = t1
1274 LET t2 = ()
1275 END
1276 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1277 \ 'E741: Value is locked: t2',
1278 \ 'E1018: Cannot assign to a constant: t2',
1279 \ 'E46: Cannot change read-only variable "t2"'])
1280endfunc
1281
1282" Test for using a class as a tuple item
1283func Test_tuple_use_class_item()
1284 let lines =<< trim END
1285 vim9script
1286 class A
1287 endclass
1288 var t = (A,)
1289 END
1290 call v9.CheckSourceScriptFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
1291
1292 let lines =<< trim END
1293 vim9script
1294 class A
1295 endclass
1296 var t = ('a', A)
1297 END
1298 call v9.CheckSourceScriptFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
1299
1300 let lines =<< trim END
1301 vim9script
1302 class A
1303 endclass
1304 def Fn()
1305 var t = (A,)
1306 enddef
1307 defcompile
1308 END
1309 call v9.CheckSourceScriptFailure(lines, 'E1405: Class "A" cannot be used as a value', 1)
1310
1311 let lines =<< trim END
1312 vim9script
1313 class A
1314 endclass
1315 def Fn()
1316 var t = ('a', A)
1317 enddef
1318 defcompile
1319 END
1320 call v9.CheckSourceScriptFailure(lines, 'E1405: Class "A" cannot be used as a value', 1)
1321endfunc
1322
1323" Test for using a user-defined type as a tuple item
1324func Test_tuple_user_defined_type_as_item()
1325 let lines =<< trim END
1326 vim9script
1327 type N = number
1328 var t = (N,)
1329 END
1330 call v9.CheckSourceScriptFailure(lines, 'E1403: Type alias "N" cannot be used as a value', 3)
1331
1332 let lines =<< trim END
1333 vim9script
1334 type N = number
1335 var t = ('a', N)
1336 END
1337 call v9.CheckSourceScriptFailure(lines, 'E1403: Type alias "N" cannot be used as a value', 3)
1338
1339 let lines =<< trim END
1340 vim9script
1341 type N = number
1342 def Fn()
1343 var t = (N,)
1344 enddef
1345 defcompile
1346 END
1347 call v9.CheckSourceScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value', 1)
1348
1349 let lines =<< trim END
1350 vim9script
1351 type N = number
1352 def Fn()
1353 var t = ('a', N)
1354 enddef
1355 defcompile
1356 END
1357 call v9.CheckSourceScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value', 1)
1358endfunc
1359
1360" Test for using a tuple as a function argument
1361func Test_tuple_func_arg()
1362 let lines =<< trim END
1363 vim9script
1364 def Fn(t: tuple<...list<string>>): tuple<...list<string>>
1365 return t[:]
1366 enddef
1367 var r1 = Fn(('a', 'b'))
1368 assert_equal(('a', 'b'), r1)
1369 var r2 = Fn(('a',))
1370 assert_equal(('a',), r2)
1371 var r3 = Fn(())
1372 assert_equal((), r3)
1373 var r4 = Fn(null_tuple)
1374 assert_equal((), r4)
1375 END
1376 call v9.CheckSourceScriptSuccess(lines)
1377
1378 func TupleArgFunc(t)
1379 return a:t[:]
1380 endfunc
1381 let r = TupleArgFunc(('a', 'b'))
1382 call assert_equal(('a', 'b'), r)
1383 let r = TupleArgFunc(('a',))
1384 call assert_equal(('a',), r)
1385 let r = TupleArgFunc(())
1386 call assert_equal((), r)
1387 let r = TupleArgFunc(test_null_tuple())
1388 call assert_equal((), r)
1389 delfunc TupleArgFunc
1390endfunc
1391
1392" Test for tuple identity
1393func Test_tuple_identity()
1394 let lines =<< trim END
1395 call assert_false((1, 2) is (1, 2))
1396 call assert_true((1, 2) isnot (1, 2))
1397 call assert_true((1, 2) isnot test_null_tuple())
1398 VAR t1 = ('abc', 'def')
1399 VAR t2 = t1
1400 call assert_true(t2 is t1)
1401 VAR t3 = (1, 2)
1402 call assert_false(t3 is t1)
1403 END
1404 call v9.CheckSourceLegacyAndVim9Success(lines)
1405endfunc
1406
1407" Test for using a compound op with a tuple
1408func Test_tuple_compound_op()
1409 let lines =<< trim END
1410 VAR t = (1, 2)
1411 LET t += (3,)
1412 END
1413 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1414 \ 'E734: Wrong variable type for +=',
1415 \ 'E734: Wrong variable type for +=',
1416 \ 'E734: Wrong variable type for +='])
1417
1418 for op in ['-', '*', '/', '%']
1419 let lines =<< trim eval END
1420 VAR t = (1, 2)
1421 LET t {op}= (3,)
1422 END
1423 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1424 \ $'E734: Wrong variable type for {op}=',
1425 \ $'E734: Wrong variable type for {op}=',
1426 \ $'E734: Wrong variable type for {op}='])
1427 endfor
1428
1429 let lines =<< trim END
1430 VAR t = (1, 2)
1431 LET t ..= (3,)
1432 END
1433 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1434 \ 'E734: Wrong variable type for .=',
1435 \ 'E1019: Can only concatenate to string',
1436 \ 'E734: Wrong variable type for .='])
1437endfunc
1438
1439" Test for using the falsy operator with tuple
1440func Test_tuple_falsy_op()
1441 let lines =<< trim END
1442 VAR t = test_null_tuple()
1443 call assert_equal('null tuple', t ?? 'null tuple')
1444 END
1445 call v9.CheckSourceLegacyAndVim9Success(lines)
1446endfunc
1447
1448" Test for tuple typecasting
1449def Test_tuple_typecast()
1450 var lines =<< trim END
1451 var x = <tuple<number>>('a', 'b')
1452 END
1453 v9.CheckSourceDefAndScriptFailure(lines, [
1454 \ 'E1012: Type mismatch; expected tuple<number> but got tuple<string, string>',
1455 \ 'E1012: Type mismatch; expected tuple<number> but got tuple<string, string>'])
1456enddef
1457
1458" Test for using a tuple in string interpolation
1459def Test_tuple_string_interop()
1460 var lines =<< trim END
1461 VAR emptytuple = ()
1462 call assert_equal("a()b", $'a{emptytuple}b')
1463 VAR nulltuple = test_null_tuple()
1464 call assert_equal("a()b", $'a{nulltuple}b')
1465
1466 #" Tuple interpolation
1467 VAR t = ('a', 'b', 'c')
1468 call assert_equal("x('a', 'b', 'c')x", $'x{t}x')
1469 END
1470 v9.CheckSourceLegacyAndVim9Success(lines)
1471
1472 lines =<< trim END
1473 call assert_equal("a()b", $'a{null_tuple}b')
1474 END
1475 v9.CheckSourceDefAndScriptSuccess(lines)
1476
1477 #" Tuple evaluation in heredoc
1478 lines =<< trim END
1479 VAR t1 = ('a', 'b', 'c')
1480 VAR data =<< eval trim DATA
1481 let x = {t1}
1482 DATA
1483 call assert_equal(["let x = ('a', 'b', 'c')"], data)
1484 END
1485 v9.CheckSourceLegacyAndVim9Success(lines)
1486
1487 #" Empty tuple evaluation in heredoc
1488 lines =<< trim END
1489 VAR t1 = ()
1490 VAR data =<< eval trim DATA
1491 let x = {t1}
1492 DATA
1493 call assert_equal(["let x = ()"], data)
1494 END
1495 v9.CheckSourceLegacyAndVim9Success(lines)
1496
1497 #" Null tuple evaluation in heredoc
1498 lines =<< trim END
1499 VAR t1 = test_null_tuple()
1500 VAR data =<< eval trim DATA
1501 let x = {t1}
1502 DATA
1503 call assert_equal(["let x = ()"], data)
1504 END
1505 v9.CheckSourceLegacyAndVim9Success(lines)
1506
1507 lines =<< trim END
1508 var t1 = null_tuple
1509 var data =<< eval trim DATA
1510 let x = {t1}
1511 DATA
1512 call assert_equal(["let x = ()"], data)
1513 END
1514 v9.CheckSourceDefAndScriptSuccess(lines)
1515enddef
1516
1517" Test for a return in "finally" block overriding the tuple return value in a
1518" try block.
1519func Test_try_finally_with_tuple_return()
1520 let lines =<< trim END
1521 func s:Fn()
1522 try
1523 return (1, 2)
1524 finally
1525 return (3, 4)
1526 endtry
1527 endfunc
1528 call assert_equal((3, 4), s:Fn())
1529 delfunc s:Fn
1530 END
1531 call v9.CheckSourceSuccess(lines)
1532
1533 let lines =<< trim END
1534 vim9script
1535 def Fn(): tuple<...list<number>>
1536 try
1537 return (1, 2)
1538 finally
1539 return (3, 4)
1540 endtry
1541 enddef
1542 assert_equal((3, 4), Fn())
1543 END
1544 call v9.CheckSourceSuccess(lines)
1545endfunc
1546
1547" Test for add() with a tuple
1548func Test_tuple_add()
1549 let lines =<< trim END
1550 VAR t = (1, 2)
1551 call add(t, 3)
1552 END
1553 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1554 \ 'E897: List or Blob required',
1555 \ 'E1013: Argument 1: type mismatch, expected list<any> but got tuple<number, number>',
1556 \ 'E1226: List or Blob required for argument 1'])
1557endfunc
1558
1559" Test for copy()
1560func Test_tuple_copy()
1561 let lines =<< trim END
1562 VAR t1 = (['a', 'b'], ['c', 'd'], ['e', 'f'])
1563 VAR t2 = copy(t1)
1564 VAR t3 = t1
1565 call assert_false(t2 is t1)
1566 call assert_true(t3 is t1)
1567 call assert_true(t2[1] is t1[1])
1568 call assert_equal((), copy(()))
1569 call assert_equal((), copy(test_null_tuple()))
1570 END
1571 call v9.CheckSourceLegacyAndVim9Success(lines)
1572endfunc
1573
1574" Test for count()
1575func Test_tuple_count()
1576 let lines =<< trim END
1577 VAR t = ('ab', 'cd', 'ab')
1578 call assert_equal(2, count(t, 'ab'))
1579 call assert_equal(0, count(t, 'xx'))
1580 call assert_equal(0, count((), 'xx'))
1581 call assert_equal(0, count(test_null_tuple(), 'xx'))
1582 call assert_fails("call count((1, 2), 1, v:true, 2)", 'E1519: Tuple index out of range: 2')
1583 END
1584 call v9.CheckSourceLegacyAndVim9Success(lines)
1585endfunc
1586
1587" Test for deepcopy()
1588func Test_tuple_deepcopy()
1589 let lines =<< trim END
1590 VAR t1 = (['a', 'b'], ['c', 'd'], ['e', 'f'])
1591 VAR t2 = deepcopy(t1)
1592 VAR t3 = t1
1593 call assert_false(t2 is t1)
1594 call assert_true(t3 is t1)
1595 call assert_false(t2[1] is t1[1])
1596 call assert_equal((), deepcopy(()))
1597 call assert_equal((), deepcopy(test_null_tuple()))
1598
1599 #" copy a recursive tuple
1600 VAR l = []
1601 VAR tuple = (l,)
1602 call add(l, tuple)
1603 call assert_equal('([(...)], )', string(deepcopy(tuple)))
1604 END
1605 call v9.CheckSourceLegacyAndVim9Success(lines)
1606endfunc
1607
1608" Test for empty()
1609func Test_tuple_empty()
1610 let lines =<< trim END
1611 call assert_true(empty(()))
1612 call assert_true(empty(test_null_tuple()))
1613 call assert_false(empty((1, 2)))
1614 VAR t = ('abc', 'def')
1615 call assert_false(empty(t))
1616 END
1617 call v9.CheckSourceLegacyAndVim9Success(lines)
1618endfunc
1619
1620" Test for eval()
1621func Test_tuple_eval()
1622 let lines =<< trim END
1623 call assert_equal((), eval('()'))
1624 call assert_equal(([],), eval('([],)'))
1625 call assert_equal((1, 2, 3), eval('(1, 2, 3)'))
1626 END
1627 call v9.CheckSourceLegacyAndVim9Success(lines)
1628endfunc
1629
1630" Test for extend() with a tuple
1631func Test_tuple_extend()
1632 let lines =<< trim END
1633 VAR t = (1, 2, 3)
1634 call extend(t, (4, 5))
1635 call extendnew(t, (4, 5))
1636 END
1637 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1638 \ 'E712: Argument of extend() must be a List or Dictionary',
1639 \ 'E1013: Argument 1: type mismatch, expected list<any> but got tuple<number, number, number>',
1640 \ 'E712: Argument of extend() must be a List or Dictionary'])
1641endfunc
1642
1643" Test for filter() with a tuple
1644func Test_tuple_filter()
1645 let lines =<< trim END
1646 VAR t = (1, 2, 3)
1647 call filter(t, 'v:val == 2')
1648 END
1649 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1650 \ 'E1524: Cannot use a tuple with function filter()',
1651 \ 'E1013: Argument 1: type mismatch, expected list<any> but got tuple<number, number, number>',
1652 \ 'E1524: Cannot use a tuple with function filter()'])
1653endfunc
1654
1655" Test for flatten() with a tuple
1656func Test_tuple_flatten()
1657 let t = ([1, 2], [3, 4], [5, 6])
1658 call assert_fails("call flatten(t, 2)", 'E686: Argument of flatten() must be a List')
1659endfunc
1660
1661" Test for flattennew() with a tuple
1662func Test_tuple_flattennew()
1663 let lines =<< trim END
1664 var t = ([1, 2], [3, 4], [5, 6])
1665 flattennew(t, 2)
1666 END
1667 call v9.CheckSourceDefFailure(lines, 'E1013: Argument 1: type mismatch, expected list<any> but got tuple<list<number>, list<number>, list<number>>')
1668endfunc
1669
1670" Test for foreach() with a tuple
1671func Test_tuple_foreach()
1672 let t = ('a', 'b', 'c')
1673 let str = ''
1674 call foreach(t, 'let str ..= v:val')
1675 call assert_equal('abc', str)
1676
1677 let sum = 0
1678 call foreach(test_null_tuple(), 'let sum += v:val')
1679 call assert_equal(0, sum)
1680
1681 let lines =<< trim END
1682 def Concatenate(k: number, v: string)
1683 g:str ..= v
1684 enddef
1685 var t = ('a', 'b', 'c')
1686 var str = 0
1687 g:str = ''
1688 call foreach(t, Concatenate)
1689 call assert_equal('abc', g:str)
1690
1691 g:str = ''
1692 call foreach(test_null_tuple(), Concatenate)
1693 call assert_equal('', g:str)
1694 END
1695 call v9.CheckSourceDefAndScriptSuccess(lines)
1696
1697 let lines =<< trim END
1698 LET g:sum = 0
1699 call foreach((1, 2, 3), 'LET g:sum += x')
1700 END
1701 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1702 \ 'E121: Undefined variable: x',
1703 \ 'E121: Undefined variable: x',
1704 \ 'E121: Undefined variable: x'])
1705endfunc
1706
1707" Test for get()
1708func Test_tuple_get()
1709 let lines =<< trim END
1710 VAR t = (10, 20, 30)
1711 for [i, v] in [[0, 10], [1, 20], [2, 30], [3, 0]]
1712 call assert_equal(v, get(t, i))
1713 endfor
1714
1715 for [i, v] in [[-1, 30], [-2, 20], [-3, 10], [-4, 0]]
1716 call assert_equal(v, get(t, i))
1717 endfor
1718 call assert_equal(0, get((), 5))
1719 call assert_equal('c', get(('a', 'b'), 2, 'c'))
1720 call assert_equal('x', get(test_null_tuple(), 0, 'x'))
1721 END
1722 call v9.CheckSourceLegacyAndVim9Success(lines)
1723endfunc
1724
1725" Test for id()
1726func Test_tuple_id()
1727 let lines =<< trim END
1728 VAR t1 = (['a'], ['b'], ['c'])
1729 VAR t2 = (['a'], ['b'], ['c'])
1730 VAR t3 = t1
1731 call assert_true(id(t1) != id(t2))
1732 call assert_true(id(t1) == id(t3))
1733 END
1734 call v9.CheckSourceLegacyAndVim9Success(lines)
1735endfunc
1736
1737" Test for index() function
1738func Test_tuple_index_func()
1739 let lines =<< trim END
1740 VAR t = (88, 33, 99, 77)
1741 call assert_equal(3, index(t, 77))
1742 call assert_equal(2, index(t, 99, 1))
1743 call assert_equal(2, index(t, 99, -4))
1744 call assert_equal(2, index(t, 99, -5))
1745 call assert_equal(-1, index(t, 66))
1746 call assert_equal(-1, index(t, 77, 4))
1747 call assert_equal(-1, index((), 8))
1748 call assert_equal(-1, index(test_null_tuple(), 9))
1749 END
1750 call v9.CheckSourceLegacyAndVim9Success(lines)
1751
1752 let lines =<< trim END
1753 VAR t = (88, 33, 99, 77)
1754 call assert_equal(-1, index(t, 77, []))
1755 END
1756 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1757 \ 'E745: Using a List as a Number',
1758 \ 'E1013: Argument 3: type mismatch, expected number but got list<any>',
1759 \ 'E1210: Number required for argument 3'])
1760
1761 let lines =<< trim END
1762 VAR t = (88,)
1763 call assert_equal(-1, index(t, 77, 1, ()))
1764 END
1765 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1766 \ 'E1520: Using a Tuple as a Number',
1767 \ 'E1013: Argument 4: type mismatch, expected bool but got tuple<any>',
1768 \ 'E1212: Bool required for argument 4'])
1769endfunc
1770
1771" Test for indexof()
1772func Test_tuple_indexof()
1773 let lines =<< trim END
1774 VAR t = ('a', 'b', 'c', 'd')
1775 call assert_equal(2, indexof(t, 'v:val =~ "c"'))
1776 call assert_equal(2, indexof(t, 'v:val =~ "c"', {'startidx': 2}))
1777 call assert_equal(-1, indexof(t, 'v:val =~ "c"', {'startidx': 3}))
1778 call assert_equal(2, indexof(t, 'v:val =~ "c"', {'startidx': -3}))
1779 call assert_equal(2, indexof(t, 'v:val =~ "c"', {'startidx': -6}))
1780 call assert_equal(-1, indexof(t, 'v:val =~ "e"'))
1781 call assert_equal(-1, indexof((), 'v:val == 1'))
1782 call assert_equal(-1, indexof(test_null_tuple(), 'v:val == 2'))
1783 END
1784 call v9.CheckSourceLegacyAndVim9Success(lines)
1785
1786 func g:MyIndexOf(k, v)
1787 echoerr 'MyIndexOf failed'
1788 endfunc
1789 let lines =<< trim END
1790 VAR t = (1, 2, 3)
1791 echo indexof(t, function('g:MyIndexOf'))
1792 END
1793 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1794 \ 'MyIndexOf failed',
1795 \ 'MyIndexOf failed',
1796 \ 'MyIndexOf failed'])
1797 delfunc g:MyIndexOf
1798endfunc
1799
1800" Test for insert()
1801func Test_tuple_insert()
1802 let lines =<< trim END
1803 VAR t = (1, 2, 3)
1804 call insert(t, 4)
1805 call insert(t, 4, 2)
1806 END
1807 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1808 \ 'E899: Argument of insert() must be a List or Blob',
1809 \ 'E1013: Argument 1: type mismatch, expected list<any> but got tuple<number, number, number>',
1810 \ 'E1226: List or Blob required for argument 1'])
1811endfunc
1812
1813" Test for items()
1814func Test_tuple_items()
1815 let lines =<< trim END
1816 VAR t = ([], {}, ())
1817 call assert_equal([[0, []], [1, {}], [2, ()]], items(t))
1818 call assert_equal([[0, 1]], items((1, )))
1819 call assert_equal([], items(()))
1820 call assert_equal([], items(test_null_tuple()))
1821 END
1822 call v9.CheckSourceLegacyAndVim9Success(lines)
1823endfunc
1824
1825" Test for join()
1826func Test_tuple_join()
1827 let lines =<< trim END
1828 VAR t = ('a', 'b', 'c')
1829 call assert_equal('a b c', join(t))
1830 call assert_equal('f o o', ('f', 'o', 'o')->join())
1831 call assert_equal('a-b-c', join(t, '-'))
1832 call assert_equal('', join(()))
1833 call assert_equal('', join(test_null_tuple()))
1834 END
1835 call v9.CheckSourceLegacyAndVim9Success(lines)
1836endfunc
1837
1838" Test for js_encode()
1839func Test_tuple_js_encode()
1840 let lines =<< trim END
1841 call assert_equal('["a","b","c"]', js_encode(('a', 'b', 'c')))
1842 call assert_equal('["a","b"]', js_encode(('a', 'b')))
1843 call assert_equal('["a"]', js_encode(('a',)))
1844 call assert_equal("[]", js_encode(()))
1845 call assert_equal("[]", js_encode(test_null_tuple()))
1846 call assert_equal('["a",,]', js_encode(('a', v:none)))
1847
1848 #" encode a recursive tuple
1849 VAR l = []
1850 VAR tuple = (l,)
1851 call add(l, tuple)
1852 call assert_equal("[[[]]]", js_encode(tuple))
1853 END
1854 call v9.CheckSourceLegacyAndVim9Success(lines)
1855endfunc
1856
1857" Test for json_encode()
1858func Test_tuple_json_encode()
1859 let lines =<< trim END
1860 call assert_equal('["a","b","c"]', json_encode(('a', 'b', 'c')))
1861 call assert_equal('["a","b"]', json_encode(('a', 'b')))
1862 call assert_equal('["a"]', json_encode(('a',)))
1863 call assert_equal("[]", json_encode(()))
1864 call assert_equal("[]", json_encode(test_null_tuple()))
1865
1866 #" encode a recursive tuple
1867 VAR l = []
1868 VAR tuple = (l,)
1869 call add(l, tuple)
1870 call assert_equal("[[[]]]", json_encode(tuple))
1871 END
1872 call v9.CheckSourceLegacyAndVim9Success(lines)
1873
1874 let lines =<< trim END
1875 VAR t = (function('min'), function('max'))
1876 VAR s = json_encode(t)
1877 END
1878 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1879 \ 'E1161: Cannot json encode a func',
1880 \ 'E1161: Cannot json encode a func',
1881 \ 'E1161: Cannot json encode a func'])
1882endfunc
1883
1884" Test for len()
1885func Test_tuple_len()
1886 let lines =<< trim END
1887 call assert_equal(0, len(()))
1888 call assert_equal(0, len(test_null_tuple()))
1889 call assert_equal(1, len(("abc",)))
1890 call assert_equal(3, len(("abc", "def", "ghi")))
1891 END
1892 call v9.CheckSourceLegacyAndVim9Success(lines)
1893endfunc
1894
1895" Test for map() with a tuple
1896func Test_tuple_map()
1897 let t = (1, 3, 5)
1898 call assert_fails("call map(t, 'v:val + 1')", 'E1524: Cannot use a tuple with function map()')
1899endfunc
1900
1901" Test for max()
1902func Test_tuple_max()
1903 let lines =<< trim END
1904 VAR t1 = (1, 3, 5)
1905 call assert_equal(5, max(t1))
1906 VAR t2 = (6,)
1907 call assert_equal(6, max(t2))
1908 call assert_equal(0, max(()))
1909 call assert_equal(0, max(test_null_tuple()))
1910 END
1911 call v9.CheckSourceLegacyAndVim9Success(lines)
1912
1913 let lines =<< trim END
1914 vim9script
1915 var x = max(('a', 2))
1916 END
1917 call v9.CheckSourceFailure(lines, 'E1030: Using a String as a Number: "a"')
1918
1919 let lines =<< trim END
1920 vim9script
1921 var x = max((1, 'b'))
1922 END
1923 call v9.CheckSourceFailure(lines, 'E1030: Using a String as a Number: "b"')
1924
1925 let lines =<< trim END
1926 vim9script
1927 def Fn()
1928 var x = max(('a', 'b'))
1929 enddef
1930 Fn()
1931 END
1932 call v9.CheckSourceFailure(lines, 'E1030: Using a String as a Number: "a"')
1933
1934 let lines =<< trim END
1935 echo max([('a', 'b'), 20])
1936 END
1937 call v9.CheckSourceLegacyAndVim9Failure(lines, [
1938 \ 'E1520: Using a Tuple as a Number',
1939 \ 'E1520: Using a Tuple as a Number',
1940 \ 'E1520: Using a Tuple as a Number'])
1941endfunc
1942
1943" Test for min()
1944func Test_tuple_min()
1945 let lines =<< trim END
1946 VAR t1 = (5, 3, 1)
1947 call assert_equal(1, min(t1))
1948 VAR t2 = (6,)
1949 call assert_equal(6, min(t2))
1950 call assert_equal(0, min(()))
1951 call assert_equal(0, min(test_null_tuple()))
1952 END
1953 call v9.CheckSourceLegacyAndVim9Success(lines)
1954
1955 let lines =<< trim END
1956 vim9script
1957 var x = min(('a', 2))
1958 END
1959 call v9.CheckSourceFailure(lines, 'E1030: Using a String as a Number: "a"')
1960
1961 let lines =<< trim END
1962 vim9script
1963 var x = min((1, 'b'))
1964 END
1965 call v9.CheckSourceFailure(lines, 'E1030: Using a String as a Number: "b"')
1966
1967
1968 let lines =<< trim END
1969 vim9script
1970 def Fn()
1971 var x = min(('a', 'b'))
1972 enddef
1973 Fn()
1974 END
1975 call v9.CheckSourceFailure(lines, 'E1030: Using a String as a Number: "a"')
1976endfunc
1977
1978" Test for reduce()
1979func Test_tuple_reduce()
1980 let lines =<< trim END
1981 call assert_equal(1, reduce((), LSTART acc, val LMIDDLE acc + val LEND, 1))
1982 call assert_equal(10, reduce((1, 3, 5), LSTART acc, val LMIDDLE acc + val LEND, 1))
1983 call assert_equal(2 * (2 * ((2 * 1) + 2) + 3) + 4, reduce((2, 3, 4), LSTART acc, val LMIDDLE 2 * acc + val LEND, 1))
1984 call assert_equal('a x y z', ('x', 'y', 'z')->reduce(LSTART acc, val LMIDDLE acc .. ' ' .. val LEND, 'a'))
1985
1986 VAR t = ('x', 'y', 'z')
1987 call assert_equal(42, reduce(t, function('get'), {'x': {'y': {'z': 42 } } }))
1988 call assert_equal(('x', 'y', 'z'), t)
1989 call assert_equal(1, reduce((1,), LSTART acc, val LMIDDLE acc + val LEND))
1990 call assert_equal('x y z', reduce(('x', 'y', 'z'), LSTART acc, val LMIDDLE acc .. ' ' .. val LEND))
1991 call assert_equal(5, reduce(test_null_tuple(), LSTART acc, val LMIDDLE acc + val LEND, 5))
1992 END
1993 call v9.CheckSourceLegacyAndVim9Success(lines)
1994
1995 call assert_equal({'x': 1, 'y': 1, 'z': 1 }, ('x', 'y', 'z')->reduce({ acc, val -> extend(acc, { val: 1 }) }, {}))
1996
1997 call assert_fails("call reduce((), { acc, val -> acc + val })", 'E998: Reduce of an empty Tuple with no initial value')
1998 call assert_fails("call reduce(test_null_tuple(), { acc, val -> acc + val })", 'E998: Reduce of an empty Tuple with no initial value')
1999
2000 let lines =<< trim END
2001 echo reduce((1, 2, 3), LSTART acc, val LMIDDLE acc + foo LEND)
2002 END
2003 call v9.CheckSourceLegacyAndVim9Failure(lines, [
2004 \ 'E121: Undefined variable: foo',
2005 \ 'E1001: Variable not found: foo',
2006 \ 'E1001: Variable not found: foo'])
2007endfunc
2008
2009" Test for remove()
2010func Test_tuple_remove()
2011 let lines =<< trim END
2012 VAR t = (1, 3, 5)
2013 call remove(t, 1)
2014 END
2015 call v9.CheckSourceLegacyAndVim9Failure(lines, [
2016 \ 'E896: Argument of remove() must be a List, Dictionary or Blob',
2017 \ 'E1013: Argument 1: type mismatch, expected list<any> but got tuple<number, number, number>',
2018 \ 'E1228: List, Dictionary or Blob required for argument 1'])
2019endfunc
2020
2021" Test for test_refcount()
2022func Test_tuple_refcount()
2023 let lines =<< trim END
2024 VAR t = (1, 2, 3)
2025 call assert_equal(1, test_refcount(t))
2026 VAR x = t
2027 call assert_equal(2, test_refcount(t))
2028 LET x = (4, 5, 6)
2029 call assert_equal(1, test_refcount(t))
2030 for n in t
2031 call assert_equal(2, test_refcount(t))
2032 endfor
2033 call assert_equal(1, test_refcount(t))
2034 END
2035 call v9.CheckSourceLegacyAndVim9Success(lines)
2036endfunc
2037
2038" Test for repeat()
2039func Test_tuple_repeat()
2040 let lines =<< trim END
2041 VAR t = ('a', 'b')
2042 call assert_equal(('a', 'b', 'a', 'b', 'a', 'b'), repeat(('a', 'b'), 3))
2043 call assert_equal(('x', 'x', 'x'), repeat(('x',), 3))
2044 call assert_equal((), repeat((), 3))
2045 call assert_equal((), repeat((), 0))
2046 call assert_equal((), repeat((), -1))
2047 call assert_equal((), repeat(test_null_tuple(), 3))
2048 END
2049 call v9.CheckSourceLegacyAndVim9Success(lines)
2050endfunc
2051
2052" Test for reverse()
2053func Test_tuple_reverse()
2054 let lines =<< trim END
2055 VAR t = (['a'], ['b'], ['c'])
2056 call assert_equal((['c'], ['b'], ['a']), reverse(t))
2057 call assert_equal(('a',), reverse(('a',)))
2058 call assert_equal((), reverse(()))
2059 call assert_equal((), reverse(test_null_tuple()))
2060 END
2061 call v9.CheckSourceLegacyAndVim9Success(lines)
2062endfunc
2063
2064" Test for slicing a tuple
2065func Test_tuple_slice_func()
2066 let lines =<< trim END
2067 VAR t = (1, 3, 5, 7, 9)
2068 call assert_equal((9,), slice(t, 4))
2069 call assert_equal((5, 7, 9), slice(t, 2))
2070 call assert_equal((), slice(t, 5))
2071 call assert_equal((), slice((), 1, 2))
2072 call assert_equal((), slice(test_null_tuple(), 1, 2))
2073 END
2074 call v9.CheckSourceLegacyAndVim9Success(lines)
2075
2076 " return value of slice() should be the correct tuple type
2077 let lines =<< trim END
2078 var t: tuple<...list<number>> = (1, 3, 5)
2079 var x: tuple<...list<number>> = slice(t, 1, 2)
2080 assert_equal((3,), x)
2081 END
2082 call v9.CheckSourceDefAndScriptSuccess(lines)
2083endfunc
2084
2085" Test for sort()
2086func Test_tuple_sort()
2087 let lines =<< trim END
2088 call sort([1.1, (1.2,)], 'f')
2089 END
2090 call v9.CheckSourceLegacyAndVim9Failure(lines, [
2091 \ 'E1521: Using a Tuple as a Float',
2092 \ 'E1521: Using a Tuple as a Float',
2093 \ 'E1521: Using a Tuple as a Float'])
2094endfunc
2095
2096" Test for stridx()
2097func Test_tuple_stridx()
2098 let lines =<< trim END
2099 call stridx(('abc', ), 'a')
2100 END
2101 call v9.CheckSourceLegacyAndVim9Failure(lines, [
2102 \ 'E1522: Using a Tuple as a String',
2103 \ 'E1013: Argument 1: type mismatch, expected string but got tuple<string>',
2104 \ 'E1174: String required for argument 1'])
2105endfunc
2106
2107" Test for string()
2108func Test_tuple_string()
2109 let lines =<< trim END
2110 VAR t1 = (1, 'as''d', [1, 2, function("strlen")], {'a': 1}, )
2111 call assert_equal("(1, 'as''d', [1, 2, function('strlen')], {'a': 1})", string(t1))
2112
2113 #" empty tuple
2114 VAR t2 = ()
2115 call assert_equal("()", string(t2))
2116
2117 #" one item tuple
2118 VAR t3 = ("a", )
2119 call assert_equal("('a', )", string(t3))
2120
2121 call assert_equal("()", string(test_null_tuple()))
2122 END
2123 call v9.CheckSourceLegacyAndVim9Success(lines)
2124
2125 " recursive tuple
2126 let lines =<< trim END
2127 VAR l = []
2128 VAR t = (l,)
2129 call add(l, t)
2130 call assert_equal('([(...)], )', string(t))
2131 END
2132 call v9.CheckSourceLegacyAndVim9Success(lines)
2133endfunc
2134
2135" Test for type()
2136func Test_tuple_type()
2137 let lines =<< trim END
2138 VAR t = (1, 2)
2139 call assert_equal(17, type(t))
2140 call assert_equal(v:t_tuple, type(t))
2141 call assert_equal(v:t_tuple, type(()))
2142 call assert_equal(v:t_tuple, type(test_null_tuple()))
2143 END
2144 call v9.CheckSourceLegacyAndVim9Success(lines)
2145endfunc
2146
2147" Test for typename()
2148func Test_tuple_typename()
2149 let lines =<< trim END
2150 call assert_equal('tuple<number, number>', typename((1, 2)))
2151 call assert_equal('tuple<string, string>', typename(('a', 'b')))
2152 call assert_equal('tuple<bool, bool>', typename((v:true, v:true)))
2153 call assert_equal('tuple<number, string>', typename((1, 'b')))
2154 call assert_equal('tuple<any>', typename(()))
2155 call assert_equal('tuple<dict<any>>', typename(({}, )))
2156 call assert_equal('tuple<list<any>>', typename(([], )))
2157 call assert_equal('tuple<list<number>>', typename(([1, 2], )))
2158 call assert_equal('tuple<list<string>>', typename((['a', 'b'], )))
2159 call assert_equal('tuple<list<list<number>>>', typename(([[1], [2]], )))
2160 call assert_equal('tuple<tuple<number, number>>', typename(((1, 2), )))
2161 VAR t1 = (([1, 2],), (['a', 'b'],))
2162 call assert_equal('tuple<tuple<list<number>>, tuple<list<string>>>', typename(t1))
2163 call assert_equal('list<tuple<number>>', typename([(1,)]))
2164 call assert_equal('list<tuple<any>>', typename([()]))
2165 call assert_equal('tuple<any>', typename(test_null_tuple()))
2166 END
2167 call v9.CheckSourceLegacyAndVim9Success(lines)
2168
2169 let lines =<< trim END
2170 var d: dict<any> = {a: 0}
2171 var t2 = (d,)
2172 t2[0].e = {b: t2}
2173 call assert_equal('tuple<dict<any>>', typename(t2))
2174 END
2175 call v9.CheckSourceDefAndScriptSuccess(lines)
2176
2177 " check the type of a circular reference tuple
2178 let lines =<< trim END
2179 # circular reference tuple
2180 var l: list<tuple<any>> = []
2181 var t = (l,)
2182 add(l, t)
2183 assert_equal('tuple<list<tuple<any>>>', typename(t))
2184 assert_equal('list<tuple<any>>', typename(l))
2185 END
2186 call v9.CheckSourceDefAndScriptSuccess(lines)
2187
2188 " When a tuple item is used in a "for" loop, the type is tuple<any>
2189 let lines =<< trim END
2190 vim9script
2191 var l = [(1, 2)]
2192 for t in l
2193 assert_equal('tuple<any>', typename(t))
2194 endfor
2195 END
2196 call v9.CheckSourceScriptSuccess(lines)
2197
2198 " type of a tuple copy should be the same
2199 let lines =<< trim END
2200 var t: tuple<...list<number>> = (1, 2)
2201 var x: tuple<...list<number>> = t
2202 assert_equal('tuple<...list<number>>', typename(x))
2203 END
2204 call v9.CheckSourceDefAndScriptSuccess(lines)
2205endfunc
2206
2207" Test for saving and restoring tuples from a viminfo file
2208func Test_tuple_viminfo()
2209 let viminfo_save = &viminfo
2210 set viminfo^=!
2211
2212 let g:MYTUPLE = ([1, 2], [3, 4], 'a', 'b', 1, 2)
2213
2214 " create a tuple with circular reference
2215 " This should not be saved in the viminfo file
2216 let l = []
2217 let g:CIRCTUPLE = (l,)
2218 call add(l, g:CIRCTUPLE)
2219
2220 wviminfo! Xviminfo
2221 unlet g:MYTUPLE
2222 unlet g:CIRCTUPLE
2223 rviminfo! Xviminfo
2224 call assert_equal(([1, 2], [3, 4], 'a', 'b', 1, 2), g:MYTUPLE)
2225 call assert_false(exists('g:CIRCTUPLE'))
2226 let &viminfo = viminfo_save
2227 call delete('Xviminfo')
2228endfunc
2229
2230" Test for list2tuple()
2231func Test_list2tuple()
2232 let lines =<< trim END
2233 call assert_equal((), list2tuple([]))
2234 call assert_equal((), list2tuple(test_null_list()))
2235 call assert_equal(('a', ['b'], {'n': 20}), list2tuple(['a', ['b'], {'n': 20}]))
2236
2237 VAR l = ['a', 'b']
2238 VAR t = list2tuple(l)
2239 LET l[0] = 'x'
2240 call assert_equal(('a', 'b'), t)
2241
2242 call assert_equal((0, 1, 2), list2tuple(range(3)))
2243
2244 call assert_equal(((),), [()]->list2tuple())
2245 END
2246 call v9.CheckSourceLegacyAndVim9Success(lines)
2247
2248 call assert_fails('call list2tuple(())', 'E1211: List required for argument 1')
2249
2250 " Check the returned type
2251 let lines =<< trim END
2252 var l1 = [1, 2]
2253 var t1: tuple<...list<number>> = list2tuple(l1)
2254 assert_equal('tuple<...list<number>>', typename(t1))
2255 var l2 = ['a', 'b']
2256 var t2: tuple<...list<string>> = list2tuple(l2)
2257 assert_equal('tuple<...list<string>>', typename(t2))
2258 var l3 = []
2259 var t3 = list2tuple(l3)
2260 assert_equal('tuple<any>', typename(t3))
2261 var l4 = [([{}])]
2262 var t4: tuple<list<dict<any>>> = list2tuple(l4)
2263 assert_equal('tuple<list<dict<any>>>', typename(t4))
2264 END
2265 call v9.CheckSourceDefAndScriptSuccess(lines)
2266endfunc
2267
2268" Test for tuple2list()
2269func Test_tuple2list()
2270 let lines =<< trim END
2271 call assert_equal([], tuple2list(()))
2272 call assert_equal([], tuple2list(test_null_tuple()))
2273
2274 VAR t1 = ('a', ['b'], {'n': 20}, ('a',))
2275 call assert_equal(['a', ['b'], {'n': 20}, ('a',)], tuple2list(t1))
2276
2277 VAR t = ('a', 'b')
2278 VAR l = tuple2list(t)
2279 LET l[0] = 'x'
2280 call assert_equal(('a', 'b'), t)
2281
2282 call assert_equal([[]], ([],)->tuple2list())
2283 END
2284 call v9.CheckSourceLegacyAndVim9Success(lines)
2285
2286 call assert_fails('call tuple2list([])', 'E1534: Tuple required for argument 1')
2287
2288 " Check the returned type
2289 let lines =<< trim END
2290 var t1 = (1, 2)
2291 var l1 = tuple2list(t1)
2292 assert_equal('list<number>', typename(l1))
2293 var t2 = ('a', 'b')
2294 var l2 = tuple2list(t2)
2295 assert_equal('list<string>', typename(l2))
2296 var t3 = ()
2297 var l3 = tuple2list(t3)
2298 assert_equal('list<any>', typename(l3))
2299 var t4 = ([({},)],)
2300 var l4 = tuple2list(t4)
2301 assert_equal('list<list<tuple<dict<any>>>>', typename(l4))
2302 END
2303 call v9.CheckSourceDefAndScriptSuccess(lines)
2304endfunc
2305
2306" vim: shiftwidth=2 sts=2 expandtab