aboutsummaryrefslogtreecommitdiff
path: root/testes
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-01-13 13:54:10 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-01-13 13:54:10 -0300
commitb07fc10e91a5954254b47280aba287220c734a4b (patch)
treee50d4e5ef9aab68487caf0944e72a7de04bb8bb5 /testes
parentcc1692515e2a6aabc6d07159e7926656e38eda53 (diff)
downloadlua-b07fc10e91a5954254b47280aba287220c734a4b.tar.gz
lua-b07fc10e91a5954254b47280aba287220c734a4b.tar.bz2
lua-b07fc10e91a5954254b47280aba287220c734a4b.zip
Allow yields inside '__close' metamethods
Initial implementation to allow yields inside '__close' metamethods. This current version still does not allow a '__close' metamethod to yield when called due to an error. '__close' metamethods from C functions also are not allowed to yield.
Diffstat (limited to 'testes')
-rw-r--r--testes/locals.lua88
1 files changed, 88 insertions, 0 deletions
diff --git a/testes/locals.lua b/testes/locals.lua
index add023ca..c9c93ccf 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -641,6 +641,94 @@ end
641print "to-be-closed variables in coroutines" 641print "to-be-closed variables in coroutines"
642 642
643do 643do
644 -- yielding inside closing metamethods
645
646 local function checktable (t1, t2)
647 assert(#t1 == #t2)
648 for i = 1, #t1 do
649 assert(t1[i] == t2[i])
650 end
651 end
652
653 local trace = {}
654 local co = coroutine.wrap(function ()
655
656 trace[#trace + 1] = "nowX"
657
658 -- will be closed after 'y'
659 local x <close> = func2close(function (_, msg)
660 assert(msg == nil)
661 trace[#trace + 1] = "x1"
662 coroutine.yield("x")
663 trace[#trace + 1] = "x2"
664 end)
665
666 return pcall(function ()
667 do -- 'z' will be closed first
668 local z <close> = func2close(function (_, msg)
669 assert(msg == nil)
670 trace[#trace + 1] = "z1"
671 coroutine.yield("z")
672 trace[#trace + 1] = "z2"
673 end)
674 end
675
676 trace[#trace + 1] = "nowY"
677
678 -- will be closed after 'z'
679 local y <close> = func2close(function(_, msg)
680 assert(msg == nil)
681 trace[#trace + 1] = "y1"
682 coroutine.yield("y")
683 trace[#trace + 1] = "y2"
684 end)
685
686 return 10, 20, 30
687 end)
688 end)
689
690 assert(co() == "z")
691 assert(co() == "y")
692 assert(co() == "x")
693 checktable({co()}, {true, 10, 20, 30})
694 checktable(trace, {"nowX", "z1", "z2", "nowY", "y1", "y2", "x1", "x2"})
695
696end
697
698
699do
700 -- yielding inside closing metamethods after an error:
701 -- not yet implemented; raises an error
702
703 local co = coroutine.wrap(function ()
704
705 local function foo (err)
706
707 local x <close> = func2close(function(_, msg)
708 assert(msg == err)
709 coroutine.yield("x")
710 return 100, 200
711 end)
712
713 if err then error(err) else return 10, 20 end
714 end
715
716 coroutine.yield(pcall(foo, nil)) -- no error
717 return pcall(foo, 10) -- 'foo' will raise an error
718 end)
719
720 local a, b = co()
721 assert(a == "x" and b == nil) -- yields inside 'x'; Ok
722
723 local a, b, c = co()
724 assert(a and b == 10 and c == 20) -- returns from 'pcall(foo, nil)'
725
726 local st, msg = co() -- error yielding after an error
727 assert(not st and string.find(msg, "attempt to yield"))
728end
729
730
731do
644 -- an error in a wrapped coroutine closes variables 732 -- an error in a wrapped coroutine closes variables
645 local x = false 733 local x = false
646 local y = false 734 local y = false