[m-rev.] New library module: table.m

Ralph Becket rafe at cs.mu.OZ.AU
Wed Jan 22 17:22:46 AEDT 2003


Fergus Henderson, Tuesday, 21 January 2003:
> On 21-Jan-2003, Ralph Becket <rafe at cs.mu.OZ.AU> wrote:
> > +table(Xss @ [Xs | _]) =
> > +    ( if 
> > +        M = length(Xss),
> > +        N = length(Xs),
> > +        all [Ys] ( member(Ys, Xss) => length(Ys) = N ),
> > +      then
> 
> Syntax error (delete the "," on the second-last line above).
> 
> Also, you didn't post the updated `.exp' file for the test case.
> Could you please repost an updated full diff?

Okay, I've also applied s/table/array2d/g throughout.

Here's the full diff:

Index: compiler/modules.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.259
diff -u -r1.259 modules.m
--- compiler/modules.m	14 Jan 2003 16:42:28 -0000	1.259
+++ compiler/modules.m	22 Jan 2003 06:09:00 -0000
@@ -758,6 +758,7 @@
 	mercury_std_library_module(Name).
 
 mercury_std_library_module("array").
+mercury_std_library_module("array2d").
 mercury_std_library_module("assoc_list").
 mercury_std_library_module("bag").
 mercury_std_library_module("benchmarking").
Index: library/array2d.m
===================================================================
RCS file: library/array2d.m
diff -N library/array2d.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ library/array2d.m	22 Jan 2003 06:06:42 -0000
@@ -0,0 +1,197 @@
+%-----------------------------------------------------------------------------%
+% array2d.m
+% Ralph Becket <rafe at cs.mu.oz.au>
+% Wed Jan 15 15:17:11 EST 2003
+% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
+%
+% Two-dimensional rectangular (i.e. not ragged) array ADT.
+%
+% XXX The same caveats re: uniqueness of arrays apply to array2ds.
+%
+%-----------------------------------------------------------------------------%
+
+:- module array2d.
+
+:- interface.
+
+:- import_module int, array, list.
+
+
+
+    % A array2d is a two-dimensional array stored in row-major order
+    % (that is, the elements of the first row in left-to-right
+    % order, followed by the elements of the second row and so forth.)
+    %
+:- type array2d(T).
+
+:- inst array2d ---> array2d(ground, ground, array).
+
+    % XXX These are work-arounds until we get nested uniqueness working.
+    %
+:- mode array2d_di == di(array2d).
+:- mode array2d_ui == in(array2d).
+:- mode array2d_uo == out(array2d).
+
+
+
+
+    % array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]]) constructs a array2d
+    % of size M * N, with the special case that bounds(array2d([]), 0, 0).
+    %
+    % An exception is thrown if the sublists are not all the same length.
+    %
+:- func array2d(list(list(T))) = array2d(T).
+:- mode array2d(in           ) = array2d_uo is det.
+
+    % new(M, N, X) = array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]])
+    % where each XIJ = X.  An exception is thrown if M < 0 or N < 0.
+    %
+:- func new(int, int, T ) = array2d(T).
+:- mode new(in,  in,  in) = array2d_uo is det.
+
+    % array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]]) ^ elem(I, J) = X
+    % where X is the J+1th element of the I+1th row (that is, indices
+    % start from zero.)
+    %
+    % An exception is thrown unless 0 =< I < M, 0 =< J < N.
+    %
+:- func array2d(T) ^ elem(int, int) = T.
+:- mode array2d_ui ^ elem(in,  in ) = out is det.
+:- mode in       ^ elem(in,  in ) = out is det.
+
+    % T ^ unsafe_elem(I, J) is the same as T ^ elem(I, J) except that
+    % behaviour is undefined if not in_bounds(T, I, J).
+    %
+:- func array2d(T) ^ unsafe_elem(int, int) = T.
+:- mode array2d_ui ^ unsafe_elem(in,  in ) = out is det.
+:- mode in       ^ unsafe_elem(in,  in ) = out is det.
+
+    % ( T0 ^ elem(I, J) := X ) = T
+    % where T ^ elem(II, JJ) = X                 if I = II, J = JJ
+    % and   T ^ elem(II, JJ) = T0 ^ elem(II, JJ) otherwise.
+    %
+    % An exception is thrown unless 0 =< I < M, 0 =< J < N.
+    %
+:- func ( array2d(T) ^ elem(int, int) := T  ) = array2d(T).
+:- mode ( array2d_di ^ elem(in,  in)  := in ) = array2d_uo is det.
+
+    % T ^ unsafe_elem(I, J) := X is the same as T ^ elem(I, J) := X except
+    % that behaviour is undefined if not in_bounds(T, I, J).
+    %
+:- func ( array2d(T) ^ unsafe_elem(int, int) := T  ) = array2d(T).
+:- mode ( array2d_di ^ unsafe_elem(in,  in)  := in ) = array2d_uo is det.
+
+    % bounds(array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]), M, N)
+    %
+:- pred bounds(array2d(T), int, int).
+:- mode bounds(array2d_ui, out, out) is det.
+:- mode bounds(in,       out, out) is det.
+
+    % in_bounds(array2d([[X11, ..., X1N], ..., [XM1, ..., XMN]), I, J)
+    % succeeds iff 0 =< I < M, 0 =< J < N.
+    %
+:- pred in_bounds(array2d(T), int, int).
+:- mode in_bounds(array2d_ui, in,  in ) is semidet.
+:- mode in_bounds(in,       in,  in ) is semidet.
+
+    % lists(array2d([[X11, ..., X1N], ..., [XM1, ..., XMN])) =
+    %     [[X11, ..., X1N], ..., [XM1, ..., XMN]]
+    %
+:- func lists(array2d(T)) = list(list(T)).
+:- mode lists(array2d_ui) = out is det.
+:- mode lists(in      ) = out is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module array, require, std_util.
+
+
+
+    % array2d(Rows, Cols, Array)
+    %
+:- type array2d(T) ---> array2d(int, int, array(T)).
+
+%-----------------------------------------------------------------------------%
+
+array2d(      []      ) = array2d(0, 0, make_empty_array).
+
+array2d(Xss @ [Xs | _]) =
+    ( if 
+        M = length(Xss),
+        N = length(Xs),
+        all [Ys] ( member(Ys, Xss) => length(Ys) = N )
+      then
+        array2d(M, N, array(condense(Xss)))
+      else
+        func_error("array2d.array2d/1: non-rectangular list of lists")
+    ).
+
+%-----------------------------------------------------------------------------%
+
+new(M, N, X) =
+    ( if   M >= 0, N >= 0
+      then array2d(M, N, array.init(M * N, X))
+      else func_error("array2d.new: bounds must be non-negative")
+    ).
+
+%-----------------------------------------------------------------------------%
+
+bounds(array2d(M, N, _A), M, N).
+
+%-----------------------------------------------------------------------------%
+
+in_bounds(array2d(M, N, _A), I, J) :-
+    0 =< I, I < M,
+    0 =< J, J < N.
+
+%-----------------------------------------------------------------------------%
+
+T ^ elem(I, J) =
+    ( if   in_bounds(T, I, J)
+      then T ^ unsafe_elem(I, J)
+      else func_error("array2d.elem: indices out of bounds")
+    ).
+
+%-----------------------------------------------------------------------------%
+
+array2d(_M, N, A) ^ unsafe_elem(I, J) = A ^ elem(I * N + J).
+
+%-----------------------------------------------------------------------------%
+
+( T ^ elem(I, J) := X ) =
+    ( if   in_bounds(T, I, J)
+      then T ^ unsafe_elem(I, J) := X
+      else func_error("array2d.'elem :=': indices out of bounds")
+    ).
+
+%-----------------------------------------------------------------------------%
+
+( array2d(M, N, A) ^ unsafe_elem(I, J) := X ) = 
+    array2d(M, N, A ^ elem(I * N + J) := X).
+
+%-----------------------------------------------------------------------------%
+
+lists(array2d(M, N, A)) = lists_2((M * N) - 1, N - 1, N, A, [], []).
+
+
+:- func lists_2(int, int, int, array(T), list(T), list(list(T))) =
+            list(list(T)).
+:- mode lists_2(in,  in,  in,  array_ui, in,      in           ) = out is det.
+:- mode lists_2(in,  in,  in,  in,       in,      in           ) = out is det.
+
+lists_2(IJ, J, N, A, Xs, Xss) =
+    ( if 0 =< IJ then
+        ( if 0 =< J then
+            lists_2(IJ - 1, J - 1, N, A, [A ^ elem(IJ) | Xs], Xss       )
+          else
+            lists_2(IJ,     N - 1, N, A, [],                  [Xs | Xss])
+        )
+      else
+        [Xs | Xss]
+    ).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
Index: library/library.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/library.m,v
retrieving revision 1.64
diff -u -r1.64 library.m
--- library/library.m	14 Jun 2002 10:18:49 -0000	1.64
+++ library/library.m	22 Jan 2003 06:08:16 -0000
@@ -30,7 +30,7 @@
 % Please keep both parts of this list in alphabetical order.
 
 % The modules intended for application programmers.
-:- import_module array, assoc_list, bag, benchmarking.
+:- import_module array, array2d, assoc_list, bag, benchmarking.
 :- import_module bimap, bintree, bintree_set, bitmap, bool, bt_array, builtin.
 :- import_module char, construct, counter, deconstruct, dir.
 :- import_module enum, eqvclass, exception.
Index: tests/hard_coded/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/hard_coded/Mmakefile,v
retrieving revision 1.182
diff -u -r1.182 Mmakefile
--- tests/hard_coded/Mmakefile	17 Jan 2003 05:57:04 -0000	1.182
+++ tests/hard_coded/Mmakefile	22 Jan 2003 06:07:48 -0000
@@ -141,6 +141,7 @@
 	term_to_univ_test \
 	test_bitset \
 	test_imported_no_tag \
+	test_array2d \
 	tim_qual1 \
 	time_test \
 	tuple_test \
Index: tests/hard_coded/test_array2d.exp
===================================================================
RCS file: tests/hard_coded/test_array2d.exp
diff -N tests/hard_coded/test_array2d.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/test_array2d.exp	22 Jan 2003 06:21:49 -0000
@@ -0,0 +1,35 @@
+Empty =
+[[]]
+
+One =
+[[1]]
+One ^ elem(0, 0) = 1
+
+Two =
+[[1, 0]
+ [0, 2]]
+Two ^ elem(0, 0) = 1
+Two ^ elem(0, 1) = 0
+Two ^ elem(1, 0) = 0
+Two ^ elem(1, 1) = 2
+
+Two_a =
+[[1, 3]
+ [0, 2]]
+
+Two_b =
+[[1, 3]
+ [4, 2]]
+
+Zeroes =
+[[0, 0, 0]
+ [0, 0, 0]
+ [0, 0, 0]]
+
+Empty ^ elem(0, 0) = exception(univ_cons(software_error("array2d.elem: indices out of bounds")))
+Zeroes ^ elem(-1, 0) = exception(univ_cons(software_error("array2d.elem: indices out of bounds")))
+Zeroes ^ elem(0, -1) = exception(univ_cons(software_error("array2d.elem: indices out of bounds")))
+Zeroes ^ elem(-1, -1) = exception(univ_cons(software_error("array2d.elem: indices out of bounds")))
+Zeroes ^ elem(3, 0) = exception(univ_cons(software_error("array2d.elem: indices out of bounds")))
+Zeroes ^ elem(0, 3) = exception(univ_cons(software_error("array2d.elem: indices out of bounds")))
+Zeroes ^ elem(3, 3) = exception(univ_cons(software_error("array2d.elem: indices out of bounds")))
Index: tests/hard_coded/test_array2d.m
===================================================================
RCS file: tests/hard_coded/test_array2d.m
diff -N tests/hard_coded/test_array2d.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/hard_coded/test_array2d.m	22 Jan 2003 06:21:04 -0000
@@ -0,0 +1,102 @@
+%-----------------------------------------------------------------------------%
+% test_array2d.m
+% Ralph Becket <rafe at cs.mu.oz.au>
+% Tue Jan 21 12:38:05 EST 2003
+% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
+%
+%-----------------------------------------------------------------------------%
+
+:- module test_array2d.
+
+:- interface.
+
+:- import_module io.
+
+
+
+:- pred main(io::di, io::uo) is cc_multi.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module int, list, string, array2d, pprint, exception.
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+
+    Empty = array2d([]) `with_type` array2d(int),
+    write_array2d("Empty", Empty, !IO),
+    io.nl(!IO),
+
+    One   = array2d([[1]]),
+    write_array2d("One", One, !IO),
+    write_array2d_elem("One", One, 0, 0, !IO),
+    io.nl(!IO),
+
+    Two   = array2d([[1, 0], [0, 2]]),
+    write_array2d("Two", Two, !IO),
+    write_array2d_elem("Two", Two, 0, 0, !IO),
+    write_array2d_elem("Two", Two, 0, 1, !IO),
+    write_array2d_elem("Two", Two, 1, 0, !IO),
+    write_array2d_elem("Two", Two, 1, 1, !IO),
+    io.nl(!IO),
+
+    Two_a = Two ^ elem(0, 1) := 3,
+    write_array2d("Two_a", Two_a, !IO),
+    io.nl(!IO),
+
+    Two_b = Two_a ^ elem(1, 0) := 4,
+    write_array2d("Two_b", Two_b, !IO),
+    io.nl(!IO),
+
+    Zeroes = array2d.new(3, 3, 0),
+    write_array2d("Zeroes", Zeroes, !IO),
+    io.nl(!IO),
+
+    write_array2d_elem("Empty",  Empty,   0,  0, !IO),
+    write_array2d_elem("Zeroes", Zeroes, -1,  0, !IO),
+    write_array2d_elem("Zeroes", Zeroes,  0, -1, !IO),
+    write_array2d_elem("Zeroes", Zeroes, -1, -1, !IO),
+    write_array2d_elem("Zeroes", Zeroes,  3,  0, !IO),
+    write_array2d_elem("Zeroes", Zeroes,  0,  3, !IO),
+    write_array2d_elem("Zeroes", Zeroes,  3,  3, !IO),
+
+    true.
+
+%-----------------------------------------------------------------------------%
+
+:- pred write_array2d(string, array2d(T), io, io).
+:- mode write_array2d(in,     array2d_ui, di, uo) is det.
+
+write_array2d(Name, Table, !IO) :-
+    io.format("%s =\n%s\n", [s(Name), s(string(Table))], !IO).
+
+%-----------------------------------------------------------------------------%
+
+:- pred write_array2d_elem(string, array2d(T), int, int, io, io).
+:- mode write_array2d_elem(in,     array2d_ui, in,  in,  di, uo) is cc_multi.
+
+write_array2d_elem(Name, Table, I, J, !IO) :-
+    io.format("%s ^ elem(%d, %d) = ", [s(Name), i(I), i(J)], !IO),
+    try((pred(X::out) is det :- X = Table ^ elem(I, J)), Result),
+    (
+        Result = succeeded(Y),
+        io.print(Y, !IO)
+    ;
+        Result = exception(_),
+        io.print(Result, !IO)
+    ),
+    io.nl(!IO).
+
+%-----------------------------------------------------------------------------%
+
+:- func string(array2d(T)) = string.
+:- mode string(array2d_ui) = out is det.
+
+string(T) = to_string(80, brackets(nest(1, separated(to_doc, line, lists(T))))).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%

--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list