vararg.lua 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. -- $Id: testes/vararg.lua $
  2. -- See Copyright Notice in file lua.h
  3. print('testing vararg')
  4. local function f (a, ...t)
  5. local x = {n = select('#', ...), ...}
  6. assert(x.n == t.n)
  7. for i = 1, x.n do
  8. assert(a[i] == x[i] and x[i] == t[i])
  9. end
  10. return x.n
  11. end
  12. local function c12 (...)
  13. assert(arg == _G.arg) -- no local 'arg'
  14. local x = {...}; x.n = #x
  15. local res = (x.n==2 and x[1] == 1 and x[2] == 2)
  16. if res then res = 55 end
  17. return res, 2
  18. end
  19. local function vararg (... t) return t end
  20. local call = function (f, args) return f(table.unpack(args, 1, args.n)) end
  21. assert(f() == 0)
  22. assert(f({1,2,3}, 1, 2, 3) == 3)
  23. assert(f({"alo", nil, 45, f, nil}, "alo", nil, 45, f, nil) == 5)
  24. assert(vararg().n == 0)
  25. assert(vararg(nil, nil).n == 2)
  26. assert(c12(1,2)==55)
  27. local a,b = assert(call(c12, {1,2}))
  28. assert(a == 55 and b == 2)
  29. a = call(c12, {1,2;n=2})
  30. assert(a == 55 and b == 2)
  31. a = call(c12, {1,2;n=1})
  32. assert(not a)
  33. assert(c12(1,2,3) == false)
  34. local a = vararg(call(next, {_G,nil;n=2}))
  35. local b,c = next(_G)
  36. assert(a[1] == b and a[2] == c and a.n == 2)
  37. a = vararg(call(call, {c12, {1,2}}))
  38. assert(a.n == 2 and a[1] == 55 and a[2] == 2)
  39. a = call(print, {'+'})
  40. assert(a == nil)
  41. local t = {1, 10}
  42. function t:f (...) local arg = {...}; return self[...]+#arg end
  43. assert(t:f(1,4) == 3 and t:f(2) == 11)
  44. print('+')
  45. local lim = 20
  46. local i, a = 1, {}
  47. while i <= lim do a[i] = i+0.3; i=i+1 end
  48. function f(a, b, c, d, ...)
  49. local more = {...}
  50. assert(a == 1.3 and more[1] == 5.3 and
  51. more[lim-4] == lim+0.3 and not more[lim-3])
  52. end
  53. local function g (a,b,c)
  54. assert(a == 1.3 and b == 2.3 and c == 3.3)
  55. end
  56. call(f, a)
  57. call(g, a)
  58. a = {}
  59. i = 1
  60. while i <= lim do a[i] = i; i=i+1 end
  61. assert(call(math.max, a) == lim)
  62. print("+")
  63. -- new-style varargs
  64. local function oneless (a, ...) return ... end
  65. function f (n, a, ...)
  66. local b
  67. assert(arg == _G.arg) -- no local 'arg'
  68. if n == 0 then
  69. local b, c, d = ...
  70. return a, b, c, d, oneless(oneless(oneless(...)))
  71. else
  72. n, b, a = n-1, ..., a
  73. assert(b == ...)
  74. return f(n, a, ...)
  75. end
  76. end
  77. a,b,c,d,e = assert(f(10,5,4,3,2,1))
  78. assert(a==5 and b==4 and c==3 and d==2 and e==1)
  79. a,b,c,d,e = f(4)
  80. assert(a==nil and b==nil and c==nil and d==nil and e==nil)
  81. do -- vararg expressions using unpack
  82. local function aux (a, v, ...t)
  83. for k, val in pairs(v) do t[k] = val end
  84. return ...
  85. end
  86. local t = table.pack(aux(10, {11, [5] = 24}, 1, 2, 3, nil, 4))
  87. assert(t.n == 5 and t[1] == 11 and t[2] == 2 and t[3] == 3
  88. and t[4] == nil and t[5] == 24)
  89. local t = table.pack(aux(nil, {1, [20] = "a", [30] = "b", n = 30}))
  90. assert(t.n == 30 and t[1] == 1 and t[20] == "a" and t[30] == "b")
  91. -- table has only those four elements
  92. assert(next(t, next(t, next(t, next(t, next(t, nil))))) == nil)
  93. local a, b, c, d = aux(nil, {}, 10, 20, 30)
  94. assert(a == 10 and b == 20 and c == 30 and d == nil)
  95. local function aux (a, b, n, ...t) t.n = n; return b, ... end
  96. local t = table.pack(aux(10, 1, 10000))
  97. assert(t.n == 10001 and t[1] == 1 and #t == 1)
  98. local function checkerr (emsg, f, ...)
  99. local st, msg = pcall(f, ...)
  100. assert(not st and string.find(msg, emsg))
  101. end
  102. checkerr("no proper 'n'", aux, 1, 1, -1)
  103. checkerr("no proper 'n'", aux, 1, 1, math.maxinteger)
  104. checkerr("no proper 'n'", aux, 1, 1, math.mininteger)
  105. checkerr("no proper 'n'", aux, 1, 1, 1.0)
  106. end
  107. -- varargs for main chunks
  108. local f = assert(load[[ return {...} ]])
  109. local x = f(2,3)
  110. assert(x[1] == 2 and x[2] == 3 and x[3] == undef)
  111. f = load[[
  112. local x = {...}
  113. for i=1,select('#', ...) do assert(x[i] == select(i, ...)) end
  114. assert(x[select('#', ...)+1] == undef)
  115. return true
  116. ]]
  117. assert(f("a", "b", nil, {}, assert))
  118. assert(f())
  119. a = {select(3, table.unpack{10,20,30,40})}
  120. assert(#a == 2 and a[1] == 30 and a[2] == 40)
  121. a = {select(1)}
  122. assert(next(a) == nil)
  123. a = {select(-1, 3, 5, 7)}
  124. assert(a[1] == 7 and a[2] == undef)
  125. a = {select(-2, 3, 5, 7)}
  126. assert(a[1] == 5 and a[2] == 7 and a[3] == undef)
  127. pcall(select, 10000)
  128. pcall(select, -10000)
  129. -- bug in 5.2.2
  130. function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
  131. p11, p12, p13, p14, p15, p16, p17, p18, p19, p20,
  132. p21, p22, p23, p24, p25, p26, p27, p28, p29, p30,
  133. p31, p32, p33, p34, p35, p36, p37, p38, p39, p40,
  134. p41, p42, p43, p44, p45, p46, p48, p49, p50, ...)
  135. local a1,a2,a3,a4,a5,a6,a7
  136. local a8,a9,a10,a11,a12,a13,a14
  137. end
  138. -- assertion fail here
  139. f()
  140. -- missing arguments in tail call
  141. do
  142. local function f(a,b,c) return c, b end
  143. local function g() return f(1,2) end
  144. local a, b = g()
  145. assert(a == nil and b == 2)
  146. end
  147. do -- vararg parameter used in nested functions
  148. local function foo (...tab1)
  149. return function (...tab2)
  150. return {tab1, tab2}
  151. end
  152. end
  153. local f = foo(10, 20, 30)
  154. local t = f("a", "b")
  155. assert(t[1].n == 3 and t[1][1] == 10)
  156. assert(t[2].n == 2 and t[2][1] == "a")
  157. end
  158. do -- vararg parameter is read-only
  159. local st, msg = load("return function (... t) t = 10 end")
  160. assert(string.find(msg, "const variable 't'"))
  161. local st, msg = load[[
  162. local function foo (...extra)
  163. return function (...) extra = nil end
  164. end
  165. ]]
  166. assert(string.find(msg, "const variable 'extra'"))
  167. end
  168. do -- _ENV as vararg parameter
  169. local st, msg = load[[
  170. local function aux (... _ENV)
  171. global <const> a
  172. a = 10
  173. end ]]
  174. assert(string.find(msg, "const variable 'a'"))
  175. local function aux (..._ENV)
  176. global a; a = 10
  177. return a
  178. end
  179. assert(aux() == 10)
  180. local function aux (... _ENV)
  181. global a = 10
  182. return a
  183. end
  184. assert(aux() == 10)
  185. end
  186. do -- access to vararg parameter
  187. local function notab (keys, t, ...v)
  188. for _, k in pairs(keys) do
  189. assert(t[k] == v[k])
  190. end
  191. assert(t.n == v.n)
  192. return ...
  193. end
  194. local t = table.pack(10, 20, 30)
  195. local keys = {-1, 0, 1, t.n, t.n + 1, 1.0, 1.1, "n", print, "k", "1"}
  196. notab(keys, t, 10, 20, 30) -- ensure stack space
  197. local m = collectgarbage"count"
  198. notab(keys, t, 10, 20, 30)
  199. -- 'notab' does not create any table/object
  200. assert(m == collectgarbage"count")
  201. -- writing to the vararg table
  202. local function foo (...t)
  203. t[1] = t[1] + 10
  204. return t[1]
  205. end
  206. assert(foo(10, 30) == 20)
  207. end
  208. print('OK')