X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FEval%2FWithLexicals%2FRole%2FLexicalHints.pm;fp=lib%2FEval%2FWithLexicals%2FRole%2FLexicalHints.pm;h=8acc369d5eb048890c949a4aff38597d9dfab145;hb=148445b9606e76f0bc86d2f5bfd5d2f8588ceb0f;hp=0000000000000000000000000000000000000000;hpb=ce313355b83f08636deaa1dd24477924e7793490;p=p5sagit%2FEval-WithLexicals.git diff --git a/lib/Eval/WithLexicals/Role/LexicalHints.pm b/lib/Eval/WithLexicals/Role/LexicalHints.pm new file mode 100644 index 0000000..8acc369 --- /dev/null +++ b/lib/Eval/WithLexicals/Role/LexicalHints.pm @@ -0,0 +1,72 @@ +package Eval::WithLexicals::Role::LexicalHints; +use Moo::Role; + +our($hints, %hints); + +has first_eval => ( + is => 'rw', + default => sub { 1 }, +); + +has hints => ( + is => 'rw', + default => sub { {} }, +); + +around eval => sub { + my $orig = shift; + my($self) = @_; + + local *Eval::WithLexicals::Cage::capture_hints; + local $Eval::WithLexicals::Cage::hints = { %{$self->hints} }; + + my @ret = $orig->(@_); + + $self->hints({ Eval::WithLexicals::Cage::capture_hints() }); + + @ret; +}; + +# XXX: Sub::Quote::capture_unroll without 'my' +use B(); +sub _capture_unroll_global { + my ($from, $captures, $indent) = @_; + join( + '', + map { + /^([\@\%\$])/ + or die "capture key should start with \@, \% or \$: $_"; + (' ' x $indent).qq{${_} = ${1}{${from}->{${\B::perlstring $_}}};\n}; + } keys %$captures + ); +} + +around setup_code => sub { + my $orig = shift; + my($self) = @_; + # Only run the prelude on the first eval, hints will be set after + # that. + if($self->first_eval) { + $self->first_eval(0); + return $self->prelude, $orig->(@_); + } else { + # Seems we can't use the technique of passing via @_ for code in a BEGIN block + return q[ BEGIN { ], _capture_unroll_global('$Eval::WithLexicals::Cage::hints', $self->hints, 2), q[ } ], + $orig->(@_); + } +}; + +around capture_code => sub { + my $orig = shift; + my($self) = @_; + + ( q{ sub Eval::WithLexicals::Cage::capture_hints { + no warnings 'closure'; + my($hints, %hints); + BEGIN { $hints = $^H; %hints = %^H; } + return q{$^H} => \$hints, q{%^H} => \%hints; + } }, + $orig->(@_) ) +}; + +1;