| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- -- $Id: testes/vararg.lua $
- -- See Copyright Notice in file lua.h
- print('testing vararg')
- local function f (a, ...t)
- local x = {n = select('#', ...), ...}
- assert(x.n == t.n)
- for i = 1, x.n do
- assert(a[i] == x[i] and x[i] == t[i])
- end
- return x.n
- end
- local function c12 (...)
- assert(arg == _G.arg) -- no local 'arg'
- local x = {...}; x.n = #x
- local res = (x.n==2 and x[1] == 1 and x[2] == 2)
- if res then res = 55 end
- return res, 2
- end
- local function vararg (... t) return t end
- local call = function (f, args) return f(table.unpack(args, 1, args.n)) end
- assert(f() == 0)
- assert(f({1,2,3}, 1, 2, 3) == 3)
- assert(f({"alo", nil, 45, f, nil}, "alo", nil, 45, f, nil) == 5)
- assert(vararg().n == 0)
- assert(vararg(nil, nil).n == 2)
- assert(c12(1,2)==55)
- local a,b = assert(call(c12, {1,2}))
- assert(a == 55 and b == 2)
- a = call(c12, {1,2;n=2})
- assert(a == 55 and b == 2)
- a = call(c12, {1,2;n=1})
- assert(not a)
- assert(c12(1,2,3) == false)
- local a = vararg(call(next, {_G,nil;n=2}))
- local b,c = next(_G)
- assert(a[1] == b and a[2] == c and a.n == 2)
- a = vararg(call(call, {c12, {1,2}}))
- assert(a.n == 2 and a[1] == 55 and a[2] == 2)
- a = call(print, {'+'})
- assert(a == nil)
- local t = {1, 10}
- function t:f (...) local arg = {...}; return self[...]+#arg end
- assert(t:f(1,4) == 3 and t:f(2) == 11)
- print('+')
- local lim = 20
- local i, a = 1, {}
- while i <= lim do a[i] = i+0.3; i=i+1 end
- function f(a, b, c, d, ...)
- local more = {...}
- assert(a == 1.3 and more[1] == 5.3 and
- more[lim-4] == lim+0.3 and not more[lim-3])
- end
- local function g (a,b,c)
- assert(a == 1.3 and b == 2.3 and c == 3.3)
- end
- call(f, a)
- call(g, a)
- a = {}
- i = 1
- while i <= lim do a[i] = i; i=i+1 end
- assert(call(math.max, a) == lim)
- print("+")
- -- new-style varargs
- local function oneless (a, ...) return ... end
- function f (n, a, ...)
- local b
- assert(arg == _G.arg) -- no local 'arg'
- if n == 0 then
- local b, c, d = ...
- return a, b, c, d, oneless(oneless(oneless(...)))
- else
- n, b, a = n-1, ..., a
- assert(b == ...)
- return f(n, a, ...)
- end
- end
- a,b,c,d,e = assert(f(10,5,4,3,2,1))
- assert(a==5 and b==4 and c==3 and d==2 and e==1)
- a,b,c,d,e = f(4)
- assert(a==nil and b==nil and c==nil and d==nil and e==nil)
- do -- vararg expressions using unpack
- local function aux (a, v, ...t)
- for k, val in pairs(v) do t[k] = val end
- return ...
- end
- local t = table.pack(aux(10, {11, [5] = 24}, 1, 2, 3, nil, 4))
- assert(t.n == 5 and t[1] == 11 and t[2] == 2 and t[3] == 3
- and t[4] == nil and t[5] == 24)
- local t = table.pack(aux(nil, {1, [20] = "a", [30] = "b", n = 30}))
- assert(t.n == 30 and t[1] == 1 and t[20] == "a" and t[30] == "b")
- -- table has only those four elements
- assert(next(t, next(t, next(t, next(t, next(t, nil))))) == nil)
- local a, b, c, d = aux(nil, {}, 10, 20, 30)
- assert(a == 10 and b == 20 and c == 30 and d == nil)
- local function aux (a, b, n, ...t) t.n = n; return b, ... end
- local t = table.pack(aux(10, 1, 10000))
- assert(t.n == 10001 and t[1] == 1 and #t == 1)
- local function checkerr (emsg, f, ...)
- local st, msg = pcall(f, ...)
- assert(not st and string.find(msg, emsg))
- end
- checkerr("no proper 'n'", aux, 1, 1, -1)
- checkerr("no proper 'n'", aux, 1, 1, math.maxinteger)
- checkerr("no proper 'n'", aux, 1, 1, math.mininteger)
- checkerr("no proper 'n'", aux, 1, 1, 1.0)
- end
- -- varargs for main chunks
- local f = assert(load[[ return {...} ]])
- local x = f(2,3)
- assert(x[1] == 2 and x[2] == 3 and x[3] == undef)
- f = load[[
- local x = {...}
- for i=1,select('#', ...) do assert(x[i] == select(i, ...)) end
- assert(x[select('#', ...)+1] == undef)
- return true
- ]]
- assert(f("a", "b", nil, {}, assert))
- assert(f())
- a = {select(3, table.unpack{10,20,30,40})}
- assert(#a == 2 and a[1] == 30 and a[2] == 40)
- a = {select(1)}
- assert(next(a) == nil)
- a = {select(-1, 3, 5, 7)}
- assert(a[1] == 7 and a[2] == undef)
- a = {select(-2, 3, 5, 7)}
- assert(a[1] == 5 and a[2] == 7 and a[3] == undef)
- pcall(select, 10000)
- pcall(select, -10000)
- -- bug in 5.2.2
- function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
- p11, p12, p13, p14, p15, p16, p17, p18, p19, p20,
- p21, p22, p23, p24, p25, p26, p27, p28, p29, p30,
- p31, p32, p33, p34, p35, p36, p37, p38, p39, p40,
- p41, p42, p43, p44, p45, p46, p48, p49, p50, ...)
- local a1,a2,a3,a4,a5,a6,a7
- local a8,a9,a10,a11,a12,a13,a14
- end
- -- assertion fail here
- f()
- -- missing arguments in tail call
- do
- local function f(a,b,c) return c, b end
- local function g() return f(1,2) end
- local a, b = g()
- assert(a == nil and b == 2)
- end
- do -- vararg parameter used in nested functions
- local function foo (...tab1)
- return function (...tab2)
- return {tab1, tab2}
- end
- end
- local f = foo(10, 20, 30)
- local t = f("a", "b")
- assert(t[1].n == 3 and t[1][1] == 10)
- assert(t[2].n == 2 and t[2][1] == "a")
- end
- do -- vararg parameter is read-only
- local st, msg = load("return function (... t) t = 10 end")
- assert(string.find(msg, "const variable 't'"))
- local st, msg = load[[
- local function foo (...extra)
- return function (...) extra = nil end
- end
- ]]
- assert(string.find(msg, "const variable 'extra'"))
- end
- do -- _ENV as vararg parameter
- local st, msg = load[[
- local function aux (... _ENV)
- global <const> a
- a = 10
- end ]]
- assert(string.find(msg, "const variable 'a'"))
- local function aux (..._ENV)
- global a; a = 10
- return a
- end
- assert(aux() == 10)
- local function aux (... _ENV)
- global a = 10
- return a
- end
- assert(aux() == 10)
- end
- do -- access to vararg parameter
- local function notab (keys, t, ...v)
- for _, k in pairs(keys) do
- assert(t[k] == v[k])
- end
- assert(t.n == v.n)
- return ...
- end
- local t = table.pack(10, 20, 30)
- local keys = {-1, 0, 1, t.n, t.n + 1, 1.0, 1.1, "n", print, "k", "1"}
- notab(keys, t, 10, 20, 30) -- ensure stack space
- local m = collectgarbage"count"
- notab(keys, t, 10, 20, 30)
- -- 'notab' does not create any table/object
- assert(m == collectgarbage"count")
- -- writing to the vararg table
- local function foo (...t)
- t[1] = t[1] + 10
- return t[1]
- end
- assert(foo(10, 30) == 20)
- end
- print('OK')
|