[m-rev.] diff: update compiler mutable documentation
Julien Fischer
juliensf at csse.unimelb.edu.au
Tue Aug 15 17:22:04 AEST 2006
Estimated hours taken: 1
Branches: main
Add new documentation for the implementation of mutables.
compiler/prog_mutable.m:
Provide an up-to-date description of the source-to-source
transformation used to implement mutables.
compiler/prog_io.m:
Delete the old description of the transformation. (This hadn't
been maintained and was quite out-of-date.)
Minor documentation update caused by the removal of the mutable
`thread_safe' attribute.
compiler/make_hlds_passes.m:
Add a pointer to the new documentation in prog_mutable.m.
Julien.
Index: compiler/make_hlds_passes.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make_hlds_passes.m,v
retrieving revision 1.47
diff -u -r1.47 make_hlds_passes.m
--- compiler/make_hlds_passes.m 14 Aug 2006 09:09:18 -0000 1.47
+++ compiler/make_hlds_passes.m 15 Aug 2006 06:45:38 -0000
@@ -1189,6 +1189,10 @@
).
add_item_clause(Item, !Status, Context, !ModuleInfo, !QualInfo, !IO) :-
Item = mutable(Name, Type, InitTerm, Inst, MutAttrs, MutVarset),
+ %
+ % The transformation here is documented in the comments at the
+ % beginning of prog_mutable.m.
+ %
( status_defined_in_this_module(!.Status, yes) ->
module_info_get_name(!.ModuleInfo, ModuleName),
varset.new_named_var(varset.init, "X", X, ProgVarSet0),
Index: compiler/prog_io.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_io.m,v
retrieving revision 1.267
diff -u -r1.267 prog_io.m
--- compiler/prog_io.m 14 Aug 2006 09:09:19 -0000 1.267
+++ compiler/prog_io.m 15 Aug 2006 07:14:37 -0000
@@ -1777,52 +1777,11 @@
).
%-----------------------------------------------------------------------------%
-
-% Mutable declaration syntax:
-%
-% :- mutable(name, type, value, inst, <attribute_list>).
-% (The list of attributes at the end is optional.)
-%
-% e.g.:
-%
-% :- mutable(counter, int, 0, ground, [thread_safe]).
-%
-% This is converted into the following:
%
-% :- semipure pred get_counter(int::out(ground)) is det.
-% :- pragma foreign_proc("C",
-% get_counter(X::out(ground)),
-% [promise_semipure, will_not_call_mercury, thread_safe],
-% "X = mutable_counter;").
+% Mutable declarations
%
-% :- impure pred set_counter(int::in(ground)) is det.
-% :- pragma foreign_proc("C",
-% set_counter(X::in(ground)),
-% [will_not_call_mercury, thread_safe],
-% "MR_trail_current_value(&mutable_counter);
-% mutable_counter = X;").
+% See prog_mutable.m for implementation details.
%
-% :- pragma foreign_decl("C", "extern MR_Word mutable_counter;").
-% :- pragma foreign_code("C", "MR_Word mutable_counter;");
-%
-% :- import_module io.
-% :- initialise initialise_counter.
-% :- impure pred initialise_mutable_counter(io::di, io::uo) is det.
-%
-% initialise_mutable_counter(!IO) :-
-% impure set_counter(0).
-%
-% If the `thread_safe' attribute is specified in <attribute_list>
-% then foreign_procs are created that have the thread_safe attribute
-% set. If the `untrailed' attribute is specified in <attribute_list>
-% then the code for trailing the mutable variable in the set predicate
-% is omitted
-
-% NOTE: we must attach the varset to the mutable item because if the
-% initial value is non-ground, then the initial value will be a variable
-% and the mutable initialisation predicate will contain references to it.
-% Ignoring the varset may lead to later compiler passes attempting to reuse
-% this variable when fresh variables are allocated.
:- pred parse_mutable_decl(module_name::in, varset::in, list(term)::in,
maybe1(item)::out) is semidet.
@@ -1834,6 +1793,9 @@
term.coerce(ValueTerm, Value),
varset.coerce(Varset, ProgVarset),
parse_mutable_inst(InstTerm, InstResult),
+ %
+ % The list of attributes is optional.
+ %
(
OptMutAttrsTerm = [],
MutAttrsResult = ok1(default_mutable_attributes)
@@ -1847,6 +1809,12 @@
InstResult = ok1(Inst),
MutAttrsResult = ok1(MutAttrs)
->
+ % We *must* attach the varset to the mutable item because if the
+ % initial value is non-ground, then the initial value will be a
+ % variable and the mutable initialisation predicate will contain
+ % references to it. Ignoring the varset may lead to later compiler
+ % passes attempting to reuse this variable when fresh variables are
+ % allocated.
Result = ok1(mutable(Name, Type, Value, Inst, MutAttrs, ProgVarset))
;
Errors = get_any_errors1(NameResult) ++ get_any_errors1(TypeResult) ++
@@ -1906,9 +1874,9 @@
map_parser(parse_mutable_attr, MutAttrTerms, MaybeAttrList),
MaybeAttrList = ok1(CollectedMutAttrs)
->
- % We check for trailed/untrailed and thread_safe/not_thread_safe
- % conflicts here and deal with conflicting foreign_name attributes in
- % make_hlds_passes.m.
+ % We check for trailed/untrailed, constant/trailed and
+ % constant/attach_to_io_state conflicts here and deal with
+ % conflicting foreign_name attributes in make_hlds_passes.m.
%
(
list.member(Conflict1 - Conflict2, ConflictingAttributes),
Index: compiler/prog_mutable.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_mutable.m,v
retrieving revision 1.13
diff -u -r1.13 prog_mutable.m
--- compiler/prog_mutable.m 14 Aug 2006 09:09:19 -0000 1.13
+++ compiler/prog_mutable.m 15 Aug 2006 07:09:51 -0000
@@ -8,9 +8,117 @@
%
% File: prog_mutable.m.
% Main authors: rafe, juliensf.
+%
+% This module defines utility predicates for dealing with mutable
+% declarations. It also contains a description of the source-to-source
+% transformation used for implementing mutables.
+%
+%-----------------------------------------------------------------------------%
+%
+% Mutables are implemented as a source-to-source transformation on the
+% parse tree. The basic transformation is as follows:
+%
+% :- mutable(<varname>, <vartype>, <initvalue>, <varinst>, [attributes]).
+%
+% ===>
+%
+% :- pragma foreign_decl("C", "extern <CType> mutable_<varname>;").
+% :- pragma foreign_code("C", "<CType> mutable_<varname>;");
+%
+% NOTES:
+%
+% * The name of the C global corresponding to mutable_<varname> may be
+% mangled.
+%
+% * <CType> is chosen on a backend-specific basis. If the value stored
+% in the mutable is always boxed it is `MR_Word' otherwise it may
+% be some native type, `MR_Integer', `MR_Float' etc.
+%
+% :- initialise initialise_mutable_<varname>/0.
+%
+% :- impure pred initialise_mutable_<varname> is det.
+%
+% initialise_mutable_<varname> :-
+% impure set_<varname>(<initval>).
+%
+% :- semipure pred get_<varname>(<vartype>::out(<varinst>)) is det.
+% :- pragma foreign_proc("C",
+% get_<varname>(X::out(<varinst>)),
+% [promise_semipure, will_not_call_mercury],
+% "
+% X = mutable_<varname>;
+% ");
+%
+% :- impure pred set_<varname>(<vartype>::in(<varinst>)) is det.
+% :- pragma foreign_proc("C",
+% set_<varname>(X::in(<varinst>)),
+% [will_not_call_mercury],
+% "
+% MR_trail_current_value(&mutable_<varname>);
+% mutable_<varname> = X;
+% ").
+%
+% NOTE: mutables *are* trailed by default. The `untrailed' attribute just
+% causes the call to MR_trail_current_value to be omitted.
+%
+% If the `attach_to_io_state' attribute is specified we also generate:
+%
+% :- pred get_varname(<vartype>::out(<varinst>), io::di, io::uo) is det.
+% :- pred set_varname(<vartype>::in(<varinst>), io::di, io::uo) is det.
+%
+% :- pragma foreign_proc("C",
+% get_varname(X::out(<varinst), IO0::di, IO::uo),
+% [promise_pure, will_not_call_mercury, tabled_for_io],
+% "
+% X = mutable_<varname>;
+% IO = IO0;
+% ").
+%
+% :- pragma foreign_proc("C",
+% set_varname(X::in(<varinst>), IO0::di, IO::uo),
+% [promise_pure, will_not_call_mercury, tabled_for_io],
+% "
+% mutable_<varname> = X;
+% IO = IO0;
+% ").
+%
+% NOTE: we could implement the above in terms of the impure get and set
+% predicates. The reason we don't is so that we can use I/O
+% tabling.
+% XXX If tabling of impure actions is ever implemented we should\
+% revisit this.
+%
+% For constant mutables (those with the `constant' attribute), the
+% transformation is a little different:
+%
+% :- mutable(<varname>, <vartype>, <initvalue>, <varinst>, [constant]).
+%
+% ===>
+%
+% (The declarations for the global are as above.)
+%
+% :- pred get_<varname>(<vartype>::out(<varinst>)) is det.
+% :- pragma foreign_proc("C",
+% get_<varname>(X::out(<varinst>)),
+% [will_not_call_mercury, promise_pure, thread_safe],
+% "
+% X = mutable_<varname>;
+% ").
%
-% Utility predicates for dealing with mutable declarations.
+% In order to initialise constant mutables we generate the following:
+%
+% :- impure pred secret_initialization_only_set_<varname>(
+% <vartype>::in(<varinst>)) is det.
%
+% :- pragma foreign_proc("C",
+% secret_initialization_only_set_<varname>(X::in(<varinst>)),
+% [will_not_call_mercury],
+% "
+% mutable_<varname> = X;
+% ").
+%
+% :- initialise secret_initialization_only_set_<varname>/0.
+%
%-----------------------------------------------------------------------------%
:- module parse_tree.prog_mutable.
@@ -68,7 +176,7 @@
% the init predicate needs to do two things: execute arbitrary Mercury code
% (call functions etc) to generate the initial (and for constant mutables,
% also final) value of the mutable, and then store this value in persistent
- % storage. However, even we could create an item that contains both
+ % storage. However, even if we could create an item that contains both
% Mercury code and backend (e.g. C) code (which is currently not possible),
% this would require the second part to be a foreign_proc goal. Such goals
% include a reference to the predicate they implement. That predicate
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list