Subject: | Acme::Don't 2.0! |
Hello, DCONWAY.
I think Acme::Don't has potential to deal with double negative
sentences, so I have implemented the function, although it is never
versatile :)
In this Acme::Don't 2.0, the following will runs as you expect:
use feature 'say';
use Acme::Don't 2.0;
don't{
say "It is not done.";
don't{
say "It is done, expectedly.";
};
say "It is not done, too.";
};
What do you think of it?
(However, it is not (yet) implementet that the "don't {...} if/unless
..." syntax.)
Regards,
--
Goro Fuji (GFUJI at CPAN.org)
Subject: | t.pm |
package Acme::Don::t;
use 5.008_001; # maybe
use warnings;
use strict;
our $VERSION = '2.0';
use B ();
#use B::Debug ();
our $cur_pad;
sub _get_gvref{
my($o) = @_;
my $gv;
if(ref($o) eq 'B::SVOP'){ # without threads
$gv = $o->gv;
}
else{ # with threads
$gv = ($cur_pad->ARRAY)[$o->padix];
}
return $gv->object_2svref;
}
sub _get_cvref{
my($o) = @_;
my $cv = ($cur_pad->ARRAY)[$o->targ];
return $cv->object_2svref;
}
sub B::OP::_dont{ }
sub B::UNOP::_dont{
my($o) = @_;
if($o->name eq 'refgen'){
my $op_gv = $o->sibling->first;
if(_get_gvref($op_gv) == \*don::t){
my $op_anoncode = $o->first->first->next;
_get_cvref($op_anoncode)->();
}
}
}
sub don::t(&){
my $cv = B::svref_2object(@_);
local $cur_pad = ($cv->PADLIST->ARRAY)[-1];
B::walkoptree($cv->ROOT, '_dont');
return;
}
1;
__END__
=for Hacking:
# by B::Terse
# with threads
UNOP (0x10137ca0) entersub [3]
UNOP (0x10137c68) null [142]
OP (0x10137c88) pushmark
& UNOP (0x10137c48) refgen
UNOP (0x10137c28) null [142]
OP (0x1013c488) pushmark
* SVOP (0x10137c08) anoncode [2] CV (0x1004f710)
UNOP (0x101a3fe8) null [17]
* PADOP (0x100fcda8) gv GV (0x101afef0) *don::t
# without threads
UNOP (0x1010e650) entersub [2]
UNOP (0x1010e618) null [142]
OP (0x1010e638) pushmark
& UNOP (0x1010e5f8) refgen
UNOP (0x1010e5c0) null [142]
OP (0x1010e5e0) pushmark
* SVOP (0x1010e5a0) anoncode [1] CV (0x1003bec8)
UNOP (0x1010cd88) null [17]
* SVOP (0x100f1008) gv GV (0x100ff1e8) *don::t
=cut
Subject: | test.pl |
#!perl -w
use strict;
use Test::More tests => 5;
use Acme::Don't 2.0;
sub Do(&){
my($block) = @_;
$block->();
}
don't{
fail;
don't{
Do{
pass;
};
don't{
fail;
don't{
pass;
};
fail;
don't{
pass;
don't{
fail;
don't{
pass;
};
fail;
};
};
fail;
Do{
fail;
};
};
pass;
};
fail;
};