package Debug::Filter::PrintExpr; use strict; use warnings; use Filter::Simple; our (@h, $p); sub gen_print { my ($self, $type, $label, $expr, $fh) = @_; # resulting code, with EXPR literally substituted by # the value of $expr and all in one single line: # # $: # { # local ($\, $,); # print 'line ', __LINE__, ':', ' EXPR = ', "'", # scalar(EXPR), "'", "\n"; # } # # @: # { # local ($\, $,); # print 'line ', __LINE__, ':', ' EXPR = ', "('", # join("', '", (EXPR)), "')", "\n"; # } # # %: # { # local ($\, $,); # print 'line ', __LINE__, ':', ' EXPR = '; # local (@Debug::Filter::PrintExpr::h, $Debug::Filter::PrintExpr::p); # push @Debug::Filter::PrintExpr::h, $Debug::Filter::PrintExpr::p # while $Debug::Filter::PrintExpr::p = [each (EXPR)], # defined $Debug::Filter::PrintExpr::p->[0]; # print '(', (join ', ', # map {"'$_->[0]' => '$_->[1]'"} @Debug::Filter::PrintExpr::h), # ')', "\n"; # } # # quotes q and qq are for code generation # quotes " and ' are for generated code my $stmt = q[{local ($\, $,); print ]; $stmt .= qq{$fh } if $fh; $stmt .= $label ? qq{'$label'} : q{'line ', __LINE__, ':'}; if ($expr) { $stmt .= qq{, ' $expr = '}; if ($type eq '$') { $stmt .= qq{, "'", scalar($expr), "'"}; } elsif ($type eq '@') { $stmt .= qq{, "('", join("', '", ($expr)), "')"}; } elsif ($type eq '%') { my $h = q{@} . $self . q{::h}; my $p = q{$} . $self . q{::p}; $stmt .= qq{; local ($h, $p); }; $stmt .= qq{push $h, $p }; $stmt .= qq{while $p = [each ($expr)], }; $stmt .= qq{defined $p} . q{->[0]; }; $stmt .= q{print '(', (join ', ', }; $stmt .= q{map {"'$_->[0]' => '$_->[1]'"} }; $stmt .= qq{$h), ')'}; } } $stmt .= q[, "\n";}]; return $stmt; } FILTER { my ($self, %opt) = @_; s/ ^\h*\# (?[%@\$]) \{\h* (?