10 Sub::Op - Install subroutines as opcodes.
20 sub dl_load_flags { 0x01 }
25 push @ISA, 'DynaLoader';
26 __PACKAGE__->bootstrap($VERSION);
35 STATIC OP *scalar_util_reftype(pTHX) {
42 PUSHs(sv_reftype(SvRV(sv), 0));
48 MODULE = Scalar::Util::Ops PACKAGE = Scalar::Util::Ops
54 k.len = sizeof("reftype")-1;
55 k.pp = scalar_util_reftype;
58 sub_op_register(aTHX_ &k);
61 In your Perl module file :
63 package Scalar::Util::Ops;
70 use Sub::Op; # Before loading our own shared library
75 push @ISA, 'DynaLoader';
76 __PACKAGE__->bootstrap($VERSION);
79 sub import { Sub::Op::enable(reftype => scalar caller) }
81 sub unimport { Sub::Op::disable(reftype => scalar caller) }
85 In your F<Makefile.PL> :
87 use ExtUtils::Depends;
89 my $ed = ExtUtils::Depends->new('Scalar::Util::Ops' => 'Sub::Op');
92 $ed->get_makefile_vars,
98 use B::Hooks::EndOfScope;
99 use Variable::Magic 0.08;
103 $placeholder = sub { require Carp; Carp::croak('PLACEHOLDER') };
104 _placeholder($placeholder);
107 my $sw = Variable::Magic::wizard(
108 data => sub { +{ guard => 0, pkg => $_[1], map => $_[2] } },
110 my ($var, $data, $name) = @_;
112 return if $data->{guard};
113 local $data->{guard} = 1;
115 return unless $data->{map}->{$name};
117 my $pkg = $data->{pkg};
118 my $fqn = join '::', $pkg, $name;
120 _incoming($name, $pkg);
123 *$fqn = $placeholder unless exists &$fqn;
134 Variable::Magic::getdata(%{"${pkg}::"}, $sw);
137 defined $data ? $data->{map} : undef;
141 my ($pkg, $name) = @_;
144 Variable::Magic::cast(%{"${pkg}::"}, $sw, $pkg, { $name => 1 });
151 Variable::Magic::dispell(%{"${pkg}::"}, $sw);
157 my $pkg = @_ > 0 ? $_[0] : caller;
158 my $fqn = "${pkg}::$name";
160 my $map = _map($pkg);
169 $^H{+(__PACKAGE__)} = 1;
171 on_scope_end { disable($name, $pkg) };
179 my $pkg = @_ > 0 ? $_[0] : caller;
180 my $fqn = "${pkg}::$name";
182 my $map = _map($pkg);
185 delete $map->{$name};
186 unless (keys %$map) {
195 my ($pkg, $inject) = @_;
197 my $stash = do { no strict 'refs'; \%{"${pkg}::"} };
199 while (my ($meth, $code) = each %$inject) {
200 next if exists $stash->{$meth} and (*{$stash->{$meth}}{CODE} // 0) == $code;
202 *{"${pkg}::$meth"} = $code;
209 $injector = Variable::Magic::wizard(
210 data => sub { +{ guard => 0, pkg => $_[1], subs => $_[2] } },
212 my ($stash, $data, $key) = @_;
214 return if $data->{guard};
215 local $data->{guard} = 1;
217 _inject($data->{pkg}, $data->{subs});
227 $B_OP_inject{first} = sub {
228 if (defined _custom_name($_[0])) {
229 $_[0] = bless $_[0], 'B::UNOP' unless $_[0]->isa('B::UNOP');
230 goto $_[0]->can('first') || die 'oops';
233 Carp::confess('Calling B::OP->first for something that isn\'t a custom op');
236 $B_OP_inject{can} = sub {
237 my ($obj, $meth) = @_;
238 if ($meth eq 'first') {
239 return undef unless defined _custom_name($obj);
241 $obj->SUPER::can($meth);
244 if (%B:: and %B::OP:: and *B::OP::type{CODE}) {
245 _inject('B::OP', \%B_OP_inject);
247 Variable::Magic::cast %B::OP::, $injector, 'B::OP', \%B_OP_inject;
250 my $B_Deparse_inject = {
252 my ($self, $op, $cx) = @_;
253 my $name = _custom_name($op);
254 die 'unhandled custom op' unless defined $name;
255 if ($op->flags & B::OPf_STACKED()) {
256 my $kid = $op->first;
257 $kid = $kid->first->sibling; # skip ex-list, pushmark
259 for (; not B::Deparse::null($kid); $kid = $kid->sibling) {
260 push @exprs, $self->deparse($kid, 6);
262 my $args = join(", ", @exprs);
263 return "$name($args)";
270 if (%B:: and %B::Deparse:: and *B::Deparse::pp_entersub{CODE}) {
271 _inject('B::Deparse', $B_Deparse_inject);
273 Variable::Magic::cast %B::Deparse::, $injector, 'B::Deparse', $B_Deparse_inject;
278 BEGIN { _monkeypatch() }
284 L<Variable::Magic>, L<B::Hooks::EndOfScope>.
286 L<ExtUtils::Depends>.
292 L<B::Hooks::OP::Check::EntersubForCV>.
296 Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.
298 You can contact me by mail or on C<irc.perl.org> (vincent).
302 Please report any bugs or feature requests to C<bug-sub-op at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Sub-Op>.
303 I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
307 You can find documentation for this module with the perldoc command.
311 Tests code coverage report is available at L<http://www.profvince.com/perl/cover/Sub-Op>.
313 =head1 COPYRIGHT & LICENSE
315 Copyright 2010 Vincent Pit, all rights reserved.
317 This program is free software; you can redistribute it and/or modify it
318 under the same terms as Perl itself.