summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPaul "LeoNerd" Evans <leonerd@leonerd.org.uk>2021-07-27 14:55:14 +0100
committerPaul Evans <leonerd@leonerd.org.uk>2021-08-25 13:52:09 +0100
commitf79e2ff95fbb22eaf18e130c7cba8a9d40be3d75 (patch)
tree18bedb48e757671114f8f63c8691677a06b62a1b /lib
parent4b21956ed64a9303ab72a46be1cd68c22bff2560 (diff)
downloadperl-f79e2ff95fbb22eaf18e130c7cba8a9d40be3d75.tar.gz
Create `defer` syntax and `OP_PUSHDEFER` opcode
Adds syntax `defer { BLOCK }` to create a deferred block; code that is deferred until the scope exits. This syntax is guarded by use feature 'defer'; Adds a new opcode, `OP_PUSHDEFER`, which is a LOGOP whose `op_other` field gives the start of an optree to be deferred until scope exit. That op pointer will be stored on the save stack and invoked as part of scope unwind. Included is support for `B::Deparse` to deparse the optree back into syntax.
Diffstat (limited to 'lib')
-rw-r--r--lib/B/Deparse-core.t1
-rw-r--r--lib/B/Deparse.pm12
-rw-r--r--lib/B/Deparse.t6
-rw-r--r--lib/B/Op_private.pm1
-rw-r--r--lib/feature.pm11
-rw-r--r--lib/warnings.pm17
6 files changed, 40 insertions, 8 deletions
diff --git a/lib/B/Deparse-core.t b/lib/B/Deparse-core.t
index ae2a800682..7d8613f521 100644
--- a/lib/B/Deparse-core.t
+++ b/lib/B/Deparse-core.t
@@ -366,6 +366,7 @@ my %not_tested = map { $_ => 1} qw(
UNITCHECK
catch
default
+ defer
else
elsif
for
diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm
index 78703cd8b0..2d33039a80 100644
--- a/lib/B/Deparse.pm
+++ b/lib/B/Deparse.pm
@@ -52,7 +52,7 @@ use B qw(class main_root main_start main_cv svref_2object opnumber perlstring
MDEREF_SHIFT
);
-$VERSION = '1.57';
+$VERSION = '1.58';
use strict;
our $AUTOLOAD;
use warnings ();
@@ -2306,6 +2306,7 @@ my %feature_keywords = (
fc => 'fc',
try => 'try',
catch => 'try',
+ defer => 'defer',
);
# keywords that are strong and also have a prototype
@@ -6582,6 +6583,15 @@ sub pp_argdefelem {
}
+sub pp_pushdefer {
+ my $self = shift;
+ my($op, $cx) = @_;
+ # defer block body is stored in the ->first of an OP_NULL that is
+ # ->first of OP_PUSHDEFER
+ my $body = $self->deparse($op->first->first);
+ return "defer {\n\t$body\n\b}\cK";
+}
+
1;
__END__
diff --git a/lib/B/Deparse.t b/lib/B/Deparse.t
index fd4d63c779..3904773655 100644
--- a/lib/B/Deparse.t
+++ b/lib/B/Deparse.t
@@ -3180,3 +3180,9 @@ catch($var) {
my $x;
SECOND();
}
+####
+# defer blocks
+# CONTEXT use feature "defer"; no warnings 'experimental::defer';
+defer {
+ $a = 123;
+}
diff --git a/lib/B/Op_private.pm b/lib/B/Op_private.pm
index 0388462b25..56cc70aa47 100644
--- a/lib/B/Op_private.pm
+++ b/lib/B/Op_private.pm
@@ -477,6 +477,7 @@ $bits{predec}{0} = $bf[0];
$bits{preinc}{0} = $bf[0];
$bits{prototype}{0} = $bf[0];
@{$bits{push}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
+$bits{pushdefer}{0} = $bf[0];
$bits{quotemeta}{0} = $bf[0];
@{$bits{rand}}{3,2,1,0} = ($bf[4], $bf[4], $bf[4], $bf[4]);
$bits{range}{0} = $bf[0];
diff --git a/lib/feature.pm b/lib/feature.pm
index 40274b553b..fc1d984d3e 100644
--- a/lib/feature.pm
+++ b/lib/feature.pm
@@ -5,13 +5,14 @@
package feature;
-our $VERSION = '1.67';
+our $VERSION = '1.68';
our %feature = (
fc => 'feature_fc',
isa => 'feature_isa',
say => 'feature_say',
try => 'feature_try',
+ defer => 'feature_defer',
state => 'feature_state',
switch => 'feature_switch',
bitwise => 'feature_bitwise',
@@ -35,7 +36,7 @@ our %feature_bundle = (
"5.23" => [qw(bareword_filehandles current_sub evalbytes fc indirect multidimensional postderef_qq say state switch unicode_eval unicode_strings)],
"5.27" => [qw(bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional postderef_qq say state switch unicode_eval unicode_strings)],
"5.35" => [qw(bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional postderef_qq say state unicode_eval unicode_strings)],
- "all" => [qw(bareword_filehandles bitwise current_sub declared_refs evalbytes fc indirect isa multidimensional postderef_qq refaliasing say signatures state switch try unicode_eval unicode_strings)],
+ "all" => [qw(bareword_filehandles bitwise current_sub declared_refs defer evalbytes fc indirect isa multidimensional postderef_qq refaliasing say signatures state switch try unicode_eval unicode_strings)],
"default" => [qw(bareword_filehandles indirect multidimensional)],
);
@@ -431,6 +432,12 @@ C<try> are caught by executing the body of the C<catch> block.
For more information, see L<perlsyn/"Try Catch Exception Handling">.
+=head2 The 'defer' feature
+
+This feature enables the C<defer> block syntax, which allows a block of code
+to be deferred until when the flow of control leaves the block which contained
+it. For more details, see L<perlsyn/defer>.
+
=head1 FEATURE BUNDLES
It's possible to load multiple features together, using
diff --git a/lib/warnings.pm b/lib/warnings.pm
index 4b634de4d4..da0a36362c 100644
--- a/lib/warnings.pm
+++ b/lib/warnings.pm
@@ -5,7 +5,7 @@
package warnings;
-our $VERSION = "1.53";
+our $VERSION = "1.54";
# Verify that we're called correctly so that warnings will work.
# Can't use Carp, since Carp uses us!
@@ -111,6 +111,9 @@ our %Offsets = (
# Warnings Categories added in Perl 5.033
'experimental::try' => 146,
+
+ # Warnings Categories added in Perl 5.035
+ 'experimental::defer' => 148,
);
our %Bits = (
@@ -124,11 +127,12 @@ our %Bits = (
'digit' => "\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [31]
'exec' => "\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [7]
'exiting' => "\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [3]
- 'experimental' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x55\x51\x05\x54\x54\x05", # [51..56,58..61,65..67,69..73]
+ 'experimental' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x55\x51\x05\x54\x54\x15", # [51..56,58..61,65..67,69..74]
'experimental::alpha_assertions' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00", # [66]
'experimental::bitwise' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00", # [58]
'experimental::const_attr' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00", # [59]
'experimental::declared_refs' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00", # [65]
+ 'experimental::defer' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10", # [74]
'experimental::isa' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", # [72]
'experimental::lexical_subs' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00", # [52]
'experimental::postderef' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00", # [55]
@@ -201,11 +205,12 @@ our %DeadBits = (
'digit' => "\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [31]
'exec' => "\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [7]
'exiting' => "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [3]
- 'experimental' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\xaa\xa2\x0a\xa8\xa8\x0a", # [51..56,58..61,65..67,69..73]
+ 'experimental' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\xaa\xa2\x0a\xa8\xa8\x2a", # [51..56,58..61,65..67,69..74]
'experimental::alpha_assertions' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00", # [66]
'experimental::bitwise' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00", # [58]
'experimental::const_attr' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00", # [59]
'experimental::declared_refs' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00", # [65]
+ 'experimental::defer' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20", # [74]
'experimental::isa' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02", # [72]
'experimental::lexical_subs' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00", # [52]
'experimental::postderef' => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00", # [55]
@@ -269,8 +274,8 @@ our %DeadBits = (
# These are used by various things, including our own tests
our $NONE = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
-our $DEFAULT = "\x10\x01\x00\x00\x00\x50\x04\x00\x00\x00\x00\x00\x00\x55\x51\x15\x54\x54\x05"; # [2,4,22,23,25,52..56,58..62,65..67,69..73]
-our $LAST_BIT = 148 ;
+our $DEFAULT = "\x10\x01\x00\x00\x00\x50\x04\x00\x00\x00\x00\x00\x00\x55\x51\x15\x54\x54\x15"; # [2,4,22,23,25,52..56,58..62,65..67,69..74]
+our $LAST_BIT = 150 ;
our $BYTES = 19 ;
sub Croaker
@@ -876,6 +881,8 @@ The current hierarchy is:
| |
| +- experimental::declared_refs
| |
+ | +- experimental::defer
+ | |
| +- experimental::isa
| |
| +- experimental::lexical_subs