[m-rev.] diff: more support for folds over version_arrays
Julien Fischer
juliensf at csse.unimelb.edu.au
Thu Nov 18 17:51:12 AEDT 2010
Branches: main
Improve support for folds over version arrays.
library/version_array.m:
Add foldl2, foldr, and foldr2.
Re-arrange C declarations in this module so that those
with static linkage are not written out to the .mh file.
s/int/MR_bool/ in a few spots.
NEWS:
Announce the new predicates.
Julien.
Index: NEWS
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/NEWS,v
retrieving revision 1.544
diff -u -r1.544 NEWS
--- NEWS 18 Nov 2010 04:12:10 -0000 1.544
+++ NEWS 18 Nov 2010 06:45:25 -0000
@@ -50,6 +50,9 @@
+ The predicates array.foldr/4 and array.foldr2/6 have been added.
+* We have added the predicates version_array.foldl2/6, version_array.foldr/4,
+ and version_array.foldr2/6 to the standard library.
+
Changes to the Mercury compiler:
* Support for building and linking against frameworks on Mac OS X has
Index: library/version_array.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/version_array.m,v
retrieving revision 1.30
diff -u -r1.30 version_array.m
--- library/version_array.m 9 Nov 2010 03:46:32 -0000 1.30
+++ library/version_array.m 18 Nov 2010 06:45:25 -0000
@@ -138,10 +138,49 @@
:- mode foldl(pred(in, in, out) is semidet, in, in, out) is semidet.
:- mode foldl(pred(in, mdi, muo) is semidet, in, mdi, muo) is semidet.
:- mode foldl(pred(in, di, uo) is semidet, in, di, uo) is semidet.
+
+ % foldl2(P, A, !Acc1, !Acc2) is equivalent to
+ % list.foldl2(P, list(A), !Acc1, !Acc2) but more efficient.
+ %
+:- pred foldl2(pred(T1, T2, T2, T3, T3), version_array(T1), T2, T2, T3, T3).
+:- mode foldl2(pred(in, in, out, in, out) is det, in, in, out, in, out)
+ is det.
+:- mode foldl2(pred(in, in, out, mdi, muo) is det, in, in, out, mdi, muo)
+ is det.
+:- mode foldl2(pred(in, in, out, di, uo) is det, in, in, out, di, uo)
+ is det.
+:- mode foldl2(pred(in, in, out, in, out) is semidet, in,
+ in, out, in, out) is semidet.
+:- mode foldl2(pred(in, in, out, mdi, muo) is semidet, in,
+ in, out, mdi, muo) is semidet.
+:- mode foldl2(pred(in, in, out, di, uo) is semidet, in,
+ in, out, di, uo) is semidet.
% foldr(F, A, X) is equivalent to list.foldr(F, list(A), Xs).
%
:- func foldr(func(T1, T2) = T2, version_array(T1), T2) = T2.
+
+:- pred foldr(pred(T1, T2, T2), version_array(T1), T2, T2).
+:- mode foldr(pred(in, in, out) is det, in, in, out) is det.
+:- mode foldr(pred(in, mdi, muo) is det, in, mdi, muo) is det.
+:- mode foldr(pred(in, di, uo) is det, in, di, uo) is det.
+:- mode foldr(pred(in, in, out) is semidet, in, in, out) is semidet.
+:- mode foldr(pred(in, mdi, muo) is semidet, in, mdi, muo) is semidet.
+:- mode foldr(pred(in, di, uo) is semidet, in, di, uo) is semidet.
+
+:- pred foldr2(pred(T1, T2, T2, T3, T3), version_array(T1), T2, T2, T3, T3).
+:- mode foldr2(pred(in, in, out, in, out) is det, in, in, out, in, out)
+ is det.
+:- mode foldr2(pred(in, in, out, mdi, muo) is det, in, in, out, mdi, muo)
+ is det.
+:- mode foldr2(pred(in, in, out, di, uo) is det, in, in, out, di, uo)
+ is det.
+:- mode foldr2(pred(in, in, out, in, out) is semidet, in,
+ in, out, in, out) is semidet.
+:- mode foldr2(pred(in, in, out, mdi, muo) is semidet, in,
+ in, out, mdi, muo) is semidet.
+:- mode foldr2(pred(in, in, out, di, uo) is semidet, in,
+ in, out, di, uo) is semidet.
% copy(A) is a copy of array A. Access to the copy is O(1).
%
@@ -228,49 +267,132 @@
%-----------------------------------------------------------------------------%
-foldl(F, VA, Acc) = foldl_2(F, VA, Acc, 0, size(VA)).
+foldl(F, VA, Acc) = do_foldl_func(F, VA, Acc, 0, size(VA)).
-:- func foldl_2(func(T1, T2) = T2, version_array(T1), T2, int, int) = T2.
+:- func do_foldl_func(func(T1, T2) = T2, version_array(T1), T2, int, int) = T2.
-foldl_2(F, VA, Acc, Lo, Hi) =
- ( if Lo < Hi then foldl_2(F, VA, F(VA ^ elem(Lo), Acc), Lo + 1, Hi)
+do_foldl_func(F, VA, Acc, Lo, Hi) =
+ ( if Lo < Hi then do_foldl_func(F, VA, F(VA ^ elem(Lo), Acc), Lo + 1, Hi)
else Acc
).
%-----------------------------------------------------------------------------%
foldl(P, VA, !Acc) :-
- foldl_2(P, VA, 0, size(VA), !Acc).
+ do_foldl_pred(P, VA, 0, size(VA), !Acc).
-:- pred foldl_2(pred(T1, T2, T2), version_array(T1), int, int, T2, T2).
-:- mode foldl_2(pred(in, in, out) is det, in, in, in, in, out) is det.
-:- mode foldl_2(pred(in, mdi, muo) is det, in, in, in, mdi, muo) is det.
-:- mode foldl_2(pred(in, di, uo) is det, in, in, in, di, uo) is det.
-:- mode foldl_2(pred(in, in, out) is semidet, in, in, in, in, out) is semidet.
-:- mode foldl_2(pred(in, mdi, muo) is semidet, in, in, in, mdi, muo) is semidet.
-:- mode foldl_2(pred(in, di, uo) is semidet, in, in, in, di, uo) is semidet.
+:- pred do_foldl_pred(pred(T1, T2, T2), version_array(T1), int, int, T2, T2).
+:- mode do_foldl_pred(pred(in, in, out) is det, in, in, in, in, out) is det.
+:- mode do_foldl_pred(pred(in, mdi, muo) is det, in, in, in, mdi, muo) is det.
+:- mode do_foldl_pred(pred(in, di, uo) is det, in, in, in, di, uo) is det.
+:- mode do_foldl_pred(pred(in, in, out) is semidet, in, in, in, in, out)
+ is semidet.
+:- mode do_foldl_pred(pred(in, mdi, muo) is semidet, in, in, in, mdi, muo)
+ is semidet.
+:- mode do_foldl_pred(pred(in, di, uo) is semidet, in, in, in, di, uo)
+ is semidet.
-foldl_2(P, VA, Lo, Hi, !Acc) :-
+do_foldl_pred(P, VA, Lo, Hi, !Acc) :-
( if Lo < Hi then
P(VA ^ elem(Lo), !Acc),
- foldl_2(P, VA, Lo + 1, Hi, !Acc)
+ do_foldl_pred(P, VA, Lo + 1, Hi, !Acc)
else
true
).
%-----------------------------------------------------------------------------%
-foldr(F, VA, Acc) = foldr_2(F, VA, Acc, size(VA) - 1).
+foldl2(P, VA, !Acc1, !Acc2) :-
+ do_foldl2(P, VA, 0, size(VA), !Acc1, !Acc2).
+
+:- pred do_foldl2(pred(T1, T2, T2, T3, T3), version_array(T1), int, int,
+ T2, T2, T3, T3).
+:- mode do_foldl2(pred(in, in, out, in, out) is det, in, in, in,
+ in, out, in, out) is det.
+:- mode do_foldl2(pred(in, in, out, mdi, muo) is det, in, in, in,
+ in, out, mdi, muo) is det.
+:- mode do_foldl2(pred(in, in, out, di, uo) is det, in, in, in,
+ in, out, di, uo) is det.
+:- mode do_foldl2(pred(in, in, out, in, out) is semidet, in, in, in,
+ in, out, in, out) is semidet.
+:- mode do_foldl2(pred(in, in, out, mdi, muo) is semidet, in, in, in,
+ in, out, mdi, muo) is semidet.
+:- mode do_foldl2(pred(in, in, out, di, uo) is semidet, in, in, in,
+ in, out, di, uo) is semidet.
+
+do_foldl2(P, VA, Lo, Hi, !Acc1, !Acc2) :-
+ ( if Lo < Hi then
+ P(VA ^ elem(Lo), !Acc1, !Acc2),
+ do_foldl2(P, VA, Lo + 1, Hi, !Acc1, !Acc2)
+ else
+ true
+ ).
+
+%-----------------------------------------------------------------------------%
-:- func foldr_2(func(T1, T2) = T2, version_array(T1), T2, int) = T2.
+foldr(F, VA, Acc) = do_foldr_func(F, VA, Acc, version_array.max(VA)).
-foldr_2(F, VA, Acc, Hi) =
- ( if 0 =< Hi then foldr_2(F, VA, F(VA ^ elem(Hi), Acc), Hi - 1)
+:- func do_foldr_func(func(T1, T2) = T2, version_array(T1), T2, int) = T2.
+
+do_foldr_func(F, VA, Acc, Hi) =
+ ( if 0 =< Hi then do_foldr_func(F, VA, F(VA ^ elem(Hi), Acc), Hi - 1)
else Acc
).
%-----------------------------------------------------------------------------%
+foldr(P, VA, !Acc) :-
+ do_foldr_pred(P, VA, version_array.max(VA), !Acc).
+
+:- pred do_foldr_pred(pred(T1, T2, T2), version_array(T1), int, T2, T2).
+:- mode do_foldr_pred(pred(in, in, out) is det, in, in, in, out) is det.
+:- mode do_foldr_pred(pred(in, mdi, muo) is det, in, in, mdi, muo) is det.
+:- mode do_foldr_pred(pred(in, di, uo) is det, in, in, di, uo) is det.
+:- mode do_foldr_pred(pred(in, in, out) is semidet, in, in, in, out)
+ is semidet.
+:- mode do_foldr_pred(pred(in, mdi, muo) is semidet, in, in, mdi, muo)
+ is semidet.
+:- mode do_foldr_pred(pred(in, di, uo) is semidet, in, in, di, uo)
+ is semidet.
+
+do_foldr_pred(P, VA, I, !Acc) :-
+ ( if I >= 0 then
+ P(VA ^ elem(I), !Acc),
+ do_foldr_pred(P, VA, I - 1, !Acc)
+ else
+ true
+ ).
+
+%-----------------------------------------------------------------------------%
+
+foldr2(P, VA, !Acc1, !Acc2) :-
+ do_foldr2(P, VA, version_array.max(VA), !Acc1, !Acc2).
+
+:- pred do_foldr2(pred(T1, T2, T2, T3, T3), version_array(T1), int,
+ T2, T2, T3, T3).
+:- mode do_foldr2(pred(in, in, out, in, out) is det, in, in,
+ in, out, in, out) is det.
+:- mode do_foldr2(pred(in, in, out, mdi, muo) is det, in, in,
+ in, out, mdi, muo) is det.
+:- mode do_foldr2(pred(in, in, out, di, uo) is det, in, in,
+ in, out, di, uo) is det.
+:- mode do_foldr2(pred(in, in, out, in, out) is semidet, in, in,
+ in, out, in, out) is semidet.
+:- mode do_foldr2(pred(in, in, out, mdi, muo) is semidet, in, in,
+ in, out, mdi, muo) is semidet.
+:- mode do_foldr2(pred(in, in, out, di, uo) is semidet, in, in,
+ in, out, di, uo) is semidet.
+
+do_foldr2(P, VA, I, !Acc1, !Acc2) :-
+ ( if I >= 0 then
+ P(VA ^ elem(I), !Acc1, !Acc2),
+ do_foldr2(P, VA, I - 1, !Acc1, !Acc2)
+ else
+ true
+ ).
+
+%-----------------------------------------------------------------------------%
+
unsafe_rewind(VA, unsafe_rewind(VA)).
%-----------------------------------------------------------------------------%
@@ -654,13 +776,13 @@
").
:- pragma foreign_decl("C", "
- /*
- ** If index is -1 then value is undefined and rest is the latest
- ** array value.
- **
- ** Otherwise value is the overwritten value at index and rest is
- ** a pointer to the next version in the chain.
- */
+/*
+** If index is -1 then value is undefined and rest is the latest
+** array value.
+**
+** Otherwise value is the overwritten value at index and rest is
+** a pointer to the next version in the chain.
+*/
typedef struct ML_va *ML_va_ptr;
@@ -676,57 +798,98 @@
#endif
};
- /*
- ** Returns a pointer to the latest version of the array.
- */
-extern ML_va_ptr ML_va_get_latest(ML_va_ptr VA);
-
- /*
- ** Returns the number of items in a version array.
- */
-extern MR_Integer ML_va_size_dolock(ML_va_ptr);
-static MR_Integer ML_va_size(ML_va_ptr);
-
- /*
- ** If I is in range then ML_va_get(VA, I, &X) sets X to the Ith item
- ** in VA (counting from zero) and returns MR_TRUE. Otherwise it
- ** returns MR_FALSE.
- */
-extern int ML_va_get_dolock(ML_va_ptr, MR_Integer, MR_Word *);
-static int ML_va_get(ML_va_ptr VA, MR_Integer I, MR_Word *Xptr);
-
- /*
- ** If I is in range then ML_va_set(VA0, I, X, VA) sets VA to be VA0
- ** updated with the Ith item as X (counting from zero) and
- ** returns MR_TRUE. Otherwise it returns MR_FALSE.
- */
-extern int ML_va_set_dolock(ML_va_ptr, MR_Integer, MR_Word,
- ML_va_ptr *);
-static int ML_va_set(ML_va_ptr, MR_Integer, MR_Word, ML_va_ptr *);
-
- /*
- ** Create a copy of VA0 as a new array.
- */
-static ML_va_ptr ML_va_flat_copy(const ML_va_ptr VA0);
-
- /*
- ** Update the array VA using the override values in VA0
- ** i.e. recreate the state of the version array as captured in VA0.
- */
-static void ML_va_rewind_into(ML_va_ptr VA, const ML_va_ptr VA0);
-
- /*
- ** `Rewinds' a version array, invalidating all extant successors
- ** including the argument.
- */
-extern ML_va_ptr ML_va_rewind_dolock(ML_va_ptr);
-static ML_va_ptr ML_va_rewind(ML_va_ptr VA);
-
- /*
- ** Resize a version array.
- */
-extern ML_va_ptr ML_va_resize_dolock(ML_va_ptr, MR_Integer, MR_Word);
-static ML_va_ptr ML_va_resize(ML_va_ptr, MR_Integer, MR_Word);
+/*
+** Returns a pointer to the latest version of the array.
+*/
+extern ML_va_ptr
+ML_va_get_latest(ML_va_ptr VA);
+
+/*
+** Returns the number of items in a version array.
+*/
+extern MR_Integer
+ML_va_size_dolock(ML_va_ptr);
+
+/*
+** If I is in range then ML_va_get(VA, I, &X) sets X to the Ith item
+** in VA (counting from zero) and returns MR_TRUE. Otherwise it
+** returns MR_FALSE.
+*/
+extern MR_bool
+ML_va_get_dolock(ML_va_ptr, MR_Integer, MR_Word *);
+
+/*
+** If I is in range then ML_va_set(VA0, I, X, VA) sets VA to be VA0
+** updated with the Ith item as X (counting from zero) and
+** returns MR_TRUE. Otherwise it returns MR_FALSE.
+*/
+extern MR_bool
+ML_va_set_dolock(ML_va_ptr, MR_Integer, MR_Word, ML_va_ptr *);
+
+/*
+** `Rewinds' a version array, invalidating all extant successors
+** including the argument.
+*/
+extern ML_va_ptr
+ML_va_rewind_dolock(ML_va_ptr);
+
+/*
+** Resize a version array.
+*/
+extern ML_va_ptr
+ML_va_resize_dolock(ML_va_ptr, MR_Integer, MR_Word);
+
+").
+
+:- pragma foreign_decl("C", local, "
+
+/*
+** Returns the number of items in a version array.
+*/
+static MR_Integer
+ML_va_size(ML_va_ptr);
+
+/*
+** If I is in range then ML_va_get(VA, I, &X) sets X to the Ith item
+** in VA (counting from zero) and returns MR_TRUE. Otherwise it
+** returns MR_FALSE.
+*/
+static MR_bool
+ML_va_get(ML_va_ptr VA, MR_Integer I, MR_Word *Xptr);
+
+/*
+** If I is in range then ML_va_set(VA0, I, X, VA) sets VA to be VA0
+** updated with the Ith item as X (counting from zero) and
+** returns MR_TRUE. Otherwise it returns MR_FALSE.
+*/
+static MR_bool
+ML_va_set(ML_va_ptr, MR_Integer, MR_Word, ML_va_ptr *);
+
+/*
+** Create a copy of VA0 as a new array.
+*/
+static ML_va_ptr
+ML_va_flat_copy(const ML_va_ptr VA0);
+
+/*
+** Update the array VA using the override values in VA0
+** i.e. recreate the state of the version array as captured in VA0.
+*/
+static void
+ML_va_rewind_into(ML_va_ptr VA, const ML_va_ptr VA0);
+
+/*
+** `Rewinds' a version array, invalidating all extant successors
+** including the argument.
+*/
+static ML_va_ptr
+ML_va_rewind(ML_va_ptr VA);
+
+/*
+** Resize a version array.
+*/
+static ML_va_ptr
+ML_va_resize(ML_va_ptr, MR_Integer, MR_Word);
").
@@ -1581,4 +1744,5 @@
").
%-----------------------------------------------------------------------------%
+:- end_module version_array.
%-----------------------------------------------------------------------------%
--------------------------------------------------------------------------
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