From: Nicholas Clark Date: Fri, 19 May 2006 20:10:47 +0000 (+0000) Subject: Add perlpragma.pod, which describes how to implement user pragmata. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=a550ee30cc7e50406a26a1de128b2f7acda230f4;p=p5sagit%2Fp5-mst-13.2.git Add perlpragma.pod, which describes how to implement user pragmata. p4raw-id: //depot/perl@28241 --- diff --git a/MANIFEST b/MANIFEST index 6e7db9b..4ca63ba 100644 --- a/MANIFEST +++ b/MANIFEST @@ -2923,6 +2923,7 @@ pod/perl.pod Perl overview (this section) pod/perlpod.pod Perl plain old documentation pod/perlpodspec.pod Perl plain old documentation format specification pod/perlport.pod Perl portability guide +pod/perlpragma.pod Perl modules: writing a user pragma pod/perlref.pod Perl references, the rest of the story pod/perlreftut.pod Perl references short introduction pod/perlre.pod Perl regular expressions, the rest of the story diff --git a/pod.lst b/pod.lst index 76fb204..e3fb860 100644 --- a/pod.lst +++ b/pod.lst @@ -87,6 +87,7 @@ h Reference Manual perlmodstyle Perl modules: how to write modules with style perlmodinstall Perl modules: how to install from CPAN perlnewmod Perl modules: preparing a new module for distribution + perlpragma Perl modules: writing a user pragma perlutil utilities packaged with the Perl distribution diff --git a/pod/perl.pod b/pod/perl.pod index b122797..c722d18 100644 --- a/pod/perl.pod +++ b/pod/perl.pod @@ -104,6 +104,7 @@ For ease of access, the Perl manual has been split up into several sections. perlmodstyle Perl modules: how to write modules with style perlmodinstall Perl modules: how to install from CPAN perlnewmod Perl modules: preparing a new module for distribution + perlpragma Perl modules: writing a user pragma perlutil utilities packaged with the Perl distribution diff --git a/pod/perlpragma.pod b/pod/perlpragma.pod new file mode 100644 index 0000000..9267bab --- /dev/null +++ b/pod/perlpragma.pod @@ -0,0 +1,138 @@ +=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 or C. 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 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, where C is in effect, addition operations are forced +to integer, whereas by default they are not, with the default behaviour being +restored via C + +The minimal implementation of the package C 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 with C<()> to prevent its C +being called. + +The interaction with the Perl compile happens inside package C: + +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 +becomes + + BEGIN { + require myint; + myint->import(); + } + +and C is + + BEGIN { + require myint; + myint->unimport(); + } + +Hence the C and C routines are called at B +for the user's code. + +User pragmata store their state by writing to C<%^H>, hence these two +routines manipulate C<%^H>. The state information in C<%^H> stored in the +optree, and can be retrieved at runtime with C, at index 10 of the +list of returned results. In the example pragma, retrieval is encapsulated +into the routine C. This uses C to determine the +state 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, which means there is a possibility that +the optree will outlive the particular thread (and therefore 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 - 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. +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 with +C. diff --git a/vms/descrip_mms.template b/vms/descrip_mms.template index 7b20ba4..6a5bc9b 100644 --- a/vms/descrip_mms.template +++ b/vms/descrip_mms.template @@ -406,13 +406,13 @@ pod16 = [.lib.pods]perlmachten.pod [.lib.pods]perlmacos.pod [.lib.pods]perlmacos pod17 = [.lib.pods]perlmodinstall.pod [.lib.pods]perlmodlib.pod [.lib.pods]perlmodstyle.pod [.lib.pods]perlmpeix.pod [.lib.pods]perlnetware.pod pod18 = [.lib.pods]perlnewmod.pod [.lib.pods]perlnumber.pod [.lib.pods]perlobj.pod [.lib.pods]perlop.pod [.lib.pods]perlopenbsd.pod pod19 = [.lib.pods]perlopentut.pod [.lib.pods]perlos2.pod [.lib.pods]perlos390.pod [.lib.pods]perlos400.pod [.lib.pods]perlothrtut.pod -pod20 = [.lib.pods]perlpacktut.pod [.lib.pods]perlplan9.pod [.lib.pods]perlpod.pod [.lib.pods]perlpodspec.pod [.lib.pods]perlport.pod [.lib.pods]perlqnx.pod -pod21 = [.lib.pods]perlre.pod [.lib.pods]perlref.pod [.lib.pods]perlreftut.pod [.lib.pods]perlrequick.pod [.lib.pods]perlreref.pod [.lib.pods]perlretut.pod -pod22 = [.lib.pods]perlriscos.pod [.lib.pods]perlrun.pod [.lib.pods]perlsec.pod [.lib.pods]perlsolaris.pod [.lib.pods]perlstyle.pod [.lib.pods]perlsub.pod -pod23 = [.lib.pods]perlsymbian.pod [.lib.pods]perlsyn.pod [.lib.pods]perlthrtut.pod [.lib.pods]perltie.pod [.lib.pods]perltoc.pod [.lib.pods]perltodo.pod -pod24 = [.lib.pods]perltooc.pod [.lib.pods]perltoot.pod [.lib.pods]perltrap.pod [.lib.pods]perltru64.pod [.lib.pods]perltw.pod [.lib.pods]perlunicode.pod -pod25 = [.lib.pods]perluniintro.pod [.lib.pods]perlutil.pod [.lib.pods]perluts.pod [.lib.pods]perlvar.pod [.lib.pods]perlvmesa.pod [.lib.pods]perlvms.pod -pod26 = [.lib.pods]perlvos.pod [.lib.pods]perlwin32.pod [.lib.pods]perlxs.pod [.lib.pods]perlxstut.pod +pod20 = [.lib.pods]perlpacktut.pod [.lib.pods]perlplan9.pod [.lib.pods]perlpod.pod [.lib.pods]perlpodspec.pod [.lib.pods]perlport.pod +pod21 = [.lib.pods]perlpragma.pod [.lib.pods]perlqnx.pod [.lib.pods]perlre.pod [.lib.pods]perlref.pod [.lib.pods]perlreftut.pod [.lib.pods]perlrequick.pod +pod22 = [.lib.pods]perlreref.pod [.lib.pods]perlretut.pod [.lib.pods]perlriscos.pod [.lib.pods]perlrun.pod [.lib.pods]perlsec.pod [.lib.pods]perlsolaris.pod +pod23 = [.lib.pods]perlstyle.pod [.lib.pods]perlsub.pod [.lib.pods]perlsymbian.pod [.lib.pods]perlsyn.pod [.lib.pods]perlthrtut.pod [.lib.pods]perltie.pod +pod24 = [.lib.pods]perltoc.pod [.lib.pods]perltodo.pod [.lib.pods]perltooc.pod [.lib.pods]perltoot.pod [.lib.pods]perltrap.pod [.lib.pods]perltru64.pod +pod25 = [.lib.pods]perltw.pod [.lib.pods]perlunicode.pod [.lib.pods]perluniintro.pod [.lib.pods]perlutil.pod [.lib.pods]perluts.pod [.lib.pods]perlvar.pod +pod26 = [.lib.pods]perlvmesa.pod [.lib.pods]perlvms.pod [.lib.pods]perlvos.pod [.lib.pods]perlwin32.pod [.lib.pods]perlxs.pod [.lib.pods]perlxstut.pod pod = $(pod0) $(pod1) $(pod2) $(pod3) $(pod4) $(pod5) $(pod6) $(pod7) $(pod8) $(pod9) $(pod10) $(pod11) $(pod12) $(pod13) $(pod14) $(pod15) $(pod16) $(pod17) $(pod18) $(pod19) $(pod20) $(pod21) $(pod22) $(pod23) $(pod24) $(pod25) $(pod26) # Would be useful to automate the generation of this rule from pod/buildtoc @@ -1146,6 +1146,10 @@ preplibrary : $(MINIPERL_EXE) $(LIBPREREQ) @ If F$Search("[.lib]pods.dir").eqs."" Then Create/Directory [.lib.pods] Copy/NoConfirm/Log $(MMS$SOURCE) [.lib.pods] +[.lib.pods]perlpragma.pod : [.pod]perlpragma.pod + @ If F$Search("[.lib]pods.dir").eqs."" Then Create/Directory [.lib.pods] + Copy/NoConfirm/Log $(MMS$SOURCE) [.lib.pods] + [.lib.pods]perlqnx.pod : [.pod]perlqnx.pod @ If F$Search("[.lib]pods.dir").eqs."" Then Create/Directory [.lib.pods] Copy/NoConfirm/Log $(MMS$SOURCE) [.lib.pods] diff --git a/win32/pod.mak b/win32/pod.mak index 079116e..1993d71 100644 --- a/win32/pod.mak +++ b/win32/pod.mak @@ -99,6 +99,7 @@ POD = \ perlpod.pod \ perlpodspec.pod \ perlport.pod \ + perlpragma.pod \ perlre.pod \ perlref.pod \ perlreftut.pod \ @@ -209,6 +210,7 @@ MAN = \ perlpod.man \ perlpodspec.man \ perlport.man \ + perlpragma.man \ perlre.man \ perlref.man \ perlreftut.man \ @@ -319,6 +321,7 @@ HTML = \ perlpod.html \ perlpodspec.html \ perlport.html \ + perlpragma.html \ perlre.html \ perlref.html \ perlreftut.html \ @@ -429,6 +432,7 @@ TEX = \ perlpod.tex \ perlpodspec.tex \ perlport.tex \ + perlpragma.tex \ perlre.tex \ perlref.tex \ perlreftut.tex \