aboutsummaryrefslogtreecommitdiff
path: root/testes/goto.lua
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-01-10 13:54:51 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-01-10 13:54:51 -0300
commit7ca3c40b50b385ead6b8bc4c54de97b61d11a12a (patch)
tree5c5998f39760b07e05135df56b8a828f2fb685c1 /testes/goto.lua
parent8a3a49250ce4a7e46ec9e90810a61d9f97aece3d (diff)
downloadlua-7ca3c40b50b385ead6b8bc4c54de97b61d11a12a.tar.gz
lua-7ca3c40b50b385ead6b8bc4c54de97b61d11a12a.tar.bz2
lua-7ca3c40b50b385ead6b8bc4c54de97b61d11a12a.zip
Another way to compile goto's
The compilation of a goto or a label just create an entry and generate boilerplate code for the gotos. As we don't know yet whether it needs a CLOSE, we code a jump followed by a CLOSE, which is then dead code. When a block ends (and then we know for sure whether there are variables that need to be closed), we check the goto's against the labels of that block. When closing a goto against a label, if it needs a CLOSE, the compiler swaps the order of the jump and the CLOSE, making the CLOSE active.
Diffstat (limited to 'testes/goto.lua')
-rw-r--r--testes/goto.lua35
1 files changed, 25 insertions, 10 deletions
diff --git a/testes/goto.lua b/testes/goto.lua
index 4ac6d7d0..103cccef 100644
--- a/testes/goto.lua
+++ b/testes/goto.lua
@@ -250,21 +250,36 @@ assert(testG(3) == "3")
250assert(testG(4) == 5) 250assert(testG(4) == 5)
251assert(testG(5) == 10) 251assert(testG(5) == 10)
252 252
253do 253do -- test goto's around to-be-closed variable
254 -- if x back goto out of scope of upvalue 254
255 local X 255 -- set 'var' and return an object that will reset 'var' when
256 -- it goes out of scope
257 local function newobj (var)
258 _ENV[var] = true
259 return setmetatable({}, {__close = function ()
260 _ENV[var] = nil
261 end})
262 end
263
256 goto L1 264 goto L1
257 265
258 ::L2:: goto L3 266 ::L4:: assert(not X); goto L5 -- varX dead here
259 267
260 ::L1:: do 268 ::L1::
261 local a <close> = setmetatable({}, {__close = function () X = true end}) 269 local varX <close> = newobj("X")
262 assert(X == nil) 270 assert(X); goto L2 -- varX alive here
263 if a then goto L2 end -- jumping back out of scope of 'a'
264 end
265 271
266 ::L3:: assert(X == true) -- checks that 'a' was correctly closed 272 ::L3::
273 assert(X); goto L4 -- varX alive here
274
275 ::L2:: assert(X); goto L3 -- varX alive here
276
277 ::L5:: -- return
267end 278end
279
280
281
282foo()
268-------------------------------------------------------------------------------- 283--------------------------------------------------------------------------------
269 284
270 285