[mercury-users] full and empty lists

Fergus Henderson fjh at cs.mu.OZ.AU
Mon Jan 21 16:05:47 AEDT 2002


On 16-Jan-2002, Dave Slutzkin <dave_slutzkin at yahoo.com> wrote:
> And indeed I do...  Except in this case:
> 
> :- func last_event(timeline::ne_tl_in) = (event::out) is det.
> 
> ...
> 	Timeline^next = [_|_] ,   % of type timeline
> 	E = last_event(Timeline^next) ,
> ...
> 
> Which gives me mode errors.  When changed to:
> 
> ...
> 	Temp = Timeline^next ,
> 	Temp = [_|_] ,
> 	E = last_event(Temp) ,
> ...
> 
> it works perfectly.

Right.  (Though I'd suggest using a more informative name, e.g. `Next',
rather than `Temp'.)

> So this mode inference doesn't work completely with field access functions? 
> Is this a bug or something not yet implemented?  Or is it something I've
> failed to understand...

The distinction is between variables and non-variables.
It's nothing specific to field access functions;
it's the same for all function calls.

For example, if you had written

	:- func foo(...) = ...
	...
	:- func last_event(timeline::ne_tl_in) = (event::out) is det.
	...
		foo(TimeLine) = [_|_] ,   % of type timeline
		E = last_event(foo(TimeLine)) ,
		...

then you'd get the same kind of error.

The reason is that mode analysis keeps track of the binding of each
variable, but it doesn't do common sub-expression elimination.
So if you use the same sub-expression (such as `foo(TimeLine)'
or `TimeLine^next') twice, and there's a unification which binds
the first occurrence, then mode analysis won't know that it also
restricts the values of the second occurrence.

So, why doesn't the mode checker do CSE first, I hear you ask?
Doing common sub-expression elimination before mode analysis would
be problematic, because CSE doesn't preserve uniqueness.
For example, if you have

	:- func foo(...) = ...
	:- mode foo(...) = uo.

	:- pred destroy(..., ..., ...).
	:- mode destroy(di, ..., ...).

	...
		destroy(foo(X), 1, Y1),
		destroy(foo(X), 2, Y2),

then it would NOT be OK to eliminate the common sub-expression foo(X)
by rewriting this as

		FooX = foo(X),
		destroy(FooX, 1, Y1),
		destroy(FooX, 2, Y2),

because the first call to destroy/3 might clobber FooX, and so it's not
OK to pass the same variable to the second call to destroy/3.

-- 
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-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list