2 use Sub::Exporter -setup => {
3 exports => [qw(eval_closure)],
4 groups => { default => [qw(eval_closure)] },
9 use Scalar::Util qw(reftype);
15 $args{source} = _canonicalize_source($args{source});
16 _validate_env($args{environment} ||= {});
18 my ($code, $e) = _clean_eval_closure(@args{qw(source environment name)});
20 croak("Failed to compile source: $e\n\nsource:\n$args{source}")
26 sub _canonicalize_source {
29 if (defined($source)) {
31 if (reftype($source) eq 'ARRAY'
32 || overload::Method($source, '@{}')) {
33 return join "\n", @$source;
35 elsif (overload::Method($source, '""')) {
39 croak("The 'source' parameter to eval_closure must be a "
40 . "string or array reference");
48 croak("The 'source' parameter to eval_closure is required");
55 croak("The 'environment' parameter must be a hashref")
56 unless reftype($env) eq 'HASH';
58 for my $var (keys %$env) {
59 croak("Environment key '$_' should start with \@, \%, or \$")
60 unless $var =~ /^([\@\%\$])/;
61 croak("Environment values must be references, not $env->{$var}")
62 unless ref($env->{$var});
66 sub _clean_eval_closure {
67 # my ($source, $__captures, $name) = @_
68 my $__captures = $_[1];
73 if ($ENV{EVAL_CLOSURE_PRINT_SOURCE}) {
74 _dump_source(_make_source(@_), $_[2]);
77 my $code = eval _make_source(@_);
80 if (defined($code) && (!ref($code) || ref($code) ne 'CODE')) {
81 $e = "The 'source' parameter must return a subroutine reference, "
90 my ($source, $__captures) = @_;
94 . substr($_, 0, 1) . '{$__captures->{\'' . $_ . '\'}};'
101 my ($source, $name) = @_;
104 if (try { require Perl::Tidy }) {
105 Perl::Tidy::perltidy(
107 destination => \$output,
114 $name = defined($name) ? $name : "__ANON__";
115 warn $name . ":\n" . $output . "\n";