package Recur_unroll; use strict; use Filter::Simple; FILTER { my ($name1, $body2, $name3, $param4, $body5); #This is the macro replacement pattern we're looking for... my $macro = 'sub name1 {$body2; return name3($param4); $body5}'; #run the macro snippet through B::Deparse (better way to grab output?) my $compiled_macro=`perl -MO=Deparse,-x9 -e'$macro'`; #screws with ', FIXME. #compile the main script my $source = `perl -MO=Deparse,-x9 -e'$_'` if $_; #same problem, Bad dog. #These are crude regex to try to match perlisms $name1 = '\s+([a-zA-Z][a-zA-Z0-9]*)\s+'; $body2 = '(.*?'; $name3 = '[^;]*?(\1'; $param4 = '([^)]*?)'; #no parens allowed inside sub parameter list $body5 = ').*?)'; #deswizzle variable order (possibly mangled by compile) #variables should be guarenteed to occur only once because of side-effects my $i; my $reorder; while ($compiled_macro=~/(name1|body2|name3|param4|body5)/g) { $reorder.="\$$1 = \$".++$i.";"; # map vars to capturing parens } $compiled_macro=~ s/name/\$name/g; #makes subroutine names var for interpolation $compiled_macro=~ s/(body\d);/$1/g; #get rid of dummy placeholder semi's $compiled_macro =~ s/([|(){}\^*+?.\[\]])/\\\\$1/g; #de-meta stuff, not $ (ick) my $regexed_macro; eval '$regexed_macro=qq/'."$compiled_macro".'/'; #interpolate pattern match junk $source =~ s{$regexed_macro} { eval $reorder; $name3=quotemeta($name3); $body2=~s/$name3/eval{local \@_=$param4;$body2 $body5};/; "sub $name1 { $body2 $body5 }"; }esgx; $_ = $source; #print STDERR "$source\n"; }; 1;