Files
mercury/browser/diff.m
Zoltan Somogyi eeb69f14ba Use explicit streams in browser/*.m.
browser/browse.m:
browser/browser_info.m:
browser/collect_lib.m:
browser/declarative_debugger.m:
browser/declarative_oracle.m:
browser/declarative_user.m:
browser/diff.m:
browser/help.m:
browser/interactive_query.m:
browser/parse.m:
browser/util.m:
    Replace implicit streams with explicit streams.

    Shorten lines longer than 79 chars.

    In some places, simplify some code, often using constructs such as
    string.format that either did not exist or were too expensive to use
    when the original code was written.

    In some places, change predicate names that were not meaningful
    without module qualification by *including* the module qualification
    in the name (e.g. init -> browser_info_init).

    In some places, add XXXs.

    In browser_info.m, make the output stream *part* of the debugger type,
    because without this, having the debugger type belong to the stream
    typeclass does NOT make sense. (The typeclass instance for debugger
    used to always write to the current output stream, which this diff
    is replacing with the use of explicitly specified streams.)

    In browse.m, consistently put stream arguments before other arguments.

    In browse.m, when exporting Mercury predicates to C, export them
    under names with the standard ML_BROWSE_ prefix, NOT under the name
    of a *different* predicate with that prefix.

    In diff.m, eliminate an unnecessary difference between what we print
    when the difference between two terms is at the root, vs what we print
    when the difference between two terms is lower down.

    In interactive_query.m, when trying to write a program out to a file,
    do NOT write the program to the current output stream if we cannot open
    the file, since that would accomplish nothing useful.

    Also in interactive_query.m, cleanup .dylib instead of .so on MacOS.

    In util.m, delete some unused predicates.

    In collect_lib.m, document why some code is not worth updating.

    In declarative_oracle.m, rename predicates with previously-ambiguous
    names.

browser/MDBFLAGS.in:
    Specify --warn-implicit-stream-calls for all Mercury modules
    in the browser directory from now.

trace/mercury_trace_browse.c:
trace/mercury_trace_cmd_browsing.c:
ssdb/ssdb.m:
    Conform to the changes in browser/*.m.

tests/debugger/queens.{exp,exp2}:
    Expect the extra output from browser/diff.m.
2021-03-05 22:54:28 +11:00

133 lines
4.9 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 2005-2006 The University of Melbourne.
% Copyright (C) 2015, 2017-2018 The Mercury team.
% This file is distributed under the terms specified in COPYING.LIB.
%---------------------------------------------------------------------------%
%
% File: diff.m.
%
% This module computes diffs between terms.
%
%---------------------------------------------------------------------------%
:- module mdb.diff.
:- interface.
:- import_module io.
:- import_module univ.
:- pred report_diffs(io.text_output_stream::in, int::in, int::in,
univ::in, univ::in, io::di, io::uo) is cc_multi.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module mdbcomp.
:- import_module mdbcomp.program_representation.
:- import_module deconstruct.
:- import_module int.
:- import_module list.
:- import_module require.
:- import_module string.
%---------------------------------------------------------------------------%
:- pragma foreign_export("C", report_diffs(in, in, in, in, in, di, uo),
"ML_report_diffs").
report_diffs(OutputStream, Drop, Max, Univ1, Univ2, !IO) :-
( if
Type1 = univ_type(Univ1),
Type2 = univ_type(Univ2),
Type1 = Type2
then
compute_diffs(Univ1, Univ2, [], [], RevDiffs),
list.reverse(RevDiffs, AllDiffs),
list.length(AllDiffs, NumAllDiffs),
( if
list.drop(Drop, AllDiffs, Diffs),
Diffs = [_ | _]
then
FirstShown = Drop + 1,
LastShown = min(Drop + Max, NumAllDiffs),
( if FirstShown = LastShown then
io.format(OutputStream,
"There are %d diffs, showing diff %d:\n",
[i(NumAllDiffs), i(FirstShown)], !IO)
else
io.format(OutputStream,
"There are %d diffs, showing diffs %d-%d:\n",
[i(NumAllDiffs), i(FirstShown), i(LastShown)], !IO)
),
list.take_upto(Max, Diffs, ShowDiffs),
list.foldl2(show_diff(OutputStream), ShowDiffs, Drop, _, !IO)
else
( if NumAllDiffs = 0 then
io.write_string(OutputStream, "There are no diffs.\n", !IO)
else if NumAllDiffs = 1 then
io.write_string(OutputStream, "There is only one diff.\n", !IO)
else
io.format(OutputStream, "There are only %d diffs.\n",
[i(NumAllDiffs)], !IO)
)
)
else
io.write_string(OutputStream,
"The two values are of different types.\n", !IO)
).
:- type term_path_diff
---> term_path_diff(term_path, univ, univ).
:- pred compute_diffs(univ::in, univ::in, term_path::in,
list(term_path_diff)::in, list(term_path_diff)::out) is cc_multi.
compute_diffs(Univ1, Univ2, !.RevPath, !RevDiffs) :-
deconstruct(univ_value(Univ1), include_details_cc, Functor1, _, Args1),
deconstruct(univ_value(Univ2), include_details_cc, Functor2, _, Args2),
( if Functor1 = Functor2 then
compute_arg_diffs(Args1, Args2, !.RevPath, 1, !RevDiffs)
else
list.reverse(!.RevPath, Path),
!:RevDiffs = [term_path_diff(Path, Univ1, Univ2) | !.RevDiffs]
).
:- pred compute_arg_diffs(list(univ)::in, list(univ)::in, term_path::in,
int::in, list(term_path_diff)::in, list(term_path_diff)::out) is cc_multi.
compute_arg_diffs([], [], _, _, !RevDiffs).
compute_arg_diffs([], [_ | _], _, _, !RevDiffs) :-
error("compute_arg_diffs: argument list mismatch").
compute_arg_diffs([_ | _], [], _, _, !RevDiffs) :-
error("compute_arg_diffs: argument list mismatch").
compute_arg_diffs([Arg1 | Args1], [Arg2 | Args2], !.RevPath, ArgNum,
!RevDiffs) :-
compute_diffs(Arg1, Arg2, [ArgNum | !.RevPath], !RevDiffs),
compute_arg_diffs(Args1, Args2, !.RevPath, ArgNum + 1, !RevDiffs).
:- pred show_diff(io.text_output_stream::in, term_path_diff::in,
int::in, int::out, io::di, io::uo) is cc_multi.
show_diff(OutputStream, Diff, !DiffNum, !IO) :-
!:DiffNum = !.DiffNum + 1,
Diff = term_path_diff(Path, UnivA, UnivB),
PathStr = path_to_string(Path),
functor(univ_value(UnivA), include_details_cc, FunctorA, ArityA),
functor(univ_value(UnivB), include_details_cc, FunctorB, ArityB),
io.format(OutputStream, "%d: mismatch at %s: %s/%d vs %s/%d\n",
[i(!.DiffNum), s(PathStr),
s(FunctorA), i(ArityA), s(FunctorB), i(ArityB)], !IO).
:- func path_to_string(list(int)) = string.
path_to_string([]) = "root".
path_to_string([Posn | Posns]) = Str :-
PosnStr = string.int_to_string(Posn),
PosnsStrs = list.map(string.int_to_string, Posns),
Str = string.join_list("/", [PosnStr | PosnsStrs]).