diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-01-13 13:54:10 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-01-13 13:54:10 -0300 |
| commit | b07fc10e91a5954254b47280aba287220c734a4b (patch) | |
| tree | e50d4e5ef9aab68487caf0944e72a7de04bb8bb5 /testes | |
| parent | cc1692515e2a6aabc6d07159e7926656e38eda53 (diff) | |
| download | lua-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.lua | 88 |
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 | |||
| 641 | print "to-be-closed variables in coroutines" | 641 | print "to-be-closed variables in coroutines" |
| 642 | 642 | ||
| 643 | do | 643 | do |
| 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 | |||
| 696 | end | ||
| 697 | |||
| 698 | |||
| 699 | do | ||
| 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")) | ||
| 728 | end | ||
| 729 | |||
| 730 | |||
| 731 | do | ||
| 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 |
