goto.lua 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. -- $Id: goto.lua,v 1.13 2016/11/07 13:11:28 roberto Exp $
  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. -- undefined label
  14. errmsg([[ goto l1; local aa ::l1:: ::l2:: print(3) ]], "local 'aa'")
  15. -- jumping over variable definition
  16. errmsg([[
  17. do local bb, cc; goto l1; end
  18. local aa
  19. ::l1:: print(3)
  20. ]], "local 'aa'")
  21. -- jumping into a block
  22. errmsg([[ do ::l1:: end goto l1 ]], "label 'l1'")
  23. errmsg([[ goto l1 do ::l1:: end ]], "label 'l1'")
  24. -- cannot continue a repeat-until with variables
  25. errmsg([[
  26. repeat
  27. if x then goto cont end
  28. local xuxu = 10
  29. ::cont::
  30. until xuxu < x
  31. ]], "local 'xuxu'")
  32. -- simple gotos
  33. local x
  34. do
  35. local y = 12
  36. goto l1
  37. ::l2:: x = x + 1; goto l3
  38. ::l1:: x = y; goto l2
  39. end
  40. ::l3:: ::l3_1:: assert(x == 13)
  41. -- long labels
  42. do
  43. local prog = [[
  44. do
  45. local a = 1
  46. goto l%sa; a = a + 1
  47. ::l%sa:: a = a + 10
  48. goto l%sb; a = a + 2
  49. ::l%sb:: a = a + 20
  50. return a
  51. end
  52. ]]
  53. local label = string.rep("0123456789", 40)
  54. prog = string.format(prog, label, label, label, label)
  55. assert(assert(load(prog))() == 31)
  56. end
  57. -- goto to correct label when nested
  58. do goto l3; ::l3:: end -- does not loop jumping to previous label 'l3'
  59. -- ok to jump over local dec. to end of block
  60. do
  61. goto l1
  62. local a = 23
  63. x = a
  64. ::l1::;
  65. end
  66. while true do
  67. goto l4
  68. goto l1 -- ok to jump over local dec. to end of block
  69. goto l1 -- multiple uses of same label
  70. local x = 45
  71. ::l1:: ;;;
  72. end
  73. ::l4:: assert(x == 13)
  74. if print then
  75. goto l1 -- ok to jump over local dec. to end of block
  76. error("should not be here")
  77. goto l2 -- ok to jump over local dec. to end of block
  78. local x
  79. ::l1:: ; ::l2:: ;;
  80. else end
  81. -- to repeat a label in a different function is OK
  82. local function foo ()
  83. local a = {}
  84. goto l3
  85. ::l1:: a[#a + 1] = 1; goto l2;
  86. ::l2:: a[#a + 1] = 2; goto l5;
  87. ::l3::
  88. ::l3a:: a[#a + 1] = 3; goto l1;
  89. ::l4:: a[#a + 1] = 4; goto l6;
  90. ::l5:: a[#a + 1] = 5; goto l4;
  91. ::l6:: assert(a[1] == 3 and a[2] == 1 and a[3] == 2 and
  92. a[4] == 5 and a[5] == 4)
  93. if not a[6] then a[6] = true; goto l3a end -- do it twice
  94. end
  95. ::l6:: foo()
  96. do -- bug in 5.2 -> 5.3.2
  97. local x
  98. ::L1::
  99. local y -- cannot join this SETNIL with previous one
  100. assert(y == nil)
  101. y = true
  102. if x == nil then
  103. x = 1
  104. goto L1
  105. else
  106. x = x + 1
  107. end
  108. assert(x == 2 and y == true)
  109. end
  110. --------------------------------------------------------------------------------
  111. -- testing closing of upvalues
  112. local debug = require 'debug'
  113. local function foo ()
  114. local t = {}
  115. do
  116. local i = 1
  117. local a, b, c, d
  118. t[1] = function () return a, b, c, d end
  119. ::l1::
  120. local b
  121. do
  122. local c
  123. t[#t + 1] = function () return a, b, c, d end -- t[2], t[4], t[6]
  124. if i > 2 then goto l2 end
  125. do
  126. local d
  127. t[#t + 1] = function () return a, b, c, d end -- t[3], t[5]
  128. i = i + 1
  129. local a
  130. goto l1
  131. end
  132. end
  133. end
  134. ::l2:: return t
  135. end
  136. local a = foo()
  137. assert(#a == 6)
  138. -- all functions share same 'a'
  139. for i = 2, 6 do
  140. assert(debug.upvalueid(a[1], 1) == debug.upvalueid(a[i], 1))
  141. end
  142. -- 'b' and 'c' are shared among some of them
  143. for i = 2, 6 do
  144. -- only a[1] uses external 'b'/'b'
  145. assert(debug.upvalueid(a[1], 2) ~= debug.upvalueid(a[i], 2))
  146. assert(debug.upvalueid(a[1], 3) ~= debug.upvalueid(a[i], 3))
  147. end
  148. for i = 3, 5, 2 do
  149. -- inner functions share 'b'/'c' with previous ones
  150. assert(debug.upvalueid(a[i], 2) == debug.upvalueid(a[i - 1], 2))
  151. assert(debug.upvalueid(a[i], 3) == debug.upvalueid(a[i - 1], 3))
  152. -- but not with next ones
  153. assert(debug.upvalueid(a[i], 2) ~= debug.upvalueid(a[i + 1], 2))
  154. assert(debug.upvalueid(a[i], 3) ~= debug.upvalueid(a[i + 1], 3))
  155. end
  156. -- only external 'd' is shared
  157. for i = 2, 6, 2 do
  158. assert(debug.upvalueid(a[1], 4) == debug.upvalueid(a[i], 4))
  159. end
  160. -- internal 'd's are all different
  161. for i = 3, 5, 2 do
  162. for j = 1, 6 do
  163. assert((debug.upvalueid(a[i], 4) == debug.upvalueid(a[j], 4))
  164. == (i == j))
  165. end
  166. end
  167. --------------------------------------------------------------------------------
  168. -- testing if x goto optimizations
  169. local function testG (a)
  170. if a == 1 then
  171. goto l1
  172. error("should never be here!")
  173. elseif a == 2 then goto l2
  174. elseif a == 3 then goto l3
  175. elseif a == 4 then
  176. goto l1 -- go to inside the block
  177. error("should never be here!")
  178. ::l1:: a = a + 1 -- must go to 'if' end
  179. else
  180. goto l4
  181. ::l4a:: a = a * 2; goto l4b
  182. error("should never be here!")
  183. ::l4:: goto l4a
  184. error("should never be here!")
  185. ::l4b::
  186. end
  187. do return a end
  188. ::l2:: do return "2" end
  189. ::l3:: do return "3" end
  190. ::l1:: return "1"
  191. end
  192. assert(testG(1) == "1")
  193. assert(testG(2) == "2")
  194. assert(testG(3) == "3")
  195. assert(testG(4) == 5)
  196. assert(testG(5) == 10)
  197. --------------------------------------------------------------------------------
  198. print'OK'