summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2006-05-19 20:10:47 +0000
committerNicholas Clark <nick@ccl4.org>2006-05-19 20:10:47 +0000
commita550ee30cc7e50406a26a1de128b2f7acda230f4 (patch)
treeee163c0558c550d53a2e2867c2e8e2d3b39b902d
parent2f08ed66616f3d2dff916adddde669909b743769 (diff)
downloadperl-a550ee30cc7e50406a26a1de128b2f7acda230f4.tar.gz
Add perlpragma.pod, which describes how to implement user pragmata.
p4raw-id: //depot/perl@28241
-rw-r--r--MANIFEST1
-rw-r--r--pod.lst1
-rw-r--r--pod/perl.pod1
-rw-r--r--pod/perlpragma.pod138
-rw-r--r--vms/descrip_mms.template18
-rw-r--r--win32/pod.mak4
6 files changed, 156 insertions, 7 deletions
diff --git a/MANIFEST b/MANIFEST
index 6e7db9bf09..4ca63bab8f 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 76fb2040fc..e3fb860b8b 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 b122797dda..c722d18b1c 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 0000000000..9267babbed
--- /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<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>.
diff --git a/vms/descrip_mms.template b/vms/descrip_mms.template
index 7b20ba4f5c..6a5bc9b57a 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 079116e86c..1993d710f9 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 \