[m-rev.] for review: convert parse trees to strings

Julien Fischer jfischer at opturion.com
Wed Nov 1 16:08:49 AEDT 2023


On Tue, 31 Oct 2023, Zoltan Somogyi wrote:

> The diff adds the typeclass constraint "pt_output(S, U)"
> to many predicates in the compiler. To avoid losing efficiency,
> we want to created versions of those predicates specialized
> to their current use case (where S is an output stream,
> and U is the I/O state), and their intended new use case
> (where U is string.builder.state, and S is the corresponding handle).
> 
> Unfortunately, adding two type_spec pragmas to every predicate
> with that constraint has two problems. First, it is tedious, and
> second, if any predicate is missed either now or later as new
> predicates are added, we lose the benefit of specialization
> in the affected part of the call tree. (This is already an issue
> in files such as library/term_io.m.)

This kind of what we might call templatey specialisation is an issue
beyond the compiler, see for example my mercury_json library.

> I therefore propose a new pragma that asks for the specialization
> of all predicates and functions in a module that have a specified
> typeclass constraint. The intended two examples would be
>
>     :- pragma type_spec_constrained_preds(pt_output(S, U),
>         [S = io.text_output_stream, U = io.state]).
>     :- pragma type_spec_constrained_preds(pt_output(S, U),
>         [S = string.builder.handle, U = string.builder.state]).

No objection from me, other than perhaps the name. For that
I suggest type_constraint_spec.

> The internal representation of this pragma would record the name
> of the module in which the pragma appears. (This would happen regardless
> of whether it appears in a .m or in a .intN file.) The compiler would
> then apply the type specialization described by the second arg
> to all predicates and functions in that module that have the
> type constraint in the first arg.

So it only applies to a single module?

> That typeclass constraint would be required to have the form of
> a typeclass name applied to one or more type variables. There are two ways
> we could go on how we determine which predicates and functions have that
> type constraint. The typeclass name would obviously have to match,
> but we could either
> 
> - require that the names of the type variables match as well, or
> - apply type specification regardless of whether the names of the
>   type variables match.
> 
> I plan to do whichever of these the current code for type_spec pragmas does,
> because
> 
> - consistency is important,
> - whatever the current code does has obviously worked well enough, and
> - it would be easier to implement :-)

For the sake of robustness, I suggest doing the second.  Users may have
perfectly valid reasons for renaming the type variables on the constraints
on predicates or functions.

> I do intend to *find out* which of the two options above the current
> code implements, and explicitly document that choice for both the old
> and new pragmas.
> 
> The syntax of the second argument above intentionally differs from
> the syntax of the existing pragma. The syntax of the type_spec pragma
> accepts two kinds of substitution specifications. One is a substitution
> for a single type variable, like this:
>
>     :- pragma type_spec(pred(subset/2), T = var(_)).
> 
> The other is for a substitution for two or more type variables, like this:
>
>     :- pragma type_spec(pred(format_quoted_char/4),
>         (Stream = string.builder.handle, State = string.builder.state)).
> 
> Basically, if you want to specify a substitution for more than one variable,
> you have to put parentheses around their conjunction.
> 
> I think putting all the variable substitutions in a list, regardless
> of whether there is only one or not, is simpler, which is why the new
> pragma examples above use that syntax. My preferred course of action
> would be to
> 
> - implement the new pragma with the syntax requiring all substitutions
>   be in a list,
> 
> - change the implementation of the old type_spec pragma to *allow*
>   all substitutions being in a list, and then
> 
> - recommend that people use the new syntax from now on.

Agreed.  The list syntax is also consistent with the vast majority of
other pragmas in the language.

> We *could* deprecate and eventually stop supporting the old syntax,

We should deprecate and eventually stop supporting it.  (But it doesn't
have to be soon.)

> but I don' see much to be gained by that course of action.

- not having to maintain the code that supports to the old syntax.
- potentially not confusing users, by having two syntaxes.

Julien.


More information about the reviews mailing list