goto.lua 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. -- $Id: testes/goto.lua $
  2. -- See Copyright Notice in file lua.h
  3. global<const> require
  4. global<const> print, load, assert, string, setmetatable
  5. global<const> collectgarbage, error
  6. print("testing goto and global declarations")
  7. collectgarbage()
  8. local function errmsg (code, m)
  9. local st, msg = load(code)
  10. assert(not st and string.find(msg, m))
  11. end
  12. -- cannot see label inside block
  13. errmsg([[ goto l1; do ::l1:: end ]], "label 'l1'")
  14. errmsg([[ do ::l1:: end goto l1; ]], "label 'l1'")
  15. -- repeated label
  16. errmsg([[ ::l1:: ::l1:: ]], "label 'l1'")
  17. errmsg([[ ::l1:: do ::l1:: end]], "label 'l1'")
  18. -- jumping over variable declaration
  19. errmsg([[ goto l1; local aa ::l1:: ::l2:: print(3) ]], "scope of 'aa'")
  20. errmsg([[ goto l2; global *; ::l1:: ::l2:: print(3) ]], "scope of '*'")
  21. errmsg([[
  22. do local bb, cc; goto l1; end
  23. local aa
  24. ::l1:: print(3)
  25. ]], "scope of 'aa'")
  26. -- jumping into a block
  27. errmsg([[ do ::l1:: end goto l1 ]], "label 'l1'")
  28. errmsg([[ goto l1 do ::l1:: end ]], "label 'l1'")
  29. -- cannot continue a repeat-until with variables
  30. errmsg([[
  31. repeat
  32. if x then goto cont end
  33. local xuxu = 10
  34. ::cont::
  35. until xuxu < x
  36. ]], "scope of 'xuxu'")
  37. -- simple gotos
  38. local x
  39. do
  40. local y = 12
  41. goto l1
  42. ::l2:: x = x + 1; goto l3
  43. ::l1:: x = y; goto l2
  44. end
  45. ::l3:: ::l3_1:: assert(x == 13)
  46. -- long labels
  47. do
  48. local prog = [[
  49. do
  50. local a = 1
  51. goto l%sa; a = a + 1
  52. ::l%sa:: a = a + 10
  53. goto l%sb; a = a + 2
  54. ::l%sb:: a = a + 20
  55. return a
  56. end
  57. ]]
  58. local label = string.rep("0123456789", 40)
  59. prog = string.format(prog, label, label, label, label)
  60. assert(assert(load(prog))() == 31)
  61. end
  62. -- ok to jump over local dec. to end of block
  63. do
  64. goto l1
  65. local a = 23
  66. x = a
  67. ::l1::;
  68. end
  69. while true do
  70. goto l4
  71. goto l1 -- ok to jump over local dec. to end of block
  72. goto l1 -- multiple uses of same label
  73. local x = 45
  74. ::l1:: ;;;
  75. end
  76. ::l4:: assert(x == 13)
  77. if print then
  78. goto l1 -- ok to jump over local dec. to end of block
  79. error("should not be here")
  80. goto l2 -- ok to jump over local dec. to end of block
  81. local x
  82. ::l1:: ; ::l2:: ;;
  83. else end
  84. -- to repeat a label in a different function is OK
  85. local function foo ()
  86. local a = {}
  87. goto l3
  88. ::l1:: a[#a + 1] = 1; goto l2;
  89. ::l2:: a[#a + 1] = 2; goto l5;
  90. ::l3::
  91. ::l3a:: a[#a + 1] = 3; goto l1;
  92. ::l4:: a[#a + 1] = 4; goto l6;
  93. ::l5:: a[#a + 1] = 5; goto l4;
  94. ::l6:: assert(a[1] == 3 and a[2] == 1 and a[3] == 2 and
  95. a[4] == 5 and a[5] == 4)
  96. if not a[6] then a[6] = true; goto l3a end -- do it twice
  97. end
  98. ::l6:: foo()
  99. do -- bug in 5.2 -> 5.3.2
  100. local x
  101. ::L1::
  102. local y -- cannot join this SETNIL with previous one
  103. assert(y == nil)
  104. y = true
  105. if x == nil then
  106. x = 1
  107. goto L1
  108. else
  109. x = x + 1
  110. end
  111. assert(x == 2 and y == true)
  112. end
  113. -- bug in 5.3
  114. do
  115. local first = true
  116. local a = false
  117. if true then
  118. goto LBL
  119. ::loop::
  120. a = true
  121. ::LBL::
  122. if first then
  123. first = false
  124. goto loop
  125. end
  126. end
  127. assert(a)
  128. end
  129. do -- compiling infinite loops
  130. goto escape -- do not run the infinite loops
  131. ::a:: goto a
  132. ::b:: goto c
  133. ::c:: goto b
  134. end
  135. ::escape::
  136. --------------------------------------------------------------------------------
  137. -- testing closing of upvalues
  138. local debug = require 'debug'
  139. local function foo ()
  140. local t = {}
  141. do
  142. local i = 1
  143. local a, b, c, d
  144. t[1] = function () return a, b, c, d end
  145. ::l1::
  146. local b
  147. do
  148. local c
  149. t[#t + 1] = function () return a, b, c, d end -- t[2], t[4], t[6]
  150. if i > 2 then goto l2 end
  151. do
  152. local d
  153. t[#t + 1] = function () return a, b, c, d end -- t[3], t[5]
  154. i = i + 1
  155. local a
  156. goto l1
  157. end
  158. end
  159. end
  160. ::l2:: return t
  161. end
  162. local a = foo()
  163. assert(#a == 6)
  164. -- all functions share same 'a'
  165. for i = 2, 6 do
  166. assert(debug.upvalueid(a[1], 1) == debug.upvalueid(a[i], 1))
  167. end
  168. -- 'b' and 'c' are shared among some of them
  169. for i = 2, 6 do
  170. -- only a[1] uses external 'b'/'b'
  171. assert(debug.upvalueid(a[1], 2) ~= debug.upvalueid(a[i], 2))
  172. assert(debug.upvalueid(a[1], 3) ~= debug.upvalueid(a[i], 3))
  173. end
  174. for i = 3, 5, 2 do
  175. -- inner functions share 'b'/'c' with previous ones
  176. assert(debug.upvalueid(a[i], 2) == debug.upvalueid(a[i - 1], 2))
  177. assert(debug.upvalueid(a[i], 3) == debug.upvalueid(a[i - 1], 3))
  178. -- but not with next ones
  179. assert(debug.upvalueid(a[i], 2) ~= debug.upvalueid(a[i + 1], 2))
  180. assert(debug.upvalueid(a[i], 3) ~= debug.upvalueid(a[i + 1], 3))
  181. end
  182. -- only external 'd' is shared
  183. for i = 2, 6, 2 do
  184. assert(debug.upvalueid(a[1], 4) == debug.upvalueid(a[i], 4))
  185. end
  186. -- internal 'd's are all different
  187. for i = 3, 5, 2 do
  188. for j = 1, 6 do
  189. assert((debug.upvalueid(a[i], 4) == debug.upvalueid(a[j], 4))
  190. == (i == j))
  191. end
  192. end
  193. --------------------------------------------------------------------------------
  194. -- testing if x goto optimizations
  195. local function testG (a)
  196. if a == 1 then
  197. goto l1
  198. error("should never be here!")
  199. elseif a == 2 then goto l2
  200. elseif a == 3 then goto l3
  201. elseif a == 4 then
  202. goto l1 -- go to inside the block
  203. error("should never be here!")
  204. ::l1:: a = a + 1 -- must go to 'if' end
  205. else
  206. goto l4
  207. ::l4a:: a = a * 2; goto l4b
  208. error("should never be here!")
  209. ::l4:: goto l4a
  210. error("should never be here!")
  211. ::l4b::
  212. end
  213. do return a end
  214. ::l2:: do return "2" end
  215. ::l3:: do return "3" end
  216. ::l1:: return "1"
  217. end
  218. assert(testG(1) == "1")
  219. assert(testG(2) == "2")
  220. assert(testG(3) == "3")
  221. assert(testG(4) == 5)
  222. assert(testG(5) == 10)
  223. do -- test goto's around to-be-closed variable
  224. global *
  225. -- set 'var' and return an object that will reset 'var' when
  226. -- it goes out of scope
  227. local function newobj (var)
  228. _ENV[var] = true
  229. return setmetatable({}, {__close = function ()
  230. _ENV[var] = nil
  231. end})
  232. end
  233. goto L1
  234. ::L4:: assert(not varX); goto L5 -- varX dead here
  235. ::L1::
  236. local varX <close> = newobj("X")
  237. assert(varX); goto L2 -- varX alive here
  238. ::L3::
  239. assert(varX); goto L4 -- varX alive here
  240. ::L2:: assert(varX); goto L3 -- varX alive here
  241. ::L5:: -- return
  242. end
  243. foo()
  244. --------------------------------------------------------------------------
  245. local function checkerr (code, err)
  246. local st, msg = load(code)
  247. assert(not st and string.find(msg, err))
  248. end
  249. do
  250. global T<const>
  251. -- globals must be declared, after a global declaration
  252. checkerr("global none; X = 1", "variable 'X'")
  253. checkerr("global none; function XX() end", "variable 'XX'")
  254. -- global variables cannot be to-be-closed
  255. checkerr("global X<close>", "cannot be")
  256. checkerr("global <close> *", "cannot be")
  257. do
  258. local X = 10
  259. do global X; X = 20 end
  260. assert(X == 10) -- local X
  261. end
  262. assert(_ENV.X == 20) -- global X
  263. -- '_ENV' cannot be global
  264. checkerr("global _ENV, a; a = 10", "variable 'a'")
  265. -- global declarations inside functions
  266. checkerr([[
  267. global none
  268. local function foo () XXX = 1 end --< ERROR]], "variable 'XXX'")
  269. if not T then -- when not in "test mode", "global" isn't reserved
  270. assert(load("global = 1; return global")() == 1)
  271. print " ('global' is not a reserved word)"
  272. else
  273. -- "global" reserved, cannot be used as a variable
  274. assert(not load("global = 1; return global"))
  275. end
  276. local foo = 20
  277. do
  278. global function foo (x)
  279. if x == 0 then return 1 else return 2 * foo(x - 1) end
  280. end
  281. assert(foo == _ENV.foo and foo(4) == 16)
  282. end
  283. assert(_ENV.foo(4) == 16)
  284. assert(foo == 20) -- local one is in context here
  285. do
  286. global foo;
  287. function foo (x) return end -- Ok after declaration
  288. end
  289. checkerr([[
  290. global<const> foo;
  291. function foo (x) return end -- ERROR: foo is read-only
  292. ]], "assign to const variable 'foo'")
  293. checkerr([[
  294. global foo <const>;
  295. function foo (x) -- ERROR: foo is read-only
  296. return
  297. end
  298. ]], "%:2%:") -- correct line in error message
  299. checkerr([[
  300. global<const> *;
  301. print(X) -- Ok to use
  302. Y = 1 -- ERROR
  303. ]], "assign to const variable 'Y'")
  304. checkerr([[
  305. global *;
  306. Y = X -- Ok to use
  307. global<const> *;
  308. Y = 1 -- ERROR
  309. ]], "assign to const variable 'Y'")
  310. global *
  311. Y = 10
  312. assert(_ENV.Y == 10)
  313. global<const> *
  314. local x = Y
  315. global *
  316. Y = x + Y
  317. assert(_ENV.Y == 20)
  318. Y = nil
  319. end
  320. do -- Ok to declare hundreds of globals
  321. global table
  322. local code = {}
  323. for i = 1, 1000 do
  324. code[#code + 1] = ";global x" .. i
  325. end
  326. code[#code + 1] = "; return x990"
  327. code = table.concat(code)
  328. _ENV.x990 = 11
  329. assert(load(code)() == 11)
  330. _ENV.x990 = nil
  331. end
  332. do -- mixing lots of global/local declarations
  333. global table
  334. local code = {}
  335. for i = 1, 200 do
  336. code[#code + 1] = ";global x" .. i
  337. code[#code + 1] = ";local y" .. i .. "=" .. (2*i)
  338. end
  339. code[#code + 1] = "; return x200 + y200"
  340. code = table.concat(code)
  341. _ENV.x200 = 11
  342. assert(assert(load(code))() == 2*200 + 11)
  343. _ENV.x200 = nil
  344. end
  345. do print "testing initialization in global declarations"
  346. global<const> a, b, c = 10, 20, 30
  347. assert(_ENV.a == 10 and b == 20 and c == 30)
  348. global<const> a, b, c = 10
  349. assert(_ENV.a == 10 and b == nil and c == nil)
  350. global table
  351. global a, b, c, d = table.unpack{1, 2, 3, 6, 5}
  352. assert(_ENV.a == 1 and b == 2 and c == 3 and d == 6)
  353. local a, b = 100, 200
  354. do
  355. global a, b = a, b
  356. end
  357. assert(_ENV.a == 100 and _ENV.b == 200)
  358. _ENV.a, _ENV.b, _ENV.c, _ENV.d = nil -- erase these globals
  359. end
  360. print'OK'