Re: getting rid of nested sub lexical problem

2001-01-11 Thread Doug MacEachern

On Sat, 30 Dec 2000, Chris Nokleberg wrote:
 
 oooh, cool. I've added this to Apache::DB.xs:
 
 int
 stop_debugger()

nice, i'll add that for the next version.
 
 It appears that setting PL_perldb to zero is all that's required to turn
 off the debugger! I thought I might have to fiddle with the symbol tables
 but this seems to work.

yeah, that should do it.
 
 I've attached the latest version of Apache::NiceRegistry (suggestions
 welcome) below. Not sure this is the right thing to do , but I call
 Apache::DB::init_debugger directly because I need the return value (don't
 want to stop_debugger if it was turned on outside of this handler), and I
 don't want the warning that Apache::DB-init produces.

calling init_debugger is fine.
 
 Also, why does Apache::DB unset $Apache::Registry::MarkLine?

it was breaking Apache::SmallProf i think.  it should local-ize that
change at least.




Re: getting rid of nested sub lexical problem

2000-12-30 Thread Chris Nokleberg

On Thu, 21 Dec 2000, Doug MacEachern wrote:

 On Thu, 19 Oct 2000, Chris Nokleberg wrote:
 
  Following up on my post on this subject a couple of months ago, here is a
  proof-of-concept drop-in replacement for Apache::Registry that eliminates
  the "my() Scoped Variable in Nested Subroutine" problem.
 
 nice hack!
  
  It requires PERL5OPT = "-d" and PERL5DB = "sub DB::DB {}" environment
  variables set when starting the mod_perl-enabled httpd. This enables the
  %DB::sub hash table that holds subroutine start and end line info. I
  presume that this has some negative (marginal?) impact on performance. If
  someone knows of a better way to reliably figure out where a subroutine
  starts and ends, please let me know.
 
 there is quite a bit of overhead when -d is enabled.  have a look at
 Apache::DB.xs, there's in init_debugger() function todo what -d does.  if
 another method was added to turn it off, after the registry script was
 compiled, the overhead would be reduced a great deal.

oooh, cool. I've added this to Apache::DB.xs:

int
stop_debugger()

CODE:
if (PL_perldb) {
PL_perldb = 0;
RETVAL = TRUE;
}
else
RETVAL = FALSE;

OUTPUT:
RETVAL


It appears that setting PL_perldb to zero is all that's required to turn
off the debugger! I thought I might have to fiddle with the symbol tables
but this seems to work.

I've attached the latest version of Apache::NiceRegistry (suggestions
welcome) below. Not sure this is the right thing to do , but I call
Apache::DB::init_debugger directly because I need the return value (don't
want to stop_debugger if it was turned on outside of this handler), and I
don't want the warning that Apache::DB-init produces.

Also, why does Apache::DB unset $Apache::Registry::MarkLine?

Thanks,
Chris

--

package Apache::NiceRegistry;

use base Apache::RegistryNG;
use strict;
use Apache::DB ();

$Apache::Registry::MarkLine = 1;

my %skip_subs = map { $_ = 1 } qw( handler BEGIN END CHECK INIT );

sub compile {
my ($pr, $eval) = @_;
$eval ||= $pr-{'sub'};

my $init_db = Apache::DB::init_debugger();
$pr-SUPER::compile($eval);
Apache::DB::stop_debugger() if $init_db;

my $package = $pr-namespace;
my @lines = split /\n/, $$eval;

foreach my $sub (grep /^$\Qpackage\E/, keys %DB::sub) {
my ($name) = $sub =~ /:([^:]+)$/;
next if $skip_subs{$name};

my ($start, $end) = $DB::sub{$sub} =~ /:(\d+)-(\d+)$/;
$lines[$start + 1] =~ s:(sub[^\{]+\{):$1\{sub\{:;
$lines[$end + 1]   =~ s:\}(?!.*\})$:\}\}\}:;
}

$$eval = join "\n", @lines;
$pr-flush_namespace($package);
$pr-SUPER::compile($eval);
}

1;





Re: getting rid of nested sub lexical problem

2000-12-21 Thread Doug MacEachern

On Thu, 19 Oct 2000, Chris Nokleberg wrote:

 Following up on my post on this subject a couple of months ago, here is a
 proof-of-concept drop-in replacement for Apache::Registry that eliminates
 the "my() Scoped Variable in Nested Subroutine" problem.

nice hack!
 
 It requires PERL5OPT = "-d" and PERL5DB = "sub DB::DB {}" environment
 variables set when starting the mod_perl-enabled httpd. This enables the
 %DB::sub hash table that holds subroutine start and end line info. I
 presume that this has some negative (marginal?) impact on performance. If
 someone knows of a better way to reliably figure out where a subroutine
 starts and ends, please let me know.

there is quite a bit of overhead when -d is enabled.  have a look at
Apache::DB.xs, there's in init_debugger() function todo what -d does.  if
another method was added to turn it off, after the registry script was
compiled, the overhead would be reduced a great deal.




RE: getting rid of nested sub lexical problem

2000-08-16 Thread Douglas Wilson



 -Original Message-
 From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]]
 Sent: Wednesday, August 16, 2000 2:17 AM
 To: [EMAIL PROTECTED]
 Subject: getting rid of nested sub lexical problem

 Below is a processed version of the increment_counter example from the
 guide that works as expected.

 --Chris

   #!/usr/bin/perl -w
   use strict;

   for (1..3){
   print "run: [time $_]\n";
   run();
   }

   sub run {

   my $counter = 0;

   increment_counter();
   increment_counter();

   sub increment_counter {{sub{
   $counter++;
   print "Counter is equal to $counter !\n";
   }}}

   } # end of sub run



That gives me a 'Variable "$counter" may be unavailable at ./tst2 line 17.'
warning. And its sort of obfuscated (to me, anyway). I'd probably do it this
way:

#!/usr/local/bin/perl -w

use strict;

#!/usr/bin/perl -w
use strict;

for (1..3){
print "run: [time $_]\n";
run();
}

{
 my $counter;

 sub run {
$counter = 0;

print $counter,"\n";

increment_counter();
increment_counter();

 }
 sub increment_counter {
   $counter++;
   print "Counter is equal to $counter !\n";
 }
}




Re: getting rid of nested sub lexical problem

2000-08-16 Thread Randal L. Schwartz

 "Douglas" == Douglas Wilson [EMAIL PROTECTED] writes:

Douglas That gives me a 'Variable "$counter" may be unavailable at ./tst2 line 17.'
Douglas warning. And its sort of obfuscated (to me, anyway). I'd probably do it this
Douglas way:

Douglas #!/usr/local/bin/perl -w

Douglas use strict;

Douglas #!/usr/bin/perl -w
Douglas use strict;

Douglas for (1..3){
Douglas print "run: [time $_]\n";
Douglas run();
Douglas }

Douglas {
Douglas  my $counter;

Douglas  sub run {
Douglas $counter = 0;

Douglas print $counter,"\n";

Douglas increment_counter();
Douglas increment_counter();

Douglas  }
Douglas  sub increment_counter {
Douglas$counter++;
Douglasprint "Counter is equal to $counter !\n";
Douglas  }
Douglas }

But *that* won't work inside the big subroutine created by
Apache::Registry (which is NOT the same as mod_perl, even though too
many people think so :), and that was the original point.  I'm
not sure the new code fixes it.  I think the problem is intractable,
or equivalent to the Travelling Salesman and the Farmer's Daughter
problem or something like that. :)

-- 
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
[EMAIL PROTECTED] URL:http://www.stonehenge.com/merlyn/
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!



Re: getting rid of nested sub lexical problem

2000-08-16 Thread chris

Converting  "sub foo" into "local *foo = sub" won't work when the function
is called before is declared, because the local only works for the rest
of the block, not the entire block. i.e. you can't do

  foo();
  local *foo = sub {
 ...
  };

Plus, I think you usually need the trailing semicolon anyway.

--Chris

On Wed, 16 Aug 2000, Dan Campbell wrote:

 [EMAIL PROTECTED] wrote:
  
  Due to forgetfulness I was recently bitten by the infamous "my() Scoped
  Variable in Nested Subroutines" problem using Apache::Registry, and it got
  me thinking about whether it is fixable.
  
  From the diagnostics:
This problem can usually be solved by making the inner subroutine
anonymous, using the sub {} syntax.  When inner anonymous subs that
reference variables in outer subroutines are called or referenced, they
are automatically rebound to the current values of such variables.
  
  I think it should be possible for Registry to pre-process the source code
  to turn all top-level named subroutines into sub refs. For example,
  convert subroutines of the form
  
sub foo { CODE }
  
  into
  
sub foo { { sub { CODE } } }
 [snip]
 
 I think it would be easier to convert
 
sub foo
 
 into
 
local *foo = sub
 
 
 That way, you don't have to parse for the matching right brace.
 Something like:
 
s/sub\s+(\w+)/local *\1 = sub/msg; # untested - just a guess
 
 might do the trick.
 
 --
 Dan Campbell