[m-rev.] global store implemented using typeclass

Fergus Henderson fjh at cs.mu.OZ.AU
Mon Aug 6 01:22:29 AEST 2001


On 23-Jul-2001, Holger Krug <hkrug at rationalizer.com> wrote:
> + % 07/17/01 hkrug at rationalizer.com:
> + %
> + %   `store' now works as well for declarative storage as also for
> + %   storage using the io__state
> + %   * `type store(S)' replaced by `typeclass store(S)'
> + %   * type `store(S)' in predicates replaced by typeclass constraint
> + %     `store(S)'
> + %   * instance declaration `instance store(io__state)' added
> + %   * public type `some_store_type' and unsafe obsolete predicate
> + %     `store__init/1' removed
> + %   
> + %   Changes are not backwards compatible:
> + %   * removed obsolete predicate `store__init/1' and type `some_store_type'
> + %   * type `store(S)' in predicate signatures have to be replaced by
> + %     typeclass constraint `<= store(S)'.
> + %
> + %   WARNING ! CHANGES 100% UNTESTED ! WARNING !

Those kind of comments, which in time will be of only historical interest,
belong in the CVS log message and/or the NEWS file rather than in the
interface documentation for the module.

Anyway, I figured out how to do this without breaking backwards compatibility.
Enclosed below is a diff against the current CVS sources.

So, I plan to commit the version below.

Comments?

----------

Estimated hours taken: 1
Branches: main

library/store.m:
	Apply a variation of changes suggested by Holger Krug
	<hkrug at rationalizer.com>: generalize the `store' module so that
	it works for storage using the io__state as well for storage
	using the store(S) type.

	This involved adding a new typeclass `store/1', new types
	`generic_mutvar/2' and `generic_ref/2', and generalizing all of the
	existing operations to use these new types and class constraints.

	For convenience, I also added new type synonyms `io_mutvar/1',
	`store_mutvar/2', `io_ref/1', and `store_ref/2'.

	For backwards compatibility, we define the old `mutvar/2' and
	`ref/2' to be `store_mutvar/2' and `store_ref/2'.  In some future
	version we should eliminate the definitions of mutvar/2 and
	ref/2 and rename generic_mutvar/2 and generic_ref/2 as mutvar/2
	and ref/2.

Workspace: /home/venus/fjh/ws-venus4/mercury
Index: library/store.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/store.m,v
retrieving revision 1.27
diff -u -d -r1.27 store.m
--- library/store.m	15 Mar 2001 07:42:26 -0000	1.27
+++ library/store.m	5 Aug 2001 15:18:16 -0000
@@ -28,15 +28,20 @@
 
 :- module store.
 :- interface.
+:- import_module io.
 
-% Stores and keys are indexed by a type S that is used to distinguish
-% between different stores.  By using an existential type declaration
-% for store__new (see below), we use the type system to ensure at
-% compile time that you never attempt to use a key from one store
-% to access a different store.
+% Stores and keys are indexed by a type S of typeclass store(S) that
+% is used to distinguish between different stores.  By using an
+% existential type declaration for store__new (see below), we use the
+% type system to ensure at compile time that you never attempt to use
+% a key from one store to access a different store.
 
+:- typeclass store(S).
 :- type store(S).
 
+:- instance store(io__state).
+:- instance store(store(S)).
+
 	% initialize a new store
 :- some [S] pred store__new(store(S)).
 :- mode          store__new(uo) is det.
@@ -46,21 +51,23 @@
 % mutvars
 %
 
-	% mutvar(T, S):
+	% generic_mutvar(T, S):
 	% a mutable variable holding a value of type T in store S
-:- type mutvar(T, S).
+:- type generic_mutvar(T, S).
+:- type io_mutvar(T) == generic_mutvar(T, io__state).
+:- type store_mutvar(T, S) == generic_mutvar(T, store(S)).
 
 	% create a new mutable variable,
 	% initialized with the specified value
-:- pred store__new_mutvar(T, mutvar(T, S), store(S), store(S)).
+:- pred store__new_mutvar(T, generic_mutvar(T, S), S, S) <= store(S).
 :- mode store__new_mutvar(in, out, di, uo) is det.
 
 	% lookup the value stored in a given mutable variable
-:- pred store__get_mutvar(mutvar(T, S), T, store(S), store(S)).
+:- pred store__get_mutvar(generic_mutvar(T, S), T, S, S) <= store(S).
 :- mode store__get_mutvar(in, out, di, uo) is det.
 
 	% replace the value stored in a given mutable variable
-:- pred store__set_mutvar(mutvar(T, S), T, store(S), store(S)).
+:- pred store__set_mutvar(generic_mutvar(T, S), T, S, S) <= store(S) .
 :- mode store__set_mutvar(in, in, di, uo) is det.
 
 	% new_cyclic_mutvar(Func, Mutvar):
@@ -80,8 +87,8 @@
 	%	init_cl(X, CList) -->
 	%	    store__new_cyclic_mutvar(func(CL) = node(X, CL), CList).
 	%
-:- pred store__new_cyclic_mutvar(func(mutvar(T, S)) = T, mutvar(T, S),
-		store(S), store(S)).
+:- pred store__new_cyclic_mutvar(func(generic_mutvar(T, S)) = T,
+		generic_mutvar(T, S), S, S) <= store(S).
 :- mode store__new_cyclic_mutvar(in, out, di, uo) is det.
 
 %-----------------------------------------------------------------------------%
@@ -89,9 +96,11 @@
 % references
 %
 
-	% ref(T, S):
+	% generic_ref(T, S):
 	% a reference to value of type T in store S
-:- type ref(T, S).
+:- type generic_ref(T, S).
+:- type io_ref(T, S) == generic_ref(T, io__state).
+:- type store_ref(T, S) == generic_ref(T, store(S)).
 
 	% new_ref(Val, Ref):	
 	%	/* In C: Ref = malloc(...); *Ref = Val; */
@@ -101,13 +110,14 @@
 	% 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 store__new_ref(T, ref(T, S), store(S), store(S)).
+:- pred store__new_ref(T, generic_ref(T, S), S, S) <= store(S).
 :- mode store__new_ref(di, out, di, uo) is det.
 
 	% ref_functor(Ref, Functor, Arity):
 	% Given a reference to a term, return the functor and arity
 	% of that term.
-:- pred store__ref_functor(ref(T, S), string, int, store(S), store(S)).
+:- pred store__ref_functor(generic_ref(T, S), string, int, S, S)
+		<= store(S).
 :- mode store__ref_functor(in, out, out, di, uo) is det.
 
 	% arg_ref(Ref, ArgNum, ArgRef):	     
@@ -117,7 +127,8 @@
 	% (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 store__arg_ref(ref(T, S), int, ref(ArgT, S), store(S), store(S)).
+:- pred store__arg_ref(generic_ref(T, S), int,
+		generic_ref(ArgT, S), S, S) <= store(S).
 :- mode store__arg_ref(in, in, out, di, uo) is det.
 
 	% new_arg_ref(Val, ArgNum, ArgRef):
@@ -126,7 +137,8 @@
 	% 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 store__new_arg_ref(T, int, ref(ArgT, S), store(S), store(S)).
+:- pred store__new_arg_ref(T, int, generic_ref(ArgT, S), S, S)
+		<= store(S).
 :- mode store__new_arg_ref(di, in, out, di, uo) is det.
 
 	% set_ref(Ref, ValueRef):
@@ -135,7 +147,8 @@
 	% 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 store__set_ref(ref(T, S), ref(T, S), store(S), store(S)).
+:- pred store__set_ref(generic_ref(T, S), generic_ref(T, S), S, S)
+		<= store(S).
 :- mode store__set_ref(in, in, di, uo) is det.
 
 	% set_ref_value(Ref, Value):
@@ -143,7 +156,7 @@
 	% 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.
-:- pred store__set_ref_value(ref(T, S), T, store(S), store(S)).
+:- pred store__set_ref_value(generic_ref(T, S), T, S, S) <= store(S).
 :- mode store__set_ref_value(in, di, di, uo) is det.
 
 	% Given a reference to a term, return that term.
@@ -151,12 +164,12 @@
 	% be inefficient if used to return large terms; it
 	% is most efficient with atomic terms.
 	% XXX current implementation buggy (does shallow copy)
-:- pred store__copy_ref_value(ref(T, S), T, store(S), store(S)).
+:- pred store__copy_ref_value(generic_ref(T, S), T, S, S) <= store(S).
 :- mode store__copy_ref_value(in, uo, di, uo) is det.
 
 	% Same as above, but without making a copy.
 	% Destroys the store.
-:- pred store__extract_ref_value(store(S), ref(T, S), T).
+:- pred store__extract_ref_value(S, generic_ref(T, S), T) <= store(S).
 :- mode store__extract_ref_value(di, in, out) is det.
 
 %-----------------------------------------------------------------------------%
@@ -181,16 +194,18 @@
 	% or if the argument is a `no_tag' type,
 	% then the behaviour is undefined, and probably harmful.
 
-:- pred store__unsafe_arg_ref(ref(T, S), int, ref(ArgT, S),
-				store(S), store(S)).
+:- pred store__unsafe_arg_ref(generic_ref(T, S), int, generic_ref(ArgT, S),
+		S, S) <= store(S).
 :- mode store__unsafe_arg_ref(in, in, out, di, uo) is det.
 
-:- pred store__unsafe_new_arg_ref(T, int, ref(ArgT, S), store(S), store(S)).
+:- pred store__unsafe_new_arg_ref(T, int, generic_ref(ArgT, S), S, S)
+		<= store(S).
 :- mode store__unsafe_new_arg_ref(di, in, out, di, uo) is det.
 
 %-----------------------------------------------------------------------------%
 %
-% Unsafe interfaces retained only for backwards compatibility
+% Interfaces retained only for backwards compatibility.
+% Some of these are unsafe.  All of them are deprecated.
 %
 
 	% OBSOLETE: use `S' or `some [S] ... S' instead.
@@ -202,19 +217,29 @@
 :- mode store__init(uo) is det.
 :- pragma obsolete(store__init/1).
 
+	% OBSOLETE: use store_mutvar/2 or generic_mutvar/2 instead.
+:- type mutvar(T, S) == store_mutvar(T, S).
+
+	% OBSOLETE: use store_mutvar/2 or generic_mutvar/2 instead.
+:- type ref(T, S) == store_ref(T, S).
+
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
 :- implementation.
 :- import_module std_util.
 
+:- typeclass store(T) where [].
+:- instance store(store(S)) where []. 
+:- instance store(io__state) where [].
+
 :- type some_store_type ---> some_store_type. 
 
 :- type store(S) ---> store(c_pointer).
 
-:- type mutvar(T, S) ---> mutvar(c_pointer).
+:- type generic_mutvar(T, S) ---> mutvar(c_pointer).
 
-:- type ref(T, S) ---> ref(c_pointer).
+:- type generic_ref(T, S) ---> ref(c_pointer).
 
 store__new(S) :-
 	store__do_init(S).
@@ -266,8 +291,8 @@
 	S = S0;
 ").
 
-:- pred store__unsafe_new_uninitialized_mutvar(mutvar(T, S),
-						store(S), store(S)).
+:- pred store__unsafe_new_uninitialized_mutvar(generic_mutvar(T, S),
+						S, S) <= store(S).
 :- mode store__unsafe_new_uninitialized_mutvar(out, di, uo) is det.
 
 :- pragma foreign_proc("C", unsafe_new_uninitialized_mutvar(Mutvar::out, S0::di, S::uo),
@@ -300,7 +325,7 @@
 	% refers to, without making a copy; it is unsafe because
 	% the store could later be modified, changing the returned
 	% value.
-:- pred store__unsafe_ref_value(ref(T, S), T, store(S), store(S)).
+:- pred store__unsafe_ref_value(generic_ref(T, S), T, S, S) <= store(S).
 :- mode store__unsafe_ref_value(in, uo, di, uo) is det.
 :- pragma foreign_proc("C", unsafe_ref_value(Ref::in, Val::uo, S0::di, S::uo),
 		will_not_call_mercury,

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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