macro

 view release on metacpan or  search on metacpan

lib/macro.pm  view on Meta::CPAN

package macro;

use 5.008_001;

use strict;
use warnings;
use warnings::register;

our $VERSION = '0.06';

use constant DEBUG => $ENV{PERL_MACRO_DEBUG} ? 1 : 0;

use Scalar::Util (); # tainted()
use Carp ();

use PPI::Document ();
use PPI::Lexer ();
my $lexer = PPI::Lexer->new();

use B ();
use B::Deparse ();
my $deparser = B::Deparse->new('-si0', '-x9');

my $backend;

if(DEBUG >= 1 && !$^C){
	require macro::filter;
	$backend = 'macro::filter';
}
else{
	require macro::compiler;
	$backend = 'macro::compiler';
}
sub import{
	my $class = shift;

	return unless @_;

	$backend->import(@_);

	return;
}

sub backend{
	return $backend;
}

sub new :method{
	my($class) = @_;

	return bless {} => $class;
}

sub defmacro :method{
	my $self = shift;

	while(my($name, $macro) = splice @_, 0, 2){
		if( !defined($name) || !defined($macro) ){
			warnings::warnif('Illigal declaration of macro');
			next;
		}
		if(Scalar::Util::tainted($name) || Scalar::Util::tainted($macro)){
			Carp::croak('Insecure dependency in macro::defmacro()');
			return;
		}

		if(exists $self->{$name}){
			warnings::warnif(qq{Macro "$name" redefined});
		}

		my $optimize;
		if(ref($macro) eq 'CODE'){
			$macro = _deparse($macro);
			$optimize = 1;
		}

		my $mdoc = $lexer->lex_source( $self->process($macro) );

		$mdoc->prune(\&_want_useless_element);
		die $@ if $@;

		$self->{$name} = $optimize ? $self->_optimize($mdoc) : $mdoc;
	}

	return;
}

sub _deparse{
	my($coderef) = @_;
	my $cv = B::svref_2object($coderef);

	if(ref($cv->START) eq 'B::NULL'){
		my $subr = sprintf '%s &%s::%s',
			($cv->XSUB ? 'XSUB' : 'undefined subroutine'),
			 $cv->GV->STASH->NAME, $cv->GV->SAFENAME;
		Carp::croak("Cannot use $subr as macro entity");
	}
	else{
		my $src = $deparser->coderef2text($coderef);
		if($src =~ s/\A ( [^\{]+ ) //xms){ # remove prototype and attributes
			my $s = $1;
			if($s =~ /( \( .+ \) )/xms){
				warnings::warnif("Subroutine prototype $1 ignored");
			}
			if($s =~ /(: \s+ \w+)/xms){
				warnings::warnif("Subroutine attribute $1 ignored");
			}
		}
		return 'do' . $src;
	}
}

 view all matches for this distribution
 view release on metacpan -  search on metacpan

( run in 2.140 seconds using v1.00-cache-2.02-grep-82fe00e-cpan-48ebf85a1963 )