goto.lua 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. local function errmsg (code, m)
  2. local st, msg = loadstring(code)
  3. assert(not st and string.find(msg, m))
  4. end
  5. -- cannot see label inside block
  6. errmsg([[ goto l1; do ::l1:: end ]], "label 'l1'")
  7. errmsg([[ do ::l1:: end goto l1; ]], "label 'l1'")
  8. -- repeated label
  9. errmsg([[ ::l1:: ::l1:: ]], "label 'l1'")
  10. -- undefined label
  11. errmsg([[ goto l1; local aa ::l1:: ::l2:: print(3) ]], "local 'aa'")
  12. -- jumping over variable definition
  13. errmsg([[
  14. do local bb, cc; goto l1; end
  15. local aa
  16. ::l1:: print(3)
  17. ]], "local 'aa'")
  18. -- jumping into a block
  19. errmsg([[ do ::l1:: end goto l1 ]], "label 'l1'")
  20. errmsg([[ goto l1 do ::l1:: end ]], "label 'l1'")
  21. -- cannot continue a repeat-until with variables
  22. errmsg([[
  23. repeat
  24. if x then goto cont end
  25. local xuxu = 10
  26. ::cont::
  27. until xuxu < x
  28. ]], "local 'xuxu'")
  29. -- simple gotos
  30. local x
  31. do
  32. local y = 12
  33. goto l1
  34. ::l2:: x = x + 1; goto l3
  35. ::l1:: x = y; goto l2
  36. end
  37. ::l3:: ::l3_1:: assert(x == 13)
  38. -- long labels
  39. do
  40. local prog = [[
  41. do
  42. local a = 1
  43. goto l%sa; a = a + 1
  44. ::l%sa:: a = a + 10
  45. goto l%sb; a = a + 2
  46. ::l%sb:: a = a + 20
  47. return a
  48. end
  49. ]]
  50. local label = string.rep("0123456789", 40)
  51. prog = string.format(prog, label, label, label, label)
  52. assert(assert(loadstring(prog))() == 31)
  53. end
  54. -- goto to correct label when nested
  55. do goto l3; ::l3:: end -- does not loop jumping to previous label 'l3'
  56. -- ok to jump over local dec. to end of block
  57. do
  58. goto l1
  59. local a = 23
  60. x = a
  61. ::l1::;
  62. end
  63. while true do
  64. goto l4
  65. goto l1 -- ok to jump over local dec. to end of block
  66. goto l1 -- multiple uses of same label
  67. local x = 45
  68. ::l1:: ;;;
  69. end
  70. ::l4:: assert(x == 13)
  71. if print then
  72. goto l1 -- ok to jump over local dec. to end of block
  73. error("should not be here")
  74. goto l2 -- ok to jump over local dec. to end of block
  75. local x
  76. ::l1:: ; ::l2:: ;;
  77. else end
  78. -- to repeat a label in a different function is OK
  79. local function foo ()
  80. local a = {}
  81. goto l3
  82. ::l1:: a[#a + 1] = 1; goto l2;
  83. ::l2:: a[#a + 1] = 2; goto l5;
  84. ::l3::
  85. ::l3a:: a[#a + 1] = 3; goto l1;
  86. ::l4:: a[#a + 1] = 4; goto l6;
  87. ::l5:: a[#a + 1] = 5; goto l4;
  88. ::l6:: assert(a[1] == 3 and a[2] == 1 and a[3] == 2 and
  89. a[4] == 5 and a[5] == 4)
  90. if not a[6] then a[6] = true; goto l3a end -- do it twice
  91. end
  92. ::l6:: foo()
  93. --------------------------------------------------------------------------------
  94. -- testing closing of upvalues
  95. local function foo ()
  96. local a = {}
  97. do
  98. local i = 1
  99. local k = 0
  100. a[0] = function (y) k = y end
  101. ::l1:: do
  102. local x
  103. if i > 2 then goto l2 end
  104. a[i] = function (y) if y then x = y else return x + k end end
  105. i = i + 1
  106. goto l1
  107. end
  108. end
  109. ::l2:: return a
  110. end
  111. local a = foo()
  112. a[1](10); a[2](20)
  113. assert(a[1]() == 10 and a[2]() == 20 and a[3] == nil)
  114. a[0](13)
  115. assert(a[1]() == 23 and a[2]() == 33)
  116. --------------------------------------------------------------------------------
  117. -- testing if x goto optimizations
  118. local function testG (a)
  119. if a == 1 then
  120. goto l1
  121. error("should never be here!")
  122. elseif a == 2 then goto l2
  123. elseif a == 3 then goto l3
  124. elseif a == 4 then
  125. goto l1 -- go to inside the block
  126. error("should never be here!")
  127. ::l1:: a = a + 1 -- must go to 'if' end
  128. else
  129. goto l4
  130. ::l4a:: a = a * 2; goto l4b
  131. error("should never be here!")
  132. ::l4:: goto l4a
  133. error("should never be here!")
  134. ::l4b::
  135. end
  136. do return a end
  137. ::l2:: do return "2" end
  138. ::l3:: do return "3" end
  139. ::l1:: return "1"
  140. end
  141. assert(testG(1) == "1")
  142. assert(testG(2) == "2")
  143. assert(testG(3) == "3")
  144. assert(testG(4) == 5)
  145. assert(testG(5) == 10)
  146. --------------------------------------------------------------------------------
  147. print'OK'