[m-rev.] For review: changes to declarative debugger (Part 1)
Zoltan Somogyi
zs at cs.mu.OZ.AU
Thu Oct 28 15:49:19 AEST 2004
On 29-Sep-2004, Ian MacLarty <maclarty at cs.mu.OZ.AU> wrote:
> For review by Zoltan.
Here is my review of the initial portion. More to come later.
Zoltan.
> Lot's of stuff in declarative_analyser.m has been redesigned to facilitate
> future improvements, such as probabalistic debugging.
Lot's -> Lots
> browser/program_representation.m
> Added builtin_call_rep to represent builtin calls.
> Made plain calls to UCI predicates be treated as primitive ops.
> Added function to say if a goal generates internal events directly.
> Added a function to say whether an atomic goal is identifiable (i.e.
> whether we can get from its goal_rep its name, module and arity).
> tests/debugger/declarative/trust.inp2
> Tests for new debugger features and changes to some old tests.
What are those changes?
> trace/mercury_trace_declarative.c
> Made the depth step size used when deciding which events to put in
> the annotated trace a variable so that it can be dynamically adjusted
> in the future.
> The EDT depth is now calculated instead of using the call depth (which
> is not always consistent with the EDT depth).
I presume you mean "instead of the call depth"?
> Made changes so that all the interface events for the sub-calls inside
> a call are included in the annotated trace, so that contours are built
> correctly.
This breaks the depth limit, so I suspect you don't mean that in all cases.
> :- pred revise_analysis(S::in, analyser_response(T)::out, analyser_state(T)::in,
> analyser_state(T)::out) is det <= mercury_edt(S, T).
Break up that line.
> % Look for the first unknown suspect in a breadth-first
> % fashion, starting at the root. If no unknown
> % suspects are found then choose a skipped suspect
> % to requery.
> ---> breadth_first
Breadth first is a bad name. Neither breadth_first nor depth_first mean
much here, because if a node is valid, its children aren't searched.
I think you mean simply top-down left-to-right.
> %
> % Follow the subterm all the way to where it's bound or
> % until it can't be followed any further (for example
> % when there is a call to a module with no tracing),
> % and ask a question about the nearest unknown suspect
> % on the subterm dependency chain. Then proceed to do
> % a binary search between this node and the root of the
> % search space (The binary search will only come into
> % effect if the oracle asserts the suspect is correct
> % or inadmissible).
"The" -> "the"
> % explicit subtree to be generated. The last argument
> % is the last suspect on the dependency chain whos
> % status was unknown (initially this is no).
"whos" -> "whose"
Was unknown when? Last in what direction? More documentation needed here.
> %
> % Perform a binary search on the array of suspects.
> % The range field gives the subrange of the array to
> % search. last_tested is the index into the array of
> % the last suspect about which a question was asked.
> %
Where do the array elements come from, and what invariants hold on them?
The range endpoints: are they inclusive or exclusive?
> ; binary(
> suspects :: array(suspect_id),
> range :: pair(int, int),
> last_testsed :: int
> ).
last_testsed -> last_tested
> analyser_state_init(IoActionMap, Analyser) :-
> empty_search_space(EmptySearchSpace),
> Analyser = analyser(EmptySearchSpace, [], no, breadth_first, no,
> IoActionMap, no).
Make empty_search_space a function.
> analyser_state_replace_io_map(IoActionMap, Analyser0, Analyser) :-
> Analyser = Analyser0 ^ io_action_map := IoActionMap.
Use state variable notation.
> start_analysis(Store, Tree, Response, !Analyser) :-
> MaybeRequireExplicit = !.Analyser ^ require_explicit,
> (
> MaybeRequireExplicit = yes(SuspectId),
> incorporate_explicit_subtree(SuspectId, Tree,
> !.Analyser ^ search_space, SearchSpace),
> !:Analyser = !.Analyser ^ search_space := SearchSpace,
> !:Analyser = !.Analyser ^ require_explicit := no,
> decide_analyser_response(Store, Response, !Analyser)
> ;
> MaybeRequireExplicit = no,
> %
> % An explicit subtree was not requested, so this is the
> % start of a new declarative debugging session.
> %
> reset_analyser(!Analyser),
> initialise_search_space(Tree, SearchSpace),
> !:Analyser = !.Analyser ^ search_space := SearchSpace,
> root_det(SearchSpace, RootId),
> !:Analyser = !.Analyser ^ last_search_question := yes(RootId),
> edt_question(!.Analyser ^ io_action_map, Store, Tree,
> Question),
> Response = revise(Question)
> ).
Since start_analysis with MaybeRequireExplicit = yes just continues an
existing analysis, you should rename the predicate.
> revise_analysis(Store, Response, !Analyser) :-
> %
> % The head of the previous_roots field in the analyser is just the
Fields don't have heads, only lists do.
> % current root of the search space, so we make the second element in
> % previous_roots the new erroneous root, make everything below it
> % unknown and re-query the current root. If there's only one previous
Is "current root" the same as "new erroneous root"?
> search(Store, !SearchSpace, breadth_first, NewMode, Response) :-
> breadth_first_search(Store, !SearchSpace, Response, NewMode).
breadth_first_search should be renamed, for the reason given above.
> breadth_first_search(Store, !SearchSpace, Response, NewMode) :-
> root_det(!.SearchSpace, RootId),
> (
> first_unknown_descendent_breadth(Store, RootId,
> !.SearchSpace, SearchSpace1, MaybeDescendent)
> ->
> SearchSpace1 = !:SearchSpace,
> (
> MaybeDescendent = yes(Unknown),
> Response = question(Unknown),
> NewMode = breadth_first
> ;
> MaybeDescendent = no,
> (
> choose_skipped_suspect(!.SearchSpace,
> LeastSkipped)
> ->
> Response = question(LeastSkipped),
> NewMode = breadth_first
Why *Least*Skipped?
> throw(internal_error("breadth_first_search",
> "no unknown or skipped suspects"))
> )
> )
> ;
> %
> % An explicit subtree is required, so pick an implicit root
> % to make explicit.
> %
> (
> pick_implicit_root(Store, !.SearchSpace, ImplicitRoot)
> ->
> Response = require_explicit(ImplicitRoot),
> NewMode = breadth_first
Could this decide to materialize a node that is not a child of RootId? If yes,
why? If not, document why it can't.
> throw(internal_error("breadth_first_search",
> "first_unknown_descendent_breadth required "++
> "an explicit subtree, but pick_implicit_roo"++
> "t couldn't find an implicit root"))
The error message is contradictory.
> follow_subterm_end_search(Store, !SearchSpace, LastUnknown, SuspectId, ArgPos,
> TermPath, NewMode, SearchResponse) :-
> find_subterm_origin(Store, SuspectId, ArgPos, TermPath, !SearchSpace,
> FindOriginResponse),
> root_det(!.SearchSpace, RootId),
> (
> FindOriginResponse = primitive_op(_, _),
> (
> LastUnknown = yes(Unknown),
> SearchResponse = question(Unknown),
> setup_binary_search(!.SearchSpace, RootId, Unknown,
> NewMode)
> ;
> LastUnknown = no,
> breadth_first_search(Store, !SearchSpace,
> SearchResponse, NewMode)
> )
> ;
> FindOriginResponse = not_found,
> (
> LastUnknown = yes(Unknown),
> SearchResponse = question(Unknown),
> setup_binary_search(!.SearchSpace, RootId, Unknown,
> NewMode)
> ;
> LastUnknown = no,
> breadth_first_search(Store, !SearchSpace,
> SearchResponse, NewMode)
> )
The code for primitive_op and not_found seem identical. Is this intentional,
and if so, why?
> (
> suspect_unknown(!.SearchSpace, OriginId)
> ->
> follow_subterm_end_search(Store, !SearchSpace,
> yes(OriginId), OriginId, OriginArgPos,
> OriginTermPath, NewMode, SearchResponse)
> ;
> follow_subterm_end_search(Store, !SearchSpace,
> LastUnknown, OriginId, OriginArgPos,
> OriginTermPath, NewMode, SearchResponse)
> )
> ).
Factor out the common code of the call here. Document why the recursive call
won't lead to an infinite loop.
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list