Add persistent hints
[p5sagit/Eval-WithLexicals.git] / lib / Eval / WithLexicals / WithHintPersistence.pm
CommitLineData
8d732f30 1package Eval::WithLexicals::WithHintPersistence;
2use Moo::Role;
3use Sub::Quote;
4
5our $VERSION = '1.001000'; # 1.1.0
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 {
70 no warnings 'closure';
71 my($hints, %hints);
72 BEGIN { $hints = $^H; %hints = %^H; }
73 return q{$^H} => \$hints, q{%^H} => \%hints;
74 } },
75 $orig->(@_) )
76};
77
78=head1 NAME
79
80Eval::WithLexicals::WithHintPersistence - Persist compile hints between evals
81
82=head1 SYNOPSIS
83
84 use Eval::WithLexicals;
85
86 my $eval = Eval::WithLexicals->with_plugins("HintPersistence")->new;
87
88=head1 DESCRIPTION
89
90Persist pragams and other compile hints between evals (for example the
91L<strict> and L<warnings> flags in effect).
92
93Saves and restores the C<$^H> and C<%^H> variables.
94
95=head1 METHODS
96
97=head2 hints
98
99 $eval->hints('$^H')
100
101Returns the internal hints hash, keys are C<$^H> and C<%^H> for the hint bits
102and hint hash respectively.
103
104=cut
105
1061;