]> git.vpit.fr Git - perl/modules/Sub-Op.git/commitdiff
Handle existing prototyped subs
authorVincent Pit <vince@profvince.com>
Sun, 3 Jan 2010 13:11:33 +0000 (14:11 +0100)
committerVincent Pit <vince@profvince.com>
Sun, 3 Jan 2010 13:11:33 +0000 (14:11 +0100)
Makefile.PL
lib/Sub/Op.pm
t/11-existing.t

index 6069830e4976897ba31de3c51e1d695ba6db5ecf..a7e84dbdec4fd9d2e4c0d1adda9439ccb7814d3f 100644 (file)
@@ -14,6 +14,7 @@ $file = "lib/$file.pm";
 my %PREREQ_PM = (
  'B::Hooks::EndOfScope' => 0,
  'DynaLoader'           => 0,
+ 'Scalar::Util'         => 0,
  'Variable::Magic'      => '0.39',
 );
 
index 76d22dacb4dab4ba36869b65ecbceaf8353ffae7..8c8f6c87a4df667033ccba09f8a57db8b118221f 100644 (file)
@@ -118,6 +118,8 @@ When L<B> and L<B::Deparse> are loaded, they get automatically monkeypatched so
 
 =cut
 
+use Scalar::Util;
+
 use B::Hooks::EndOfScope;
 use Variable::Magic 0.08;
 
@@ -147,6 +149,16 @@ my $sw = Variable::Magic::wizard(
  },
 );
 
+sub _tag {
+ my ($pkg, $name) = @_;
+
+ my $fqn = join '::', $pkg, $name;
+
+ return {
+  proto => prototype($fqn),
+ };
+}
+
 sub _map {
  my ($pkg) = @_;
 
@@ -161,8 +173,14 @@ sub _map {
 sub _cast {
  my ($pkg, $name) = @_;
 
- no strict 'refs';
- Variable::Magic::cast(%{"${pkg}::"}, $sw, $pkg, { $name => 1 });
+ my $map = { $name => _tag(@_) };
+
+ {
+  no strict 'refs';
+  Variable::Magic::cast(%{"${pkg}::"}, $sw, $pkg, $map);
+ }
+
+ return $map;
 }
 
 sub _dispell {
@@ -245,9 +263,15 @@ sub enable {
  my $map = _map($pkg);
 
  if (defined $map) {
-  $map->{$name} = 1;
+  $map->{$name} = _tag($pkg, $name);
  } else {
-  _cast($pkg, $name);
+  $map = _cast($pkg, $name);
+ }
+
+ my $proto = $map->{$name}->{proto};
+ if (defined $proto) {
+  no strict 'refs';
+  Scalar::Util::set_prototype(\&{"${pkg}::$name"}, undef);
  }
 
  $^H |= 0x00020000;
@@ -273,6 +297,12 @@ sub disable {
  my $map = _map($pkg);
 
  if (defined $map) {
+  my $proto = $map->{$name}->{proto};
+  if (defined $proto) {
+   no strict 'refs';
+   Scalar::Util::set_prototype(\&{"${pkg}::$name"}, $proto);
+  }
+
   delete $map->{$name};
   unless (keys %$map) {
    _dispell($pkg);
index 58e23a0a9c02e028f674db046f968171984c5b26..0339bc850b391436f5fe1d7beb6bf97071f58562 100644 (file)
@@ -5,11 +5,14 @@ use warnings;
 
 use blib 't/Sub-Op-LexicalSub';
 
-use Test::More tests => (4 + 2 * 4) + (2 * 5);
+use Test::More tests => 2 *((4 + 2 * 4) + (2 * 5) + 1);
 
 our $call_foo;
 sub foo { ok $call_foo, 'the preexistent foo was called' }
 
+our $call_bar;
+sub bar () { ok $call_bar, 'the preexistent bar was called' }
+
 our $called;
 
 {
@@ -66,6 +69,9 @@ our $called;
  }
 }
 
+is prototype('main::foo'), undef, "foo's prototype was preserved";
+is prototype('main::bar'), '',    "bar's prototype was preserved";
+
 __DATA__
 foo();
 ----
@@ -109,3 +115,46 @@ my $foo = \&foo;
 &$foo;
 ----
 foo # () #
+####
+bar();
+----
+bar # () # [ ]
+####
+bar;
+----
+bar # () # [ ]
+####
+bar(1);
+----
+bar # () # [ 1 ]
+####
+bar 2;
+----
+bar # () # [ 2 ]
+####
+local $call_bar = 1;
+&bar();
+----
+bar # () #
+####
+local $call_bar = 1;
+&bar;
+----
+bar # () #
+####
+local $call_bar = 1;
+&bar(3);
+----
+bar # () #
+####
+local $call_bar = 1;
+my $bar = \&bar;
+$bar->();
+----
+bar # () #
+####
+local $call_bar = 1;
+my $bar = \&bar;
+&$bar;
+----
+bar # () #