Files
mercury/browser/help.m
Zoltan Somogyi 6ea8406ac8 Fix more warnings from --warn-inconsistent-pred-order-clauses.
browser/browse.m:
browser/browser_info.m:
browser/collect_lib.m:
browser/debugger_interface.m:
browser/declarative_analyser.m:
browser/declarative_debugger.m:
browser/declarative_edt.m:
browser/declarative_execution.m:
browser/declarative_oracle.m:
browser/declarative_test.m:
browser/declarative_tree.m:
browser/declarative_user.m:
browser/diff.m:
browser/dl.m:
browser/frame.m:
browser/help.m:
browser/interactive_query.m:
browser/io_action.m:
browser/listing.m:
browser/mdb.m:
browser/mer_browser.m:
browser/name_mangle.m:
browser/term_rep.m:
browser/tree234_cc.m:
    Fix inconsistencies between (a) the order in which functions and predicates
    are declared, and (b) the order in which they are defined.

    In most modules, either the order of the declarations or the order
    of the definitions made sense, and I changed the other to match.
    In some modules, neither made sense, so I changed *both* to an order
    that *does* make sense (i.e. it has related predicates together).

    In some places, put dividers between groups of related
    functions/predicates, to make the groups themselves more visible.

    In some places, fix comments or programming style.

browser/MDB_FLAGS.in:
    Since all the modules in this directory are now free from any warnings
    generated by --warn-inconsistent-pred-order-clauses, specify that option
    by default in this directory to keep it that way.
2017-04-29 14:08:50 +10:00

295 lines
9.7 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 1998-2000, 2003-2006 The University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% File: help.m.
% Author: zs.
% Stability: low.
%
% This file provides a basic help system that stores information in help nodes
% which are organized as a tree structure of arbitrary depth.
%
% The help system consists of a list of help list entries. Each entry
% has a name, an index (an integer that determines its position in the list),
% and a help node. Each node contains text that should shed some light
% on the topic named by the node's entry. Each node also has an associated
% list of child entries; this list may of course be empty.
%
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- module mdb.help.
:- interface.
:- import_module io.
:- import_module list.
:- import_module type_desc.
:- type system.
:- type path == list(string).
:- type help_res
---> help_ok
; help_error(string).
%---------------------------------------------------------------------------%
% Initialize an empty help system.
%
:- pred init(system::out) is det.
% Add a node to the given help system, at the given path, and with
% the given name and index. If successful, return help_ok and the
% updated help system; if not, return an error message and the
% original help system.
%
:- pred add_help_node(system::in, path::in, int::in,
string::in, string::in, help_res::out, system::out) is det.
% Print the top-level help nodes. This should give an overview
% of the main topics for which help is available.
%
:- pred help(system::in, io.output_stream::in, io::di, io::uo) is det.
% Print the help node at the given path. If there is none,
% print the top-level nodes.
%
:- pred path(system::in, path::in, io.output_stream::in,
help_res::out, io::di, io::uo) is det.
% Print all help nodes with the given name. If there are none,
% print the top-level nodes.
%
:- pred name(system::in, string::in, io.output_stream::in,
io::di, io::uo) is det.
%---------------------------------------------------------------------------%
% Return the type_info for the type system, for use by C code.
%
:- pred help_system_type(type_desc::out) is det.
% Help interpret a help_res for C code.
%
:- pred result_is_error(help_res::in, string::out) is semidet.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module int.
:- import_module require.
:- import_module string.
:- type system == list(entry).
:- type node
---> node(
text,
list(entry)
).
:- type text == string. % Should be one or more complete lines.
:- type entry
---> entry(
int, % This integer determines the position
% of the node in the node list. A node
% list is always sorted on this field.
string, % The name of the node, which should
% be one word or phrase. It must be
% unique within the node list, but
% need not be unique globally.
node
).
%---------------------------------------------------------------------------%
:- pragma foreign_export("C", init(out), "ML_HELP_init").
:- pragma foreign_export("C", add_help_node(in, in, in, in, in, out, out),
"ML_HELP_add_help_node").
:- pragma foreign_export("C", help(in, in, di, uo), "ML_HELP_help").
:- pragma foreign_export("C", path(in, in, in, out, di, uo), "ML_HELP_path").
:- pragma foreign_export("C", name(in, in, in, di, uo), "ML_HELP_name").
:- pragma foreign_export("C", help_system_type(out),
"ML_HELP_help_system_type").
:- pragma foreign_export("C", result_is_error(in, out),
"ML_HELP_result_is_error").
%---------------------------------------------------------------------------%
init([]).
add_help_node(Sys0, Path, Index, Name, Text, Res, Sys) :-
Node = node(Text, []),
add_node(Sys0, Path, Index, Name, Node, Res, Sys).
:- pred add_node(system::in, path::in, int::in,
string::in, node::in, help_res::out, system::out) is det.
add_node(Nodes0, [Step | Steps], Index, Name, NewNode, Res, Nodes) :-
( if one_path_step(Nodes0, Step, Entry0) then
Entry0 = entry(EntryIndex, EntryName, EntryNode0),
EntryNode0 = node(Text, SubNodes0),
add_node(SubNodes0, Steps, Index, Name, NewNode, Res, SubNodes),
EntryNode = node(Text, SubNodes),
Entry = entry(EntryIndex, EntryName, EntryNode),
replace_entry(Nodes0, Entry, Nodes)
else
string.append("invalid path component ", Step, Msg),
Res = help_error(Msg),
Nodes = Nodes0
).
add_node(Nodes0, [], Index, Name, Node, Res, Nodes) :-
( if
list.member(Entry1, Nodes0),
Entry1 = entry(Index, _, _)
then
Res = help_error("entry with given index already exists"),
Nodes = Nodes0
else if
list.member(Entry1, Nodes0),
Entry1 = entry(_, Name, _)
then
Res = help_error("entry with given name already exists"),
Nodes = Nodes0
else
Res = help_ok,
insert_into_entry_list(Nodes0, Index, Name, Node, Nodes)
).
:- pred insert_into_entry_list(list(entry)::in, int::in, string::in, node::in,
list(entry)::out) is det.
insert_into_entry_list([], Index, Name, Node, [Entry]) :-
Entry = entry(Index, Name, Node).
insert_into_entry_list([Head | Tail], Index, Name, Node, List) :-
Head = entry(HeadIndex, _, _),
( if HeadIndex < Index then
insert_into_entry_list(Tail, Index, Name, Node, NewTail),
List = [Head | NewTail]
else
Entry = entry(Index, Name, Node),
List = [Entry, Head | Tail]
).
%---------------------------------------------------------------------------%
help(Sys, Stream, !IO) :-
print_entry_list(Sys, Stream, !IO).
path(Entries, Path, Stream, Result, !IO) :-
(
Path = [Step | Tail],
( if one_path_step(Entries, Step, Entry) then
Entry = entry(_, _, EntryNode),
(
Tail = [],
EntryNode = node(Text, _),
io.write_string(Stream, Text, !IO),
Result = help_ok
;
Tail = [_ | _],
EntryNode = node(_, SubEntries),
path(SubEntries, Tail, Stream, Result, !IO)
)
else
Msg = "error at path component """ ++ Step ++ """",
Result = help_error(Msg)
)
;
Path = [],
Result = help_error("the path does not go that deep")
).
name(Sys, Name, Stream, !IO) :-
search_entry_list(Sys, Name, 0, Count, Stream, !IO),
( if Count = 0 then
io.write_string("There is no such help topic.\n", !IO),
help(Sys, Stream, !IO)
else
true
).
:- pred search_entry_list(list(entry)::in, string::in, int::in, int::out,
io.output_stream::in, io::di, io::uo) is det.
search_entry_list([], _, !C, _, !IO).
search_entry_list([Entry | Tail], Name, !C, Stream, !IO) :-
Entry = entry(_, EntryName, Node),
( if Name = EntryName then
% We print this node, but don't search its children.
print_node(Node, Stream, !IO),
!:C = !.C + 1
else
search_node(Node, Name, !C, Stream, !IO),
search_entry_list(Tail, Name, !C, Stream, !IO)
).
:- pred search_node(node::in, string::in, int::in, int::out,
io.output_stream::in, io::di, io::uo) is det.
search_node(node(_, SubNodes), Name, !C, Stream, !IO) :-
search_entry_list(SubNodes, Name, !C, Stream, !IO).
%---------------------------------------------------------------------------%
:- pred print_entry_list(list(entry)::in, io.output_stream::in,
io::di, io::uo) is det.
print_entry_list([], _, !IO).
print_entry_list([entry(_, _, Node) | Nodes], Stream, !IO) :-
print_node(Node, Stream, !IO),
print_entry_list(Nodes, Stream, !IO).
:- pred print_node(node::in, io.output_stream::in, io::di, io::uo) is det.
print_node(node(Text, _Nodes), Stream, !IO) :-
io.write_string(Stream, Text, !IO).
% XXX print_entry_list(Nodes, Stream, !IO).
%---------------------------------------------------------------------------%
:- pred one_path_step(list(entry)::in, string::in, entry::out) is semidet.
one_path_step([Head | Tail], Name, Entry) :-
Head = entry(_, HeadName, _),
( if HeadName = Name then
Entry = Head
else
one_path_step(Tail, Name, Entry)
).
:- pred replace_entry(list(entry)::in, entry::in, list(entry)::out) is det.
replace_entry([], _, _) :-
error("replace_entry: entry to be replaced not found").
replace_entry([Head | Tail], Entry, List) :-
Head = entry(HeadIndex, _, _),
Entry = entry(EntryIndex, _, _),
( if HeadIndex = EntryIndex then
List = [Entry | Tail]
else
replace_entry(Tail, Entry, NewTail),
List = [Head | NewTail]
).
%---------------------------------------------------------------------------%
help_system_type(Type) :-
init(HelpInit),
Type = type_of(HelpInit).
result_is_error(help_error(Msg), Msg).
%---------------------------------------------------------------------------%