Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
grab backtraces before information is lost
plus various cleanups to deal with our multi-level exception system
  • Loading branch information
TimToady committed Apr 15, 2015
1 parent 9862a14 commit 06dfca6
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 34 deletions.
4 changes: 2 additions & 2 deletions src/core/Backtrace.pm
Expand Up @@ -35,9 +35,9 @@ my class Backtrace is List {
self.new(nqp::backtrace(nqp::getattr(nqp::decont($e), Exception, '$!ex')), $offset);
}

multi method new() {
multi method new(Int $offset = 0) {
try { die() };
self.new($!, 2);
self.new($!, 2 + $offset);
}

# note that backtraces are nqp::list()s, marshalled to us as Parcel
Expand Down
4 changes: 2 additions & 2 deletions src/core/Buf.pm
Expand Up @@ -108,7 +108,7 @@ my role Blob[::T = uint8] does Positional[T] does Stringy is repr('VMArray') is
if ($ifrom < 0) {
X::OutOfRange.new(
what => 'From argument to subbuf',
got => $from,
got => $from.gist,
range => (0..self.elems),
comment => "use *{$ifrom} if you want to index relative to the end"
).fail;
Expand All @@ -117,7 +117,7 @@ my role Blob[::T = uint8] does Positional[T] does Stringy is repr('VMArray') is
if ($ifrom > self.elems) {
X::OutOfRange.new(
what => 'From argument to subbuf',
got => $from,
got => $from.gist,
range => (0..self.elems),
).fail;
}
Expand Down
57 changes: 36 additions & 21 deletions src/core/Exception.pm
Expand Up @@ -4,23 +4,36 @@ my class X::ControlFlow { ... }

my class Exception {
has $!ex;

method backtrace() { Backtrace.new(self) }
has $!bt;

method backtrace() {
if $!bt { $!bt }
elsif nqp::isconcrete($!ex) {
if $!ex.^name eq 'BOOTException' {
" Only a low-level backtrace is available here:\n "
~ nqp::join("\n ", nqp::backtracestrings($!ex));
}
else {
Backtrace.new(nqp::decont($!ex));
}
}
else { '' }
}

multi method Str(Exception:D:) {
self.?message.Str // 'Something went wrong'
self.?message.Str // 'Something went wrong in ' ~ self.WHAT.gist;
}

multi method gist(Exception:D:) {
my $str = try self.?message;
return "Error while creating error string: $!" if $!;
my $str = nqp::isconcrete($!ex) ?? nqp::p6box_s(nqp::getmessage($!ex)) !! try self.?message;
$str //= "Internal error";
$str ~= "\n";
try $str ~= self.backtrace;
return "$str\nError while creating backtrace: $!.message()\n$!.backtrace.full();" if $!;
try $str ~= self.backtrace || Backtrace.new() || ' (no backtrace available)';
return $str;
}

method throw() is hidden-from-backtrace {
method throw($bt?) is hidden-from-backtrace {
nqp::bindattr(self, Exception, '$!bt', $bt) if $bt;
nqp::bindattr(self, Exception, '$!ex', nqp::newexception())
unless nqp::isconcrete($!ex);
nqp::setpayload($!ex, nqp::decont(self));
Expand Down Expand Up @@ -530,9 +543,10 @@ my class X::OutOfRange is Exception {
has $.range = '<unknown>';
has $.comment;
method message() {
$.comment.defined
my $result = $.comment.defined
?? "$.what out of range. Is: $.got, should be in $.range.gist(); $.comment"
!! "$.what out of range. Is: $.got, should be in $.range.gist()"
!! "$.what out of range. Is: $.got, should be in $.range.gist()";
$result;
}
}

Expand Down Expand Up @@ -1400,8 +1414,11 @@ my class X::TypeCheck is Exception {
method gotn() { (try $!got.^name) // "?" }
method expectedn() { (try $!expected.^name) // "?" }
method priors() {
nqp::isconcrete($!got) && $!got ~~ Failure && !try { $!got.sink } && $!
?? "Earlier error:\n $!\n in file Who Knows? at line Beats Me!\n\n" !! '';
my $prior = do if nqp::isconcrete($!got) && $!got ~~ Failure {
"Earlier failure:\n " ~ $!got.mess ~ "\nFinal error:\n ";
}
else { '' }
$prior;
}
method message() {
self.priors() ~
Expand Down Expand Up @@ -1681,24 +1698,22 @@ my class X::Multi::NoMatch is Exception {
my @priors;
if $.capture {
for $.capture.list {
@bits.push($where ?? .perl !! .WHAT.perl );
try @bits.push($where ?? .perl !! .WHAT.perl );
@bits.push($_.^name) if $!;
when Failure {
my $x = .exception;
try $x.throw;
@priors.push(" $!\n in file <mumble> at line...uh...\n");
@priors.push(" " ~ .mess);
}
}
for $.capture.hash {
if .value ~~ Failure {
my $x = .value.exception;
try $x.throw;
@priors.push(" $!\n in file...I forget where offhand...\n");
@priors.push(" " ~ .value.mess);
}
if .value ~~ Bool {
@bits.push(':' ~ ('!' x !.value) ~ .key);
}
else {
@bits.push(":{.key}({$where ?? .value.perl !! .value.WHAT.perl })");
try @bits.push(":$(.key)($($where ?? .value.?perl !! .value.WHAT.?perl ))");
@bits.push($_.value.^name) if $!;
}
}
}
Expand All @@ -1711,7 +1726,7 @@ my class X::Multi::NoMatch is Exception {
@bits.unshift($invocant ~ ': ' ~ $first);
}
my $cap = '(' ~ @bits.join(", ") ~ ')';
@priors = "Earlier errors:\n", @priors, "\n" if @priors;
@priors = "Earlier failures:\n", @priors, "\nFinal error:\n " if @priors;
@priors.join ~
join "\n ",
"Cannot call $.dispatcher.name()$cap; none of these signatures match:",
Expand Down
24 changes: 17 additions & 7 deletions src/core/Failure.pm
@@ -1,8 +1,15 @@
my class Failure {
has $.exception;
has $.backtrace;
has $!handled;

method new($exception) { self.bless(:$exception) }
method new($exception) {
self.bless(:$exception);
}

submethod BUILD (:$!exception) {
$!backtrace = $!exception.backtrace() || Backtrace.new(9);
}

# TODO: should be Failure:D: multi just like method Bool,
# but obscure problems prevent us from making Mu.defined
Expand All @@ -13,11 +20,14 @@ my class Failure {
}
multi method Bool(Failure:D:) { $!handled = 1; Bool::False; }

method Int(Failure:D:) { $!handled ?? 0 !! $!exception.throw; }
method Num(Failure:D:) { $!handled ?? 0e0 !! $!exception.throw; }
method Numeric(Failure:D:) { $!handled ?? 0e0 !! $!exception.throw; }
multi method Str(Failure:D:) { $!handled ?? '' !! $!exception.throw; }
multi method gist(Failure:D:) { $!handled ?? $.perl !! $!exception.throw; }
method Int(Failure:D:) { $!handled ?? 0 !! $!exception.throw($!backtrace); }
method Num(Failure:D:) { $!handled ?? 0e0 !! $!exception.throw($!backtrace); }
method Numeric(Failure:D:) { $!handled ?? 0e0 !! $!exception.throw($!backtrace); }
multi method Str(Failure:D:) { $!handled ?? '' !! $!exception.throw($!backtrace); }
multi method gist(Failure:D:) { $!handled ?? $.mess !! $!exception.throw($!backtrace); }
method mess (Failure:D:) {
self.exception.message ~ "\n" ~ self.backtrace;
}

Failure.^add_fallback(
-> $, $ { True },
Expand All @@ -26,7 +36,7 @@ my class Failure {
}
);
method sink() is hidden-from-backtrace {
$!exception.throw unless $!handled
$!exception.throw($!backtrace) unless $!handled
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/core/Str.pm
Expand Up @@ -1570,7 +1570,7 @@ sub chrs(*@c) returns Str:D {
sub SUBSTR-START-OOR(\from,\max) {
X::OutOfRange.new(
:what<Start argument to substr>,
:got(from),
:got(from.gist),
:range("0.." ~ max),
:comment( nqp::istype(from, Callable) || -from > max
?? ''
Expand All @@ -1580,7 +1580,7 @@ sub SUBSTR-START-OOR(\from,\max) {
sub SUBSTR-CHARS-OOR(\chars) {
X::OutOfRange.new(
:what<Number of characters argument to substr>,
:got(chars),
:got(chars.gist),
:range("0..Inf"),
:comment("use *{chars} if you want to index relative to the end"),
);
Expand Down

0 comments on commit 06dfca6

Please sign in to comment.