forked from aniani/vim
Problem: crash when importing invalid tuple
(Yang LUO, Yanju Chen)
Solution: set type to VAR_UNKNOWN, so that it isn't freed
(Yegappan Lakshmanan)
closes: #17362
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2379 lines
67 KiB
VimL
2379 lines
67 KiB
VimL
" Tests for the Tuple types
|
||
|
||
import './vim9.vim' as v9
|
||
|
||
func TearDown()
|
||
" Run garbage collection after every test
|
||
call test_garbagecollect_now()
|
||
endfunc
|
||
|
||
" Tuple declaration
|
||
func Test_tuple_declaration()
|
||
let lines =<< trim END
|
||
var Fn = function('min')
|
||
var t = (1, 'a', true, 3.1, 0z10, ['x'], {'a': []}, Fn)
|
||
assert_equal((1, 'a', true, 3.1, 0z10, ['x'], {'a': []}, Fn), t)
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
" Multiline tuple declaration
|
||
let lines =<< trim END
|
||
var t = (
|
||
'a',
|
||
'b',
|
||
)
|
||
assert_equal(('a', 'b'), t)
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
" Tuple declaration with comments
|
||
let lines =<< trim END
|
||
var t = ( # xxx
|
||
# xxx
|
||
'a', # xxx
|
||
# xxx
|
||
'b', # xxx
|
||
) # xxx
|
||
assert_equal(('a', 'b'), t)
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
" Tuple declaration separated by '|'
|
||
let lines =<< trim END
|
||
VAR t1 = ('a', 'b') | VAR t2 = ('c', 'd')
|
||
call assert_equal(('a', 'b'), t1)
|
||
call assert_equal(('c', 'd'), t2)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
" Space after and before parens
|
||
let lines =<< trim END
|
||
var t = ( 1, 2 )
|
||
assert_equal((1, 2), t)
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
endfunc
|
||
|
||
" Tuple declaration error
|
||
func Test_tuple_declaration_error()
|
||
let lines =<< trim END
|
||
var t: tuple<> = ('a', 'b')
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, "E1008: Missing <type> after > = ('a', 'b')")
|
||
|
||
let lines =<< trim END
|
||
var t: tuple = ('a', 'b')
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, "E1008: Missing <type> after tuple")
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<number> = ('a','b')
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, "E1069: White space required after ',': ,'b')")
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<number> = ('a', 'b','c')
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, "E1069: White space required after ',': ,'c')")
|
||
|
||
let lines =<< trim END
|
||
var t: tuple <number> = ()
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, "E1068: No white space allowed before '<'")
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<number,string>
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, "E1069: White space required after ','")
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<number , string>
|
||
END
|
||
call v9.CheckSourceDefFailure(lines, "E1068: No white space allowed before ','")
|
||
|
||
let lines =<< trim END
|
||
var t = ('a', 'b' , 'c')
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, [
|
||
\ "E1068: No white space allowed before ','",
|
||
\ "E1068: No white space allowed before ','"])
|
||
|
||
let lines =<< trim END
|
||
VAR t = ('a', 'b' 'c')
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ "E1527: Missing comma in Tuple: 'c')",
|
||
\ "E1527: Missing comma in Tuple: 'c')",
|
||
\ "E1527: Missing comma in Tuple: 'c')"])
|
||
|
||
let lines =<< trim END
|
||
VAR t = ('a', 'b',
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ "E1526: Missing end of Tuple ')'",
|
||
\ "E1526: Missing end of Tuple ')'",
|
||
\ "E1526: Missing end of Tuple ')'"])
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<number, ...> = (1, 2, 3)
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, [
|
||
\ 'E1010: Type not recognized: ',
|
||
\ 'E1010: Type not recognized: '])
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<number, ...number> = (1, 2, 3)
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, [
|
||
\ 'E1539: Variadic tuple must end with a list type: number',
|
||
\ 'E1539: Variadic tuple must end with a list type: number'])
|
||
|
||
" Invalid expression in the tuple
|
||
let lines =<< trim END
|
||
def Foo()
|
||
var t = (1, 1*2, 2)
|
||
enddef
|
||
defcompile
|
||
END
|
||
call v9.CheckSourceDefFailure(lines, 'E1004: White space required before and after ''*'' at "*2, 2)"')
|
||
|
||
let lines =<< trim END
|
||
VAR t = ('a', , 'b',)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E15: Invalid expression: ", ''b'',)"',
|
||
\ "E1068: No white space allowed before ',': , 'b',)",
|
||
\ 'E15: Invalid expression: ", ''b'',)"'])
|
||
|
||
let lines =<< trim END
|
||
VAR t = ('a', 'b', ,)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E15: Invalid expression: ",)"',
|
||
\ "E1068: No white space allowed before ',': ,)",
|
||
\ 'E15: Invalid expression: ",)"'])
|
||
|
||
let lines =<< trim END
|
||
VAR t = (, 'a', 'b')
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E15: Invalid expression: ", ''a'', ''b'')"',
|
||
\ "E1015: Name expected: , 'a', 'b')",
|
||
\ 'E15: Invalid expression: ", ''a'', ''b'')"'])
|
||
|
||
let lines =<< trim END
|
||
var t: tupel<number> = (1,)
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, 'E1010: Type not recognized: tupel<number>')
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<number> = [1, 2]
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, 'E1012: Type mismatch; expected tuple<number> but got list<number>')
|
||
endfunc
|
||
|
||
" Test for indexing a tuple
|
||
func Test_tuple_indexing()
|
||
let lines =<< trim END
|
||
VAR t = ('a', 'b', 'c')
|
||
call assert_equal(['a', 'b', 'c'], [t[0], t[1], t[2]])
|
||
call assert_equal(['c', 'b', 'a'], [t[-1], t[-2], t[-3]])
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
" Indexing a tuple passed as a function argument
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(t: any)
|
||
call assert_equal(['a', 'b', 'c'], [t[0], t[1], t[2]])
|
||
call assert_equal(['c', 'b', 'a'], [t[-1], t[-2], t[-3]])
|
||
enddef
|
||
Fn(('a', 'b', 'c'))
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<...list<number>> = (10, 20)
|
||
var x: number = t[0]
|
||
assert_equal(10, x)
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<...list<list<number>>> = ([1, 2], [3, 4])
|
||
t[0][1] = 5
|
||
assert_equal(([1, 5], [3, 4]), t)
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<list<number>> = ([2, 4],)
|
||
t[0][1] = 6
|
||
assert_equal(([2, 6],), t)
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
endfunc
|
||
|
||
" Indexing a tuple in a Dict
|
||
func Test_tuple_in_a_dict_index()
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn()
|
||
var d = {a: (1, 2)}
|
||
var x = d.a[0]
|
||
assert_equal('number', typename(x))
|
||
enddef
|
||
Fn()
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
endfunc
|
||
|
||
func Test_tuple_index_error()
|
||
let lines =<< trim END
|
||
echo ('a', 'b', 'c')[3]
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1519: Tuple index out of range: 3',
|
||
\ 'E1519: Tuple index out of range: 3',
|
||
\ 'E1519: Tuple index out of range: 3'])
|
||
|
||
let lines =<< trim END
|
||
echo ('a', 'b', 'c')[-4]
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1519: Tuple index out of range: -4',
|
||
\ 'E1519: Tuple index out of range: -4',
|
||
\ 'E1519: Tuple index out of range: -4'])
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(t: any)
|
||
echo t[3]
|
||
enddef
|
||
Fn(('a', 'b', 'c'))
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1519: Tuple index out of range: 3')
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(t: any)
|
||
echo t[-4]
|
||
enddef
|
||
Fn(('a', 'b', 'c'))
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1519: Tuple index out of range: -4')
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(t: any)
|
||
var x = t[0]
|
||
enddef
|
||
Fn(())
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1519: Tuple index out of range: 0')
|
||
|
||
" Index a null tuple
|
||
let lines =<< trim END
|
||
VAR t = test_null_tuple()
|
||
LET t[0][0] = 10
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1519: Tuple index out of range: 0',
|
||
\ 'E1519: Tuple index out of range: 0',
|
||
\ 'E1519: Tuple index out of range: 0'])
|
||
|
||
let lines =<< trim END
|
||
var x = null_tuple
|
||
x[0][0] = 10
|
||
END
|
||
call v9.CheckSourceDefExecAndScriptFailure(lines, [
|
||
\ 'E1519: Tuple index out of range: 0',
|
||
\ 'E1519: Tuple index out of range: 0'])
|
||
|
||
" Use a float as the index
|
||
let lines =<< trim END
|
||
VAR t = (1, 2)
|
||
VAR x = t[0.1]
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E805: Using a Float as a Number',
|
||
\ 'E1012: Type mismatch; expected number but got float',
|
||
\ 'E805: Using a Float as a Number'])
|
||
endfunc
|
||
|
||
" Test for slicing a tuple
|
||
func Test_tuple_slice()
|
||
let lines =<< trim END
|
||
VAR t = (1, 3, 5, 7, 9)
|
||
call assert_equal((3, 5), t[1 : 2])
|
||
call assert_equal((9,), t[4 : 4])
|
||
call assert_equal((7, 9), t[3 : 6])
|
||
call assert_equal((1, 3, 5), t[: 2])
|
||
call assert_equal((5, 7, 9), t[2 :])
|
||
call assert_equal((1, 3, 5, 7, 9), t[:])
|
||
call assert_equal((), test_null_tuple()[:])
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
let lines =<< trim END
|
||
call assert_equal(('b', 'c'), ('a', 'b', 'c')[1 : 5])
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for concatenating tuples
|
||
func Test_tuple_concatenate()
|
||
let lines =<< trim END
|
||
VAR t1 = ('a', 'b') + ('c', 'd')
|
||
call assert_equal(('a', 'b', 'c', 'd'), t1)
|
||
|
||
VAR t2 = ('a',) + ('b',)
|
||
call assert_equal(('a', 'b'), t2)
|
||
|
||
VAR t3 = ('a',) + ()
|
||
call assert_equal(('a',), t3)
|
||
|
||
VAR t4 = () + ('b',)
|
||
call assert_equal(('b',), t4)
|
||
|
||
VAR t5 = ('a', 'b') + test_null_tuple()
|
||
call assert_equal(('a', 'b'), t5)
|
||
call assert_equal('tuple<string, string>', typename(t5))
|
||
|
||
VAR t6 = test_null_tuple() + ('c', 'd')
|
||
call assert_equal(('c', 'd'), t6)
|
||
call assert_equal('tuple<string, string>', typename(t6))
|
||
|
||
VAR t7 = ('a', 'b') + (8, 9)
|
||
call assert_equal(('a', 'b', 8, 9), t7)
|
||
call assert_equal('tuple<string, string, number, number>', typename(t7))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
let lines =<< trim END
|
||
var t1: tuple<...list<tuple<number, number>>> = ()
|
||
var t2: tuple<...list<tuple<number, number>>> = ()
|
||
var t: tuple<...list<tuple<number, number>>> = t1 + t2
|
||
assert_equal((), t)
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<...list<number>> = (1, 2) + ('a', 'b')
|
||
END
|
||
call v9.CheckSourceDefExecAndScriptFailure(lines, [
|
||
\ 'E1012: Type mismatch; expected tuple<...list<number>> but got tuple<number, number, string, string>',
|
||
\ 'E1012: Type mismatch; expected tuple<...list<number>> but got tuple<number, number, string, string>'])
|
||
|
||
let lines =<< trim END
|
||
var a: tuple<...list<number>> = (1, 2)
|
||
var b: tuple<...list<string>> = ('a', 'b')
|
||
var t = a + b
|
||
END
|
||
call v9.CheckSourceDefExecAndScriptFailure(lines, [
|
||
\ 'E1540: Cannot use a variadic tuple in concatenation',
|
||
\ 'E1540: Cannot use a variadic tuple in concatenation'])
|
||
|
||
let lines =<< trim END
|
||
var a: tuple<...list<number>> = (1, 2)
|
||
var b: tuple<string, string> = ('a', 'b')
|
||
var t = a + b
|
||
END
|
||
call v9.CheckSourceDefExecAndScriptFailure(lines, [
|
||
\ 'E1540: Cannot use a variadic tuple in concatenation',
|
||
\ 'E1540: Cannot use a variadic tuple in concatenation'])
|
||
|
||
let lines =<< trim END
|
||
var a: tuple<number, ...list<string>> = (1, 'a', 'b')
|
||
var b: tuple<number, ...list<string>> = (2, 'c', 'd')
|
||
var t = a + b
|
||
END
|
||
call v9.CheckSourceDefExecAndScriptFailure(lines, [
|
||
\ 'E1540: Cannot use a variadic tuple in concatenation',
|
||
\ 'E1540: Cannot use a variadic tuple in concatenation'])
|
||
|
||
let lines =<< trim END
|
||
var a: tuple<number, ...list<string>> = (1, 'a', 'b')
|
||
var b: tuple<...list<string>> = ('c', 'd')
|
||
var t = a + b
|
||
END
|
||
call v9.CheckSourceDefExecAndScriptFailure(lines, [
|
||
\ 'E1540: Cannot use a variadic tuple in concatenation',
|
||
\ 'E1540: Cannot use a variadic tuple in concatenation'])
|
||
|
||
let lines =<< trim END
|
||
var a: tuple<...list<string>> = ('a', 'b')
|
||
var b: tuple<number, ...list<string>> = (2, 'c', 'd')
|
||
var t = a + b
|
||
END
|
||
call v9.CheckSourceDefExecAndScriptFailure(lines, [
|
||
\ 'E1540: Cannot use a variadic tuple in concatenation',
|
||
\ 'E1540: Cannot use a variadic tuple in concatenation'])
|
||
|
||
let lines =<< trim END
|
||
var t1: tuple<...list<tuple<number, number>>> = ()
|
||
var t2: tuple<...list<tuple<number, string>>> = ()
|
||
var t = t1 + t2
|
||
END
|
||
call v9.CheckSourceDefExecAndScriptFailure(lines, [
|
||
\ 'E1540: Cannot use a variadic tuple in concatenation',
|
||
\ 'E1540: Cannot use a variadic tuple in concatenation'])
|
||
|
||
" Make sure the correct line number is used in the error message
|
||
let lines =<< trim END
|
||
vim9script
|
||
var t1: tuple<...list<tuple<number, number>>> = ()
|
||
var t2: tuple<...list<tuple<number, string>>> = ()
|
||
var t = t1 + t2
|
||
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1540: Cannot use a variadic tuple in concatenation', 4)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
|
||
def Fn()
|
||
var t1: tuple<...list<tuple<number, number>>> = ()
|
||
var t2: tuple<...list<tuple<number, string>>> = ()
|
||
var t = t1 + t2
|
||
|
||
enddef
|
||
Fn()
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1540: Cannot use a variadic tuple in concatenation', 3)
|
||
|
||
" One or both the operands are variadic tuples
|
||
let lines =<< trim END
|
||
var a1: tuple<number, number> = (1, 2)
|
||
var b1: tuple<...list<string>> = ('a', 'b')
|
||
var t1 = a1 + b1
|
||
assert_equal((1, 2, 'a', 'b'), t1)
|
||
|
||
var a2: tuple<string, string> = ('a', 'b')
|
||
var b2: tuple<number, ...list<string>> = (1, 'c', 'd')
|
||
var t2 = a2 + b2
|
||
assert_equal(('a', 'b', 1, 'c', 'd'), t2)
|
||
|
||
var a3: tuple<...list<string>> = ('a', 'b')
|
||
var b3: tuple<...list<string>> = ('c', 'd')
|
||
var t3 = a3 + b3
|
||
assert_equal(('a', 'b', 'c', 'd'), t3)
|
||
|
||
var a4: tuple<...list<number>> = (1, 2)
|
||
var t4 = a4 + ()
|
||
assert_equal((1, 2), t4)
|
||
|
||
var b5: tuple<...list<number>> = (1, 2)
|
||
var t5 = () + b5
|
||
assert_equal((1, 2), t5)
|
||
|
||
var a6: tuple<...list<number>> = (1, 2)
|
||
var t6 = a6 + null_tuple
|
||
assert_equal((1, 2), t6)
|
||
|
||
var b7: tuple<...list<string>> = ('a', 'b')
|
||
var t7 = null_tuple + b7
|
||
assert_equal(('a', 'b'), t7)
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
VAR t = test_null_tuple() + test_null_tuple()
|
||
call assert_equal(test_null_tuple(), t)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(x: any, y: any): any
|
||
return x + y
|
||
enddef
|
||
assert_equal((1, 2), Fn((1,), (2,)))
|
||
assert_equal((1, 'a'), Fn((1,), ('a',)))
|
||
assert_equal((1,), Fn((1,), null_tuple))
|
||
assert_equal(('a',), Fn(null_tuple, ('a',)))
|
||
assert_equal((), Fn(null_tuple, null_tuple))
|
||
END
|
||
call v9.CheckSourceScriptSuccess(lines)
|
||
|
||
" Test for concatenating to lists containing tuples
|
||
let lines =<< trim END
|
||
var x = [test_null_tuple()] + [test_null_tuple()]
|
||
assert_equal([(), ()], x)
|
||
var y = [()] + [()]
|
||
assert_equal([(), ()], y)
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
endfunc
|
||
|
||
" Test for comparing tuples
|
||
func Test_tuple_compare()
|
||
let lines =<< trim END
|
||
call assert_false((1, 2) == (1, 3))
|
||
call assert_true((1, 2) == (1, 2))
|
||
call assert_true((1,) == (1,))
|
||
call assert_true(() == ())
|
||
call assert_false((1, 2) == (1, 2, 3))
|
||
call assert_false((1, 2) == test_null_tuple())
|
||
VAR t1 = (1, 2)
|
||
VAR t2 = t1
|
||
call assert_true(t1 == t2)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
let lines =<< trim END
|
||
echo (1.0, ) == 1.0
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1517: Can only compare Tuple with Tuple',
|
||
\ 'E1072: Cannot compare tuple with float',
|
||
\ 'E1072: Cannot compare tuple with float'])
|
||
|
||
let lines =<< trim END
|
||
echo 1.0 == (1.0,)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1517: Can only compare Tuple with Tuple',
|
||
\ 'E1072: Cannot compare float with tuple',
|
||
\ 'E1072: Cannot compare float with tuple'])
|
||
|
||
let lines =<< trim END
|
||
echo (1, 2) =~ []
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E691: Can only compare List with List',
|
||
\ 'E1072: Cannot compare tuple with list',
|
||
\ 'E1072: Cannot compare tuple with list'])
|
||
|
||
let lines =<< trim END
|
||
echo (1, 2) =~ (1, 2)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1518: Invalid operation for Tuple',
|
||
\ 'E1518: Invalid operation for Tuple',
|
||
\ 'E1518: Invalid operation for Tuple'])
|
||
endfunc
|
||
|
||
" Test for assigning multiple items from a tuple
|
||
func Test_multi_assign_from_tuple()
|
||
let lines =<< trim END
|
||
VAR [v1, v2] = ('a', 'b')
|
||
call assert_equal(['a', 'b'], [v1, v2])
|
||
|
||
VAR [v3] = ('c',)
|
||
call assert_equal('c', v3)
|
||
|
||
VAR [v4; v5] = ('a', 'b', 'c')
|
||
call assert_equal('a', v4)
|
||
call assert_equal(('b', 'c'), v5)
|
||
|
||
VAR [v6; v7] = ('a',)
|
||
call assert_equal('a', v6)
|
||
call assert_equal((), v7)
|
||
|
||
VAR sum = 0
|
||
for [v8, v9] in ((2, 2), (2, 3))
|
||
LET sum += v8 * v9
|
||
endfor
|
||
call assert_equal(10, sum)
|
||
|
||
#" for: rest of the items in a List
|
||
LET sum = 0
|
||
for [v10; v11] in ((2, 1, 2, 5), (2, 1, 2, 10))
|
||
LET sum += v10 * max(v11)
|
||
endfor
|
||
call assert_equal(30, sum)
|
||
|
||
#" for: one item in the list
|
||
LET sum = 0
|
||
for [v12; v13] in ((2, 6), (2, 7))
|
||
LET sum += v12 * max(v13)
|
||
endfor
|
||
call assert_equal(26, sum)
|
||
|
||
#" for: zero items in the list
|
||
LET sum = 0
|
||
for [v14; v15] in ((4,), (5,))
|
||
LET sum += v14 + max(v15)
|
||
endfor
|
||
call assert_equal(9, sum)
|
||
|
||
#" A null tuple should be treated like an empty tuple
|
||
for [v16, v17] in test_null_tuple()
|
||
endfor
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<...list<number>> = (4, 8)
|
||
var [x: number, y: number] = t
|
||
assert_equal([4, 8], [x, y])
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
" Test a mix lists and tuples with "any" type
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(x: any): string
|
||
var str = ''
|
||
for [a, b] in x
|
||
str ..= a .. b
|
||
endfor
|
||
return str
|
||
enddef
|
||
# List of lists
|
||
assert_equal('abcd', Fn([['a', 'b'], ['c', 'd']]))
|
||
# List of tuples
|
||
assert_equal('abcd', Fn([('a', 'b'), ('c', 'd')]))
|
||
# Tuple of lists
|
||
assert_equal('abcd', Fn((['a', 'b'], ['c', 'd'])))
|
||
# Tuple of tuples
|
||
assert_equal('abcd', Fn((('a', 'b'), ('c', 'd'))))
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
VAR [v1, v2] = ('a', 'b', 'c')
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1537: Less targets than Tuple items',
|
||
\ 'E1093: Expected 2 items but got 3',
|
||
\ 'E1537: Less targets than Tuple items'])
|
||
|
||
let lines =<< trim END
|
||
VAR [v1, v2, v3] = ('a', 'b')
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1538: More targets than Tuple items',
|
||
\ 'E1093: Expected 3 items but got 2',
|
||
\ 'E1538: More targets than Tuple items'])
|
||
|
||
let lines =<< trim END
|
||
VAR [v1; v2] = test_null_tuple()
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1536: Tuple required',
|
||
\ 'E1093: Expected 1 items but got 0',
|
||
\ 'E1536: Tuple required'])
|
||
|
||
let lines =<< trim END
|
||
for [v1, v2] in (('a', 'b', 'c'),)
|
||
endfor
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1537: Less targets than Tuple items',
|
||
\ 'E1537: Less targets than Tuple items',
|
||
\ 'E1537: Less targets than Tuple items'])
|
||
|
||
let lines =<< trim END
|
||
for [v1, v2] in (('a',),)
|
||
endfor
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1538: More targets than Tuple items',
|
||
\ 'E1538: More targets than Tuple items',
|
||
\ 'E1538: More targets than Tuple items'])
|
||
|
||
let lines =<< trim END
|
||
for [v1, v2] in (test_null_tuple(),)
|
||
endfor
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1536: Tuple required',
|
||
\ 'E1538: More targets than Tuple items',
|
||
\ 'E1536: Tuple required'])
|
||
|
||
let lines =<< trim END
|
||
for [v1; v2] in (test_null_tuple(),)
|
||
endfor
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1536: Tuple required',
|
||
\ 'E1538: More targets than Tuple items',
|
||
\ 'E1536: Tuple required'])
|
||
|
||
" List assignment errors using a function tuple argument
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(x: tuple<...list<number>>)
|
||
var [a, b] = x
|
||
enddef
|
||
Fn((1, 2, 3))
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1093: Expected 2 items but got 3')
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(x: tuple<number>)
|
||
var [a, b] = x
|
||
enddef
|
||
Fn((1,))
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1093: Expected 2 items but got 1')
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(x: tuple<number>)
|
||
var [a, b] = x
|
||
enddef
|
||
Fn(null_tuple)
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1093: Expected 2 items but got 0')
|
||
endfunc
|
||
|
||
" Test for performing an arithmetic operation on multiple variables using
|
||
" items from a tuple
|
||
func Test_multi_arithmetic_op_from_tuple()
|
||
let lines =<< trim END
|
||
VAR x = 10
|
||
VAR y = 10
|
||
LET [x, y] += (2, 4)
|
||
call assert_equal([12, 14], [x, y])
|
||
LET [x, y] -= (4, 2)
|
||
call assert_equal([8, 12], [x, y])
|
||
LET [x, y] *= (2, 3)
|
||
call assert_equal([16, 36], [x, y])
|
||
LET [x, y] /= (4, 2)
|
||
call assert_equal([4, 18], [x, y])
|
||
LET [x, y] %= (3, 5)
|
||
call assert_equal([1, 3], [x, y])
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
" The "." operator is supported only in Vim script
|
||
let lines =<< trim END
|
||
let x = 'a'
|
||
let y = 'b'
|
||
let [x, y] .= ('a', 'b')
|
||
call assert_equal(['aa', 'bb'], [x, y])
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
VAR x = 'a'
|
||
VAR y = 'b'
|
||
LET [x, y] ..= ('a', 'b')
|
||
call assert_equal(('aa', 'bb'), (x, y))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for using a tuple in a for statement
|
||
func Test_tuple_for()
|
||
let lines =<< trim END
|
||
VAR sum = 0
|
||
for v1 in (1, 3, 5)
|
||
LET sum += v1
|
||
endfor
|
||
call assert_equal(9, sum)
|
||
|
||
LET sum = 0
|
||
for v2 in ()
|
||
LET sum += v2
|
||
endfor
|
||
call assert_equal(0, sum)
|
||
|
||
LET sum = 0
|
||
for v2 in test_null_tuple()
|
||
LET sum += v2
|
||
endfor
|
||
call assert_equal(0, sum)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
" ignoring the for loop assignment using '_'
|
||
let lines =<< trim END
|
||
vim9script
|
||
var count = 0
|
||
for _ in (1, 2, 3)
|
||
count += 1
|
||
endfor
|
||
assert_equal(3, count)
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
var sum = 0
|
||
for v in null_tuple
|
||
sum += v
|
||
endfor
|
||
assert_equal(0, sum)
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Foo()
|
||
for x in ((1, 2), (3, 4))
|
||
endfor
|
||
enddef
|
||
Foo()
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
|
||
" Test for assigning multiple items from a tuple in a for loop
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn()
|
||
for [x, y] in ([1, 2],)
|
||
assert_equal([1, 2], [x, y])
|
||
endfor
|
||
enddef
|
||
defcompile
|
||
Fn()
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
|
||
" iterate over tuple<...list<number>
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn()
|
||
var t: tuple<...list<number>> = (1, 2)
|
||
var sum = 0
|
||
for i: number in t
|
||
sum += i
|
||
endfor
|
||
assert_equal(3, sum)
|
||
enddef
|
||
Fn()
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
|
||
" iterate over tuple<...list<list<number>>>
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn()
|
||
var t: tuple<...list<list<number>>> = ([1, 2], [3, 4])
|
||
var sum = 0
|
||
for [x: number, y: number] in t
|
||
sum += x + y
|
||
endfor
|
||
assert_equal(10, sum)
|
||
enddef
|
||
Fn()
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
|
||
" iterate over tuple<...list<tuple<...list<number>>>>
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn()
|
||
var t: tuple<...list<tuple<...list<number>>>> = ((1, 2), (3, 4))
|
||
var sum = 0
|
||
for [x: number, y: number] in t
|
||
sum += x + y
|
||
endfor
|
||
assert_equal(10, sum)
|
||
enddef
|
||
Fn()
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
|
||
" iterate over tuple<...list<list<number>>>
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn()
|
||
var t: tuple<...list<list<number>>> = ([1, 2], [3, 4])
|
||
var sum = 0
|
||
for [x: number, y: number] in t
|
||
sum += x + y
|
||
endfor
|
||
assert_equal(10, sum)
|
||
enddef
|
||
Fn()
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
|
||
" iterate over a tuple<...list<any>>
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn()
|
||
var t: tuple<...list<any>> = (1, 'x', true, [], {}, ())
|
||
var str = ''
|
||
for v in t
|
||
str ..= string(v)
|
||
endfor
|
||
assert_equal("1'x'true[]{}()", str)
|
||
enddef
|
||
Fn()
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
|
||
" use multiple variable assignment syntax with a tuple<...list<number>>
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn()
|
||
var t: tuple<...list<number>> = (1, 2, 3)
|
||
for [i] in t
|
||
endfor
|
||
enddef
|
||
Fn()
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1140: :for argument must be a sequence of lists or tuples', 2)
|
||
endfunc
|
||
|
||
" Test for checking the tuple type in assignment and return value
|
||
func Test_tuple_type_check()
|
||
let lines =<< trim END
|
||
var t: tuple<...list<number>> = ('a', 'b')
|
||
END
|
||
call v9.CheckSourceDefFailure(lines, 'E1012: Type mismatch; expected tuple<...list<number>> but got tuple<string, string>', 1)
|
||
|
||
let lines =<< trim END
|
||
var t1: tuple<...list<string>> = ('a', 'b')
|
||
assert_equal(('a', 'b'), t1)
|
||
var t2 = (1, 2)
|
||
assert_equal((1, 2), t2)
|
||
var t = null_tuple
|
||
assert_equal(null_tuple, t)
|
||
t = test_null_tuple()
|
||
assert_equal(test_null_tuple(), t)
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
var t = ('a', 'b')
|
||
t = (1, 2)
|
||
END
|
||
call v9.CheckSourceDefFailure(lines, 'E1012: Type mismatch; expected tuple<string, string> but got tuple<number, number>', 2)
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<number> = []
|
||
END
|
||
call v9.CheckSourceDefFailure(lines, 'E1012: Type mismatch; expected tuple<number> but got list<any>', 1)
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<number> = {}
|
||
END
|
||
call v9.CheckSourceDefFailure(lines, 'E1012: Type mismatch; expected tuple<number> but got dict<any>', 1)
|
||
|
||
let lines =<< trim END
|
||
var l: list<number> = (1, 2)
|
||
END
|
||
call v9.CheckSourceDefFailure(lines, 'E1012: Type mismatch; expected list<number> but got tuple<number, number>', 1)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(): tuple<...list<tuple<...list<string>>>>
|
||
return ((1, 2), (3, 4))
|
||
enddef
|
||
defcompile
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected tuple<...list<tuple<...list<string>>>> but got tuple<tuple<number, number>, tuple<number, number>>', 1)
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<number> = ()
|
||
END
|
||
call v9.CheckSourceDefSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(): tuple<tuple<string>>
|
||
return ()
|
||
enddef
|
||
defcompile
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(t: tuple<...list<number>>)
|
||
enddef
|
||
Fn(('a', 'b'))
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1013: Argument 1: type mismatch, expected tuple<...list<number>> but got tuple<string, string>')
|
||
|
||
let lines =<< trim END
|
||
var t: any = (1, 2)
|
||
t = ('a', 'b')
|
||
END
|
||
call v9.CheckSourceDefSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<...list<any>> = (1, 2)
|
||
t = ('a', 'b')
|
||
END
|
||
call v9.CheckSourceDefSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
var nll: tuple<list<number>> = ([1, 2],)
|
||
nll->copy()[0]->extend(['x'])
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, [
|
||
\ 'E1013: Argument 2: type mismatch, expected list<number> but got list<string>',
|
||
\ 'E1013: Argument 2: type mismatch, expected list<number> but got list<string> in extend()'])
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(y: tuple<number, ...list<bool>>)
|
||
var x: tuple<number, ...list<string>>
|
||
x = y
|
||
enddef
|
||
|
||
var t: tuple<number, ...list<bool>> = (1, true, false)
|
||
Fn(t)
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1012: Type mismatch; expected tuple<number, ...list<string>> but got tuple<number, ...list<bool>>')
|
||
endfunc
|
||
|
||
" Test for setting the type of a script variable to tuple
|
||
func Test_tuple_scriptvar_type()
|
||
" Uninitialized script variable should retain the type
|
||
let lines =<< trim END
|
||
vim9script
|
||
var foobar: tuple<list<string>>
|
||
def Foo()
|
||
var x = foobar
|
||
assert_equal('tuple<list<string>>', typename(x))
|
||
enddef
|
||
Foo()
|
||
END
|
||
call v9.CheckSourceScriptSuccess(lines)
|
||
|
||
" Initialized script variable should retain the type
|
||
let lines =<< trim END
|
||
vim9script
|
||
var foobar: tuple<...list<string>> = ('a', 'b')
|
||
def Foo()
|
||
var x = foobar
|
||
assert_equal('tuple<...list<string>>', typename(x))
|
||
enddef
|
||
Foo()
|
||
END
|
||
call v9.CheckSourceScriptSuccess(lines)
|
||
endfunc
|
||
|
||
" Test for modifying a tuple
|
||
func Test_tuple_modify()
|
||
let lines =<< trim END
|
||
var t = (1, 2)
|
||
t[0] = 3
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, ['E1532: Cannot modify a tuple', 'E1532: Cannot modify a tuple'])
|
||
endfunc
|
||
|
||
def Test_using_null_tuple()
|
||
var lines =<< trim END
|
||
var x = null_tuple
|
||
assert_true(x is null_tuple)
|
||
var y = copy(x)
|
||
assert_true(y is null_tuple)
|
||
call assert_true((1, 2) != null_tuple)
|
||
call assert_true(null_tuple != (1, 2))
|
||
assert_equal(0, count(null_tuple, 'xx'))
|
||
var z = deepcopy(x)
|
||
assert_true(z is null_tuple)
|
||
assert_equal(1, empty(x))
|
||
assert_equal('xx', get(x, 0, 'xx'))
|
||
assert_equal(-1, index(null_tuple, 10))
|
||
assert_equal(-1, indexof(null_tuple, 'v:val == 2'))
|
||
assert_equal('', join(null_tuple))
|
||
assert_equal(0, len(x))
|
||
assert_equal(0, min(null_tuple))
|
||
assert_equal(0, max(null_tuple))
|
||
assert_equal((), repeat(null_tuple, 3))
|
||
assert_equal((), reverse(null_tuple))
|
||
assert_equal((), slice(null_tuple, 0, 0))
|
||
assert_equal('()', string(x))
|
||
assert_equal('tuple<any>', typename(x))
|
||
assert_equal(17, type(x))
|
||
END
|
||
v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
lines =<< trim END
|
||
# An uninitialized tuple is not equal to null
|
||
var t1: tuple<any>
|
||
assert_true(t1 != null)
|
||
|
||
# An empty tuple is equal to null_tuple but not equal to null
|
||
var t2: tuple<any> = ()
|
||
assert_true(t2 == null_tuple)
|
||
assert_true(t2 != null)
|
||
|
||
# null_tuple is equal to null
|
||
assert_true(null_tuple == null)
|
||
END
|
||
v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
lines =<< trim END
|
||
var x = null_tupel
|
||
END
|
||
v9.CheckSourceDefAndScriptFailure(lines, [
|
||
\ 'E1001: Variable not found: null_tupel',
|
||
\ 'E121: Undefined variable: null_tupel'])
|
||
enddef
|
||
|
||
" Test for modifying a mutable item in a tuple
|
||
func Test_tuple_modify_mutable_item()
|
||
let lines =<< trim END
|
||
VAR t = ('a', ['b', 'c'], {'a': 10, 'b': 20})
|
||
LET t[1][1] = 'x'
|
||
LET t[2].a = 30
|
||
call assert_equal(('a', ['b', 'x'], {'a': 30, 'b': 20}), t)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
let lines =<< trim END
|
||
VAR t = ('a', (['b'], 'c'))
|
||
LET t[1][0][0] = 'x'
|
||
call assert_equal(('a', (['x'], 'c')), t)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
" Use a negative index
|
||
let lines =<< trim END
|
||
VAR t = ([1, 2], [3])
|
||
LET t[-2][-2] = 5
|
||
call assert_equal(([5, 2], [3]), t)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
let lines =<< trim END
|
||
VAR t = ('a', ('b', 'c'))
|
||
LET t[1][0] = 'x'
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1532: Cannot modify a tuple',
|
||
\ 'E1532: Cannot modify a tuple',
|
||
\ 'E1532: Cannot modify a tuple'])
|
||
|
||
let lines =<< trim END
|
||
VAR t = ['a', ('b', 'c')]
|
||
LET t[1][0] = 'x'
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1532: Cannot modify a tuple',
|
||
\ 'E1532: Cannot modify a tuple',
|
||
\ 'E1532: Cannot modify a tuple'])
|
||
|
||
let lines =<< trim END
|
||
VAR t = {'a': ('b', 'c')}
|
||
LET t['a'][0] = 'x'
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1532: Cannot modify a tuple',
|
||
\ 'E1532: Cannot modify a tuple',
|
||
\ 'E1532: Cannot modify a tuple'])
|
||
|
||
let lines =<< trim END
|
||
VAR t = {'a': ['b', ('c',)]}
|
||
LET t['a'][1][0] = 'x'
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1532: Cannot modify a tuple',
|
||
\ 'E1532: Cannot modify a tuple',
|
||
\ 'E1532: Cannot modify a tuple'])
|
||
|
||
let lines =<< trim END
|
||
let t = ('a', 'b', 'c', 'd')
|
||
let t[1 : 2] = ('x', 'y')
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1533: Cannot slice a tuple')
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<...list<string>> = ('a', 'b', 'c', 'd')
|
||
t[1 : 2] = ('x', 'y')
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, [
|
||
\ 'E1533: Cannot slice a tuple',
|
||
\ 'E1533: Cannot slice a tuple'])
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<...list<string>> = ('a', 'b', 'c', 'd')
|
||
t[ : 2] = ('x', 'y')
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, [
|
||
\ 'E1533: Cannot slice a tuple',
|
||
\ 'E1533: Cannot slice a tuple'])
|
||
|
||
let lines =<< trim END
|
||
let t = ('a', 'b', 'c', 'd')
|
||
let t[ : ] = ('x', 'y')
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1533: Cannot slice a tuple')
|
||
|
||
let lines =<< trim END
|
||
var t: tuple<...list<string>> = ('a', 'b', 'c', 'd')
|
||
t[ : ] = ('x', 'y')
|
||
END
|
||
call v9.CheckSourceDefAndScriptFailure(lines, [
|
||
\ 'E1533: Cannot slice a tuple',
|
||
\ 'E1533: Cannot slice a tuple'])
|
||
|
||
let lines =<< trim END
|
||
VAR t = ('abc',)
|
||
LET t[0][1] = 'x'
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ "E689: Index not allowed after a string: t[0][1] = 'x'",
|
||
\ 'E1148: Cannot index a string',
|
||
\ "E689: Index not allowed after a string: t[0][1] = 'x'"])
|
||
|
||
" Out of range indexing
|
||
let lines =<< trim END
|
||
VAR t = ([1, 2], [3])
|
||
LET t[2][0] = 5
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1519: Tuple index out of range: 2',
|
||
\ 'E1519: Tuple index out of range: 2',
|
||
\ 'E1519: Tuple index out of range: 2'])
|
||
|
||
let lines =<< trim END
|
||
VAR t = ([1, 2], [3])
|
||
LET t[-3][0] = 5
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1519: Tuple index out of range: -3',
|
||
\ 'E1519: Tuple index out of range: -3',
|
||
\ 'E1519: Tuple index out of range: -3'])
|
||
|
||
" Use a null tuple
|
||
let lines =<< trim END
|
||
VAR t = test_null_tuple()
|
||
LET t[0][0] = 5
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1519: Tuple index out of range: 0',
|
||
\ 'E1519: Tuple index out of range: 0',
|
||
\ 'E1519: Tuple index out of range: 0'])
|
||
endfunc
|
||
|
||
" Test for locking and unlocking a tuple variable
|
||
func Test_tuple_lock()
|
||
" lockvar 0
|
||
let g:t = ([0, 1],)
|
||
let lines =<< trim END
|
||
lockvar 0 g:t
|
||
LET g:t = ()
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1122: Variable is locked: g:t',
|
||
\ 'E1122: Variable is locked: t',
|
||
\ 'E1122: Variable is locked: g:t'])
|
||
unlet g:t
|
||
|
||
" Tuple is immutable. So "lockvar 1" is not applicable to a tuple.
|
||
|
||
" lockvar 2
|
||
let g:t = ([0, 1],)
|
||
let lines =<< trim END
|
||
lockvar 2 g:t
|
||
call add(g:t[0], 2)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E741: Value is locked: add() argument',
|
||
\ 'E741: Value is locked: add() argument',
|
||
\ 'E741: Value is locked: add() argument'])
|
||
unlet g:t
|
||
|
||
" lockvar 3
|
||
let g:t = ([0, 1],)
|
||
let lines =<< trim END
|
||
lockvar 3 g:t
|
||
LET g:t[0][0] = 10
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E741: Value is locked: g:t[0][0] = 10',
|
||
\ 'E1119: Cannot change locked list item',
|
||
\ 'E741: Value is locked: g:t[0][0] = 10'])
|
||
unlet g:t
|
||
|
||
let lines =<< trim END
|
||
VAR t = ([0, 1],)
|
||
lockvar 2 t
|
||
call add(t[0], 2)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E741: Value is locked: add() argument',
|
||
\ 'E1178: Cannot lock or unlock a local variable',
|
||
\ 'E741: Value is locked: add() argument'])
|
||
|
||
let lines =<< trim END
|
||
LET g:t = ([0, 1],)
|
||
lockvar 2 g:t
|
||
unlockvar 2 g:t
|
||
call add(g:t[0], 3)
|
||
call assert_equal(([0, 1, 3], ), g:t)
|
||
unlet g:t
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
let lines =<< trim END
|
||
VAR t1 = (1, 2)
|
||
const t2 = t1
|
||
LET t2 = ()
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E741: Value is locked: t2',
|
||
\ 'E1018: Cannot assign to a constant: t2',
|
||
\ 'E46: Cannot change read-only variable "t2"'])
|
||
endfunc
|
||
|
||
" Test for using a class as a tuple item
|
||
func Test_tuple_use_class_item()
|
||
let lines =<< trim END
|
||
vim9script
|
||
class A
|
||
endclass
|
||
var t = (A,)
|
||
END
|
||
call v9.CheckSourceScriptFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
class A
|
||
endclass
|
||
var t = ('a', A)
|
||
END
|
||
call v9.CheckSourceScriptFailure(lines, 'E1405: Class "A" cannot be used as a value', 4)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
class A
|
||
endclass
|
||
def Fn()
|
||
var t = (A,)
|
||
enddef
|
||
defcompile
|
||
END
|
||
call v9.CheckSourceScriptFailure(lines, 'E1405: Class "A" cannot be used as a value', 1)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
class A
|
||
endclass
|
||
def Fn()
|
||
var t = ('a', A)
|
||
enddef
|
||
defcompile
|
||
END
|
||
call v9.CheckSourceScriptFailure(lines, 'E1405: Class "A" cannot be used as a value', 1)
|
||
endfunc
|
||
|
||
" Test for using a user-defined type as a tuple item
|
||
func Test_tuple_user_defined_type_as_item()
|
||
let lines =<< trim END
|
||
vim9script
|
||
type N = number
|
||
var t = (N,)
|
||
END
|
||
call v9.CheckSourceScriptFailure(lines, 'E1403: Type alias "N" cannot be used as a value', 3)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
type N = number
|
||
var t = ('a', N)
|
||
END
|
||
call v9.CheckSourceScriptFailure(lines, 'E1403: Type alias "N" cannot be used as a value', 3)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
type N = number
|
||
def Fn()
|
||
var t = (N,)
|
||
enddef
|
||
defcompile
|
||
END
|
||
call v9.CheckSourceScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value', 1)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
type N = number
|
||
def Fn()
|
||
var t = ('a', N)
|
||
enddef
|
||
defcompile
|
||
END
|
||
call v9.CheckSourceScriptFailure(lines, 'E1407: Cannot use a Typealias as a variable or value', 1)
|
||
endfunc
|
||
|
||
" Test for using a tuple as a function argument
|
||
func Test_tuple_func_arg()
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(t: tuple<...list<string>>): tuple<...list<string>>
|
||
return t[:]
|
||
enddef
|
||
var r1 = Fn(('a', 'b'))
|
||
assert_equal(('a', 'b'), r1)
|
||
var r2 = Fn(('a',))
|
||
assert_equal(('a',), r2)
|
||
var r3 = Fn(())
|
||
assert_equal((), r3)
|
||
var r4 = Fn(null_tuple)
|
||
assert_equal((), r4)
|
||
END
|
||
call v9.CheckSourceScriptSuccess(lines)
|
||
|
||
func TupleArgFunc(t)
|
||
return a:t[:]
|
||
endfunc
|
||
let r = TupleArgFunc(('a', 'b'))
|
||
call assert_equal(('a', 'b'), r)
|
||
let r = TupleArgFunc(('a',))
|
||
call assert_equal(('a',), r)
|
||
let r = TupleArgFunc(())
|
||
call assert_equal((), r)
|
||
let r = TupleArgFunc(test_null_tuple())
|
||
call assert_equal((), r)
|
||
delfunc TupleArgFunc
|
||
endfunc
|
||
|
||
" Test for tuple identity
|
||
func Test_tuple_identity()
|
||
let lines =<< trim END
|
||
call assert_false((1, 2) is (1, 2))
|
||
call assert_true((1, 2) isnot (1, 2))
|
||
call assert_true((1, 2) isnot test_null_tuple())
|
||
VAR t1 = ('abc', 'def')
|
||
VAR t2 = t1
|
||
call assert_true(t2 is t1)
|
||
VAR t3 = (1, 2)
|
||
call assert_false(t3 is t1)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for using a compound op with a tuple
|
||
func Test_tuple_compound_op()
|
||
let lines =<< trim END
|
||
VAR t = (1, 2)
|
||
LET t += (3,)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E734: Wrong variable type for +=',
|
||
\ 'E734: Wrong variable type for +=',
|
||
\ 'E734: Wrong variable type for +='])
|
||
|
||
for op in ['-', '*', '/', '%']
|
||
let lines =<< trim eval END
|
||
VAR t = (1, 2)
|
||
LET t {op}= (3,)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ $'E734: Wrong variable type for {op}=',
|
||
\ $'E734: Wrong variable type for {op}=',
|
||
\ $'E734: Wrong variable type for {op}='])
|
||
endfor
|
||
|
||
let lines =<< trim END
|
||
VAR t = (1, 2)
|
||
LET t ..= (3,)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E734: Wrong variable type for .=',
|
||
\ 'E1019: Can only concatenate to string',
|
||
\ 'E734: Wrong variable type for .='])
|
||
endfunc
|
||
|
||
" Test for using the falsy operator with tuple
|
||
func Test_tuple_falsy_op()
|
||
let lines =<< trim END
|
||
VAR t = test_null_tuple()
|
||
call assert_equal('null tuple', t ?? 'null tuple')
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for tuple typecasting
|
||
def Test_tuple_typecast()
|
||
var lines =<< trim END
|
||
var x = <tuple<number>>('a', 'b')
|
||
END
|
||
v9.CheckSourceDefAndScriptFailure(lines, [
|
||
\ 'E1012: Type mismatch; expected tuple<number> but got tuple<string, string>',
|
||
\ 'E1012: Type mismatch; expected tuple<number> but got tuple<string, string>'])
|
||
enddef
|
||
|
||
" Test for using a tuple in string interpolation
|
||
def Test_tuple_string_interop()
|
||
var lines =<< trim END
|
||
VAR emptytuple = ()
|
||
call assert_equal("a()b", $'a{emptytuple}b')
|
||
VAR nulltuple = test_null_tuple()
|
||
call assert_equal("a()b", $'a{nulltuple}b')
|
||
|
||
#" Tuple interpolation
|
||
VAR t = ('a', 'b', 'c')
|
||
call assert_equal("x('a', 'b', 'c')x", $'x{t}x')
|
||
END
|
||
v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
lines =<< trim END
|
||
call assert_equal("a()b", $'a{null_tuple}b')
|
||
END
|
||
v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
#" Tuple evaluation in heredoc
|
||
lines =<< trim END
|
||
VAR t1 = ('a', 'b', 'c')
|
||
VAR data =<< eval trim DATA
|
||
let x = {t1}
|
||
DATA
|
||
call assert_equal(["let x = ('a', 'b', 'c')"], data)
|
||
END
|
||
v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
#" Empty tuple evaluation in heredoc
|
||
lines =<< trim END
|
||
VAR t1 = ()
|
||
VAR data =<< eval trim DATA
|
||
let x = {t1}
|
||
DATA
|
||
call assert_equal(["let x = ()"], data)
|
||
END
|
||
v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
#" Null tuple evaluation in heredoc
|
||
lines =<< trim END
|
||
VAR t1 = test_null_tuple()
|
||
VAR data =<< eval trim DATA
|
||
let x = {t1}
|
||
DATA
|
||
call assert_equal(["let x = ()"], data)
|
||
END
|
||
v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
lines =<< trim END
|
||
var t1 = null_tuple
|
||
var data =<< eval trim DATA
|
||
let x = {t1}
|
||
DATA
|
||
call assert_equal(["let x = ()"], data)
|
||
END
|
||
v9.CheckSourceDefAndScriptSuccess(lines)
|
||
enddef
|
||
|
||
" Test for a return in "finally" block overriding the tuple return value in a
|
||
" try block.
|
||
func Test_try_finally_with_tuple_return()
|
||
let lines =<< trim END
|
||
func s:Fn()
|
||
try
|
||
return (1, 2)
|
||
finally
|
||
return (3, 4)
|
||
endtry
|
||
endfunc
|
||
call assert_equal((3, 4), s:Fn())
|
||
delfunc s:Fn
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn(): tuple<...list<number>>
|
||
try
|
||
return (1, 2)
|
||
finally
|
||
return (3, 4)
|
||
endtry
|
||
enddef
|
||
assert_equal((3, 4), Fn())
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
endfunc
|
||
|
||
" Test for evaluating a recursive tuple that results in an error
|
||
func Test_recursive_tuple_eval_fails()
|
||
let lines =<< trim END
|
||
call assert_fails(((((((((((((((('tag xyz', func2(pat, flags, infn)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E121: Undefined variable: pat',
|
||
\ 'E1001: Variable not found: pat',
|
||
\ 'E121: Undefined variable: pat'])
|
||
endfunc
|
||
|
||
" The following used to crash Vim
|
||
func Test_import_invalid_tuple()
|
||
let lines =<< trim END
|
||
imp(",G0}11*f[+\x","#|
|
||
END
|
||
new
|
||
call setline(1, lines)
|
||
call assert_fails('source', 'E114: Missing double quote: "#|')
|
||
bw!
|
||
endfunc
|
||
|
||
" Test for add() with a tuple
|
||
func Test_tuple_add()
|
||
let lines =<< trim END
|
||
VAR t = (1, 2)
|
||
call add(t, 3)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E897: List or Blob required',
|
||
\ 'E1013: Argument 1: type mismatch, expected list<any> but got tuple<number, number>',
|
||
\ 'E1226: List or Blob required for argument 1'])
|
||
endfunc
|
||
|
||
" Test for copy()
|
||
func Test_tuple_copy()
|
||
let lines =<< trim END
|
||
VAR t1 = (['a', 'b'], ['c', 'd'], ['e', 'f'])
|
||
VAR t2 = copy(t1)
|
||
VAR t3 = t1
|
||
call assert_false(t2 is t1)
|
||
call assert_true(t3 is t1)
|
||
call assert_true(t2[1] is t1[1])
|
||
call assert_equal((), copy(()))
|
||
call assert_equal((), copy(test_null_tuple()))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for count()
|
||
func Test_tuple_count()
|
||
let lines =<< trim END
|
||
VAR t = ('ab', 'cd', 'ab')
|
||
call assert_equal(2, count(t, 'ab'))
|
||
call assert_equal(0, count(t, 'xx'))
|
||
call assert_equal(0, count((), 'xx'))
|
||
call assert_equal(0, count(test_null_tuple(), 'xx'))
|
||
call assert_fails("call count((1, 2), 1, v:true, 2)", 'E1519: Tuple index out of range: 2')
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for deepcopy()
|
||
func Test_tuple_deepcopy()
|
||
let lines =<< trim END
|
||
VAR t1 = (['a', 'b'], ['c', 'd'], ['e', 'f'])
|
||
VAR t2 = deepcopy(t1)
|
||
VAR t3 = t1
|
||
call assert_false(t2 is t1)
|
||
call assert_true(t3 is t1)
|
||
call assert_false(t2[1] is t1[1])
|
||
call assert_equal((), deepcopy(()))
|
||
call assert_equal((), deepcopy(test_null_tuple()))
|
||
|
||
#" copy a recursive tuple
|
||
VAR l = []
|
||
VAR tuple = (l,)
|
||
call add(l, tuple)
|
||
call assert_equal('([(...)], )', string(deepcopy(tuple)))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for empty()
|
||
func Test_tuple_empty()
|
||
let lines =<< trim END
|
||
call assert_true(empty(()))
|
||
call assert_true(empty(test_null_tuple()))
|
||
call assert_false(empty((1, 2)))
|
||
VAR t = ('abc', 'def')
|
||
call assert_false(empty(t))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for eval()
|
||
func Test_tuple_eval()
|
||
let lines =<< trim END
|
||
call assert_equal((), eval('()'))
|
||
call assert_equal(([],), eval('([],)'))
|
||
call assert_equal((1, 2, 3), eval('(1, 2, 3)'))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for extend() with a tuple
|
||
func Test_tuple_extend()
|
||
let lines =<< trim END
|
||
VAR t = (1, 2, 3)
|
||
call extend(t, (4, 5))
|
||
call extendnew(t, (4, 5))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E712: Argument of extend() must be a List or Dictionary',
|
||
\ 'E1013: Argument 1: type mismatch, expected list<any> but got tuple<number, number, number>',
|
||
\ 'E712: Argument of extend() must be a List or Dictionary'])
|
||
endfunc
|
||
|
||
" Test for filter() with a tuple
|
||
func Test_tuple_filter()
|
||
let lines =<< trim END
|
||
VAR t = (1, 2, 3)
|
||
call filter(t, 'v:val == 2')
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1524: Cannot use a tuple with function filter()',
|
||
\ 'E1013: Argument 1: type mismatch, expected list<any> but got tuple<number, number, number>',
|
||
\ 'E1524: Cannot use a tuple with function filter()'])
|
||
endfunc
|
||
|
||
" Test for flatten() with a tuple
|
||
func Test_tuple_flatten()
|
||
let t = ([1, 2], [3, 4], [5, 6])
|
||
call assert_fails("call flatten(t, 2)", 'E686: Argument of flatten() must be a List')
|
||
endfunc
|
||
|
||
" Test for flattennew() with a tuple
|
||
func Test_tuple_flattennew()
|
||
let lines =<< trim END
|
||
var t = ([1, 2], [3, 4], [5, 6])
|
||
flattennew(t, 2)
|
||
END
|
||
call v9.CheckSourceDefFailure(lines, 'E1013: Argument 1: type mismatch, expected list<any> but got tuple<list<number>, list<number>, list<number>>')
|
||
endfunc
|
||
|
||
" Test for foreach() with a tuple
|
||
func Test_tuple_foreach()
|
||
let t = ('a', 'b', 'c')
|
||
let str = ''
|
||
call foreach(t, 'let str ..= v:val')
|
||
call assert_equal('abc', str)
|
||
|
||
let sum = 0
|
||
call foreach(test_null_tuple(), 'let sum += v:val')
|
||
call assert_equal(0, sum)
|
||
|
||
let lines =<< trim END
|
||
def Concatenate(k: number, v: string)
|
||
g:str ..= v
|
||
enddef
|
||
var t = ('a', 'b', 'c')
|
||
var str = 0
|
||
g:str = ''
|
||
call foreach(t, Concatenate)
|
||
call assert_equal('abc', g:str)
|
||
|
||
g:str = ''
|
||
call foreach(test_null_tuple(), Concatenate)
|
||
call assert_equal('', g:str)
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
let lines =<< trim END
|
||
LET g:sum = 0
|
||
call foreach((1, 2, 3), 'LET g:sum += x')
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E121: Undefined variable: x',
|
||
\ 'E121: Undefined variable: x',
|
||
\ 'E121: Undefined variable: x'])
|
||
endfunc
|
||
|
||
" Test for get()
|
||
func Test_tuple_get()
|
||
let lines =<< trim END
|
||
VAR t = (10, 20, 30)
|
||
for [i, v] in [[0, 10], [1, 20], [2, 30], [3, 0]]
|
||
call assert_equal(v, get(t, i))
|
||
endfor
|
||
|
||
for [i, v] in [[-1, 30], [-2, 20], [-3, 10], [-4, 0]]
|
||
call assert_equal(v, get(t, i))
|
||
endfor
|
||
call assert_equal(0, get((), 5))
|
||
call assert_equal('c', get(('a', 'b'), 2, 'c'))
|
||
call assert_equal('x', get(test_null_tuple(), 0, 'x'))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for id()
|
||
func Test_tuple_id()
|
||
let lines =<< trim END
|
||
VAR t1 = (['a'], ['b'], ['c'])
|
||
VAR t2 = (['a'], ['b'], ['c'])
|
||
VAR t3 = t1
|
||
call assert_true(id(t1) != id(t2))
|
||
call assert_true(id(t1) == id(t3))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for index() function
|
||
func Test_tuple_index_func()
|
||
let lines =<< trim END
|
||
VAR t = (88, 33, 99, 77)
|
||
call assert_equal(3, index(t, 77))
|
||
call assert_equal(2, index(t, 99, 1))
|
||
call assert_equal(2, index(t, 99, -4))
|
||
call assert_equal(2, index(t, 99, -5))
|
||
call assert_equal(-1, index(t, 66))
|
||
call assert_equal(-1, index(t, 77, 4))
|
||
call assert_equal(-1, index((), 8))
|
||
call assert_equal(-1, index(test_null_tuple(), 9))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
let lines =<< trim END
|
||
VAR t = (88, 33, 99, 77)
|
||
call assert_equal(-1, index(t, 77, []))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E745: Using a List as a Number',
|
||
\ 'E1013: Argument 3: type mismatch, expected number but got list<any>',
|
||
\ 'E1210: Number required for argument 3'])
|
||
|
||
let lines =<< trim END
|
||
VAR t = (88,)
|
||
call assert_equal(-1, index(t, 77, 1, ()))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1520: Using a Tuple as a Number',
|
||
\ 'E1013: Argument 4: type mismatch, expected bool but got tuple<any>',
|
||
\ 'E1212: Bool required for argument 4'])
|
||
endfunc
|
||
|
||
" Test for indexof()
|
||
func Test_tuple_indexof()
|
||
let lines =<< trim END
|
||
VAR t = ('a', 'b', 'c', 'd')
|
||
call assert_equal(2, indexof(t, 'v:val =~ "c"'))
|
||
call assert_equal(2, indexof(t, 'v:val =~ "c"', {'startidx': 2}))
|
||
call assert_equal(-1, indexof(t, 'v:val =~ "c"', {'startidx': 3}))
|
||
call assert_equal(2, indexof(t, 'v:val =~ "c"', {'startidx': -3}))
|
||
call assert_equal(2, indexof(t, 'v:val =~ "c"', {'startidx': -6}))
|
||
call assert_equal(-1, indexof(t, 'v:val =~ "e"'))
|
||
call assert_equal(-1, indexof((), 'v:val == 1'))
|
||
call assert_equal(-1, indexof(test_null_tuple(), 'v:val == 2'))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
func g:MyIndexOf(k, v)
|
||
echoerr 'MyIndexOf failed'
|
||
endfunc
|
||
let lines =<< trim END
|
||
VAR t = (1, 2, 3)
|
||
echo indexof(t, function('g:MyIndexOf'))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'MyIndexOf failed',
|
||
\ 'MyIndexOf failed',
|
||
\ 'MyIndexOf failed'])
|
||
delfunc g:MyIndexOf
|
||
endfunc
|
||
|
||
" Test for insert()
|
||
func Test_tuple_insert()
|
||
let lines =<< trim END
|
||
VAR t = (1, 2, 3)
|
||
call insert(t, 4)
|
||
call insert(t, 4, 2)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E899: Argument of insert() must be a List or Blob',
|
||
\ 'E1013: Argument 1: type mismatch, expected list<any> but got tuple<number, number, number>',
|
||
\ 'E1226: List or Blob required for argument 1'])
|
||
endfunc
|
||
|
||
" Test for islocked()
|
||
func Test_tuple_islocked()
|
||
let lines =<< trim END
|
||
let t = (1, [2], 3)
|
||
call assert_equal(0, islocked('t'))
|
||
call assert_equal(0, islocked('t[1]'))
|
||
lockvar 1 t
|
||
call assert_equal(1, islocked('t'))
|
||
call assert_equal(0, islocked('t[1]'))
|
||
unlockvar t
|
||
call assert_equal(0, islocked('t'))
|
||
lockvar 2 t
|
||
call assert_equal(1, islocked('t[1]'))
|
||
unlockvar t
|
||
call assert_equal(0, islocked('t[1]'))
|
||
END
|
||
call v9.CheckSourceSuccess(lines)
|
||
endfunc
|
||
|
||
" Test for items()
|
||
func Test_tuple_items()
|
||
let lines =<< trim END
|
||
VAR t = ([], {}, ())
|
||
call assert_equal([[0, []], [1, {}], [2, ()]], items(t))
|
||
call assert_equal([[0, 1]], items((1, )))
|
||
call assert_equal([], items(()))
|
||
call assert_equal([], items(test_null_tuple()))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for join()
|
||
func Test_tuple_join()
|
||
let lines =<< trim END
|
||
VAR t = ('a', 'b', 'c')
|
||
call assert_equal('a b c', join(t))
|
||
call assert_equal('f o o', ('f', 'o', 'o')->join())
|
||
call assert_equal('a-b-c', join(t, '-'))
|
||
call assert_equal('', join(()))
|
||
call assert_equal('', join(test_null_tuple()))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for js_encode()
|
||
func Test_tuple_js_encode()
|
||
let lines =<< trim END
|
||
call assert_equal('["a","b","c"]', js_encode(('a', 'b', 'c')))
|
||
call assert_equal('["a","b"]', js_encode(('a', 'b')))
|
||
call assert_equal('["a"]', js_encode(('a',)))
|
||
call assert_equal("[]", js_encode(()))
|
||
call assert_equal("[]", js_encode(test_null_tuple()))
|
||
call assert_equal('["a",,]', js_encode(('a', v:none)))
|
||
|
||
#" encode a recursive tuple
|
||
VAR l = []
|
||
VAR tuple = (l,)
|
||
call add(l, tuple)
|
||
call assert_equal("[[[]]]", js_encode(tuple))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for json_encode()
|
||
func Test_tuple_json_encode()
|
||
let lines =<< trim END
|
||
call assert_equal('["a","b","c"]', json_encode(('a', 'b', 'c')))
|
||
call assert_equal('["a","b"]', json_encode(('a', 'b')))
|
||
call assert_equal('["a"]', json_encode(('a',)))
|
||
call assert_equal("[]", json_encode(()))
|
||
call assert_equal("[]", json_encode(test_null_tuple()))
|
||
|
||
#" encode a recursive tuple
|
||
VAR l = []
|
||
VAR tuple = (l,)
|
||
call add(l, tuple)
|
||
call assert_equal("[[[]]]", json_encode(tuple))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
let lines =<< trim END
|
||
VAR t = (function('min'), function('max'))
|
||
VAR s = json_encode(t)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1161: Cannot json encode a func',
|
||
\ 'E1161: Cannot json encode a func',
|
||
\ 'E1161: Cannot json encode a func'])
|
||
endfunc
|
||
|
||
" Test for len()
|
||
func Test_tuple_len()
|
||
let lines =<< trim END
|
||
call assert_equal(0, len(()))
|
||
call assert_equal(0, len(test_null_tuple()))
|
||
call assert_equal(1, len(("abc",)))
|
||
call assert_equal(3, len(("abc", "def", "ghi")))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for map() with a tuple
|
||
func Test_tuple_map()
|
||
let t = (1, 3, 5)
|
||
call assert_fails("call map(t, 'v:val + 1')", 'E1524: Cannot use a tuple with function map()')
|
||
endfunc
|
||
|
||
" Test for max()
|
||
func Test_tuple_max()
|
||
let lines =<< trim END
|
||
VAR t1 = (1, 3, 5)
|
||
call assert_equal(5, max(t1))
|
||
VAR t2 = (6,)
|
||
call assert_equal(6, max(t2))
|
||
call assert_equal(0, max(()))
|
||
call assert_equal(0, max(test_null_tuple()))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
var x = max(('a', 2))
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1030: Using a String as a Number: "a"')
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
var x = max((1, 'b'))
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1030: Using a String as a Number: "b"')
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn()
|
||
var x = max(('a', 'b'))
|
||
enddef
|
||
Fn()
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1030: Using a String as a Number: "a"')
|
||
|
||
let lines =<< trim END
|
||
echo max([('a', 'b'), 20])
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1520: Using a Tuple as a Number',
|
||
\ 'E1520: Using a Tuple as a Number',
|
||
\ 'E1520: Using a Tuple as a Number'])
|
||
endfunc
|
||
|
||
" Test for min()
|
||
func Test_tuple_min()
|
||
let lines =<< trim END
|
||
VAR t1 = (5, 3, 1)
|
||
call assert_equal(1, min(t1))
|
||
VAR t2 = (6,)
|
||
call assert_equal(6, min(t2))
|
||
call assert_equal(0, min(()))
|
||
call assert_equal(0, min(test_null_tuple()))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
var x = min(('a', 2))
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1030: Using a String as a Number: "a"')
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
var x = min((1, 'b'))
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1030: Using a String as a Number: "b"')
|
||
|
||
|
||
let lines =<< trim END
|
||
vim9script
|
||
def Fn()
|
||
var x = min(('a', 'b'))
|
||
enddef
|
||
Fn()
|
||
END
|
||
call v9.CheckSourceFailure(lines, 'E1030: Using a String as a Number: "a"')
|
||
endfunc
|
||
|
||
" Test for reduce()
|
||
func Test_tuple_reduce()
|
||
let lines =<< trim END
|
||
call assert_equal(1, reduce((), LSTART acc, val LMIDDLE acc + val LEND, 1))
|
||
call assert_equal(10, reduce((1, 3, 5), LSTART acc, val LMIDDLE acc + val LEND, 1))
|
||
call assert_equal(2 * (2 * ((2 * 1) + 2) + 3) + 4, reduce((2, 3, 4), LSTART acc, val LMIDDLE 2 * acc + val LEND, 1))
|
||
call assert_equal('a x y z', ('x', 'y', 'z')->reduce(LSTART acc, val LMIDDLE acc .. ' ' .. val LEND, 'a'))
|
||
|
||
VAR t = ('x', 'y', 'z')
|
||
call assert_equal(42, reduce(t, function('get'), {'x': {'y': {'z': 42 } } }))
|
||
call assert_equal(('x', 'y', 'z'), t)
|
||
call assert_equal(1, reduce((1,), LSTART acc, val LMIDDLE acc + val LEND))
|
||
call assert_equal('x y z', reduce(('x', 'y', 'z'), LSTART acc, val LMIDDLE acc .. ' ' .. val LEND))
|
||
call assert_equal(5, reduce(test_null_tuple(), LSTART acc, val LMIDDLE acc + val LEND, 5))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
call assert_equal({'x': 1, 'y': 1, 'z': 1 }, ('x', 'y', 'z')->reduce({ acc, val -> extend(acc, { val: 1 }) }, {}))
|
||
|
||
call assert_fails("call reduce((), { acc, val -> acc + val })", 'E998: Reduce of an empty Tuple with no initial value')
|
||
call assert_fails("call reduce(test_null_tuple(), { acc, val -> acc + val })", 'E998: Reduce of an empty Tuple with no initial value')
|
||
|
||
let lines =<< trim END
|
||
echo reduce((1, 2, 3), LSTART acc, val LMIDDLE acc + foo LEND)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E121: Undefined variable: foo',
|
||
\ 'E1001: Variable not found: foo',
|
||
\ 'E1001: Variable not found: foo'])
|
||
endfunc
|
||
|
||
" Test for remove()
|
||
func Test_tuple_remove()
|
||
let lines =<< trim END
|
||
VAR t = (1, 3, 5)
|
||
call remove(t, 1)
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E896: Argument of remove() must be a List, Dictionary or Blob',
|
||
\ 'E1013: Argument 1: type mismatch, expected list<any> but got tuple<number, number, number>',
|
||
\ 'E1228: List, Dictionary or Blob required for argument 1'])
|
||
endfunc
|
||
|
||
" Test for test_refcount()
|
||
func Test_tuple_refcount()
|
||
let lines =<< trim END
|
||
VAR t = (1, 2, 3)
|
||
call assert_equal(1, test_refcount(t))
|
||
VAR x = t
|
||
call assert_equal(2, test_refcount(t))
|
||
LET x = (4, 5, 6)
|
||
call assert_equal(1, test_refcount(t))
|
||
for n in t
|
||
call assert_equal(2, test_refcount(t))
|
||
endfor
|
||
call assert_equal(1, test_refcount(t))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for repeat()
|
||
func Test_tuple_repeat()
|
||
let lines =<< trim END
|
||
VAR t = ('a', 'b')
|
||
call assert_equal(('a', 'b', 'a', 'b', 'a', 'b'), repeat(('a', 'b'), 3))
|
||
call assert_equal(('x', 'x', 'x'), repeat(('x',), 3))
|
||
call assert_equal((), repeat((), 3))
|
||
call assert_equal((), repeat((), 0))
|
||
call assert_equal((), repeat((), -1))
|
||
call assert_equal((), repeat(test_null_tuple(), 3))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for reverse()
|
||
func Test_tuple_reverse()
|
||
let lines =<< trim END
|
||
VAR t = (['a'], ['b'], ['c'])
|
||
call assert_equal((['c'], ['b'], ['a']), reverse(t))
|
||
call assert_equal(('a',), reverse(('a',)))
|
||
call assert_equal((), reverse(()))
|
||
call assert_equal((), reverse(test_null_tuple()))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for slicing a tuple
|
||
func Test_tuple_slice_func()
|
||
let lines =<< trim END
|
||
VAR t = (1, 3, 5, 7, 9)
|
||
call assert_equal((9,), slice(t, 4))
|
||
call assert_equal((5, 7, 9), slice(t, 2))
|
||
call assert_equal((), slice(t, 5))
|
||
call assert_equal((), slice((), 1, 2))
|
||
call assert_equal((), slice(test_null_tuple(), 1, 2))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
" return value of slice() should be the correct tuple type
|
||
let lines =<< trim END
|
||
var t: tuple<...list<number>> = (1, 3, 5)
|
||
var x: tuple<...list<number>> = slice(t, 1, 2)
|
||
assert_equal((3,), x)
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
endfunc
|
||
|
||
" Test for sort()
|
||
func Test_tuple_sort()
|
||
let lines =<< trim END
|
||
call sort([1.1, (1.2,)], 'f')
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1521: Using a Tuple as a Float',
|
||
\ 'E1521: Using a Tuple as a Float',
|
||
\ 'E1521: Using a Tuple as a Float'])
|
||
endfunc
|
||
|
||
" Test for stridx()
|
||
func Test_tuple_stridx()
|
||
let lines =<< trim END
|
||
call stridx(('abc', ), 'a')
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Failure(lines, [
|
||
\ 'E1522: Using a Tuple as a String',
|
||
\ 'E1013: Argument 1: type mismatch, expected string but got tuple<string>',
|
||
\ 'E1174: String required for argument 1'])
|
||
endfunc
|
||
|
||
" Test for string()
|
||
func Test_tuple_string()
|
||
let lines =<< trim END
|
||
VAR t1 = (1, 'as''d', [1, 2, function("strlen")], {'a': 1}, )
|
||
call assert_equal("(1, 'as''d', [1, 2, function('strlen')], {'a': 1})", string(t1))
|
||
|
||
#" empty tuple
|
||
VAR t2 = ()
|
||
call assert_equal("()", string(t2))
|
||
|
||
#" one item tuple
|
||
VAR t3 = ("a", )
|
||
call assert_equal("('a', )", string(t3))
|
||
|
||
call assert_equal("()", string(test_null_tuple()))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
" recursive tuple
|
||
let lines =<< trim END
|
||
VAR l = []
|
||
VAR t = (l,)
|
||
call add(l, t)
|
||
call assert_equal('([(...)], )', string(t))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for type()
|
||
func Test_tuple_type()
|
||
let lines =<< trim END
|
||
VAR t = (1, 2)
|
||
call assert_equal(17, type(t))
|
||
call assert_equal(v:t_tuple, type(t))
|
||
call assert_equal(v:t_tuple, type(()))
|
||
call assert_equal(v:t_tuple, type(test_null_tuple()))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
endfunc
|
||
|
||
" Test for typename()
|
||
func Test_tuple_typename()
|
||
let lines =<< trim END
|
||
call assert_equal('tuple<number, number>', typename((1, 2)))
|
||
call assert_equal('tuple<string, string>', typename(('a', 'b')))
|
||
call assert_equal('tuple<bool, bool>', typename((v:true, v:true)))
|
||
call assert_equal('tuple<number, string>', typename((1, 'b')))
|
||
call assert_equal('tuple<any>', typename(()))
|
||
call assert_equal('tuple<dict<any>>', typename(({}, )))
|
||
call assert_equal('tuple<list<any>>', typename(([], )))
|
||
call assert_equal('tuple<list<number>>', typename(([1, 2], )))
|
||
call assert_equal('tuple<list<string>>', typename((['a', 'b'], )))
|
||
call assert_equal('tuple<list<list<number>>>', typename(([[1], [2]], )))
|
||
call assert_equal('tuple<tuple<number, number>>', typename(((1, 2), )))
|
||
VAR t1 = (([1, 2],), (['a', 'b'],))
|
||
call assert_equal('tuple<tuple<list<number>>, tuple<list<string>>>', typename(t1))
|
||
call assert_equal('list<tuple<number>>', typename([(1,)]))
|
||
call assert_equal('list<tuple<any>>', typename([()]))
|
||
call assert_equal('tuple<any>', typename(test_null_tuple()))
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
let lines =<< trim END
|
||
var d: dict<any> = {a: 0}
|
||
var t2 = (d,)
|
||
t2[0].e = {b: t2}
|
||
call assert_equal('tuple<dict<any>>', typename(t2))
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
" check the type of a circular reference tuple
|
||
let lines =<< trim END
|
||
# circular reference tuple
|
||
var l: list<tuple<any>> = []
|
||
var t = (l,)
|
||
add(l, t)
|
||
assert_equal('tuple<list<tuple<any>>>', typename(t))
|
||
assert_equal('list<tuple<any>>', typename(l))
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
|
||
" When a tuple item is used in a "for" loop, the type is tuple<any>
|
||
let lines =<< trim END
|
||
vim9script
|
||
var l = [(1, 2)]
|
||
for t in l
|
||
assert_equal('tuple<any>', typename(t))
|
||
endfor
|
||
END
|
||
call v9.CheckSourceScriptSuccess(lines)
|
||
|
||
" type of a tuple copy should be the same
|
||
let lines =<< trim END
|
||
var t: tuple<...list<number>> = (1, 2)
|
||
var x: tuple<...list<number>> = t
|
||
assert_equal('tuple<...list<number>>', typename(x))
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
endfunc
|
||
|
||
" Test for saving and restoring tuples from a viminfo file
|
||
func Test_tuple_viminfo()
|
||
let viminfo_save = &viminfo
|
||
set viminfo^=!
|
||
|
||
let g:MYTUPLE = ([1, 2], [3, 4], 'a', 'b', 1, 2)
|
||
|
||
" create a tuple with circular reference
|
||
" This should not be saved in the viminfo file
|
||
let l = []
|
||
let g:CIRCTUPLE = (l,)
|
||
call add(l, g:CIRCTUPLE)
|
||
|
||
wviminfo! Xviminfo
|
||
unlet g:MYTUPLE
|
||
unlet g:CIRCTUPLE
|
||
rviminfo! Xviminfo
|
||
call assert_equal(([1, 2], [3, 4], 'a', 'b', 1, 2), g:MYTUPLE)
|
||
call assert_false(exists('g:CIRCTUPLE'))
|
||
let &viminfo = viminfo_save
|
||
call delete('Xviminfo')
|
||
endfunc
|
||
|
||
" Test for list2tuple()
|
||
func Test_list2tuple()
|
||
let lines =<< trim END
|
||
call assert_equal((), list2tuple([]))
|
||
call assert_equal((), list2tuple(test_null_list()))
|
||
call assert_equal(('a', ['b'], {'n': 20}), list2tuple(['a', ['b'], {'n': 20}]))
|
||
|
||
VAR l = ['a', 'b']
|
||
VAR t = list2tuple(l)
|
||
LET l[0] = 'x'
|
||
call assert_equal(('a', 'b'), t)
|
||
|
||
call assert_equal((0, 1, 2), list2tuple(range(3)))
|
||
|
||
call assert_equal(((),), [()]->list2tuple())
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
call assert_fails('call list2tuple(())', 'E1211: List required for argument 1')
|
||
|
||
" Check the returned type
|
||
let lines =<< trim END
|
||
var l1 = [1, 2]
|
||
var t1: tuple<...list<number>> = list2tuple(l1)
|
||
assert_equal('tuple<...list<number>>', typename(t1))
|
||
var l2 = ['a', 'b']
|
||
var t2: tuple<...list<string>> = list2tuple(l2)
|
||
assert_equal('tuple<...list<string>>', typename(t2))
|
||
var l3 = []
|
||
var t3 = list2tuple(l3)
|
||
assert_equal('tuple<any>', typename(t3))
|
||
var l4 = [([{}])]
|
||
var t4: tuple<list<dict<any>>> = list2tuple(l4)
|
||
assert_equal('tuple<list<dict<any>>>', typename(t4))
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
endfunc
|
||
|
||
" Test for tuple2list()
|
||
func Test_tuple2list()
|
||
let lines =<< trim END
|
||
call assert_equal([], tuple2list(()))
|
||
call assert_equal([], tuple2list(test_null_tuple()))
|
||
|
||
VAR t1 = ('a', ['b'], {'n': 20}, ('a',))
|
||
call assert_equal(['a', ['b'], {'n': 20}, ('a',)], tuple2list(t1))
|
||
|
||
VAR t = ('a', 'b')
|
||
VAR l = tuple2list(t)
|
||
LET l[0] = 'x'
|
||
call assert_equal(('a', 'b'), t)
|
||
|
||
call assert_equal([[]], ([],)->tuple2list())
|
||
END
|
||
call v9.CheckSourceLegacyAndVim9Success(lines)
|
||
|
||
call assert_fails('call tuple2list([])', 'E1534: Tuple required for argument 1')
|
||
|
||
" Check the returned type
|
||
let lines =<< trim END
|
||
var t1 = (1, 2)
|
||
var l1 = tuple2list(t1)
|
||
assert_equal('list<number>', typename(l1))
|
||
var t2 = ('a', 'b')
|
||
var l2 = tuple2list(t2)
|
||
assert_equal('list<string>', typename(l2))
|
||
var t3 = ()
|
||
var l3 = tuple2list(t3)
|
||
assert_equal('list<any>', typename(l3))
|
||
var t4 = ([({},)],)
|
||
var l4 = tuple2list(t4)
|
||
assert_equal('list<list<tuple<dict<any>>>>', typename(l4))
|
||
END
|
||
call v9.CheckSourceDefAndScriptSuccess(lines)
|
||
endfunc
|
||
|
||
" vim: shiftwidth=2 sts=2 expandtab
|