Files
mercury/browser/help.m
Zoltan Somogyi c2a696d8b6 Clean up the runtime system's handling of type_infos and pseudo_type_infos.
Estimated hours taken: 40

Clean up the runtime system's handling of type_infos and pseudo_type_infos.
This cleanup has two major aspects. First, it represents type_infos and
pseudo_type_infos with distinct C types, and reducing the use of casts
to the minimum. These casts are in two kinds of places: in a few macros
defined in runtime/mercury_type_info.h, and at the interfaces between C code
and Mercury code (since Mercury code represents (pseudo-)type_infos, like
everything else, as Words). Part of this aspect is the separation of the
type "MR_TypeInfo" from the type "MR_TypeInfoParams"; a MR_TypeInfo can be
used as a source of type parameters directly only when it is first order.
Second, it removes the confusion between the types named "type_info" and
"type_ctor_info" defined by the modules private_builtin.m and std_util.m,
by renaming the types defined in std_util.m to "type_desc" and
"type_ctor_desc".

To avoid doing this cleanup twice, this diff also removes support for the
old type_ctor_info representation. This in turn makes it feasible to provide
conditionally enabled code to support unification and comparison by RTTI.

runtime/mercury_grade.h:
	Increment the binary compatibility version number. This is required
	by the dropping of support for old type_ctor_info representations.

runtime/mercury_type_info.h:
	Define the types MR_TypeInfo, MR_PseudoTypeInfo and MR_TypeInfoParams,
	and macros that operate on them.

	Remove the types and macros that were useful only with the old RTTI
	representation.

	Move the section that deals with initializing code addresses in
	type_ctor_info structure for grades without static code addresses
	to the logical place.

	Add a const qualifier to the MR_sectag_alternatives field in
	MR_DuPtagLayout, since this simplifies code manipulating du types.

	Convert the whole file to 4 space indentation, since it is a nuisance
	if only part of it is so indented.

runtime/mercury_deep_copy.h:
runtime/mercury_deep_copy_body.h:
runtime/mercury_tabling.h:
runtime/mercury_tabling.c:
	Clean up the implementation as described above.

runtime/mercury_type_info.c:
runtime/mercury_make_type_info_body.h:
	Clean up the implementation as described above.

	Eliminate the code duplication between the function MR_make_type_info
	and MR_create_type_info, and their helpers, which do the same thing
	except for how they allocate memory, by putting the common code into
	the new file mercury_make_type_info_body.h, and including it twice
	in two different #define contexts.

	Move the (updated) documentation of those functions to
	mercury_type_info.h, where it belongs.

runtime/mercury_ho_call.c:
runtime/mercury_unify_compare_body.h:
	Clean up the implementation as described above.

	Eliminate the code duplication between the implementation of unify
	and compare, which do very similar jobs, by putting the common code
	into the new file mercury_unify_compare_body.h, and including it three
	times in two different #define contexts. The third time is for defining
	the body of a C function which does the same thing as compare. This
	is necessary for unification and comparison by RTTI, since the
	unification or comparison of two structured terms requires comparing
	their subterms. (There is no need for a separate C function for
	unification; the C comparison function is sufficient.)

	mercury_unify_compare_body.h has conditional support for unification
	and comparison by RTTI. Although this has been tested and is known
	to work, it is turned off for the moment. This may change after
	benchmarking.

runtime/Mmakefile:
	Add the new include files to the list.

library/std_util.m:
	Rename type_info to type_desc and type_ctor_info to type_info_desc.
	Keep the old names as equivalence types, for the time being.
	Document the representations.

	Move the macros that refer to type_descs and type_ctor_descs here from
	runtime/mercury_type_info.h, since this is the only place where they
	are used. Rename them to conform to the new names of the types.

	Clean up the implementation of the RTTI predicates and functions
	as described above. In the process, fix some bugs where type variables
	were expanded twice, with the second expansion's code being incorrect.
	Also factor out some common code, and unfactor some uncommon code
	(where a function had two uses, but its implementation was inefficient
	overkill for one of them).

library/builtin.m:
library/private_builtin.m:
library/io.m:
library/store.m:
runtime/mercury_layout_util.[ch]:
trace/mercury_trace_declarative.c:
trace/mercury_trace_external.c:
trace/mercury_trace_vars.[ch]:
	When calling C functions involving type_infos, cast them to the new
	types.

runtime/mercury_stack_layout.h:
	Fix a bug that was masked by casts in its client code.

compiler/rtti_out.m:
	Delete from the output a cast made unnecessary by the new const
	qualifier on MR_sectag_alternatives.

browser/browse.m:
browser/help.m:
library/io.m:
library/term.m:
tests/hard_coded/construct.m;
tests/hard_coded/existential_types_test.m:
tests/hard_coded/higher_order_type_manip.{m,exp}:
	Refer to the types defined in std_util.m by their new names.

tests/hard_coded/existential_rtti.{m,exp}:
	Make the test tougher by printing out not just one deconstructed term,
	but deconstructed versions of all the terms created by this test.
2000-03-24 10:28:07 +00:00

282 lines
9.2 KiB
Mathematica

%---------------------------------------------------------------------------%
% Copyright (C) 1998-2000 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 list, io, std_util.
:- type help__system.
:- type help__path == list(string).
:- type help__res ---> help__ok ; help__error(string).
%-----------------------------------------------------------------------------%
% Initialize an empty help system.
:- pred help__init(help__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 ok and the
% updated help system; if not, return an error message and the
% original help system.
:- pred help__add_help_node(help__system::in, help__path::in, int::in,
string::in, string::in, help__res::out, help__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__help(help__system::in, io__output_stream::in,
io__state::di, io__state::uo) is det.
% Print the help node at the given path. If there is none,
% print the top-level nodes.
:- pred help__path(help__system::in, help__path::in, io__output_stream::in,
help__res::out, io__state::di, io__state::uo) is det.
% Print all help nodes with the given name. If there are none,
% print the top-level nodes.
:- pred help__name(help__system::in, string::in, io__output_stream::in,
io__state::di, io__state::uo) is det.
%-----------------------------------------------------------------------------%
% Return the type_info for the type help__system, for use by C code.
:- pred help__help_system_type(type_desc::out) is det.
% Help interpret a help__res for C code.
:- pred help__result_is_error(help__res::in, string::out) is semidet.
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module int, string, require.
:- type help__system == list(help__entry).
:- type help__node
---> node(
help__text,
list(help__entry)
).
:- type help__text == string. % Should be one or more complete lines.
:- type help__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 export(help__init(out), "ML_HELP_init").
:- pragma export(help__add_help_node(in, in, in, in, in, out, out),
"ML_HELP_add_help_node").
:- pragma export(help__help(in, in, di, uo), "ML_HELP_help").
:- pragma export(help__path(in, in, in, out, di, uo), "ML_HELP_path").
:- pragma export(help__name(in, in, in, di, uo), "ML_HELP_name").
:- pragma export(help__help_system_type(out), "ML_HELP_help_system_type").
:- pragma export(help__result_is_error(in, out), "ML_HELP_result_is_error").
%-----------------------------------------------------------------------------%
help__init([]).
help__add_help_node(Sys0, Path, Index, Name, Text, Res, Sys) :-
Node = node(Text, []),
help__add_node(Sys0, Path, Index, Name, Node, Res, Sys).
:- pred help__add_node(help__system::in, help__path::in, int::in,
string::in, help__node::in, help__res::out, help__system::out) is det.
help__add_node(Nodes0, [Step | Steps], Index, Name, NewNode, Res, Nodes) :-
( help__one_path_step(Nodes0, Step, Entry0) ->
Entry0 = entry(EntryIndex, EntryName, EntryNode0),
EntryNode0 = node(Text, SubNodes0),
help__add_node(SubNodes0, Steps, Index, Name, NewNode,
Res, SubNodes),
EntryNode = node(Text, SubNodes),
Entry = entry(EntryIndex, EntryName, EntryNode),
help__replace_entry(Nodes0, Entry, Nodes)
;
string__append("invalid path component ", Step, Msg),
Res = help__error(Msg),
Nodes = Nodes0
).
help__add_node(Nodes0, [], Index, Name, Node, Res, Nodes) :-
(
list__member(Entry1, Nodes0),
Entry1 = entry(Index, _, _)
->
Res = help__error("entry with given index already exists"),
Nodes = Nodes0
;
list__member(Entry1, Nodes0),
Entry1 = entry(_, Name, _)
->
Res = help__error("entry with given name already exists"),
Nodes = Nodes0
;
Res = help__ok,
help__insert_into_entry_list(Nodes0, Index, Name, Node, Nodes)
).
:- pred help__insert_into_entry_list(list(help__entry)::in,
int::in, string::in, help__node::in, list(help__entry)::out) is det.
help__insert_into_entry_list([], Index, Name, Node, [Entry]) :-
Entry = entry(Index, Name, Node).
help__insert_into_entry_list([Head | Tail], Index, Name, Node, List) :-
Head = entry(HeadIndex, _, _),
( HeadIndex < Index ->
help__insert_into_entry_list(Tail, Index, Name, Node, NewTail),
List = [Head | NewTail]
;
Entry = entry(Index, Name, Node),
List = [Entry, Head | Tail]
).
%-----------------------------------------------------------------------------%
help__help(Sys, Stream) -->
help__print_entry_list(Sys, Stream).
help__name(Sys, Name, Stream) -->
help__search_entry_list(Sys, Name, 0, Count, Stream),
( { Count = 0 } ->
io__write_string("There is no such help topic.\n"),
help__help(Sys, Stream)
;
[]
).
:- pred help__search_entry_list(list(help__entry)::in, string::in,
int::in, int::out, io__output_stream::in,
io__state::di, io__state::uo) is det.
help__search_entry_list([], _, C, C, _) --> [].
help__search_entry_list([Entry | Tail], Name, C0, C, Stream) -->
{ Entry = entry(_, EntryName, Node) },
( { Name = EntryName } ->
% We print this node, but don't search its children.
help__print_node(Node, Stream),
{ C is C0 + 1 }
;
help__search_node(Node, Name, C0, C1, Stream),
help__search_entry_list(Tail, Name, C1, C, Stream)
).
:- pred help__search_node(help__node::in, string::in, int::in, int::out,
io__output_stream::in, io__state::di, io__state::uo) is det.
help__search_node(node(_, SubNodes), Name, C0, C, Stream) -->
help__search_entry_list(SubNodes, Name, C0, C, Stream).
help__path(Entries, Path, Stream, Result) -->
( { Path = [Step] } ->
( { help__one_path_step(Entries, Step, Entry) } ->
{ Entry = entry(_, _, EntryNode) },
{ EntryNode = node(Text, _) },
io__write_string(Stream, Text),
{ Result = help__ok }
;
{ string__append_list(["error at path component """,
Step, """"], Msg) },
{ Result = help__error(Msg) }
)
; { Path = [Step | Tail] } ->
( { help__one_path_step(Entries, Step, Entry) } ->
{ Entry = entry(_, _, EntryNode) },
{ EntryNode = node(_, SubEntries) },
help__path(SubEntries, Tail, Stream, Result)
;
{ string__append_list(["error at path component """,
Step, """"], Msg) },
{ Result = help__error(Msg) }
)
;
{ Result = help__error("the path does not go that deep") }
).
%-----------------------------------------------------------------------------%
:- pred help__print_entry_list(list(help__entry)::in, io__output_stream::in,
io__state::di, io__state::uo) is det.
help__print_entry_list([], _) --> [].
help__print_entry_list([entry(_, _, Node) | Nodes], Stream) -->
help__print_node(Node, Stream),
help__print_entry_list(Nodes, Stream).
:- pred help__print_node(help__node::in, io__output_stream::in,
io__state::di, io__state::uo) is det.
help__print_node(node(Text, _Nodes), Stream) -->
io__write_string(Stream, Text).
% XXX help__print_entry_list(Nodes, Stream).
%-----------------------------------------------------------------------------%
:- pred help__one_path_step(list(help__entry)::in, string::in,
help__entry::out) is semidet.
help__one_path_step([Head | Tail], Name, Entry) :-
Head = entry(_, HeadName, _),
( HeadName = Name ->
Entry = Head
;
help__one_path_step(Tail, Name, Entry)
).
:- pred help__replace_entry(list(help__entry)::in, help__entry::in,
list(help__entry)::out) is det.
help__replace_entry([], _, _) :-
error("help__replace_entry: entry to be replaced not found").
help__replace_entry([Head | Tail], Entry, List) :-
Head = entry(HeadIndex, _, _),
Entry = entry(EntryIndex, _, _),
( HeadIndex = EntryIndex ->
List = [Entry | Tail]
;
help__replace_entry(Tail, Entry, NewTail),
List = [Head | NewTail]
).
%-----------------------------------------------------------------------------%
help__help_system_type(Type) :-
help__init(HelpInit),
Type = type_of(HelpInit).
help__result_is_error(help__error(Msg), Msg).
%-----------------------------------------------------------------------------%