tr_store.m
Fergus Henderson
fjh at kryten.cs.mu.OZ.AU
Sat Sep 27 01:25:32 AEST 1997
extras/trailed_update/tr_store.m:
New file. A backtrackable version of library/store.m.
extras/trailed_update/tr_array.m:
Delete the `mui_' and `mdi_' prefixes on predicate names.
This was done for consistency with tr_store.m.
extras/trailed_update/trailed_update.m:
Add tr_store.m to the list of modules in the `trailed_update'
library.
extras/trailed_update/.cvsignore:
Ignore .c and .h files.
cvs diff: Diffing .
Index: .cvsignore
===================================================================
RCS file: .cvsignore
diff -N .cvsignore
--- /dev/null Sat Sep 27 01:08:06 1997
+++ .cvsignore Thu Sep 18 19:00:05 1997
@@ -0,0 +1,2 @@
+*.c
+*.h
Index: Mmakefile
===================================================================
RCS file: /home/staff/zs/imp/mercury/extras/trailed_update/Mmakefile,v
retrieving revision 1.1
diff -u -u -r1.1 Mmakefile
--- 1.1 1997/09/11 06:55:04
+++ Mmakefile 1997/09/19 08:06:31
@@ -1,5 +1,9 @@
GRADE = asm_fast.gc.tr
-RM_C = :
+MCFLAGS=-O6 --intermodule-optimization
+MLFLAGS=--static
+# RM_C = :
+# MLFLAGS=-g
+# MGNUCFLAGS=-g
MAIN_TARGET = libtrailed_update
Index: tr_array.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/extras/trailed_update/tr_array.m,v
retrieving revision 1.2
diff -u -u -r1.2 tr_array.m
--- 1.2 1997/09/20 06:46:22
+++ tr_array.m 1997/09/26 15:17:36
@@ -23,17 +23,17 @@
% Operations that perform backtrackable destructive update.
%
- % tr_array__mdi_set sets the nth element of an array, and returns the
+ % tr_array__set sets the nth element of an array, and returns the
% resulting array (good opportunity for destructive update ;-).
% It is an error if the index is out of bounds.
-:- pred tr_array__mdi_set(array(T), int, T, array(T)).
-:- mode tr_array__mdi_set(array_mdi, in, in, array_muo) is det.
+:- pred tr_array__set(array(T), int, T, array(T)).
+:- mode tr_array__set(array_mdi, in, in, array_muo) is det.
- % tr_array__mdi_semidet_set sets the nth element of an array,
+ % tr_array__semidet_set sets the nth element of an array,
% and returns the resulting array.
% It fails if the index is out of bounds.
-:- pred tr_array__mdi_semidet_set(array(T), int, T, array(T)).
-:- mode tr_array__mdi_semidet_set(array_mdi, in, in, array_muo) is semidet.
+:- pred tr_array__semidet_set(array(T), int, T, array(T)).
+:- mode tr_array__semidet_set(array_mdi, in, in, array_muo) is semidet.
%-----------------------------------------------------------------------------%
@@ -44,114 +44,114 @@
% "mostly_unique"-ness.
%
- % tr_array__mui_min returns the lower bound of the array.
+ % tr_array__min returns the lower bound of the array.
% Note: in this implementation, the lower bound is always zero.
-:- pred tr_array__mui_min(array(_T), int).
-:- mode tr_array__mui_min(array_mui, out) is det.
-:- mode tr_array__mui_min(in, out) is det.
-
- % tr_array__mui_max returns the upper bound of the array.
-:- pred tr_array__mui_max(array(_T), int).
-:- mode tr_array__mui_max(array_mui, out) is det.
-:- mode tr_array__mui_max(in, out) is det.
+:- pred tr_array__min(array(_T), int).
+:- mode tr_array__min(array_mui, out) is det.
+:- mode tr_array__min(in, out) is det.
+
+ % tr_array__max returns the upper bound of the array.
+:- pred tr_array__max(array(_T), int).
+:- mode tr_array__max(array_mui, out) is det.
+:- mode tr_array__max(in, out) is det.
- % tr_array__mui_size returns the length of the array,
+ % tr_array__size returns the length of the array,
% i.e. upper bound - lower bound + 1.
-:- pred tr_array__mui_size(array(_T), int).
-:- mode tr_array__mui_size(array_mui, out) is det.
-:- mode tr_array__mui_size(in, out) is det.
+:- pred tr_array__size(array(_T), int).
+:- mode tr_array__size(array_mui, out) is det.
+:- mode tr_array__size(in, out) is det.
- % tr_array__mui_bounds returns the upper and lower bounds of an array.
+ % tr_array__bounds returns the upper and lower bounds of an array.
% Note: in this implementation, the lower bound is always zero.
-:- pred tr_array__mui_bounds(array(_T), int, int).
-:- mode tr_array__mui_bounds(array_mui, out, out) is det.
-:- mode tr_array__mui_bounds(in, out, out) is det.
+:- pred tr_array__bounds(array(_T), int, int).
+:- mode tr_array__bounds(array_mui, out, out) is det.
+:- mode tr_array__bounds(in, out, out) is det.
- % tr_array__mui_in_bounds checks whether an index is in the bounds
+ % tr_array__in_bounds checks whether an index is in the bounds
% of an array.
-:- pred tr_array__mui_in_bounds(array(_T), int).
-:- mode tr_array__mui_in_bounds(array_mui, in) is semidet.
-:- mode tr_array__mui_in_bounds(in, in) is semidet.
+:- pred tr_array__in_bounds(array(_T), int).
+:- mode tr_array__in_bounds(array_mui, in) is semidet.
+:- mode tr_array__in_bounds(in, in) is semidet.
%-----------------------------------------------------------------------------%
- % tr_array__mui_lookup returns the Nth element of an array.
+ % tr_array__lookup returns the Nth element of an array.
% It is an error if the index is out of bounds.
-:- pred tr_array__mui_lookup(array(T), int, T).
-:- mode tr_array__mui_lookup(array_mui, in, out) is det.
-:- mode tr_array__mui_lookup(in, in, out) is det.
+:- pred tr_array__lookup(array(T), int, T).
+:- mode tr_array__lookup(array_mui, in, out) is det.
+:- mode tr_array__lookup(in, in, out) is det.
- % tr_array__mui_semidet_lookup returns the Nth element of an array.
+ % tr_array__semidet_lookup returns the Nth element of an array.
% It fails if the index is out of bounds.
-:- pred tr_array__mui_semidet_lookup(array(T), int, T).
-:- mode tr_array__mui_semidet_lookup(array_mui, in, out) is semidet.
-:- mode tr_array__mui_semidet_lookup(in, in, out) is semidet.
+:- pred tr_array__semidet_lookup(array(T), int, T).
+:- mode tr_array__semidet_lookup(array_mui, in, out) is semidet.
+:- mode tr_array__semidet_lookup(in, in, out) is semidet.
- % tr_array__mui_slow_set sets the nth element of an array,
+ % tr_array__slow_set sets the nth element of an array,
% and returns the resulting array. The initial array is not
% required to be unique, so the implementation may not be able to use
% destructive update.
% It is an error if the index is out of bounds.
-:- pred tr_array__mui_slow_set(array(T), int, T, array(T)).
-:- mode tr_array__mui_slow_set(array_mui, in, in, array_uo) is det.
-:- mode tr_array__mui_slow_set(in, in, in, array_uo) is det.
+:- pred tr_array__slow_set(array(T), int, T, array(T)).
+:- mode tr_array__slow_set(array_mui, in, in, array_uo) is det.
+:- mode tr_array__slow_set(in, in, in, array_uo) is det.
- % tr_array__mui_semidet_slow_set sets the nth element of an array,
+ % tr_array__semidet_slow_set sets the nth element of an array,
% and returns the resulting array. The initial array is not
% required to be unique, so the implementation may not be able to use
% destructive update.
% It fails if the index is out of bounds.
-:- pred tr_array__mui_semidet_slow_set(array(T), int, T, array(T)).
-:- mode tr_array__mui_semidet_slow_set(array_mui, in, in, array_uo) is semidet.
-:- mode tr_array__mui_semidet_slow_set(in, in, in, array_uo) is semidet.
+:- pred tr_array__semidet_slow_set(array(T), int, T, array(T)).
+:- mode tr_array__semidet_slow_set(array_mui, in, in, array_uo) is semidet.
+:- mode tr_array__semidet_slow_set(in, in, in, array_uo) is semidet.
- % tr_array__mui_copy(Array0, Array):
+ % tr_array__copy(Array0, Array):
% Makes a new unique copy of an array.
-:- pred tr_array__mui_copy(array(T), array(T)).
-:- mode tr_array__mui_copy(array_mui, array_uo) is det.
-:- mode tr_array__mui_copy(in, array_uo) is det.
+:- pred tr_array__copy(array(T), array(T)).
+:- mode tr_array__copy(array_mui, array_uo) is det.
+:- mode tr_array__copy(in, array_uo) is det.
- % tr_array__mui_resize(Array0, Size, Init, Array):
+ % tr_array__resize(Array0, Size, Init, Array):
% The array is expanded or shrunk to make it fit
% the new size `Size'. Any new entries are filled
% with `Init'.
-:- pred tr_array__mui_resize(array(T), int, T, array(T)).
-:- mode tr_array__mui_resize(array_mui, in, in, array_uo) is det.
-:- mode tr_array__mui_resize(in, in, in, array_uo) is det.
+:- pred tr_array__resize(array(T), int, T, array(T)).
+:- mode tr_array__resize(array_mui, in, in, array_uo) is det.
+:- mode tr_array__resize(in, in, in, array_uo) is det.
- % tr_array__mui_shrink(Array0, Size, Array):
+ % tr_array__shrink(Array0, Size, Array):
% The array is shrunk to make it fit the new size `Size'.
% It is an error if `Size' is larger than the size of `Array0'.
-:- pred tr_array__mui_shrink(array(T), int, array(T)).
-:- mode tr_array__mui_shrink(array_mui, in, array_uo) is det.
-:- mode tr_array__mui_shrink(in, in, array_uo) is det.
+:- pred tr_array__shrink(array(T), int, array(T)).
+:- mode tr_array__shrink(array_mui, in, array_uo) is det.
+:- mode tr_array__shrink(in, in, array_uo) is det.
- % tr_array__mui_to_list takes an array and returns a list containing
+ % tr_array__to_list takes an array and returns a list containing
% the elements of the array in the same order that they
% occurred in the array.
-:- pred tr_array__mui_to_list(array(T), list(T)).
-:- mode tr_array__mui_to_list(array_mui, out) is det.
-:- mode tr_array__mui_to_list(in, out) is det.
+:- pred tr_array__to_list(array(T), list(T)).
+:- mode tr_array__to_list(array_mui, out) is det.
+:- mode tr_array__to_list(in, out) is det.
- % tr_array__mui_fetch_items takes an array and a lower and upper
+ % tr_array__fetch_items takes an array and a lower and upper
% index, and places those items in the array between these
% indices into a list. It is an error if either index is
% out of bounds.
-:- pred tr_array__mui_fetch_items(array(T), int, int, list(T)).
-:- mode tr_array__mui_fetch_items(array_mui, in, in, out) is det.
-:- mode tr_array__mui_fetch_items(in, in, in, out) is det.
+:- pred tr_array__fetch_items(array(T), int, int, list(T)).
+:- mode tr_array__fetch_items(array_mui, in, in, out) is det.
+:- mode tr_array__fetch_items(in, in, in, out) is det.
- % tr_array__mui_bsearch takes an array, an element to be found
+ % tr_array__bsearch takes an array, an element to be found
% and a comparison predicate and returns the position of
% the element in the array. Assumes the array is in sorted
% order. Fails if the element is not present. If the
% element to be found appears multiple times, the index of
% the first occurrence is returned.
-:- pred tr_array__mui_bsearch(array(T), T, pred(T, T, comparison_result),
+:- pred tr_array__bsearch(array(T), T, pred(T, T, comparison_result),
maybe(int)).
-:- mode tr_array__mui_bsearch(array_mui, in, pred(in, in, out) is det, out)
+:- mode tr_array__bsearch(array_mui, in, pred(in, in, out) is det, out)
is det.
-:- mode tr_array__mui_bsearch(in, in, pred(in, in, out) is det, out) is det.
+:- mode tr_array__bsearch(in, in, pred(in, in, out) is det, out) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -161,11 +161,11 @@
/****
lower bounds other than zero are not supported
- % tr_array__mui_resize takes an array and new lower and upper bounds.
+ % tr_array__resize takes an array and new lower and upper bounds.
% the array is expanded or shrunk at each end to make it fit
% the new bounds.
-:- pred tr_array__mui_resize(array(T), int, int, array(T)).
-:- mode tr_array__mui_resize(in, in, in, out) is det.
+:- pred tr_array__resize(array(T), int, int, array(T)).
+:- mode tr_array__resize(in, in, in, out) is det.
****/
%-----------------------------------------------------------------------------%
@@ -177,62 +177,62 @@
%-----------------------------------------------------------------------------%
-:- pragma c_code(tr_array__mdi_set(Array0::array_mdi, Index::in, Item::in,
+:- pragma c_code(tr_array__set(Array0::array_mdi, Index::in, Item::in,
Array::array_muo),
will_not_call_mercury,
"{
MR_ArrayType *array = (MR_ArrayType *) Array0;
if ((Unsigned) Index >= (Unsigned) array->size) {
- fatal_error(""tr_array__mdi_set: array index out of bounds"");
+ fatal_error(""tr_array__set: array index out of bounds"");
}
MR_trail_current_value(&array->elements[Index]);
array->elements[Index] = Item; /* destructive update! */
Array = Array0;
}").
-tr_array__mdi_semidet_set(Array0, Index, Item, Array) :-
- tr_array__mui_in_bounds(Array0, Index),
- tr_array__mdi_set(Array0, Index, Item, Array).
+tr_array__semidet_set(Array0, Index, Item, Array) :-
+ tr_array__in_bounds(Array0, Index),
+ tr_array__set(Array0, Index, Item, Array).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
-:- pragma c_code(tr_array__mui_min(Array::array_mui, Min::out),
+:- pragma c_code(tr_array__min(Array::array_mui, Min::out),
will_not_call_mercury,
"
/* Array not used */
Min = 0;
").
-:- pragma c_code(tr_array__mui_min(Array::in, Min::out),
+:- pragma c_code(tr_array__min(Array::in, Min::out),
will_not_call_mercury,
"
/* Array not used */
Min = 0;
").
-:- pragma c_code(tr_array__mui_max(Array::array_mui, Max::out),
+:- pragma c_code(tr_array__max(Array::array_mui, Max::out),
will_not_call_mercury,
"
Max = ((MR_ArrayType *)Array)->size - 1;
").
-:- pragma c_code(tr_array__mui_max(Array::in, Max::out),
+:- pragma c_code(tr_array__max(Array::in, Max::out),
will_not_call_mercury,
"
Max = ((MR_ArrayType *)Array)->size - 1;
").
-tr_array__mui_bounds(Array, Min, Max) :-
- tr_array__mui_min(Array, Min),
- tr_array__mui_max(Array, Max).
+tr_array__bounds(Array, Min, Max) :-
+ tr_array__min(Array, Min),
+ tr_array__max(Array, Max).
%-----------------------------------------------------------------------------%
-:- pragma c_code(tr_array__mui_size(Array::array_mui, Max::out),
+:- pragma c_code(tr_array__size(Array::array_mui, Max::out),
will_not_call_mercury,
"
Max = ((MR_ArrayType *)Array)->size;
").
-:- pragma c_code(tr_array__mui_size(Array::in, Max::out),
+:- pragma c_code(tr_array__size(Array::in, Max::out),
will_not_call_mercury,
"
Max = ((MR_ArrayType *)Array)->size;
@@ -240,40 +240,40 @@
%-----------------------------------------------------------------------------%
-tr_array__mui_in_bounds(Array, Index) :-
- tr_array__mui_bounds(Array, Min, Max),
+tr_array__in_bounds(Array, Index) :-
+ tr_array__bounds(Array, Min, Max),
Min =< Index, Index =< Max.
-tr_array__mui_semidet_lookup(Array, Index, Item) :-
- tr_array__mui_in_bounds(Array, Index),
- tr_array__mui_lookup(Array, Index, Item).
-
-tr_array__mui_semidet_slow_set(Array0, Index, Item, Array) :-
- tr_array__mui_in_bounds(Array0, Index),
- tr_array__mui_slow_set(Array0, Index, Item, Array).
+tr_array__semidet_lookup(Array, Index, Item) :-
+ tr_array__in_bounds(Array, Index),
+ tr_array__lookup(Array, Index, Item).
+
+tr_array__semidet_slow_set(Array0, Index, Item, Array) :-
+ tr_array__in_bounds(Array0, Index),
+ tr_array__slow_set(Array0, Index, Item, Array).
-tr_array__mui_slow_set(Array0, Index, Item, Array) :-
- tr_array__mui_copy(Array0, Array1),
+tr_array__slow_set(Array0, Index, Item, Array) :-
+ tr_array__copy(Array0, Array1),
array__set(Array1, Index, Item, Array).
%-----------------------------------------------------------------------------%
-:- pragma c_code(tr_array__mui_lookup(Array::array_mui, Index::in, Item::out),
+:- pragma c_code(tr_array__lookup(Array::array_mui, Index::in, Item::out),
will_not_call_mercury,
"{
MR_ArrayType *array = (MR_ArrayType *) Array;
if ((Unsigned) Index >= (Unsigned) array->size) {
- fatal_error(""tr_array__mui_lookup: ""
+ fatal_error(""tr_array__lookup: ""
""array index out of bounds"");
}
Item = array->elements[Index];
}").
-:- pragma c_code(tr_array__mui_lookup(Array::in, Index::in, Item::out),
+:- pragma c_code(tr_array__lookup(Array::in, Index::in, Item::out),
will_not_call_mercury,
"{
MR_ArrayType *array = (MR_ArrayType *) Array;
if ((Unsigned) Index >= (Unsigned) array->size) {
- fatal_error(""tr_array__mui_lookup: array index out of bounds"");
+ fatal_error(""tr_array__lookup: array index out of bounds"");
}
Item = array->elements[Index];
}").
@@ -319,7 +319,7 @@
").
:- pragma c_code(
- tr_array__mui_resize(Array0::array_mui, Size::in, Item::in,
+ tr_array__resize(Array0::array_mui, Size::in, Item::in,
Array::array_uo),
will_not_call_mercury,
"
@@ -327,7 +327,7 @@
").
:- pragma c_code(
- tr_array__mui_resize(Array0::in, Size::in, Item::in,
+ tr_array__resize(Array0::in, Size::in, Item::in,
Array::array_uo),
will_not_call_mercury,
"
@@ -353,7 +353,7 @@
old_array_size = old_array->size;
if (old_array_size == array_size) return old_array;
if (old_array_size < array_size) {
- fatal_error(""tr_array__mui_shrink: can't shrink to a larger size"");
+ fatal_error(""tr_array__shrink: can't shrink to a larger size"");
}
array = (MR_ArrayType *) make_many(Word, array_size + 1);
@@ -372,7 +372,7 @@
").
:- pragma c_code(
- tr_array__mui_shrink(Array0::array_mui, Size::in, Array::array_uo),
+ tr_array__shrink(Array0::array_mui, Size::in, Array::array_uo),
will_not_call_mercury,
"
Array = (Word) ML_tr_shrink_array(
@@ -380,7 +380,7 @@
").
:- pragma c_code(
- tr_array__mui_shrink(Array0::in, Size::in, Array::array_uo),
+ tr_array__shrink(Array0::in, Size::in, Array::array_uo),
will_not_call_mercury,
"
Array = (Word) ML_tr_shrink_array(
@@ -417,14 +417,14 @@
").
:- pragma c_code(
- tr_array__mui_copy(Array0::array_mui, Array::array_uo),
+ tr_array__copy(Array0::array_mui, Array::array_uo),
will_not_call_mercury,
"
Array = (Word) ML_tr_copy_array((MR_ArrayType *) Array0);
").
:- pragma c_code(
- tr_array__mui_copy(Array0::in, Array::array_uo),
+ tr_array__copy(Array0::in, Array::array_uo),
will_not_call_mercury,
"
Array = (Word) ML_tr_copy_array((MR_ArrayType *) Array0);
@@ -432,35 +432,35 @@
%-----------------------------------------------------------------------------%
-tr_array__mui_to_list(Array, List) :-
- tr_array__mui_bounds(Array, Low, High),
- tr_array__mui_fetch_items(Array, Low, High, List).
+tr_array__to_list(Array, List) :-
+ tr_array__bounds(Array, Low, High),
+ tr_array__fetch_items(Array, Low, High, List).
%-----------------------------------------------------------------------------%
-tr_array__mui_fetch_items(Array, Low, High, List) :-
+tr_array__fetch_items(Array, Low, High, List) :-
(
Low > High
->
List = []
;
Low1 is Low + 1,
- tr_array__mui_fetch_items(Array, Low1, High, List0),
- tr_array__mui_lookup(Array, Low, Item),
+ tr_array__fetch_items(Array, Low1, High, List0),
+ tr_array__lookup(Array, Low, Item),
List = [Item|List0]
).
%-----------------------------------------------------------------------------%
-tr_array__mui_bsearch(A, El, Compare, Result) :-
- tr_array__mui_bounds(A, Lo, Hi),
- tr_array__mui_bsearch_2(A, Lo, Hi, El, Compare, Result).
+tr_array__bsearch(A, El, Compare, Result) :-
+ tr_array__bounds(A, Lo, Hi),
+ tr_array__bsearch_2(A, Lo, Hi, El, Compare, Result).
-:- pred tr_array__mui_bsearch_2(array(T), int, int, T,
+:- pred tr_array__bsearch_2(array(T), int, int, T,
pred(T, T, comparison_result), maybe(int)).
-:- mode tr_array__mui_bsearch_2(in, in, in, in, pred(in, in, out) is det,
+:- mode tr_array__bsearch_2(in, in, in, in, pred(in, in, out) is det,
out) is det.
-tr_array__mui_bsearch_2(Array, Lo, Hi, El, Compare, Result) :-
+tr_array__bsearch_2(Array, Lo, Hi, El, Compare, Result) :-
Width is Hi - Lo,
% If Width < 0, there is no range left.
@@ -470,7 +470,7 @@
% If Width == 0, we may just have found our element.
% Do a Compare to check.
( Width = 0 ->
- tr_array__mui_lookup(Array, Lo, X),
+ tr_array__lookup(Array, Lo, X),
( call(Compare, El, X, (=)) ->
Result = yes(Lo)
;
@@ -480,16 +480,16 @@
% Otherwise find the middle element of the range
% and check against that.
Mid is (Lo + Hi) >> 1, % `>> 1' is hand-optimized `div 2'.
- tr_array__mui_lookup(Array, Mid, XMid),
+ tr_array__lookup(Array, Mid, XMid),
call(Compare, XMid, El, Comp),
( Comp = (<),
Mid1 is Mid + 1,
- tr_array__mui_bsearch_2(Array, Mid1, Hi, El, Compare, Result)
+ tr_array__bsearch_2(Array, Mid1, Hi, El, Compare, Result)
; Comp = (=),
- tr_array__mui_bsearch_2(Array, Lo, Mid, El, Compare, Result)
+ tr_array__bsearch_2(Array, Lo, Mid, El, Compare, Result)
; Comp = (>),
Mid1 is Mid - 1,
- tr_array__mui_bsearch_2(Array, Lo, Mid1, El, Compare, Result)
+ tr_array__bsearch_2(Array, Lo, Mid1, El, Compare, Result)
)
)
).
Index: tr_store.m
===================================================================
RCS file: tr_store.m
diff -N tr_store.m
--- /dev/null Sat Sep 27 01:08:06 1997
+++ tr_store.m Sat Sep 27 01:15:00 1997
@@ -0,0 +1,322 @@
+%-----------------------------------------------------------------------------%
+% Copyright (C) 1997 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: tr_store.m.
+% Main author: fjh.
+% Stability: low.
+%
+% This file provides facilities for manipulating mutable backtrackable stores.
+% This is a backtrackable version of the standard library module `store.m';
+% the interface and implementation are almost identifical to store.m,
+% the only difference is that destructive updates are recorded on a trail
+% so that updates can be undone on backtracking.
+%
+% See store.m for documentation, and for the definition of the types
+% `store', `mutvar', and `ref'.
+%
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- module tr_store.
+:- interface.
+:- import_module store.
+
+%-----------------------------------------------------------------------------%
+%
+% mutvars
+%
+
+ % create a new mutable variable,
+ % initialized with the specified value
+:- pred tr_store__new_mutvar(T, mutvar(T, S), store(S), store(S)).
+:- mode tr_store__new_mutvar(in, out, mdi, muo) is det.
+
+ % lookup the value stored in a given mutable variable
+:- pred tr_store__get_mutvar(mutvar(T, S), T, store(S), store(S)).
+:- mode tr_store__get_mutvar(in, out, mdi, muo) is det.
+
+ % replace the value stored in a given mutable variable
+:- pred tr_store__set_mutvar(mutvar(T, S), T, store(S), store(S)).
+:- mode tr_store__set_mutvar(in, in, mdi, muo) is det.
+
+%-----------------------------------------------------------------------------%
+%
+% references
+%
+
+ % new_ref(Val, Ref):
+ % /* In C: Ref = malloc(...); *Ref = Val; */
+ % Given a value of any type `T', insert a copy of the term
+ % into the store and return a new reference to that term.
+ % (This does not actually perform a copy, it just returns a view
+ % of the representation of that value.
+ % It does however allocate one cell to hold the reference;
+ % you can use new_arg_ref to avoid that.)
+:- pred tr_store__new_ref(T, ref(T, S), store(S), store(S)).
+:- mode tr_store__new_ref(mdi, out, mdi, muo) is det.
+
+ % ref_functor(Ref, Functor, Arity):
+ % Given a reference to a term, return the functor and arity
+ % of that term.
+:- pred tr_store__ref_functor(ref(T, S), string, int, store(S), store(S)).
+:- mode tr_store__ref_functor(in, out, out, mdi, muo) is det.
+
+ % arg_ref(Ref, ArgNum, ArgRef):
+ % /* Psuedo-C code: ArgRef = &Ref[ArgNum]; */
+ % Given a reference to a term, return a reference to
+ % the specified argument (field) of that term
+ % (argument numbers start from zero).
+ % It is an error if the argument number is out of range,
+ % or if the argument reference has the wrong type.
+:- pred tr_store__arg_ref(ref(T, S), int, ref(ArgT, S), store(S), store(S)).
+:- mode tr_store__arg_ref(in, in, out, mdi, muo) is det.
+
+ % new_arg_ref(Val, ArgNum, ArgRef):
+ % /* Psuedo-C code: ArgRef = &Val[ArgNum]; */
+ % Equivalent to `new_ref(Val, Ref), arg_ref(Ref, ArgNum, ArgRef)',
+ % except that it is more efficient.
+ % It is an error if the argument number is out of range,
+ % or if the argument reference has the wrong type.
+:- pred tr_store__new_arg_ref(T, int, ref(ArgT, S), store(S), store(S)).
+:- mode tr_store__new_arg_ref(mdi, in, out, mdi, muo) is det.
+
+ % set_ref(Ref, ValueRef):
+ % /* Pseudo-C code: *Ref = *ValueRef; */
+ % Given a reference to a term (Ref),
+ % a reference to another term (ValueRef),
+ % update the store so that the term referred to by Ref
+ % is replaced with the term referenced by ValueRef.
+:- pred tr_store__set_ref(ref(T, S), ref(T, S), store(S), store(S)).
+:- mode tr_store__set_ref(in, in, mdi, muo) is det.
+
+ % set_ref_value(Ref, Value):
+ % /* Pseudo-C code: *Ref = Value; */
+ % Given a reference to a term (Ref), and a value (Value),
+ % update the store so that the term referred to by Ref
+ % is replaced with Value.
+ % (Argument numbers start from zero).
+:- pred tr_store__set_ref_value(ref(T, S), ArgT, store(S), store(S)).
+:- mode tr_store__set_ref_value(in, mdi, mdi, muo) is det.
+
+ % Given a reference to a term, return that term.
+ % Note that this requires making a copy, so this pred may
+ % be inefficient if used to return large terms; it
+ % is most efficient with atomic terms.
+:- pred tr_store__copy_ref_value(ref(T, S), T, store(S), store(S)).
+:- mode tr_store__copy_ref_value(in, uo, mdi, muo) is det.
+
+ % Same as above, but without making a copy.
+ % Destroys the store.
+:- pred tr_store__extract_ref_value(store(S), ref(T, S), T).
+:- mode tr_store__extract_ref_value(mdi, in, out) is det.
+
+%-----------------------------------------------------------------------------%
+%
+% Nasty performance hacks
+%
+% WARNING: use of these procedures is dangerous!
+% Use them only only as a last resort, only if performance
+% is critical, and only if profiling shows that using the
+% safe versions is a bottleneck.
+%
+% These procedures may vanish in some future version of Mercury.
+
+ % `unsafe_arg_ref' is the same as `arg_ref',
+ % and `unsafe_new_arg_ref' is the same as `new_arg_ref'
+ % except that they doesn't check for errors,
+ % and they don't work for `no_tag' types (types with
+ % exactly one functor which has exactly one argument),
+ % and they don't work for types with >4 functors.
+ % If the argument number is out of range,
+ % or if the argument reference has the wrong type,
+ % or if the argument is a `no_tag' type,
+ % then the behaviour is undefined, and probably harmful.
+
+:- pred tr_store__unsafe_arg_ref(ref(T, S), int, ref(ArgT, S),
+ store(S), store(S)).
+:- mode tr_store__unsafe_arg_ref(in, in, out, mdi, muo) is det.
+
+:- pred tr_store__unsafe_new_arg_ref(T, int, ref(ArgT, S), store(S), store(S)).
+:- mode tr_store__unsafe_new_arg_ref(mdi, in, out, mdi, muo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+:- import_module std_util.
+
+:- type mutvar(T, S).
+
+:- type store(S).
+
+:- pragma c_code(init(_S0::muo), will_not_call_mercury, "").
+
+:- pragma c_code(new_mutvar(Val::in, Mutvar::out, S0::mdi, S::muo),
+ will_not_call_mercury,
+"
+ incr_hp(Mutvar, 1);
+ *(Word *)Mutvar = Val;
+ S = S0;
+").
+
+:- pragma c_code(get_mutvar(Mutvar::in, Val::out, S0::mdi, S::muo),
+ will_not_call_mercury,
+"
+ Val = *(Word *)Mutvar;
+ S = S0;
+").
+
+:- pragma c_code(set_mutvar(Mutvar::in, Val::in, S0::mdi, S::muo),
+ will_not_call_mercury,
+"
+ MR_trail_current_value((Word *) Mutvar);
+ *(Word *)Mutvar = Val;
+ S = S0;
+").
+
+%-----------------------------------------------------------------------------%
+
+:- pragma c_code(new_ref(Val::mdi, Ref::out, S0::mdi, S::muo),
+ will_not_call_mercury,
+"
+ incr_hp(Ref, 1);
+ *(Word *)Ref = Val;
+ S = S0;
+").
+
+copy_ref_value(Ref, Val) -->
+ /* XXX need to deep-copy non-atomic types */
+ unsafe_ref_value(Ref, Val).
+
+ % unsafe_ref_value extracts the value that a reference
+ % refers to, without making a copy; it is unsafe because
+ % the store could later be modified, changing the returned
+ % value.
+:- pred tr_store__unsafe_ref_value(ref(T, S), T, store(S), store(S)).
+:- mode tr_store__unsafe_ref_value(in, uo, mdi, muo) is det.
+:- pragma c_code(unsafe_ref_value(Ref::in, Val::uo, S0::mdi, S::muo),
+ will_not_call_mercury,
+"
+ Val = *(Word *)Ref;
+ S = S0;
+").
+
+ref_functor(Ref, Functor, Arity) -->
+ unsafe_ref_value(Ref, Val),
+ { functor(Val, Functor, Arity) }.
+
+:- pragma c_header_code("
+ /* ML_arg() is defined in std_util.m */
+ bool ML_arg(Word term_type_info, Word *term, Word argument_index,
+ Word *arg_type_info, Word **argument_ptr);
+").
+
+:- pragma c_code(arg_ref(Ref::in, ArgNum::in, ArgRef::out, S0::mdi, S::muo),
+ will_not_call_mercury,
+"{
+ Word arg_type_info;
+ Word* arg_ref;
+
+ save_transient_registers();
+
+ if (!ML_arg(TypeInfo_for_T, (Word *) Ref, ArgNum,
+ &arg_type_info, &arg_ref))
+ {
+ fatal_error(""tr_store__arg_ref: argument number out of range"");
+ }
+
+ if (ML_compare_type_info(arg_type_info, TypeInfo_for_ArgT) !=
+ COMPARE_EQUAL)
+ {
+ fatal_error(""tr_store__arg_ref: argument has wrong type"");
+ }
+
+ restore_transient_registers();
+
+ ArgRef = (Word) arg_ref;
+ S = S0;
+}").
+
+:- pragma c_code(new_arg_ref(Val::mdi, ArgNum::in, ArgRef::out, S0::mdi, S::muo),
+ will_not_call_mercury,
+"{
+ Word arg_type_info;
+ Word* arg_ref;
+
+ save_transient_registers();
+
+ if (!ML_arg(TypeInfo_for_T, (Word *) &Val, ArgNum,
+ &arg_type_info, &arg_ref))
+ {
+ fatal_error(""tr_store__new_arg_ref: argument number out of range"");
+ }
+
+ if (ML_compare_type_info(arg_type_info, TypeInfo_for_ArgT) !=
+ COMPARE_EQUAL)
+ {
+ fatal_error(""tr_store__new_arg_ref: argument has wrong type"");
+ }
+
+ restore_transient_registers();
+
+ /*
+ ** For no_tag types, the argument may have the same address as the
+ ** term. Since the term (Val) is currently on the C stack, we can't
+ ** return a pointer to it; so if that is the case, then we need
+ ** to copy it to the heap before returning.
+ */
+ if (arg_ref == &Val) {
+ incr_hp(ArgRef, 1);
+ *(Word *)ArgRef = Val;
+ } else {
+ ArgRef = (Word) arg_ref;
+ }
+ S = S0;
+}").
+
+:- pragma c_code(set_ref(Ref::in, ValRef::in, S0::mdi, S::muo),
+ will_not_call_mercury,
+"
+ MR_trail_current_value((Word *) Ref);
+ *(Word *)Ref = *(Word *)ValRef;
+ S = S0;
+").
+
+:- pragma c_code(set_ref_value(Ref::in, Val::mdi, S0::mdi, S::muo),
+ will_not_call_mercury,
+"
+ MR_trail_current_value((Word *) Ref);
+ *(Word *)Ref = Val;
+ S = S0;
+").
+
+:- pragma c_code(extract_ref_value(_S::mdi, Ref::in, Val::out),
+ will_not_call_mercury,
+"
+ Val = *(Word *)Ref;
+").
+
+%-----------------------------------------------------------------------------%
+
+:- pragma c_code(unsafe_arg_ref(Ref::in, Arg::in, ArgRef::out, S0::mdi, S::muo),
+ will_not_call_mercury,
+"{
+ /* unsafe - does not check type & arity, won't handle no_tag types */
+ Word *Ptr = (Word *) strip_tag(Ref);
+ ArgRef = (Word) &Ptr[Arg];
+ S = S0;
+}").
+
+:- pragma c_code(unsafe_new_arg_ref(Val::mdi, Arg::in, ArgRef::out,
+ S0::mdi, S::muo), will_not_call_mercury,
+"{
+ /* unsafe - does not check type & arity, won't handle no_tag types */
+ Word *Ptr = (Word *) strip_tag(Val);
+ ArgRef = (Word) &Ptr[Arg];
+ S = S0;
+}").
+
+%-----------------------------------------------------------------------------%
cvs diff: Diffing samples
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list