develooper Front page | perl.perl5.porters | Postings from November 2000

Plan to try again with Carp

Thread Next
Ben Tilly
November 25, 2000 14:02
Plan to try again with Carp
Message ID:
As I mentioned a long time ago, Carp's internal semantics
make little sense.  There is also the possibility for
endless loops if you have circular inheritance as this

package A;
@ISA = ("A");
use Carp;
sub complain {
package B;
A::complain("Hello world\n");

I have a fix for this.

But before I do this, what kind of heuristics should I
use?  I would like to have some rule for what kinds of
packages a given package trusts (right now itself and
everything it has in @ISA, but we can change that later)
and then fill that out with a transitive relationship.
Then croak() and carp() should produce a message from
the first untrusted call they find.

I don't think that $Carp::CarpLevel has any useful role
in shortmess.  Possibly in longmess?

The exact definition of a trusted call would be that
the calling package does not trust the called package,
and vica versa.  Plus the package calling is not part
of the internal guts of Perl, and the package called
is not part of the internal guts of Perl's warning

This is similar to - but not the same as - the current
system.  One key difference is the following.  Suppose
that we have a package with a function like the one I
show at:

(except that it should use "croak" instead of "confess")

If this was a method and two packages inherit from it,
but don't inherit from each other, there is no reason
that it should not report an error in one of those
packages from the point of view of the other.

Now what is the definition of stuff internal to the
warning system?  Today it is kept track of by explicit
accounting - you have 2 call levels to shortmess_heavy
and longmess_heavy so they just skip those before even
beginning to calculate.  (One for the call to carp(),
croak(), confess(), or cluck(), then one more to
shortmess() or longmess().  With the introduction of
Carp/ this was obfuscated with gotos to
shortmess_heavy and longmess_heavy.)  This is rather
inflexible.  Instead I think there should be a hash
whose keys are packages to just skip.  Definitely 'Carp'
should be a key, and I think that 'warnings' should be
as well.

Now what is the definition of stuff internal to Perl?
For calls that wind up going to longmess_heavy you can
fake it with $Carp::CarpLevel.  With calls going to
shortmess_heavy you have nothing useful.  (Certainly the
heuristic used in the warn() function from
fails miserably.)  However by using a hash called
%Carp::Ignore we can fix that.

So to summarize I would like to kill the undocumented
$Carp::CarpLevel.  I would then like to have the logic
look something like this:

sub longmess_heavy {
  my $i;
    my $pkg = caller(++$i);
    unless($pkg) { # ??
      $i = 1;
    redo if $Internal{$pkg};
    redo if $Ignore{$pkg};
  report_error_from($i, @_);

sub shortmess_heavy {
  return longmess_heavy(@_) if $Verbose;
  my $cache;
  my $i = 1;
    my $called = caller($i++);
    my $caller = caller($i);
    return longmess_heavy(@_) unless($caller);
    redo if $Internal{$called};
    redo if $Ignore($caller);
    redo if trusts($called, $caller, $cache);
    redo if trusts($caller, $called, $cache);
  report_error_from($i, @_);

Where right now trusts would be basically "inherits from"
though we could change that later.

Feedback?  Comments?

Get more from the Web.  FREE MSN Explorer download :

Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About