[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