X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FEval%2FWithLexicals.pm;fp=lib%2FEval%2FWithLexicals.pm;h=7028702ef651a9319d5d1a0911545eebff4e76eb;hb=148445b9606e76f0bc86d2f5bfd5d2f8588ceb0f;hp=fab265c66655b6f419830f6cf6e539a49e2ec3f5;hpb=ce313355b83f08636deaa1dd24477924e7793490;p=p5sagit%2FEval-WithLexicals.git diff --git a/lib/Eval/WithLexicals.pm b/lib/Eval/WithLexicals.pm index fab265c..7028702 100644 --- a/lib/Eval/WithLexicals.pm +++ b/lib/Eval/WithLexicals.pm @@ -1,110 +1,12 @@ package Eval::WithLexicals; use Moo; -use Sub::Quote; our $VERSION = '1.001000'; # 1.1.0 $VERSION = eval $VERSION; -has lexicals => (is => 'rw', default => quote_sub q{ {} }); - -{ - my %valid_contexts = map +($_ => 1), qw(list scalar void); - - has context => ( - is => 'rw', default => quote_sub(q{ 'list' }), - isa => sub { - my ($val) = @_; - die "Invalid context type $val - should be list, scalar or void" - unless $valid_contexts{$val}; - }, - ); -} - -has in_package => ( - is => 'rw', default => quote_sub q{ 'Eval::WithLexicals::Scratchpad' } -); - -has prelude => ( - is => 'rw', default => quote_sub q{ 'use strictures 1;' } -); - -sub eval { - my ($self, $to_eval) = @_; - local *Eval::WithLexicals::Cage::current_line; - local *Eval::WithLexicals::Cage::pad_capture; - local *Eval::WithLexicals::Cage::grab_captures; - my $setup = Sub::Quote::capture_unroll('$_[2]', $self->lexicals, 2); - my $package = $self->in_package; - my $prelude = $self->prelude; - local our $current_code = qq!${prelude} -${setup} -sub Eval::WithLexicals::Cage::current_line { -package ${package}; -#line 1 "(eval)" -${to_eval} -;sub Eval::WithLexicals::Cage::pad_capture { } -BEGIN { Eval::WithLexicals::Util::capture_list() } -sub Eval::WithLexicals::Cage::grab_captures { - no warnings 'closure'; no strict 'vars'; - package Eval::WithLexicals::VarScope;!; - $self->_eval_do(\$current_code, $self->lexicals, $to_eval); - my @ret; - my $ctx = $self->context; - if ($ctx eq 'list') { - @ret = Eval::WithLexicals::Cage::current_line(); - } elsif ($ctx eq 'scalar') { - $ret[0] = Eval::WithLexicals::Cage::current_line(); - } else { - Eval::WithLexicals::Cage::current_line(); - } - $self->lexicals({ - %{$self->lexicals}, - %{$self->_grab_captures}, - }); - @ret; -} - -sub _grab_captures { - my ($self) = @_; - my $cap = Eval::WithLexicals::Cage::grab_captures(); - foreach my $key (keys %$cap) { - my ($sigil, $name) = $key =~ /^(.)(.+)$/; - my $var_scope_name = $sigil.'Eval::WithLexicals::VarScope::'.$name; - if ($cap->{$key} eq eval "\\${var_scope_name}") { - delete $cap->{$key}; - } - } - $cap; -} - -sub _eval_do { - my ($self, $text_ref, $lexicals, $original) = @_; - local @INC = (sub { - if ($_[1] eq '/eval_do') { - open my $fh, '<', $text_ref; - $fh; - } else { - (); - } - }, @INC); - do '/eval_do' or die $@; -} - -{ - package Eval::WithLexicals::Util; - - use B qw(svref_2object); - - sub capture_list { - my $pad_capture = \&Eval::WithLexicals::Cage::pad_capture; - my @names = grep $_ ne '&', map $_->PV, grep $_->isa('B::PV'), - svref_2object($pad_capture)->OUTSIDE->PADLIST->ARRAYelt(0)->ARRAY; - $Eval::WithLexicals::current_code .= - '+{ '.join(', ', map "'$_' => \\$_", @names).' };' - ."\n}\n}\n1;\n"; - } -} +with 'Eval::WithLexicals::Role::Eval'; +with 'Eval::WithLexicals::Role::PreludeEachTime'; =head1 NAME