Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
333 views
in Technique[技术] by (71.8m points)

debugging - gprolog: Getting a stacktrace after an exception

While using gprolog I often have exceptions without any kind of line numbers or context like this one:

uncaught exception: error(instantiation_error,(is)/2)

Without any kind of context. I know I can do a trace but it would take very long to debug it with trace since I need to execute a lot of things before getting to the place where the error occur.

Any idea on how to have this stacktrace ? Or a dynamic trace / notrace ?

EDIT: Or just automate the printing of the whole trace output.

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

@gusbro's answer (s(X)) shows you how you somewhat solve this with GNU's debugger. However, if you cannot afford to see all the printing going on, or it is much too slow, you might consider the following "debugger" available as library(debug) in Scryer.

I personally do not use debuggers offered by Prolog systems for the simple reason that most of them print much too much, are often buggy themselves, and have their own specific ever changing conventions, I can't afford to learn.

:- op(900, fx, [@,$,$-]).

$-(G_0) :-
   catch(G_0, Ex, ( portray_clause(exception:Ex:G_0), throw(Ex) ) ).

$(G_0) :-
   portray_clause(call:G_0),
   $-G_0,
   portray_clause(exit:G_0).

@(G_0) :-
   (   $-G_0
   *-> true
   ;   portray_clause(badfail:G_0),
       throw(goal_failed(G_0))
   ).

:- op(950, fy, *).
*(_).

To use it, simply add $-, $, or @ in front of a specific goal.

$- means: only signal exceptions going through this goal

$ additionally show call and exit

@ assures that there is at least one answer, and if not, it is reported and an exception is thrown.

Use above annotations sparingly!

* removes the goal. This is for generalizing a program doing program modification/ in a pure monotonic program. You need this in case of unexpected failures. For examples how to use it, see the following answers/debugging sessions 1, 2, 3, 4, 5, 6, 7, 8, 9.

_/*term*/ replaces a term by an anonymous variable. This generalizes a program even further than * alone. Example sessions: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10.

In this manner you can reduce the information you watch significantly.

In other systems supporting meta_predicate directives like SICStus, YAP and SWI, add in front the following directive:

:- meta_predicate(( $-(0), $(0), @(0) )).

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...