Skip to content

Commit

Permalink
First cut of a backtrace printer. With recent Parrot improvements, it…
Browse files Browse the repository at this point in the history
… actually seems to show the Perl 6 line numbers reasonably reliably. Many enhancements to come, but commit early, commit often and all that. :-)
  • Loading branch information
jnthn committed May 30, 2010
1 parent 339d0b9 commit b066578
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
5 changes: 5 additions & 0 deletions build/Makefile.in
Expand Up @@ -74,6 +74,7 @@ SOURCES = \
src/gen/locator_pm.pir \
src/gen/versiondetectionactions_pm.pir \
src/gen/loader_pm.pir \
src/gen/backtraceprinter_pm.pir \
$(PERL6_G) \
$(PERL6_A) \
$(DYNEXT_TARGET)
Expand Down Expand Up @@ -362,6 +363,10 @@ src/gen/loader_pm.pir: $(PARROT) $(NQP_PBC) src/Perl6/Module/Loader.pm
$(NQP_EXE) --output=src/gen/loader_pm.pir --encoding=utf8 \
--target=pir src/Perl6/Module/Loader.pm

src/gen/backtraceprinter_pm.pir: $(PARROT) $(NQP_PBC) src/Perl6/BacktracePrinter.pm
$(NQP_EXE) --output=src/gen/backtraceprinter_pm.pir --encoding=utf8 \
--target=pir src/Perl6/BacktracePrinter.pm

src/gen/builtins.pir: build/gen_builtins_pir.pl $(BUILTINS_PIR)
$(PERL) build/gen_builtins_pir.pl $(BUILTINS_PIR) > src/gen/builtins.pir

Expand Down
69 changes: 69 additions & 0 deletions src/Perl6/BacktracePrinter.pm
@@ -0,0 +1,69 @@
class Perl6::BacktracePrinter;

# Drives the overall backtrace production process.
method backtrace_for($exception) {
my @backtrace := $exception.backtrace();
if self.is_runtime(@backtrace) {
# Runtime error. Start with the error message.
my $trace := pir::getattribute__pps($exception, 'message') ~ "\n";

# If top frame is 'die', drop it from the top.
if ~@backtrace[0]<sub> eq '&die' {
@backtrace.shift;
}

# Go through frames to find annotations to print.
my $cur_annotations;
for @backtrace {
# If we're seeking an annotation set, take the current one.
unless $cur_annotations {
$cur_annotations := $_<annotations>;
}

# If we hit the end of the user's code, we're done; emit last
# annotations and say we're in main program body.
if ~$_<sub> eq '!UNIT_START' {
$trace := $trace ~ self.backtrace_line(0, $cur_annotations);
last;
}

# If we're not in an intermediate block, then we've hit some sub
# should emit annotations here. We go on not having a p6type but
# also checking for some built-in ops can be handy and give more
# informative line numbers.
if !pir::isnull(pir::getprop__psp('$!p6type', $_<sub>))
|| pir::substr(~$_<sub>, 0, 6) eq '&infix' {
$trace := $trace ~ self.backtrace_line($_<sub>, $cur_annotations);
$cur_annotations := 0;
}
}
return $trace;
} else {
# For parse time exceptions, we just want the message, with no
# back trace beyond this.
return "===SORRY!===\n" ~
pir::getattribute__pps($exception, 'message') ~ "\n";
}
}

# Checks if we have a !UNIT_START anywhere in the backtrace, in which case
# we must be at runtime.
method is_runtime(@backtrace) {
for @backtrace {
if ~$_<sub> eq '!UNIT_START' {
return 1;
}
}
return 0;
}

# Renders one line in the backtrace, using the given sub name and
# annotations set.
method backtrace_line($current_sub, $location) {
"in " ~
($current_sub ?? "'" ~ ~$current_sub ~ "'" !! 'main program body') ~
" at " ~
($location<line> ?? 'line ' ~ $location<line> !! '<unknown line>' ) ~
($location<file> ?? ':' ~ $location<file> !! '' ) ~
"\n"
}
8 changes: 8 additions & 0 deletions src/Perl6/Compiler.pir
Expand Up @@ -117,6 +117,7 @@ Perl6::Compiler - Perl6 compiler
.include 'src/gen/locator_pm.pir'
.include 'src/gen/versiondetectionactions_pm.pir'
.include 'src/gen/loader_pm.pir'
.include 'src/gen/backtraceprinter_pm.pir'
.include 'src/gen/perl6-grammar.pir'
.include 'src/gen/perl6-actions.pir'

Expand Down Expand Up @@ -190,6 +191,13 @@ Perl6::Compiler - Perl6 compiler
.return (module)
.end

.sub 'backtrace' :method
.param pmc exception
$P0 = get_hll_global ['Perl6'], 'BacktracePrinter'
$S0 = $P0.'backtrace_for'(exception)
.return ($S0)
.end

.sub 'main' :main
.param pmc args_str
# Fire any of the setting's INIT phasers before we enter the runloop, so
Expand Down

0 comments on commit b066578

Please sign in to comment.