also preserve warnings
[p5sagit/Eval-WithLexicals.git] / lib / Eval / WithLexicals / WithHintPersistence.pm
CommitLineData
8d732f30 1package Eval::WithLexicals::WithHintPersistence;
2use Moo::Role;
3use Sub::Quote;
4
9aa1478d 5our $VERSION = '1.002000'; # 1.2.0
8d732f30 6$VERSION = eval $VERSION;
7
8# Used localised
9our($hints, %hints);
10
11has hints => (
12 is => 'rw',
13 default => quote_sub q{ {} },
14);
15
16has _first_eval => (
17 is => 'rw',
18 default => quote_sub q{ 1 },
19);
20
21around eval => sub {
22 my $orig = shift;
23 my($self) = @_;
24
25 local *Eval::WithLexicals::Cage::capture_hints;
26 local $Eval::WithLexicals::Cage::hints = { %{$self->hints} };
27
28 my @ret = $orig->(@_);
29
30 $self->hints({ Eval::WithLexicals::Cage::capture_hints() });
31
32 @ret;
33};
34
35# XXX: Sub::Quote::capture_unroll without 'my'
36use B();
37sub _capture_unroll_global {
38 my ($from, $captures, $indent) = @_;
39 join(
40 '',
41 map {
42 /^([\@\%\$])/
43 or die "capture key should start with \@, \% or \$: $_";
44 (' ' x $indent).qq{${_} = ${1}{${from}->{${\B::perlstring $_}}};\n};
45 } keys %$captures
46 );
47}
48
49sub setup_code {
50 my($self) = @_;
51 # Only run the prelude on the first eval, hints will be set after
52 # that.
53 if($self->_first_eval) {
54 $self->_first_eval(0);
55 return $self->prelude;
56 } else {
57 # Seems we can't use the technique of passing via @_ for code in a BEGIN
58 # block
59 return q[ BEGIN { ],
60 _capture_unroll_global('$Eval::WithLexicals::Cage::hints', $self->hints, 2),
61 q[ } ],
62 }
63};
64
65around capture_code => sub {
66 my $orig = shift;
67 my($self) = @_;
68
69 ( q{ sub Eval::WithLexicals::Cage::capture_hints {
14786ff8 70 my ($hints, %hints, $warn_bits);
71 BEGIN {
72 no warnings 'closure';
73 $hints = $^H;
74 %hints = %^H;
75 $warn_bits = ${^WARNING_BITS};
76 }
77 return (
78 q{$^H} => \$hints,
79 q{%^H} => \%hints,
80 q{${^WARNING_BITS}} => \$warn_bits,
81 );
8d732f30 82 } },
83 $orig->(@_) )
84};
85
54153012 861;
87__END__
88
8d732f30 89=head1 NAME
90
91Eval::WithLexicals::WithHintPersistence - Persist compile hints between evals
92
93=head1 SYNOPSIS
94
95 use Eval::WithLexicals;
96
97 my $eval = Eval::WithLexicals->with_plugins("HintPersistence")->new;
98
99=head1 DESCRIPTION
100
101Persist pragams and other compile hints between evals (for example the
102L<strict> and L<warnings> flags in effect).
103
104Saves and restores the C<$^H> and C<%^H> variables.
105
106=head1 METHODS
107
108=head2 hints
109
110 $eval->hints('$^H')
111
112Returns the internal hints hash, keys are C<$^H> and C<%^H> for the hint bits
113and hint hash respectively.
114
54153012 115=head1 SUPPORT
8d732f30 116
54153012 117See L<Eval::WithLexicals> for support and contact information.
118
119=head1 AUTHORS
120
121See L<Eval::WithLexicals> for authors.
122
123=head1 COPYRIGHT AND LICENSE
124
125See L<Eval::WithLexicals> for the copyright and license.
126
127=cut