Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I warn about function usage in `perl -c`?

Our codebase includes various debugging hooks that should only be used for testing. As an illustrative example:

sub example {
   my ($arg) = @_;
   my $result = do_something_with($arg);
   debug_dump_values($arg); # debugging code
   return $result;
}

Of course, such debugging code should not be committed (or even deployed). Is there a way to generate a warning when running this code through perl -c? Something along the lines of

Debug function debug_dump_values() called at example.pl line 4.

This would be trivial to implement as a runtime warning:

sub debug_dump_values {
    carp "Debug function debug_dump_values() called";
    ...
}

But I want a warning that shows up in my text editor through its syntax check plugin, so it needs to be a "compile-time" warning.

like image 858
Stefan Majewsky Avatar asked Nov 09 '22 23:11

Stefan Majewsky


1 Answers

I think this isn't an easy thing to accomplish - it's not going to be possible without some significant rejigging of coding style.

Approaches I can think of:

Put your 'debug' code into a separate module.

Embed a warning in the module that indicates it's enabled - embed within a 'BEGIN' block. (This won't necessarily tell you which sub is being called though, nor where)

E.g.

BEGIN { 
    carp "Debugging module is imported" 
}

Advantages of this might be - you can have a 'debug' and 'not debug' module, and have the same subs in both. The 'not debug' would put in dummy subs.

You can then use B::Lint to validate your module and check if subs are all defined:

perl -MO=Lint[,OPTIONS] foo.pl

undefined-subs This option warns whenever an undefined subroutine is invoked. This option will only catch explicitly invoked subroutines such as foo() and not indirect invocations such as &$subref() or $obj->meth() . Note that some programs or modules delay definition of subs until runtime by means of the AUTOLOAD mechanism

Assign your sub via a reference.

Edit: Doesn't work as well as I thought - had a notion of declaring anonymous subs and creating references within 'BEGIN' blocks - that doesn't work as well as I thought - it only errors at runtime, because you get errors of scope.

Best I can offer is:

use strict;
use warnings;

my $debug = 1;

##debug code bit. 
#Comment out if not needed
my $debug_sub = gimme_debug();

sub gimme_debug {
    if ( $debug ) { 
        warn "Debugging enabled\n"; 
        return sub { print "Got values of :", @_, "\n"; };
    }
    else { warn "Debug subroutine defined with debug disabled!" };
}

#... way down code ... 

&$debug_sub ( "Some input" );

If you remove the declaration of then you'll get a compile time warning because $debug_sub is undeclared. This might combine with the above, e.g. bundling it in a module or object.

Automated testing

It doesn't do specifically what you asked about, however you may want to consider it anyway. Automated testing for your code/modules. For example, using TAP::Harness. It's a bit more complicated and intensive than what you're asking, but having something that'll automatically trap debug code (and otherwise validate the various components of your code) is probably the 'right' way to do it.

I've also heard of (but not done much with) Class::Inspector which may be suitable for your needs. But I think at a fairly fundamental level - what you're trying to do isn't checked at compile time, because it's very difficult to evaluate which bits of code are actually being called without actually running the code. So anything you do like this would be something you have to 'hand manage' in some fashion.

The Halting Problem

"In computability theory, the halting problem is the problem of determining, from a description of an arbitrary computer program and an input, whether the program will finish running or continue to run forever.

Alan Turing proved in 1936 that a general algorithm to solve the halting problem for all possible program-input pairs cannot exist. A key part of the proof was a mathematical definition of a computer and program, which became known as a Turing machine; the halting problem is undecidable over Turing machines. It is one of the first examples of a decision problem."

So if you do come up with a good solution to this - there's probably a usefully large prize on offer :).

like image 51
Sobrique Avatar answered Nov 15 '22 06:11

Sobrique