sleepingsquirrel,

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:

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
And here is the altered Loop_unroll module:
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)

-stvn

In reply to Re: Playing with (macro/source-filter) fire by stvn
in thread Playing with (macro/source-filter) fire by sleepingsquirrel

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.