~ubuntu-branches/ubuntu/utopic/libdevel-pragma-perl/utopic

« back to all changes in this revision

Viewing changes to lib/Devel/Pragma.pm

  • Committer: Package Import Robot
  • Author(s): Damyan Ivanov, gregor herrmann, Salvatore Bonaccorso, Damyan Ivanov
  • Date: 2013-10-22 09:41:47 UTC
  • mfrom: (2.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20131022094147-27vu2s1k6ypp0a7p
* Team upload

[ gregor herrmann ]
* debian/control: update {versioned,alternative} (build) dependencies.

[ Salvatore Bonaccorso ]
* Change Vcs-Git to canonical URI (git://anonscm.debian.org)
* Change search.cpan.org based URIs to metacpan.org based URIs

[ Damyan Ivanov ]
* Imported Upstream version 0.60
* add years to main upstream copyright notice
* add ppport.h to debian/copyright (how did this escape NEW review?)
* update (build-)dependencies
* bump debhelper build-dependency to ensure hardening support
* claim conformance with Policy 3.9.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
use 5.008;
4
4
 
 
5
# make sure this is loaded first
 
6
use Lexical::SealRequireHints;
 
7
 
5
8
use strict;
6
9
use warnings;
7
10
 
8
 
our $VERSION = '0.54';
9
 
 
10
 
use B::Hooks::EndOfScope;
11
11
use B::Hooks::OP::Annotation;
12
12
use B::Hooks::OP::Check;
13
13
use Carp qw(carp croak);
16
16
 
17
17
use base qw(Exporter);
18
18
 
19
 
our @EXPORT_OK = qw(my_hints new_scope ccstash scope fqname on_require);
 
19
our $VERSION = '0.60';
 
20
our @EXPORT_OK = qw(my_hints hints new_scope ccstash scope fqname on_require);
20
21
our %EXPORT_TAGS = (all => [ @EXPORT_OK ]);
21
22
 
22
 
my $REQUIRE_KEY = 0;
 
23
# Perform (XS) cleanup on global destruction (DESTROY is defined in Pragma.xs).
 
24
# END blocks don't work for this: see https://rt.cpan.org/Ticket/Display.html?id=80400
 
25
# according to perlvar, package variables are garbage collected after END blocks
 
26
our $__GLOBAL_DESTRUCTION_MONITOR__ = bless {};
23
27
 
24
28
XSLoader::load(__PACKAGE__, $VERSION);
25
29
 
27
31
sub my_hints() {
28
32
    # set HINT_LOCALIZE_HH (0x20000)
29
33
    $^H |= 0x20000;
30
 
    my $hints = \%^H;
31
 
 
32
 
    unless ($hints->{'Devel::Pragma'}) {
33
 
        $hints->{'Devel::Pragma'} = 1;
34
 
        xs_enter();
35
 
        on_scope_end \&xs_leave;
36
 
    }
37
 
 
38
 
    return $hints;
 
34
    return \%^H;
39
35
}
40
36
 
 
37
BEGIN { *hints = \&my_hints }
 
38
 
41
39
# make sure the "enable lexically-scoped %^H" flag is set (on by default in 5.10)
42
40
sub check_hints() {
43
41
    unless ($^H & 0x20000) {
44
42
        carp('Devel::Pragma: unexpected $^H (HINT_LOCALIZE_HH bit not set) - setting it now, but results may be unreliable');
45
43
    }
46
 
    return my_hints; # create it if it doesn't exist - in some perls, it starts out NULL
 
44
    return hints; # create it if it doesn't exist - in some perls, it starts out NULL
47
45
}
48
46
 
49
47
# return a unique integer ID for the current scope
58
56
    my $hints = check_hints();
59
57
 
60
58
    # this is %^H as an integer - it changes as scopes are entered/exited i.e. it's a unique
61
 
    # identifier for the currently-compiling scope (the scope in which new_scope 
 
59
    # identifier for the currently-compiling scope (the scope in which new_scope
62
60
    # is called)
63
61
    #
64
62
    # we don't need to stack/unstack it in %^H as %^H itself takes care of that
65
63
    # note: we need to call this *after* %^H is referenced (and possibly autovivified) above
66
64
    #
67
 
    # every time new_scope is called, we write this scope ID to $^H{"Devel::Pragma::Scope::$caller"}.
68
 
    # if $^H{"Devel::Pragma::Scope::$caller"} == scope() (i.e. the stored scope ID is the same as the
 
65
    # every time new_scope is called, we write this scope ID to $^H{"Devel::Pragma::new_scope::$caller"}.
 
66
    # if $^H{"Devel::Pragma::new_scope::$caller"} == scope() (i.e. the stored scope ID is the same as the
69
67
    # current scope ID), then we're augmenting the current scope; otherwise we're in a new scope - i.e.
70
68
    # a nested or outer scope that didn't previously "use MyPragma"
71
69
 
72
70
    my $current_scope = scope();
73
 
    my $id = "Devel::Pragma::Scope($caller)";
 
71
    my $id = "Devel::Pragma::new_scope::$caller";
74
72
    my $old_scope = exists($hints->{$id}) ? $hints->{$id} : 0;
75
73
    my $new_scope; # is this a scope in which new_scope has not previously been called?
76
74
 
117
115
 
118
116
# run registered callbacks after performing a compile-time require or do FILE
119
117
sub _post_require($) {
120
 
    local $@; # if there was an exception on require, make sure we don't clobber it 
 
118
    local $@; # if there was an exception on require, make sure we don't clobber it
121
119
    _callback(1, shift)
122
120
}
123
121
 
124
122
# common code for pre- and post-require hooks
125
 
sub _callback($) {
 
123
sub _callback($$) {
126
124
    my ($index, $hints) = @_;
127
 
 
128
 
    if (my $hooks = $hints->{'Devel::Pragma(Hooks)'}) {
129
 
        for my $key (sort(keys(%$hooks))) {
130
 
            eval { $hooks->{$key}->[$index]->($hints) };
131
 
 
132
 
            if ($@) {
133
 
                my $stage = $index == 0 ? 'pre' : 'post';
134
 
                carp __PACKAGE__ . ": exception in $stage-require callback: $@";
135
 
            }
 
125
    my $pairs = $hints->{'Devel::Pragma::on_require'} || [];
 
126
 
 
127
    for my $pair (@$pairs) {
 
128
        eval { $pair->[$index]->($hints) };
 
129
 
 
130
        if ($@) {
 
131
            my $stage = [ qw(pre post) ]->[$index];
 
132
            carp __PACKAGE__ . ": exception in $stage-require callback: $@";
136
133
        }
137
134
    }
138
135
}
140
137
# register pre- and/or post-require hooks
141
138
# these are only called if the require occurs at compile-time
142
139
sub on_require($$) {
143
 
    my $hints = my_hints();
 
140
    my $hints = hints();
144
141
 
145
142
    for my $index (0 .. 1) {
146
143
        my $arg = $_[$index];
150
147
            unless ($arg and _isa($arg, 'CODE'));
151
148
    }
152
149
 
153
 
    $hints->{'Devel::Pragma(Hooks)'}->{++$REQUIRE_KEY} = [ @_ ];
 
150
    my $old_callbacks = $hints->{'Devel::Pragma::on_require'} || [];
 
151
    $hints->{'Devel::Pragma::on_require'} = [ @$old_callbacks, [ @_ ] ];
154
152
 
155
 
    # return $REQUIRE_KEY;
156
153
    return;
157
154
}
158
155
 
159
 
# sub on_require_remove($) {
160
 
#     my $index = shift;
161
 
#     my $hints = my_hints();
162
 
#     my $hooks = $hints->{'Devel::Pragma(Hooks)'};
163
 
164
 
#     croak(sprintf('%s: attempt to remove a non-existent require hook', __PACKAGE__))
165
 
#         unless ($hooks->{$index});
166
 
167
 
#     delete $hooks->{$index};
168
 
# }
169
 
 
170
156
# make sure "enable lexically-scoped %^H" is set in older perls, and export the requested functions
171
157
sub import {
172
158
    my $class = shift;
184
170
 
185
171
=head1 SYNOPSIS
186
172
 
187
 
  package MyPragma;
188
 
 
189
 
  use Devel::Pragma qw(:all);
190
 
 
191
 
  sub import {
192
 
      my ($class, %options) = @_;
193
 
      my $hints = my_hints;   # lexically-scoped %^H
194
 
      my $caller = ccstash(); # currently-compiling stash
195
 
 
196
 
      unless ($hints->{MyPragma}) { # top-level
197
 
           $hints->{MyPragma} = 1;
198
 
 
199
 
           # disable/enable this pragma before/after compile-time requires
200
 
           on_require \&teardown, \&setup;
201
 
      }
202
 
 
203
 
      if (new_scope($class)) {
204
 
          ...
205
 
      }
206
 
 
207
 
      my $scope_id = scope();
208
 
  }
 
173
    package MyPragma;
 
174
 
 
175
    use Devel::Pragma qw(:all);
 
176
 
 
177
    sub import {
 
178
        my ($class, %options) = @_;
 
179
        my $hints  = hints;        # lexically-scoped %^H
 
180
        my $caller = ccstash();    # currently-compiling stash
 
181
 
 
182
        unless ($hints->{MyPragma}) { # top-level
 
183
            $hints->{MyPragma} = 1;
 
184
 
 
185
            # disable/enable this pragma before/after compile-time requires
 
186
            on_require \&teardown, \&setup;
 
187
        }
 
188
 
 
189
        if (new_scope($class)) {
 
190
            ...
 
191
        }
 
192
 
 
193
        my $scope_id = scope();
 
194
    }
209
195
 
210
196
=head1 DESCRIPTION
211
197
 
219
205
 
220
206
    use Devel::Pragma qw(:all);
221
207
 
222
 
=head2 my_hints
223
 
 
224
 
Until perl change #33311, which isn't currently available in any stable
225
 
perl release, values set in %^H are visible in files compiled by C<use>, C<require> and C<do FILE>.
226
 
This makes pragmas leak from the scope in which they're meant to be enabled into scopes in which
227
 
they're not. C<my_hints> fixes that by making %^H lexically scoped i.e. it prevents %^H leaking
228
 
across file boundaries.
229
 
 
230
 
C<my_hints> installs versions of perl's C<require> and C<do FILE> builtins in the
231
 
currently-compiling scope which clear %^H before they execute and restore its values afterwards.
232
 
Thus it can be thought of a lexically-scoped backport of change #33311.
233
 
 
234
 
Note that C<my_hints> also sets the $^H bit that "localizes" (or in this case "lexicalizes") %^H.
235
 
 
236
 
The return value is a reference to %^H.
 
208
=head2 hints
 
209
 
 
210
This function enables the scoped behaviour of the hints hash (C<%^H>) and then returns a reference to it.
 
211
 
 
212
The hints hash is a compile-time global variable (which is also available at runtime in recent perls) that
 
213
can be used to implement lexically-scoped features and pragmas. This function provides a convenient
 
214
way to access this hash without the need to perform the bit-twiddling that enables it on older perls.
 
215
In addition, this module loads L<Lexical::SealRequireHints>, which implements bugfixes
 
216
that are required for the correct operation of the hints hash on older perls (< 5.12.0).
 
217
 
 
218
Typically, C<hints> should be called from a pragma's C<import> (and optionally C<unimport>) method:
 
219
 
 
220
    package MyPragma;
 
221
 
 
222
    use Devel::Pragma qw(hints);
 
223
 
 
224
    sub import {
 
225
        my $class = shift;
 
226
        my $hints = hints;
 
227
 
 
228
        if ($hints->{MyPragma}) {
 
229
            # ...
 
230
        } else {
 
231
            $hints->{MyPragma} = ...;
 
232
        }
 
233
 
 
234
        # ...
 
235
    }
237
236
 
238
237
=head2 new_scope
239
238
 
263
262
 
264
263
A warning is issued if C<scope> (or C<new_scope>) is called in a context in which it doesn't make sense i.e. if the
265
264
scoped behaviour of C<%^H> has not been enabled - either by explicitly modifying C<$^H>, or by calling
266
 
L<"my_hints"> or L<"on_require">.
 
265
L<"hints"> or L<"on_require">.
267
266
 
268
267
=head2 ccstash
269
268
 
363
362
typically via C<use> statements.
364
363
 
365
364
C<on_require> takes two callbacks (i.e. anonymous subs or sub references), each of which is called
366
 
with a reference to C<%^H>. The first callback is called before C<require>, and the second is called
367
 
after C<require> has loaded and compiled its file. %^H is cleared before C<require> and restored
368
 
afterwards. (If the file has already been loaded, or the required value is a vstring rather than
369
 
a file name, then both the callbacks and the clearance/restoration of C<%^H> are skipped.)
 
365
with a reference to a copy of C<%^H>. The first callback is called before C<require>, and the second
 
366
is called after C<require> has loaded and compiled its file. If the file has already been loaded,
 
367
or the required value is a vstring rather than a file name, then both the callbacks are skipped.
370
368
 
371
369
Multiple callbacks can be registered in a given scope, and they are called in the order in which they
372
370
are registered. Callbacks are unregistered automatically at the end of the (compilation of) the scope
373
371
in which they are registered.
374
372
 
375
 
C<on_require> callbacks can be used to disable/re-enable OP check hooks installed via
376
 
L<B::Hooks::OP::Check|B::Hooks::OP::Check> i.e. they can be used to make check hooks
377
 
lexically-scoped.
378
 
 
379
 
    package MyPragma;
380
 
 
381
 
    use Devel::Pragma qw(:all);
382
 
 
383
 
    sub import {
384
 
        my ($class, %args) = @_;
385
 
        my $hints = my_hints;
386
 
 
387
 
        unless ($hints->{MyPragma}) { # top-level
388
 
            $hints->{MyPragma} = 1;
389
 
            on_scope_end \&teardown;
390
 
            on_require \&teardown, \&setup;
391
 
            setup;
392
 
        }
393
 
    }
394
 
 
395
 
C<on_require> callbacks can also be used to rollback/restore lexical side-effects i.e. lexical features
396
 
whose side-effects extend beyond C<%^H> (like L<"my_hints">, C<on_require> implicitly renders C<%^H> lexically-scoped).
 
373
C<on_require> callbacks can be used to rollback/restore lexical side-effects i.e. lexical features
 
374
whose side-effects extend beyond C<%^H> (like L<"hints">, C<on_require> implicitly enables the scoped
 
375
behaviour of C<%^H>).
397
376
 
398
377
Fatal exceptions raised in C<on_require> callbacks are trapped and reported as warnings. If a fatal
399
378
exception is raised in the C<require> or C<do FILE> call, the post-C<require> callbacks are invoked
401
380
 
402
381
=head1 VERSION
403
382
 
404
 
0.54
 
383
0.60
405
384
 
406
385
=head1 SEE ALSO
407
386
 
435
414
 
436
415
=head1 COPYRIGHT AND LICENSE
437
416
 
438
 
Copyright (C) 2008-2010 by chocolateboy
 
417
Copyright (C) 2008-2013 by chocolateboy
439
418
 
440
419
This library is free software; you can redistribute it and/or modify
441
420
it under the same terms as Perl itself, either Perl version 5.8.1 or,