[m-rev.] For review: tidy up lazy.m

Ralph Becket rafe at csse.unimelb.edu.au
Mon May 11 12:36:24 AEST 2009


Estimated hours taken: 0.2
Branches: main

extras/lazy_evaluation/lazy.m:
	Conform to current layout conventions.
	Remove function modes (they're not needed these days).
	Update closure cells with value cells, rather than new closures
	returning the previously computed result.

Index: lazy.m
===================================================================
RCS file: /home/mercury1/repository/mercury/extras/lazy_evaluation/lazy.m,v
retrieving revision 1.3
diff -u -r1.3 lazy.m
--- lazy.m	28 Jul 2006 05:31:02 -0000	1.3
+++ lazy.m	11 May 2009 02:24:56 -0000
@@ -1,5 +1,7 @@
+%---------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
 %-----------------------------------------------------------------------------%
-% Copyright (C) 1999, 2006 The University of Melbourne.
+% Copyright (C) 1999, 2006, 2009 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.
 %-----------------------------------------------------------------------------%
@@ -27,35 +29,35 @@
 :- module lazy.
 :- interface.
 
-% A lazy(T) is a value of type T which will only be evaluated on demand.
+    % A lazy(T) is a value of type T which will only be evaluated on
+    % demand.
+    %
 :- type lazy(T).
 
-% :- inst lazy(I).  % abstract
-:- inst lazy == lazy(ground).
-
-% Convert a value from type T to lazy(T)
+    % Convert a value from type T to lazy(T)
+    %
 :- func val(T) = lazy(T).
-:- mode val(in) = out(lazy) is det.
 
-% Construct a lazily-evaluated lazy(T) from a closure
+    % Construct a lazily-evaluated lazy(T) from a closure
+    %
 :- func delay((func) = T) = lazy(T).
-:- mode delay((func) = out is det) = out(lazy) is det.
 
-% Force the evaluation of a lazy(T), and return the result as type T.
-% Note that if the type T may itself contains subterms of type lazy(T),
-% as is the case when T is a recursive type like the lazy_list(T) type
-% defined in lazy_list.m, those subterms will not be evaluated --
-% force/1 only forces evaluation of the lazy/1 term at the top level.
+    % Force the evaluation of a lazy(T), and return the result as type T.
+    % Note that if the type T may itself contains subterms of type lazy(T),
+    % as is the case when T is a recursive type like the lazy_list(T) type
+    % defined in lazy_list.m, those subterms will not be evaluated --
+    % force/1 only forces evaluation of the lazy/1 term at the top level.
+    %
 :- func force(lazy(T)) = T.
-:- mode force(in(lazy)) = out is det.
 
+%-----------------------------------------------------------------------------%
 %
 % The declarative semantics of the above constructs are given by the
 % following equations:
 %
-%	val(X) = delay((func) = X).
+%   val(X) = delay((func) = X).
 %
-%	force(delay(F)) = apply(F).
+%   force(delay(F)) = apply(F).
 %
 % The operational semantics satisfy the following:
 %
@@ -75,90 +77,74 @@
 %   is O(the time to evaluate (X1 = force(X)) + the time to evaluate
 %   (Y1 = force(Y)) + the time to unify X1 and Y1).
 %
-% -----------------------------------------------------------------------------%
-
-% The following may be needed occaisionally, in case
-% the compiler can't infer the right higher-order inst...
-% It just returns its argument, cast to the correct inst.
-:- func inst_cast(lazy(T)) = lazy(T).
-:- mode inst_cast(in) = out(lazy) is det.
+%-----------------------------------------------------------------------------%
 
 %-----------------------------------------------------------------------------%
 
 :- implementation.
 :- interface.
 
-% implementation details
-:- inst lazy(I) ---> value(I) ; closure((func) = out(I) is det).
-
 :- implementation.
 
-% Note that we use a user-defined equality predicate to ensure
-% that unifying two lazy(T) values will do the right thing.
+    % Note that we use a user-defined equality predicate to ensure
+    % that unifying two lazy(T) values will do the right thing.
+    %
 :- type lazy(T) ---> value(T) ; closure((func) = T)
-	where equality is equal_values.
+    where equality is equal_values.
 
-:- pred equal_values(lazy(T), lazy(T)).
-:- mode equal_values(in, in) is semidet.
-equal_values(X, Y) :-
-	force(inst_cast(X)) = force(inst_cast(Y)).
+:- pred equal_values(lazy(T)::in, lazy(T)::in) is semidet.
 
-:- pragma c_code(inst_cast(F::in) = (F2::out(lazy)),
-	[will_not_call_mercury, thread_safe], "F2 = F;").
+equal_values(X, Y) :-
+    force(X) = force(Y).
 
 %-----------------------------------------------------------------------------%
 
 val(X) = value(X).
 delay(F) = closure(F).
 
-% If the compiler were to evaluate calls to delay/1 at compile time,
-% it could put the resulting closure/1 term in read-only memory,
-% which would make destructively updating it rather dangerous.
-% So we'd better not let the compiler inline delay/1.
+    % If the compiler were to evaluate calls to delay/1 at compile time,
+    % it could put the resulting closure/1 term in read-only memory,
+    % which would make destructively updating it rather dangerous.
+    % So we'd better not let the compiler inline delay/1.
+    %
 :- pragma no_inline(delay/1).
 
 %-----------------------------------------------------------------------------%
 
-% The call to promise_only_solution is needed to tell the
-% compiler that force will return equal answers given
-% arguments that are equal but that have different representations.
-force(Lazy) = promise_only_solution(do_force(Lazy)).
-
-:- pred do_force(lazy(T), T).
-:- mode do_force(in(lazy), out) is cc_multi.
-
-% The pragma promise_pure is needed to tell the compiler that
-% do_force is pure, even though it calls impure code.
-:- pragma promise_pure(do_force/2).
-
-do_force(Lazy, Value) :-
-	(	
-		Lazy = value(Value)
-	;
-		Lazy = closure(Func),
-		Value = apply(Func),
-
-		% Destructively update the closure with a new
-		% closure that immediately returns the same value,
-		% to avoid having to recompute the same result
-		% next time.
-		NewFunc = ((func) = Result :- Result = Value),
-		impure update_closure(Lazy, NewFunc)
-	).
-
-:- impure pred update_closure(T1, T2).
-:-        mode update_closure(in, in) is det.
+    % The promise_equivalent_solutions scope is needed to tell the compiler
+    % that force will return equal answers given arguments that are equal
+    % but that have different representations.
+    %
+force(Lazy) = Value :-
+    promise_pure (
+        promise_equivalent_solutions [Value]
+        (
+            Lazy = value(Value)
+        ;
+            Lazy = closure(Func),
+            Value = apply(Func),
+
+                % Destructively update the Lazy cell with the value
+                % to avoid having to recompute the same result
+                % next time.
+                %
+            impure update_in_place(Lazy, value(Value))
+        )
+    ).
+
+    % Note that the implementation of this impure predicate relies on
+    % some details of the Mercury implementation.
+    %
+:- impure pred update_in_place(lazy(T)::in, lazy(T)::in) is det.
 
-% Note that the implementation of this impure predicate relies on
-% some details of the Mercury implementation.
 :- pragma foreign_proc("C", 
-	update_closure(MercuryTerm::in, NewValue::in),
-	[will_not_call_mercury],
+    update_in_place(HeapCell::in, NewValue::in),
+    [will_not_call_mercury],
 "
-	/* strip off tag bits */
-	Word *ptr = (Word *) MR_strip_tag(MercuryTerm);
-	/* destructively update value */
-	*ptr = NewValue;
+    /* strip off tag bits */
+    Word *ptr = (Word *) MR_strip_tag(HeapCell);
+    /* destructively update value */
+    *ptr = NewValue;
 ").
 
 %-----------------------------------------------------------------------------%
--------------------------------------------------------------------------
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