goto.lua 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. -- $Id: testes/goto.lua $
  2. -- See Copyright Notice in file all.lua
  3. collectgarbage()
  4. local function errmsg (code, m)
  5. local st, msg = load(code)
  6. assert(not st and string.find(msg, m))
  7. end
  8. -- cannot see label inside block
  9. errmsg([[ goto l1; do ::l1:: end ]], "label 'l1'")
  10. errmsg([[ do ::l1:: end goto l1; ]], "label 'l1'")
  11. -- repeated label
  12. errmsg([[ ::l1:: ::l1:: ]], "label 'l1'")
  13. errmsg([[ ::l1:: do ::l1:: end]], "label 'l1'")
  14. -- undefined label
  15. errmsg([[ goto l1; local aa ::l1:: ::l2:: print(3) ]], "local 'aa'")
  16. -- jumping over variable definition
  17. errmsg([[
  18. do local bb, cc; goto l1; end
  19. local aa
  20. ::l1:: print(3)
  21. ]], "local 'aa'")
  22. -- jumping into a block
  23. errmsg([[ do ::l1:: end goto l1 ]], "label 'l1'")
  24. errmsg([[ goto l1 do ::l1:: end ]], "label 'l1'")
  25. -- cannot continue a repeat-until with variables
  26. errmsg([[
  27. repeat
  28. if x then goto cont end
  29. local xuxu = 10
  30. ::cont::
  31. until xuxu < x
  32. ]], "local 'xuxu'")
  33. -- simple gotos
  34. local x
  35. do
  36. local y = 12
  37. goto l1
  38. ::l2:: x = x + 1; goto l3
  39. ::l1:: x = y; goto l2
  40. end
  41. ::l3:: ::l3_1:: assert(x == 13)
  42. -- long labels
  43. do
  44. local prog = [[
  45. do
  46. local a = 1
  47. goto l%sa; a = a + 1
  48. ::l%sa:: a = a + 10
  49. goto l%sb; a = a + 2
  50. ::l%sb:: a = a + 20
  51. return a
  52. end
  53. ]]
  54. local label = string.rep("0123456789", 40)
  55. prog = string.format(prog, label, label, label, label)
  56. assert(assert(load(prog))() == 31)
  57. end
  58. -- ok to jump over local dec. to end of block
  59. do
  60. goto l1
  61. local a = 23
  62. x = a
  63. ::l1::;
  64. end
  65. while true do
  66. goto l4
  67. goto l1 -- ok to jump over local dec. to end of block
  68. goto l1 -- multiple uses of same label
  69. local x = 45
  70. ::l1:: ;;;
  71. end
  72. ::l4:: assert(x == 13)
  73. if print then
  74. goto l1 -- ok to jump over local dec. to end of block
  75. error("should not be here")
  76. goto l2 -- ok to jump over local dec. to end of block
  77. local x
  78. ::l1:: ; ::l2:: ;;
  79. else end
  80. -- to repeat a label in a different function is OK
  81. local function foo ()
  82. local a = {}
  83. goto l3
  84. ::l1:: a[#a + 1] = 1; goto l2;
  85. ::l2:: a[#a + 1] = 2; goto l5;
  86. ::l3::
  87. ::l3a:: a[#a + 1] = 3; goto l1;
  88. ::l4:: a[#a + 1] = 4; goto l6;
  89. ::l5:: a[#a + 1] = 5; goto l4;
  90. ::l6:: assert(a[1] == 3 and a[2] == 1 and a[3] == 2 and
  91. a[4] == 5 and a[5] == 4)
  92. if not a[6] then a[6] = true; goto l3a end -- do it twice
  93. end
  94. ::l6:: foo()
  95. do -- bug in 5.2 -> 5.3.2
  96. local x
  97. ::L1::
  98. local y -- cannot join this SETNIL with previous one
  99. assert(y == nil)
  100. y = true
  101. if x == nil then
  102. x = 1
  103. goto L1
  104. else
  105. x = x + 1
  106. end
  107. assert(x == 2 and y == true)
  108. end
  109. -- bug in 5.3
  110. do
  111. local first = true
  112. local a = false
  113. if true then
  114. goto LBL
  115. ::loop::
  116. a = true
  117. ::LBL::
  118. if first then
  119. first = false
  120. goto loop
  121. end
  122. end
  123. assert(a)
  124. end
  125. do -- compiling infinite loops
  126. goto escape -- do not run the infinite loops
  127. ::a:: goto a
  128. ::b:: goto c
  129. ::c:: goto b
  130. end
  131. ::escape::
  132. --------------------------------------------------------------------------------
  133. -- testing closing of upvalues
  134. local debug = require 'debug'
  135. local function foo ()
  136. local t = {}
  137. do
  138. local i = 1
  139. local a, b, c, d
  140. t[1] = function () return a, b, c, d end
  141. ::l1::
  142. local b
  143. do
  144. local c
  145. t[#t + 1] = function () return a, b, c, d end -- t[2], t[4], t[6]
  146. if i > 2 then goto l2 end
  147. do
  148. local d
  149. t[#t + 1] = function () return a, b, c, d end -- t[3], t[5]
  150. i = i + 1
  151. local a
  152. goto l1
  153. end
  154. end
  155. end
  156. ::l2:: return t
  157. end
  158. local a = foo()
  159. assert(#a == 6)
  160. -- all functions share same 'a'
  161. for i = 2, 6 do
  162. assert(debug.upvalueid(a[1], 1) == debug.upvalueid(a[i], 1))
  163. end
  164. -- 'b' and 'c' are shared among some of them
  165. for i = 2, 6 do
  166. -- only a[1] uses external 'b'/'b'
  167. assert(debug.upvalueid(a[1], 2) ~= debug.upvalueid(a[i], 2))
  168. assert(debug.upvalueid(a[1], 3) ~= debug.upvalueid(a[i], 3))
  169. end
  170. for i = 3, 5, 2 do
  171. -- inner functions share 'b'/'c' with previous ones
  172. assert(debug.upvalueid(a[i], 2) == debug.upvalueid(a[i - 1], 2))
  173. assert(debug.upvalueid(a[i], 3) == debug.upvalueid(a[i - 1], 3))
  174. -- but not with next ones
  175. assert(debug.upvalueid(a[i], 2) ~= debug.upvalueid(a[i + 1], 2))
  176. assert(debug.upvalueid(a[i], 3) ~= debug.upvalueid(a[i + 1], 3))
  177. end
  178. -- only external 'd' is shared
  179. for i = 2, 6, 2 do
  180. assert(debug.upvalueid(a[1], 4) == debug.upvalueid(a[i], 4))
  181. end
  182. -- internal 'd's are all different
  183. for i = 3, 5, 2 do
  184. for j = 1, 6 do
  185. assert((debug.upvalueid(a[i], 4) == debug.upvalueid(a[j], 4))
  186. == (i == j))
  187. end
  188. end
  189. --------------------------------------------------------------------------------
  190. -- testing if x goto optimizations
  191. local function testG (a)
  192. if a == 1 then
  193. goto l1
  194. error("should never be here!")
  195. elseif a == 2 then goto l2
  196. elseif a == 3 then goto l3
  197. elseif a == 4 then
  198. goto l1 -- go to inside the block
  199. error("should never be here!")
  200. ::l1:: a = a + 1 -- must go to 'if' end
  201. else
  202. goto l4
  203. ::l4a:: a = a * 2; goto l4b
  204. error("should never be here!")
  205. ::l4:: goto l4a
  206. error("should never be here!")
  207. ::l4b::
  208. end
  209. do return a end
  210. ::l2:: do return "2" end
  211. ::l3:: do return "3" end
  212. ::l1:: return "1"
  213. end
  214. assert(testG(1) == "1")
  215. assert(testG(2) == "2")
  216. assert(testG(3) == "3")
  217. assert(testG(4) == 5)
  218. assert(testG(5) == 10)
  219. do
  220. -- if x back goto out of scope of upvalue
  221. local X
  222. goto L1
  223. ::L2:: goto L3
  224. ::L1:: do
  225. local a <close> = setmetatable({}, {__close = function () X = true end})
  226. assert(X == nil)
  227. if a then goto L2 end -- jumping back out of scope of 'a'
  228. end
  229. ::L3:: assert(X == true) -- checks that 'a' was correctly closed
  230. end
  231. --------------------------------------------------------------------------------
  232. print'OK'