Files
mercury/browser/util.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

174 lines
5.5 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 1998-2002, 2004-2007, 2010-2011 The University of Melbourne.
% Copyright (C) 2015, 2018 The Mercury team.
% This file is distributed under the terms specified in COPYING.LIB.
%---------------------------------------------------------------------------%
:- module mdb.util.
:- interface.
:- import_module mdbcomp.
:- import_module mdbcomp.prim_data.
:- import_module bool.
:- import_module io.
:- import_module list.
%---------------------------------------------------------------------------%
:- func is_function(pred_or_func) = bool.
:- type line_number == int.
% Get user input via the same method used by the internal debugger.
%
:- pred trace_getline(io.input_stream::in, io.output_stream::in,
string::in, io.result(string)::out, io::di, io::uo) is det.
% trace_get_command is similar to trace_getline except that
% it breaks lines into semicolon separated commands, and
% replaces EOF with the command 'quit'.
%
:- pred trace_get_command(io.input_stream::in, io.output_stream::in,
string::in, string::out, io::di, io::uo) is det.
:- pred zip_with(pred(T1, T2, T3)::in(pred(in, in, out) is det),
list(T1)::in, list(T2)::in, list(T3)::out) is det.
%---------------------------------------------------------------------------e
%---------------------------------------------------------------------------%
:- implementation.
:- import_module require.
%---------------------------------------------------------------------------%
is_function(pf_predicate) = no.
is_function(pf_function) = yes.
trace_getline(MdbIn, MdbOut, Prompt, Result, !IO) :-
call_trace_getline(MdbIn, MdbOut, Prompt, Line, Success, !IO),
( if Success = 0 then
Result = eof
else
Result = ok(Line)
).
:- pred call_trace_getline(input_stream::in, output_stream::in, string::in,
string::out, int::out, io.state::di, io.state::uo) is det.
:- pragma foreign_decl("C", "
#include ""mercury_wrapper.h""
#include ""mercury_string.h""
#include ""mercury_trace_base.h""
#include ""mercury_library_types.h""
").
:- pragma foreign_proc("C",
call_trace_getline(MdbIn::in, MdbOut::in, Prompt::in, Line::out,
Success::out, _IO0::di, _IO::uo),
% We need to use will_not_call_mercury here,
% because MR_make_aligned_string_copy() references MR_hp,
% which only works for will_not_call_mercury foreign_procs.
[will_not_call_mercury, promise_pure, tabled_for_io],
"
char *line = NULL;
MercuryFile *mdb_in = (MercuryFile *) MdbIn;
MercuryFile *mdb_out = (MercuryFile *) MdbOut;
if (MR_address_of_trace_getline != NULL) {
line = (*MR_address_of_trace_getline)((char *) Prompt,
MR_file(*mdb_in), MR_file(*mdb_out));
} else {
MR_tracing_not_enabled();
/* not reached */
}
if (line == NULL) {
/* we copy the null string to avoid warnings about const */
MR_make_aligned_string_copy(Line, """");
Success = 0;
} else {
MR_make_aligned_string_copy(Line, line);
MR_free(line);
Success = 1;
}
").
call_trace_getline(MdbIn, MdbOut, Prompt, Line, Success, !IO) :-
io.write_string(MdbOut, Prompt, !IO),
io.flush_output(MdbOut, !IO),
io.read_line_as_string(MdbIn, Result, !IO),
(
Result = ok(Line),
Success = 1
;
Result = eof,
Line = "",
Success = 0
;
Result = error(Error),
unexpected($pred, io.error_message(Error))
).
:- pragma foreign_proc("C",
trace_get_command(MdbIn::in, MdbOut::in, Prompt::in, Line::out,
_IO0::di, _IO::uo),
[may_call_mercury, promise_pure, tabled_for_io],
"
char *line;
MercuryFile *mdb_in = (MercuryFile *) MdbIn;
MercuryFile *mdb_out = (MercuryFile *) MdbOut;
if (MR_address_of_trace_getline != NULL) {
line = (*MR_address_of_trace_get_command)((char *) Prompt,
MR_file(*mdb_in), MR_file(*mdb_out));
MR_make_aligned_string_copy(Line, line);
MR_free(line);
} else {
ML_BROWSER_trace_get_command_fallback(MdbIn, MdbOut, Prompt, &Line);
}
").
trace_get_command(MdbIn, MdbOut, Prompt, Line, !IO) :-
trace_get_command_fallback(MdbIn, MdbOut, Prompt, Line, !IO).
% This is called by trace_get_command when the trace library is not linked
% in.
%
:- pred trace_get_command_fallback(io.input_stream::in, io.output_stream::in,
string::in, string::out, io::di, io::uo) is det.
:- pragma foreign_export("C",
trace_get_command_fallback(in, in, in, out, di, uo),
"ML_BROWSER_trace_get_command_fallback").
trace_get_command_fallback(MdbIn, MdbOut, Prompt, String, !IO) :-
io.write_string(MdbOut, Prompt, !IO),
io.flush_output(MdbOut, !IO),
io.read_line_as_string(MdbIn, Result, !IO),
(
Result = ok(String)
;
Result = eof,
String = "quit"
;
Result = error(Error),
unexpected($pred, io.error_message(Error))
).
zip_with(_Pred, [], [], []).
zip_with(_Pred, [], [_ | _], _) :-
unexpected($pred, "list length mismatch").
zip_with(_Pred, [_ | _], [], _) :-
unexpected($pred, "list length mismatch").
zip_with(Pred, [X | Xs], [Y | Ys], XYs) :-
Pred(X, Y, HeadXY),
zip_with(Pred, Xs, Ys, TailXYs),
XYs = [HeadXY | TailXYs].
%---------------------------------------------------------------------------%