diff options
Diffstat (limited to 'Master/tlpkg/tlperl/lib/pods/perlpragma.pod')
-rw-r--r-- | Master/tlpkg/tlperl/lib/pods/perlpragma.pod | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl/lib/pods/perlpragma.pod b/Master/tlpkg/tlperl/lib/pods/perlpragma.pod new file mode 100644 index 00000000000..856014438e5 --- /dev/null +++ b/Master/tlpkg/tlperl/lib/pods/perlpragma.pod @@ -0,0 +1,147 @@ +=head1 NAME + +perlpragma - how to write a user pragma + +=head1 DESCRIPTION + +A pragma is a module which influences some aspect of the compile time or run +time behaviour of Perl, such as C<strict> or C<warnings>. With Perl 5.10 you +are no longer limited to the built in pragmata; you can now create user +pragmata that modify the behaviour of user functions within a lexical scope. + +=head1 A basic example + +For example, say you need to create a class implementing overloaded +mathematical operators, and would like to provide your own pragma that +functions much like C<use integer;> You'd like this code + + use MyMaths; + + my $l = MyMaths->new(1.2); + my $r = MyMaths->new(3.4); + + print "A: ", $l + $r, "\n"; + + use myint; + print "B: ", $l + $r, "\n"; + + { + no myint; + print "C: ", $l + $r, "\n"; + } + + print "D: ", $l + $r, "\n"; + + no myint; + print "E: ", $l + $r, "\n"; + +to give the output + + A: 4.6 + B: 4 + C: 4.6 + D: 4 + E: 4.6 + +I<i.e.>, where C<use myint;> is in effect, addition operations are forced +to integer, whereas by default they are not, with the default behaviour being +restored via C<no myint;> + +The minimal implementation of the package C<MyMaths> would be something like +this: + + package MyMaths; + use warnings; + use strict; + use myint(); + use overload '+' => sub { + my ($l, $r) = @_; + # Pass 1 to check up one call level from here + if (myint::in_effect(1)) { + int($$l) + int($$r); + } else { + $$l + $$r; + } + }; + + sub new { + my ($class, $value) = @_; + bless \$value, $class; + } + + 1; + +Note how we load the user pragma C<myint> with an empty list C<()> to +prevent its C<import> being called. + +The interaction with the Perl compilation happens inside package C<myint>: + + package myint; + + use strict; + use warnings; + + sub import { + $^H{myint} = 1; + } + + sub unimport { + $^H{myint} = 0; + } + + sub in_effect { + my $level = shift // 0; + my $hinthash = (caller($level))[10]; + return $hinthash->{myint}; + } + + 1; + +As pragmata are implemented as modules, like any other module, C<use myint;> +becomes + + BEGIN { + require myint; + myint->import(); + } + +and C<no myint;> is + + BEGIN { + require myint; + myint->unimport(); + } + +Hence the C<import> and C<unimport> routines are called at B<compile time> +for the user's code. + +User pragmata store their state by writing to the magical hash C<%^H>, +hence these two routines manipulate it. The state information in C<%^H> is +stored in the optree, and can be retrieved read-only at runtime with C<caller()>, +at index 10 of the list of returned results. In the example pragma, retrieval +is encapsulated into the routine C<in_effect()>, which takes as parameter +the number of call frames to go up to find the value of the pragma in the +user's script. This uses C<caller()> to determine the value of +C<$^H{myint}> when each line of the user's script was called, and +therefore provide the correct semantics in the subroutine implementing the +overloaded addition. + +=head1 Implementation details + +The optree is shared between threads. This means there is a possibility that +the optree will outlive the particular thread (and therefore the interpreter +instance) that created it, so true Perl scalars cannot be stored in the +optree. Instead a compact form is used, which can only store values that are +integers (signed and unsigned), strings or C<undef> - references and +floating point values are stringified. If you need to store multiple values +or complex structures, you should serialise them, for example with C<pack>. +The deletion of a hash key from C<%^H> is recorded, and as ever can be +distinguished from the existence of a key with value C<undef> with +C<exists>. + +B<Don't> attempt to store references to data structures as integers which +are retrieved via C<caller> and converted back, as this will not be threadsafe. +Accesses would be to the structure without locking (which is not safe for +Perl's scalars), and either the structure has to leak, or it has to be +freed when its creating thread terminates, which may be before the optree +referencing it is deleted, if other threads outlive it. |