Add perlpragma.pod, which describes how to implement user pragmata.
Nicholas Clark [Fri, 19 May 2006 20:10:47 +0000 (20:10 +0000)]
p4raw-id: //depot/perl@28241

MANIFEST
pod.lst
pod/perl.pod
pod/perlpragma.pod [new file with mode: 0644]
vms/descrip_mms.template
win32/pod.mak

index 6e7db9b..4ca63ba 100644 (file)
--- 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 (file)
--- 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
 
index b122797..c722d18 100644 (file)
@@ -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 (file)
index 0000000..9267bab
--- /dev/null
@@ -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<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 C<()> to prevent its C<import>
+being called.
+
+The interaction with the Perl compile 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 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<caller>, at index 10 of the
+list of returned results. In the example pragma, retrieval is encapsulated
+into the routine C<in_effect()>. This uses C<caller(1)> 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<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>.
index 7b20ba4..6a5bc9b 100644 (file)
@@ -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]
index 079116e..1993d71 100644 (file)
@@ -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  \