tags:

views:

77

answers:

3

I have some code the requires the application to be completely loaded and compiled before it should be executed.

Is there a way to check whether my Perl program is still in the compilation stage?

I have something that works, but there must be a better way:

sub check_compile {
  printf("checking\n");
  foreach my $depth (0..10) {
    my ($package, $filename, $line, $subroutine) = caller($depth);
    last unless (defined($package));

    printf("  %s %s %s %s %s\n", $depth, $package, $filename, $line, $subroutine);

    if ($subroutine =~ /::BEGIN$/) {
      printf("in compile\n");
      return 1;
    }

  }

  printf("not in compile\n");
  return 0;
}


BEGIN {
  check_compile();
}

use subpkg;

check_compile();

and subpkg.pm contains:

package subpkg;

use strict;
use warnings;

printf("initing subpkg\n");
main::check_compile();

1; # successfully loaded
+5  A: 

I assume your code doesn't make much use of eval - otherwise compilation will be taking place 'mixed in' with execution - but you might review the use of INIT and similar blocks here as a possible way to simplify this.

INIT blocks are run just before the Perl runtime begins execution, in "first in, first out" (FIFO) order.

martin clayton
Of course. Now that you mention it, it seems obvious. Still seems like Perl'd have a status var reflecting this.
mmccoo
`eval` isn't the only way to mix compilation into run-time. `require` and `do` will also pull in new code and compile it during normal execution.
Dave Sherohman
+2  A: 

See $^S in perlvar:

Current state of the interpreter.

    $^S         State
    ---------   -------------------
    undef       Parsing module/eval
    true (1)    Executing an eval
    false (0)   Otherwise

The first state may happen in $SIG{DIE} and $SIG{WARN} handlers.

    BEGIN { print "Compile $^S\n" }
    print "Run-time $^S\n";
    eval { print "Eval $^S\n" };

    Compile
    Run time 0
    Eval 1
mobrule
`$^S` is also undefined for compile-time `eval`s (say, an `eval` in a `BEGIN` block)
mobrule
a case that I didn't have in my question was other packages that are use'd. Initialization code there happens when $^S is true. At that point, there's more compilation to be done.
mmccoo
A: 

Untested, but AFAIK should do it:

sub main_run_phase_entered {
    local $@;
    ! eval q!use warnings FATAL => 'all'; CHECK{} 1!
}

Update: nope, fails for me (with 5.10.1) in an END{} block. The CHECK{} doesn't run, but doesn't complain either.

ysth