4 use Sub::Exporter -setup => {
5 exports => [qw(eval_closure)],
6 groups => { default => [qw(eval_closure)] },
12 use Scalar::Util qw(reftype);
18 $args{source} = _canonicalize_source($args{source});
19 _validate_env($args{environment} ||= {});
21 $args{source} = _line_directive($args{description}) . $args{source}
22 if defined $args{description};
24 my ($code, $e) = _clean_eval_closure(@args{qw(source environment)});
26 croak("Failed to compile source: $e\n\nsource:\n$args{source}")
32 sub _canonicalize_source {
35 if (defined($source)) {
37 if (reftype($source) eq 'ARRAY'
38 || overload::Method($source, '@{}')) {
39 return join "\n", @$source;
41 elsif (overload::Method($source, '""')) {
45 croak("The 'source' parameter to eval_closure must be a "
46 . "string or array reference");
54 croak("The 'source' parameter to eval_closure is required");
61 croak("The 'environment' parameter must be a hashref")
62 unless reftype($env) eq 'HASH';
64 for my $var (keys %$env) {
65 croak("Environment key '$var' should start with \@, \%, or \$")
66 unless $var =~ /^([\@\%\$])/;
67 croak("Environment values must be references, not $env->{$var}")
68 unless ref($env->{$var});
73 my ($description) = @_;
75 return qq{#line 1 "$description"\n};
78 sub _clean_eval_closure {
79 my ($source, $captures) = @_;
81 if ($ENV{EVAL_CLOSURE_PRINT_SOURCE}) {
82 _dump_source(_make_compiler_source(@_));
85 my @capture_keys = keys %$captures;
86 my ($compiler, $e) = _make_compiler($source, @capture_keys);
88 if (defined $compiler) {
89 $code = $compiler->(@$captures{@capture_keys});
92 if (defined($code) && (!ref($code) || ref($code) ne 'CODE')) {
93 $e = "The 'source' parameter must return a subroutine reference, "
104 my $compiler = eval _make_compiler_source(@_);
106 return ($compiler, $e);
108 memoize('_make_compiler');
110 sub _make_compiler_source {
111 my ($source, @capture_keys) = @_;
116 'my ' . $_ . ' = ' . substr($_, 0, 1) . '{$_[' . $i++ . ']};'
127 if (try { require Perl::Tidy }) {
128 Perl::Tidy::perltidy(
130 destination => \$output,