diff: documentation for trailing interface
Fergus Henderson
fjh at mundook.cs.mu.OZ.AU
Sat Sep 20 19:21:13 AEST 1997
doc/reference_manual.texi:
Various improvements to the documentation for trailing
based on Peter Schachte's feedback.
doc/user_guide.texi:
doc/transition.texi:
Minor typographical corrections.
cvs diff: Diffing .
Index: reference_manual.texi
===================================================================
RCS file: /home/staff/zs/imp/mercury/doc/reference_manual.texi,v
retrieving revision 1.69
diff -u -r1.69 reference_manual.texi
--- reference_manual.texi 1997/09/19 06:56:30 1.69
+++ reference_manual.texi 1997/09/20 07:20:12
@@ -2116,7 +2116,7 @@
lambda expression to specify which mode you want.
You can also create higher-order function terms of non-zero arity
-and higher-order predicate terms by "currying",
+and higher-order predicate terms by ``currying'',
i.e. specifying the first few arguments to a predicate or function, but
leaving the remaining arguments unspecified. For example, the
unification
@@ -2588,9 +2588,9 @@
Thus, to summarize, there are in fact a variety of different operational
semantics for Mercury. In one of them, the strict sequential semantics, there
-is no nondeterminism -- the behaviour is always specified exactly.
+is no nondeterminism --- the behaviour is always specified exactly.
Programs are executed top-down using SLDNF (or something equivalent),
-mode analysis does "minimal" reordering (in a precisely defined sense),
+mode analysis does ``minimal'' reordering (in a precisely defined sense),
function calls, conjunctions and disjunctions are executed depth-first
left-to-right, and function evaluation is strict. All implementations
are required to support the strict sequential semantics, so that a
@@ -2725,7 +2725,7 @@
If there is a @code{pragma c_code} declaration for a mode of a predicate
or function, then that mode of the predicate may not have determinism
@samp{multi} or @samp{nondet}, there must not be any clauses for that
-predicate or function, and there must be a @code{pragma c_code} goal
+predicate or function, and there must be a @code{pragma c_code} declaration
for every mode of the predicate or function.
For example, the following piece of code gives a predicate,
@@ -3036,12 +3036,12 @@
In certain compilation grades (see the ``Compilation model options''
section of the Mercury User's Guide), the University of Melbourne
Mercury implementation supports trailing. Trailing is a means
-of having side-effects such as destructive updates to data structures
+of having side-effects, such as destructive updates to data structures,
undone on backtracking. The basic idea is that during forward
execution, whenever you perform a destructive modification to
-a data structure that may still be live on backtracking
-you should record whatever information is necessary on
-a stack-like data structure called the ``trail''. Then, if
+a data structure that may still be live on backtracking,
+you should record whatever information is necessary to restore it
+on a stack-like data structure called the ``trail''. Then, if
a computation fails, and execution backtracks to before those
those updates were performed, the Mercury runtime engine will
traverse the trail back to the most recent choice point,
@@ -3067,8 +3067,8 @@
@node Choice points
@subsubsection Choice points
-A "choice point" is a point in the computation to
-which execution might backtrack. The "current"
+A ``choice point'' is a point in the computation to
+which execution might backtrack. The ``current''
choice point is the one that was most recently
encountered; that is also the one to which execution
will branch if the current computation fails.
@@ -3077,30 +3077,43 @@
execution ever backtracks to the choice point that was current
at the time of trailing, then the update will be undone.
-Note that if the Mercury compiler determines that it will never
+If the Mercury compiler determines that it will never
need to backtrack to a particular choice point, then it will
-"prune" away that choice point. If a choice point is pruned,
+``prune'' away that choice point. If a choice point is pruned,
the trail entries for those updates will be discarded;
any updates occurring after that choice point will not be undone.
-Execution may subsequently backtrack to a @emph{prior} choice point,
+
+Note that execution may subsequently backtrack to a @emph{prior} choice point,
but if so, the values updated will not be live at that point, so
-there is no need to undo the updates.
+there is no need to undo the updates. The reason that the updated values
+are guaranteed to not be live is that the Mercury compiler will only
+prune choice points when it is guaranteed to be safe to do so.
+The compiler may commit to a goal in two circumstances: if it is guaranteed
+that execution will never attempt to backtrack over that goal, or
+if the goal has no outputs. In the former case, execution
+cannot backtrack to a prior choice point, and in the latter case,
+the values updated within the goal cannot be live after the goal
+has succeeded, since the goal has no outputs.
For example:
@example
-:- mode q(out) is nondet.
-:- mode r(in) is det.
-p :-
- q(X), r(X), fail.
+:- mode q(mdi, muo) is nondet.
+:- mode p(mdi) is semidet.
+p(X) :- q(X, _Y), fail.
+
@end example
-Here any choice points created in @code{q/1} will be pruned away
-before the call to @code{r/1}. At the call to @code{fail},
-execution will backtrack; any updates performed inside @code{q/1}
-will not be undone, but that should be OK, since the variable
- at samp{X} will no longer be live.
+Here any choice points created in @code{q/2} will be pruned away
+before the call to @code{fail/1}. At the call to @code{fail},
+execution will backtrack; any updates performed inside @code{q/2}
+will not be undone, but that should be OK, because the variable
+ at samp{_Y} will no longer be live.
+
+Oh, but @samp{X} @emph{will} be live. Oh-oh...
+
+XXX we really should fix that bug.
@node Value trailing
@subsubsection Value trailing
@@ -3172,7 +3185,7 @@
A call to @samp{MR_trail_function(@var{untrail_func}, @var{value})}
ensures that
if future execution ever backtracks to current choicepoint,
-then @code{(*@var{untrail_func})(@var{value}, MR_undo)} will called.
+then @code{(*@var{untrail_func})(@var{value}, MR_undo)} will be called.
It also ensures that if the current choice point is pruned because
execution commits to never backtracking to it,
then @code{(*@var{untrail_func})(@var{value}, MR_commit)} will be called.
@@ -3186,9 +3199,11 @@
@samp{MR_undo} or @samp{MR_exception}, then it should undo the effects
of the update(s) specified by @var{value}, and the free any resources
associated with that trail entry. If it is called with @var{reason}
-being @samp{MR_commit} or @samp{MR_gc}, then it should not undo the
+being @samp{MR_commit} then it should not undo the
effects, instead it should merely free any resources associated with
-the trail entry.
+the trail entry. If it is called with anything else
+(such as @samp{MR_gc}), then it should probably abort execution
+with an error message.
@node Delayed goals and floundering
@subsubsection Delayed goals and floundering
@@ -3205,9 +3220,10 @@
the computation --- for example, after executing a negated goal --- it
is important for the system to check that their are no outstanding
delayed goals which might cause failure, before execution commits
-to this execution path. If this check was omitted, then it could
-lead to unsound behavior, such as a negation failing even though
-logically speaking it ought to have succeeded.
+to this execution path. If there are any such delayed goals, the
+computation is said to ``flounder''. If the check for floundering was
+omitted, then it could lead to unsound behavior, such as a negation
+failing even though logically speaking it ought to have succeeded.
The check for floundering can be implemented using the function trail,
by simply calling @samp{MR_trail_function()} to add a function trail
@@ -3216,6 +3232,8 @@
(For an example of this, see the @samp{ML_cfloat_untrail_func()}
function in the file @samp{extras/clpr/cfloat.m} in the Mercury
distribution.)
+If your function does detect floundering, then it should print
+an error message and then abort execution.
@node Avoiding redundant trailing
@subsubsection Avoiding redundant trailing
@@ -3226,7 +3244,8 @@
to record enough information to recover the original state of the
data structure for @emph{every} update on the trail; instead, it is
enough to record the original state of each updated data structure
-just once for each choice point, rather than once for each update.
+just once for each choice point occurring after the data structure
+is allocated, rather than once for each update.
The functions described below provide a means to avoid
redundant trailing.
@@ -3251,7 +3270,7 @@
point to which execution would backtrack if the current computation
failed.
- at code{MR_null_choicepoint_id()} returns a "null" value that is
+ at code{MR_null_choicepoint_id()} returns a ``null'' value that is
distinct from any value ever returned by @code{MR_current_choicepoint_id}.
(Note that @code{MR_null_choicepoint_id()}
is a macro that is guaranteed to be suitable for use as a
@@ -3272,17 +3291,22 @@
compare the result from that call with the value saved in
the @samp{prev_choicepoint} field in the data structure.
If they are different, then you must trail the update,
-and update the prev_choicepoint field with the new value.
-But if they are equal, then you can avoid trailing the
-update.
+and update the prev_choicepoint field with the new value;
+furthermore, you must also take care that on backtracking the
+previous value of the @samp{prev_choicepoint} field in your data
+structure is restored to its previous value, by trailing that update too.
+But if @code{MR_current_choice_id()} and the @code{prev_choicepoint} field
+are equal, then you can safely perform the update to your data
+structure without trailing it.
Note that there is a cost to this -- you have to include
an extra field in your data structure for each part of
-the data structure which you might update, and you
+the data structure which you might update, you
need to perform a test for each update to decide whether
-or not to trail it. Whether or not the benefits from
-avoiding redundant trailing outweigh these costs
-will depend on your application.
+or not to trail it, and if you do need to trail the update,
+then you have an extra field that you need to trail.
+Whether or not the benefits from avoiding redundant trailing
+outweigh these costs will depend on your application.
@c @item @code{void MR_untrail_to(MR_TrailEntry *@var{old_trail_ptr}, MR_untrail_reason @var{reason});}
@c
Index: transition_guide.texi
===================================================================
RCS file: /home/staff/zs/imp/mercury/doc/transition_guide.texi,v
retrieving revision 1.21
diff -u -r1.21 transition_guide.texi
--- transition_guide.texi 1997/08/20 07:43:07 1.21
+++ transition_guide.texi 1997/09/20 04:56:18
@@ -602,7 +602,7 @@
and in fact that's exactly how the Mercury compiler implements lambda
expressions.
-The current implementation of solutions/2 is a "zero-copy" implementation,
+The current implementation of solutions/2 is a ``zero-copy'' implementation,
so the cost of solutions/2 is proportional the number of solutions, but
independent of the size of the solutions. (This may change in
future implementations.)
Index: user_guide.texi
===================================================================
RCS file: /home/staff/zs/imp/mercury/doc/user_guide.texi,v
retrieving revision 1.96
diff -u -r1.96 user_guide.texi
--- user_guide.texi 1997/08/25 02:25:09 1.96
+++ user_guide.texi 1997/09/20 04:59:24
@@ -428,8 +428,8 @@
you can use the @samp{|} command to enter an interactive term browser.
(Within the term browser, type @samp{h.} for help.)
Also note that in the debugger, we use a version of @code{error/1}
-which fails rather than aborting after printing the "Software Error:" message.
-This makes debugging easier,
+which fails rather than aborting after printing the ``Software Error:''
+message. This makes debugging easier,
but will of course change the behaviour after an error occurs.
@node Using SICStus
@@ -795,7 +795,7 @@
If you want, once you have built a library, you could then install
(i.e. copy) the shared object library, the static object library,
the interface files and the initialization file into a different directory,
-or into several different directories, for that matter -- though it
+or into several different directories, for that matter --- though it
is probably easiest for the users of the library if you keep them
in a single directory.
Or alternatively, you could package them up into a @samp{tar}, @samp{shar}, or
@@ -2005,7 +2005,7 @@
@table @code
@item --no-emit-c-loops
-Use only gotos -- don't emit C loop constructs.
+Use only gotos --- don't emit C loop constructs.
@sp 1
@item --use-macro-for-redo-fail
More information about the developers
mailing list