File Coverage

blib/lib/Syntax/Keyword/Try.pm
Criterion Covered Total %
statement 35 37 94.5
branch 14 18 77.7
condition 1 3 33.3
subroutine 10 10 100.0
pod 0 3 0.0
total 60 71 84.5


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2016-2023 -- leonerd@leonerd.org.uk
5              
6             package Syntax::Keyword::Try 0.29;
7              
8 15     15   3235506 use v5.14;
  15         224  
9 15     15   102 use warnings;
  15         29  
  15         373  
10              
11 15     15   74 use Carp;
  15         31  
  15         9374  
12              
13             require XSLoader;
14             XSLoader::load( __PACKAGE__, our $VERSION );
15              
16             =head1 NAME
17              
18             C - a C syntax for perl
19              
20             =head1 SYNOPSIS
21              
22             use Syntax::Keyword::Try;
23              
24             sub foo {
25             try {
26             attempt_a_thing();
27             return "success";
28             }
29             catch ($e) {
30             warn "It failed - $e";
31             return "failure";
32             }
33             }
34              
35             =head1 DESCRIPTION
36              
37             This module provides a syntax plugin that implements exception-handling
38             semantics in a form familiar to users of other languages, being built on a
39             block labeled with the C keyword, followed by at least one of a C
40             or C block.
41              
42             As well as providing a handy syntax for this useful behaviour, this module
43             also serves to contain a number of code examples for how to implement parser
44             plugins and manipulate optrees to provide new syntax and behaviours for perl
45             code.
46              
47             Syntax similar to this module has now been added to core perl, starting at
48             version 5.34.0. If you are writing new code, it is suggested that you instead
49             use the L module instead, as that will enable the core
50             feature on those supported perl versions, falling back to
51             C on older perls.
52              
53             =head1 Experimental Features
54              
55             Some of the features of this module are currently marked as experimental. They
56             will provoke warnings in the C category, unless silenced.
57              
58             You can silence this with C but then that will
59             silence every experimental warning, which may hide others unintentionally. For
60             a more fine-grained approach you can instead use the import line for this
61             module to only silence this module's warnings selectively:
62              
63             use Syntax::Keyword::Try qw( try :experimental(typed) );
64              
65             use Syntax::Keyword::Try qw( try :experimental ); # all of the above
66              
67             Don't forget to import the main C symbol itself, to activate the syntax.
68              
69             =cut
70              
71             =head1 KEYWORDS
72              
73             =head2 try
74              
75             try {
76             STATEMENTS...
77             }
78             ...
79              
80             A C statement provides the main body of code that will be invoked, and
81             must be followed by either a C statement, a C statement, or
82             both.
83              
84             Execution of the C statement itself begins from the block given to the
85             statement and continues until either it throws an exception, or completes
86             successfully by reaching the end of the block. What will happen next depends
87             on the presence of a C or C statement immediately following
88             it.
89              
90             The body of a C block may contain a C expression. If executed,
91             such an expression will cause the entire containing function to return with
92             the value provided. This is different from a plain C block, in which
93             circumstance only the C itself would return, not the entire function.
94              
95             The body of a C block may contain loop control expressions (C,
96             C, C) which will have their usual effect on any loops that the
97             C block is contained by.
98              
99             The parsing rules for the set of statements (the C block and its
100             associated C and C) are such that they are parsed as a self-
101             contained statement. Because of this, there is no need to end with a
102             terminating semicolon.
103              
104             Even though it parses as a statement and not an expression, a C block can
105             still yield a value if it appears as the final statement in its containing
106             C or C block. For example:
107              
108             my $result = do {
109             try { attempt_func() }
110             catch ($e) { "Fallback Value" }
111             };
112              
113             Note (especially to users of L and similar) that the C
114             block itself does not necessarily stop exceptions thrown inside it from
115             propagating outside. It is the presence of a later C block which
116             causes this to happen. A C with only a C and no C will
117             still propagate exceptions up to callers as normal.
118              
119             =head2 catch
120              
121             ...
122             catch ($var) {
123             STATEMENTS...
124             }
125              
126             or
127              
128             ...
129             catch {
130             STATEMENTS...
131             }
132              
133             A C statement provides a block of code to the preceding C
134             statement that will be invoked in the case that the main block of code throws
135             an exception. Optionally a new lexical variable can be provided to store the
136             exception in. If not provided, the C block can inspect the raised
137             exception by looking in C<$@> instead.
138              
139             Presence of this C statement causes any exception thrown by the
140             preceding C block to be non-fatal to the surrounding code. If the
141             C block wishes to optionally handle some exceptions but not others, it
142             can re-raise it (or another exception) by calling C in the usual manner.
143              
144             As with C, the body of a C block may also contain a C
145             expression, which as before, has its usual meaning, causing the entire
146             containing function to return with the given value. The body may also contain
147             loop control expressions (C, C or C) which also have their
148             usual effect.
149              
150             If a C statement is not given, then any exceptions raised by the C
151             block are raised to the caller in the usual way.
152              
153             =head2 catch (Typed)
154              
155             ...
156             catch ($var isa Class) { ... }
157              
158             ...
159             catch ($var =~ m/^Regexp match/) { ... }
160              
161             I
162              
163             Optionally, multiple catch statements can be provided, where each block is
164             given a guarding condition, to control whether or not it will catch particular
165             exception values. Use of this syntax will provoke an C category
166             warning on supporting perl versions, unless silenced by importing the
167             C<:experimental(typed)> tag (see above).
168              
169             Two kinds of condition are supported:
170              
171             =over 4
172              
173             =item *
174              
175             catch ($var isa Class)
176              
177             The block is invoked only if the caught exception is a blessed object, and
178             derives from the given package name.
179              
180             On Perl version 5.32 onwards, this condition test is implemented using the
181             same op type that the core C<$var isa Class> syntax is provided by and works
182             in exactly the same way.
183              
184             On older perl versions it is emulated by a compatibility function. Currently
185             this function does not respect a C<< ->isa >> method overload on the exception
186             instance. Usually this should not be a problem, as exception class types
187             rarely provide such a method.
188              
189             =item *
190              
191             catch ($var =~ m/regexp/)
192              
193             The block is invoked only if the caught exception is a string that matches
194             the given regexp.
195              
196             =back
197              
198             When an exception is caught, each condition is tested in the order they are
199             written in, until a matching case is found. If such a case is found the
200             corresponding block is invoked, and no further condition is tested. If no
201             contional block matched and there is a default (unconditional) block at the
202             end then that is invoked instead. If no such block exists, then the exception
203             is propagated up to the calling scope.
204              
205             =head2 finally
206              
207             ...
208             finally {
209             STATEMENTS...
210             }
211              
212             A C statement provides a block of code to the preceding C
213             statement (or C pair) which is executed afterwards, both in the
214             case of a normal execution or a thrown exception. This code block may be used
215             to provide whatever clean-up operations might be required by preceding code.
216              
217             Because it is executed during a stack cleanup operation, a C block
218             may not cause the containing function to return, or to alter the return value
219             of it. It also cannot see the containing function's C<@_> arguments array
220             (though as it is block scoped within the function, it will continue to share
221             any normal lexical variables declared up until that point). It is protected
222             from disturbing the value of C<$@>. If the C block code throws an
223             exception, this will be printed as a warning and discarded, leaving C<$@>
224             containing the original exception, if one existed.
225              
226             =head1 OTHER MODULES
227              
228             There are already quite a number of modules on CPAN that provide a
229             C-like syntax for Perl.
230              
231             =over 2
232              
233             =item *
234              
235             L
236              
237             =item *
238              
239             L
240              
241             =item *
242              
243             L
244              
245             =item *
246              
247             L
248              
249             =back
250              
251             In addition, core perl itself gained a C syntax based on this
252             module at version 5.34.0. It is available as C.
253              
254             They are compared here, by feature:
255              
256             =head2 True syntax plugin
257              
258             Like L and L, this module is implemented as a true
259             syntax plugin, allowing it to provide new parsing rules not available to
260             simple functions. Most notably here it means that the resulting combination
261             does not need to end in a semicolon.
262              
263             The core C is also implemented as true native syntax in the
264             perl parser.
265              
266             In comparison, L is plain perl and provides its functionality using
267             regular perl functions; as such its syntax requires the trailing semicolon.
268              
269             L is a hybrid that uses L to parse the syntax tree.
270              
271             =head2 C<@_> in a try or catch block
272              
273             Because the C and C block code is contained in a true block rather
274             than an entire anonymous subroutine, invoking it does not interfere with the
275             C<@_> arguments array. Code inside these blocks can interact with the
276             containing function's array as before.
277              
278             This feature is unique among these modules; none of the others listed have
279             this ability.
280              
281             The core C also behaves in this manner.
282              
283             =head2 C in a try or catch block
284              
285             Like L and L, the C statement has its
286             usual effect within a subroutine containing syntax provided by this module.
287             Namely, it causes the containing C itself to return.
288              
289             It also behaves this way using the core C.
290              
291             In comparison, using L or L mean that a C statement
292             will only exit from the C block.
293              
294             =head2 C/C/C in a try or catch block
295              
296             The loop control keywords of C, C and C have their usual
297             effect on dynamically contained loops.
298              
299             These also work fine when using the core C.
300              
301             L documents that these do not work there. The other
302             modules make no statement either way.
303              
304             =head2 Value Semantics
305              
306             Like L and L, the syntax provided by this module
307             only works as a syntax-level statement and not an expression. You cannot
308             assign from the result of a C block. A common workaround is to wrap
309             the C statement inside a C block, where its final expression
310             can be captured and used as a value.
311              
312             The same C block wrapping also works for the core C.
313              
314             In comparison, the behaviour implemented by L can be used as a
315             valued expression, such as assigned to a variable or returned to the caller of
316             its containing function.
317              
318             =head2 C without C
319              
320             Like L, the syntax provided by this module allows a
321             C block to be followed by only a C block, with no C. In
322             this case, exceptions thrown by code contained by the C are not
323             suppressed, instead they propagate as normal to callers. This matches the
324             behaviour familiar to Java or C++ programmers.
325              
326             In comparison, the code provided by L and L always suppress
327             exception propagation even without an actual C block.
328              
329             The L module does not allow a C block not followed by C.
330              
331             The core C does not implement C at all, and also
332             requires that every C block be followed by a C.
333              
334             =head2 Typed C
335              
336             L and L make no attempt to perform any kind of typed dispatch
337             to distinguish kinds of exception caught by C blocks.
338              
339             Likewise the core C currently does not provide this ability,
340             though it remains an area of ongoing design work.
341              
342             L and L both attempt to provide a kind of
343             typed dispatch where different classes of exception are caught by different
344             blocks of code, or propagated up entirely to callers.
345              
346             This module provides such an ability, via the currently-experimental
347             C syntax.
348              
349             The design thoughts continue on the RT ticket
350             L.
351              
352             =cut
353              
354             sub import
355             {
356 16     16   121 my $pkg = shift;
357 16         41 my $caller = caller;
358              
359 16         53 $pkg->import_into( $caller, @_ );
360             }
361              
362             sub unimport
363             {
364 1     1   482 my $pkg = shift;
365 1         4 my $caller = caller;
366              
367 1         3 $pkg->unimport_into( $caller, @_ );
368             }
369              
370             my @EXPERIMENTAL = qw( typed );
371              
372 17     17 0 119 sub import_into { shift->apply( sub { $^H{ $_[0] }++ }, @_ ) }
  16     16   90  
373 1     1 0 5 sub unimport_into { shift->apply( sub { delete $^H{ $_[0] } }, @_ ) }
  1     1   6  
374              
375             sub apply
376             {
377 17     17 0 38 my $pkg = shift;
378 17         44 my ( $cb, $caller, @syms ) = @_;
379              
380 17 100       118 @syms or @syms = qw( try );
381              
382 17         60 my %syms = map { $_ => 1 } @syms;
  18         121  
383 17 100       172 $cb->( "Syntax::Keyword::Try/try" ) if delete $syms{try};
384              
385             # Largely for Feature::Compat::Try's benefit
386 17 100       60 $cb->( "Syntax::Keyword::Try/no_finally" ) if delete $syms{"-no_finally"};
387 17 50       51 $cb->( "Syntax::Keyword::Try/require_catch" ) if delete $syms{"-require_catch"};
388 17 100       55 $cb->( "Syntax::Keyword::Try/require_var" ) if delete $syms{"-require_var"};
389              
390             # stablised experiments
391 17         87 delete $syms{":experimental($_)"} for qw( var );
392              
393 17         44 foreach ( @EXPERIMENTAL ) {
394 17 50       59 $cb->( "Syntax::Keyword::Try/experimental($_)" ) if delete $syms{":experimental($_)"};
395             }
396              
397 17 100       48 if( delete $syms{":experimental"} ) {
398 2         12 $cb->( "Syntax::Keyword::Try/experimental($_)" ) for @EXPERIMENTAL;
399             }
400              
401             # Ignore requests for these, as they come automatically with `try`
402 17         69 delete @syms{qw( catch finally )};
403              
404 16 50 33     98 if( $syms{try_value} or $syms{":experimental(try_value)"} ) {
405 0         0 croak "The 'try_value' experimental feature is now removed\n" .
406             "Instead, you should use do { try ... } to yield a value from a try/catch statement";
407             }
408              
409 16 50       26980 croak "Unrecognised import symbols @{[ keys %syms ]}" if keys %syms;
  0            
410             }
411              
412             =head1 WITH OTHER MODULES
413              
414             =head2 Future::AsyncAwait
415              
416             As of C version 0.10 and L version
417             0.07, cross-module integration tests assert that basic C blocks
418             inside an C work correctly, including those that attempt to
419             C from inside C.
420              
421             use Future::AsyncAwait;
422             use Syntax::Keyword::Try;
423              
424             async sub attempt
425             {
426             try {
427             await func();
428             return "success";
429             }
430             catch {
431             return "failed";
432             }
433             }
434              
435             =head1 ISSUES
436              
437             =head2 Thread-safety at load time cannot be assured before perl 5.16
438              
439             On F versions 5.16 and above this module is thread-safe.
440              
441             On F version 5.14 this module is thread-safe provided that it is
442             Cd before any additional threads are created.
443              
444             However, when using 5.14 there is a race condition if this module is loaded
445             late in the program startup, after additional threads have been created. This
446             leads to the potential for it to be started up multiple times concurrently,
447             which creates data races when modifying internal structures and likely leads
448             to a segmentation fault, either during load or soon after when more code is
449             compiled.
450              
451             As a workaround, for any such program that creates multiple threads, loads
452             additional code (such as dynamically-discovered plugins), and has to run on
453             5.14, it should make sure to
454              
455             use Syntax::Keyword::Try;
456              
457             early on in startup, before it spins out any additional threads.
458              
459             (See also L)
460              
461             =head2 $@ is not local'ised by C before perl 5.24
462              
463             On F versions 5.24 and above, or when using only control-flow statement
464             syntax, C<$@> is always correctly Cised.
465              
466             However, when using the experimental value-yielding expression version
467             C on perl versions 5.22 or older, the Cisation of C<$@>
468             does not correctly apply around the expression. After such an expression, the
469             value of C<$@> will leak out if a failure happened and the C block was
470             invoked, overwriting any previous value that was visible there.
471              
472             (See also L)
473              
474             =head1 ACKNOWLEDGEMENTS
475              
476             With thanks to C, C and others from C for
477             assisting with trickier bits of XS logic.
478              
479             =head1 AUTHOR
480              
481             Paul Evans
482              
483             =cut
484              
485             0x55AA;