Put core back into core, persistence becomes a plugin
[p5sagit/Eval-WithLexicals.git] / lib / Eval / WithLexicals / WithHintPersistence.pm
CommitLineData
d9087132 1package Eval::WithLexicals::WithHintPersistence;
148445b9 2use Moo::Role;
3
4our($hints, %hints);
5
6has first_eval => (
7 is => 'rw',
8 default => sub { 1 },
9);
10
11has hints => (
12 is => 'rw',
13 default => sub { {} },
14);
15
16around eval => sub {
17 my $orig = shift;
18 my($self) = @_;
19
20 local *Eval::WithLexicals::Cage::capture_hints;
21 local $Eval::WithLexicals::Cage::hints = { %{$self->hints} };
22
23 my @ret = $orig->(@_);
24
25 $self->hints({ Eval::WithLexicals::Cage::capture_hints() });
26
27 @ret;
28};
29
30# XXX: Sub::Quote::capture_unroll without 'my'
31use B();
32sub _capture_unroll_global {
33 my ($from, $captures, $indent) = @_;
34 join(
35 '',
36 map {
37 /^([\@\%\$])/
38 or die "capture key should start with \@, \% or \$: $_";
39 (' ' x $indent).qq{${_} = ${1}{${from}->{${\B::perlstring $_}}};\n};
40 } keys %$captures
41 );
42}
43
d9087132 44sub setup_code {
148445b9 45 my($self) = @_;
46 # Only run the prelude on the first eval, hints will be set after
47 # that.
48 if($self->first_eval) {
49 $self->first_eval(0);
d9087132 50 return $self->prelude;
148445b9 51 } else {
d9087132 52 # Seems we can't use the technique of passing via @_ for code in a BEGIN
53 # block
54 return q[ BEGIN { ],
55 _capture_unroll_global('$Eval::WithLexicals::Cage::hints', $self->hints, 2),
56 q[ } ],
148445b9 57 }
58};
59
60around capture_code => sub {
61 my $orig = shift;
62 my($self) = @_;
63
64 ( q{ sub Eval::WithLexicals::Cage::capture_hints {
d9087132 65 no warnings 'closure'; # XXX: can we limit the scope of this?
148445b9 66 my($hints, %hints);
67 BEGIN { $hints = $^H; %hints = %^H; }
68 return q{$^H} => \$hints, q{%^H} => \%hints;
69 } },
70 $orig->(@_) )
71};
72
731;