#! perl -slw
use strict;
use Macro;
MACRO sub fred {
my( $a, $b, $c ) = @_;
return ( $a + $b ) * $c;
}
ENDMACRO
my( $x, $y, $z ) = ( 1, 4, 7 );
print fred( $x, $y, $z );
for my $x ( 1 .. 10 ) {
print fred( $x, $y, $z );
}
__END__
P:\test>435608
35
35
42
49
56
63
70
77
84
91
98
####
my( $x, $y, $z ) = ( 1, 4, 7 );
print do{
our $MACRO_RETURN;
local $MACRO_RETURN;
$MACRO_RETURN = ( $x + $y ) * $z; goto MACRO_RETURN;;
MACRO_RETURN: $MACRO_RETURN
};
for my $x ( 1 .. 10 ) {
print do{
our $MACRO_RETURN;
local $MACRO_RETURN;
$MACRO_RETURN = ( $x + $y ) * $z; goto MACRO_RETURN;;
MACRO_RETURN: $MACRO_RETURN
};
}
####
package Macro;
use strict;
use warnings;
use Filter::Simple;
my %macros;
FILTER_ONLY
executable => sub {
while(
s[
MACRO\s+
sub\s+
(\w+)\s+
\{\s+
my\s*\( \s* ( [^\)]+? ) \s* \)\s* =\s* \@_;\s+
( .*? )
\} \s*
ENDMACRO
][]xsmg
) {
my( $name, $args, $body ) = ( $1, $2, $3 );
$body =~ s[[\r\n]+][]g;
$macros{ $name } = [
[ split ',\s*', $args ],
"do{
our \$MACRO_RETURN;
local \$MACRO_RETURN;
$body;
MACRO_RETURN: \$MACRO_RETURN
}"
];
}
for my $macro ( keys %macros ) {
s[
$macro\( \s* ( [^\)]+ ) \s* \)
]{
my @actual = split '\s*,\s*', $1;
my @formal = @{ $macros{ $macro }[ 0 ] };
my $do = $macros{ $macro }[ 1 ];
my %substs; @substs{ @formal } = @actual;
$do =~ s[([\$][\w]+)]{
exists $substs{ $1 } ? $substs{ $1 } : $1
}eg;
$do =~ s[return\s*(.*?)\s*;]
[\$MACRO_RETURN = $1; goto MACRO_RETURN;]g;
$do;
}xeg;
}
$_;
};
1;