diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-01-10 13:54:51 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-01-10 13:54:51 -0300 |
| commit | 7ca3c40b50b385ead6b8bc4c54de97b61d11a12a (patch) | |
| tree | 5c5998f39760b07e05135df56b8a828f2fb685c1 /testes/goto.lua | |
| parent | 8a3a49250ce4a7e46ec9e90810a61d9f97aece3d (diff) | |
| download | lua-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.lua | 35 |
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") | |||
| 250 | assert(testG(4) == 5) | 250 | assert(testG(4) == 5) |
| 251 | assert(testG(5) == 10) | 251 | assert(testG(5) == 10) |
| 252 | 252 | ||
| 253 | do | 253 | do -- 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 | ||
| 267 | end | 278 | end |
| 279 | |||
| 280 | |||
| 281 | |||
| 282 | foo() | ||
| 268 | -------------------------------------------------------------------------------- | 283 | -------------------------------------------------------------------------------- |
| 269 | 284 | ||
| 270 | 285 | ||
