Intruiging idea. I am a fan of LISP style (runtime code expansion) more than C style (text substitution) macros myself. So this node grabbed my attention. But I tried running your code, which worked, but when I added a few print statments to see the guts of it, it looked to me that nothing is really happening.
Here is the output I got:
And here is the altered Loop_unroll module:MACRO (NOT-COMPILED): for ($var1=$cons2;$var3<$cons4;$var5++) {$body6} -e syntax OK MACRO (COMPILED & DEPARSED): while ($var3 < $cons4) { $body6; } continue { ++$var5 } SOURCE (NOT-COMPILED): #use Recur_unroll; my $x; for($x=0;$x<8;$x++) { my $f=fact($x); print "factorial($x)=$f\n"; } sub fact { return(1) if ($_[0] <= 0); return $_[0]*fact($_[0]-1); } 1; -e syntax OK SOURCE (COMPILED & DEPARSED): my $x; while ($x < 8) { my $f = fact($x); print "factorial($x)=$f\n"; } continue { ++$x } sub fact { $_[0] <= 0 and return 1; return $_[0] * fact($_[0] - 1); } '???'; REORDER: $var3 = $1;$cons4 = $2;$body6 = $3;$var5 = $4; REG-EXED MACRO: while \((\$[a-zA-Z][a-zA-Z0-9]*) < (\d+)\) \{ ([^}]+); \} continue \{ \+\+(\$[a-zA-Z][a-zA-Z0-9]*) \} FINAL SOURCE: my $x; while ($x < 8) { my $f = fact($x); print "factorial($x)=$f\n"; } continue { ++$x } sub fact { $_[0] <= 0 and return 1; return $_[0] * fact($_[0] - 1); } '???'; MACRO (NOT-COMPILED): for ($var1=$cons2;$var3<$cons4;$var5++) {$body6} -e syntax OK MACRO (COMPILED & DEPARSED): while ($var3 < $cons4) { $body6; } continue { ++$var5 } SOURCE (NOT-COMPILED): SOURCE (COMPILED & DEPARSED): REORDER: $var3 = $1;$cons4 = $2;$body6 = $3;$var5 = $4; REG-EXED MACRO: while \((\$[a-zA-Z][a-zA-Z0-9]*) < (\d+)\) \{ ([^}]+); \} continue \{ \+\+(\$[a-zA-Z][a-zA-Z0-9]*) \} FINAL SOURCE: factorial()=1 factorial(1)=1 factorial(2)=2 factorial(3)=6 factorial(4)=24 factorial(5)=120 factorial(6)=720 factorial(7)=5040
package Loop_unroll; use strict; use Filter::Simple; FILTER { my $unroll_limit = 10; #max unrolling depth my ($var1, $cons2, $var3, $cons4, $var5, $body6); #This is the macro replacement pattern we're looking for... my $macro = 'for ($var1=$cons2;$var3<$cons4;$var5++) {$body6}'; print "MACRO (NOT-COMPILED): $macro\n"; #run the macro snippet through B::Deparse (better way to grab outp +ut?) my $compiled_macro=`perl -MO=Deparse,-x9 -e'$macro'`; #screws with + ', FIX ME. print "MACRO (COMPILED & DEPARSED): $compiled_macro\n"; print "SOURCE (NOT-COMPILED): $_\n"; #compile the main script my $source = `perl -MO=Deparse,-x9 -e'$_'` if $_; #same proble +m, Bad dog. print "SOURCE (COMPILED & DEPARSED): $source\n"; #These are crude regex to try to match perl variables and integers $var1 = $var3 = $var5 = '(\$[a-zA-Z][a-zA-Z0-9]*)'; $cons2 = $cons4 = '(\d+)'; $body6 = '([^}]+)'; #barf, should be something nicer, no nested bl +ocks #deswizzle variable order (mangled by compile) #variables should be guarenteed to occur only once because of side +-effects my $i; my $reorder; while ($compiled_macro=~/(var1|cons2|var3|cons4|var5|body6)/g) { $reorder.="\$$1 = \$".++$i.";"; # map vars to capturing parens } print "REORDER: $reorder\n"; $compiled_macro=~s/([|(){}\^*+?.\[\]])/\\\\$1/g; #de-meta stuff, n +ot $ (ick) my $regexed_macro; eval '$regexed_macro=qq/'."$compiled_macro".'/'; #interpolate patt +ern match junk print "REG-EXED MACRO: $regexed_macro\n"; $source =~ s{$regexed_macro} { eval $reorder; # better method? ($var1 eq $var3 and $var1 eq $var5 and $cons4 - $cons2 < $unroll_limit) ? "$var1 = $cons2;".("{$body6;} $var1++;") x ($c +ons4-$cons2) : $&; #Lazy like a fox. }eg; $_ = $source; print "FINAL SOURCE: $source\n"; }; 1;
Am I missing something?
(BTW - I am on Mac OS X (10.3.2) with Perl v5.8.0)
In reply to Re: Playing with (macro/source-filter) fire
by stvn
in thread Playing with (macro/source-filter) fire
by sleepingsquirrel
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |