PerlX-ScopeFunction
view release on metacpan or search on metacpan
lib/PerlX/ScopeFunction.pm view on Meta::CPAN
package PerlX::ScopeFunction;
use v5.36;
our $VERSION = "0.05";
use Package::Stash;
use Const::Fast qw( const );
use Keyword::Simple;
use PPR;
our %STASH = ();
const our $do => \&__do;
const our $also => \&__also;
const our $tap => \&__also;
sub __parse_imports (@args) {
my %import_as;
my $keyword;
while (@args) {
my $it = shift @args;
if (defined($keyword)) {
if (!ref($it)) {
$import_as{$keyword} = $keyword;
$keyword = $it;
} elsif (ref($it) eq 'HASH') {
$import_as{$keyword} = $it->{'-as'} // $keyword;
$keyword = undef;
}
} else {
if (!ref($it)) {
$keyword = $it
}
}
}
$import_as{$keyword} = $keyword if defined($keyword);
return \%import_as;
}
sub import ($class, @args) {
my $caller = (caller)[0];
my %handler = (
'let' =>[
sub { __define_keyword( \&__rewrite_let, $_[0] ) },
sub { __undefine_keyword( $_[0] ) },
],
'with' =>[
sub { __define_keyword( \&__rewrite_with, $_[0] ) },
sub { __undefine_keyword( $_[0] ) },
],
'$also' => [
sub { __import_scalar_symbol(\\&__also, $_[0], $_[1]) },
sub { __unimport_scalar_symbol($_[0], $_[1]) },
],
'$tap' => [
sub { __import_scalar_symbol(\\&__also, $_[0], $_[1]) },
sub { __unimport_scalar_symbol($_[0], $_[1]) },
],
'$do' => [
sub { __import_scalar_symbol(\\&__do, $_[0], $_[1]) },
sub { __unimport_scalar_symbol($_[0], $_[1]) },
],
);
my %import_as = do {
if (@args > 0) {
%{ __parse_imports(@args) };
} else {
map { $_ => $_ } keys %handler
}
};
for (keys %import_as) {
my ($importer, $unimporter) = @{$handler{$_}};
my $as = $import_as{$_};
$importer->($as, $caller);
push @{ $STASH{$caller} }, sub { $unimporter->($as, $caller) };
}
}
sub unimport ($class) {
my $caller = (caller)[0];
for my $unimporter (@{ $STASH{$caller} // []}) {
$unimporter->();
}
}
sub __do {
my ($self, $code) = @_;
local $_ = $self;
return $self->$code();
}
sub __also {
my ($self, $code) = @_;
local $_ = $self;
$self->$code();
return $self;
}
sub __import_scalar_symbol ($code, $symbol, $pkg) {
Package::Stash->new($pkg)->add_symbol($symbol, $code);
}
sub __unimport_scalar_symbol ($symbol, $pkg) {
Package::Stash->new($pkg)->remove_symbol($symbol);
}
sub __define_keyword ($code, $keyword) {
Keyword::Simple::define $keyword, $code;
}
sub __undefine_keyword ($keyword) {
Keyword::Simple::undefine $keyword;
}
my $GRAMMAR = qr{
(?(DEFINE)
(?<LetAssignmentSequence>
((?&LetAssignment))
(?: ; (?&PerlOWS) ((?&LetAssignment)))*
(?: ; )?
)
(?<LetAssignmentLHS>
(?>(?&PerlLvalue))
)
(?<LetAssignment>
(?&LetAssignmentLHS) (?&PerlOWS) = (?&PerlOWS) (?&PerlExpression)
)
)
$PPR::GRAMMAR
}x;
sub __comb_PerlVariable ($code) {
map {
s/(?&PerlOWS) $GRAMMAR//xg;
$_
} map {
grep { defined } m/((?&PerlVariable)) $GRAMMAR/xsg;
( run in 0.902 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )