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