[m-users.] Using type constructors in predicate heads

Zoltan Somogyi zoltan.somogyi at runbox.com
Mon Nov 8 00:35:29 AEDT 2021


2021-11-07 20:50 GMT+11:00 "Sean Charles (emacstheviking)" <objitsu at gmail.com>:
> An additional change I had to make, seeking explanation! I think I know why but just would like to fully understand… here is the predicate that is calling the do_gencall predicate, note that the type of Term is an snode...
> 
> :- pred translate_all_terms(renderer, lsnode, tcon, tcon).
> :- mode translate_all_terms(renderer, in, in, out) is det.
> 
> translate_all_terms(_, [], !_T).
> 
> translate_all_terms(R, [ Term | Terms ], !T) :-
>     TPos = snpos(Term),
>     ( if Term = sexp(Spos, [ tk(Tpos,F) | Args ]) then
>         (
>             is_illegal_inst(F)
>         ->
>             syntax.error(TPos, top_level_form_required, !T)
>         ;
>             (
>                 bifmap(F, _Inst)
>             ->
>                 % FELT function call
>                 syntax.error(TPos, msg("this is a felt call"), !T)
>             ;
>                 do_gencall(0, R,
>                     sexp(Spos, [tk(Tpos,F) | Args ]),  % <— the change!
>                     !T)
> 		% it was: do_gencall(0, R, Term, !T),

The reason why "the change!" is needed is that when mode analysis
processes the condition of the top if-then-else, what it sees is NOT
"Term = sexp(Spos, [tk(Tpos, F) | Args])". Instead, what it sees is the
decomposition of that unification into simpler unifications, which each contain
at most one function symbol. In this case, that would mean something like
Term = sexp(Spos, Locns), Locns = [HeadLocn | Args], HeadLocn = tk(Tpos, F).
The parser transforms all unifications, both explicit and implicit, in the source code
into this form, which we call superhomogeneous form, because it makes the
job of pretty much all compiler passes much easier.

The one undesirable consequence of using superhomogeneous form
is that when mode analysis looks at Locns = [HeadLocns | Args], it will record
the fact that Locns is a nonempty list in Locns' inst, but this fact will not thereby
propagate to the insts of the variables whose values *contain* Locns,
such as Term; their insts will remain what they were. In this case, that means
that Term's inst will remain ground, resulting in the error message you quoted.

Once upon a time, we did try to modify mode analysis to keep track of these
relationships, precisely to allow e.g. Term's inst to be updated when Locns's
inst was updated, but this turned out to be a bad idea for two reasons.
It required a great deal of housekeeping code, and it slowed down mode
analysis by an unacceptable amount (as in: its execution time grew to be larger
than the execution time of the rest of the compiler).

Zoltan.


More information about the users mailing list