On Oct 30, 2021, at 2:44 PM, John Rose <john.r.r...@oracle.com<mailto:john.r.r...@oracle.com>> wrote:
its own avowed language feature And, full disclosure, besides pass-by-name I see two other language features that could be distinguished from the current design, whether or not they ever appear separately (as I hope pass-by-name/autoquote will some day appear, for expression tree processing more than loggers). 2. Reified argument types: There is a nifty way that javac captures the static types of the “hole” arguments of the template and makes them available, in case the template processor would find it useful. (This is not reified type arguments, but could be a building block.) This happens also for many uses of method handles and invokedynamic, but always “under the covers”. This is the first time static argument types have been reified as part of an API design. Perhaps that deserves some pathfinding discussion at this point. Perhaps string templates intrinsically “own the turf” of reifying static argument types, but I don’t see this yet; I think they have a natural “ask” for reified types, but *are not alone*. If S.T.s are an early customer of such things, it would be wise to take a breath and think ahead, to other customers, if possible aligning the way S.T.s do it from the first with some set of likely futures. 3. Static validation: This is a biggie. We want a hook that allows (though does not require) a S.T. provider to validate a string template, once for each distinct context. What is the static context? Well, in x."y\{z}" that would be at least the string containing y plus (see above) the static type of z, plus something derived from x. Plus maybe—I hope—an indy-like context, so that the validation logic has the option (but not requirement) to look up the stack for permission checks. Plus, probably, the entire contents of x (which is not static if x is a proper variable!). I call it “static” validation because clearly we want to play out the validation logic the first time some given context is evaluated, but we don’t want to replay it for later evaluations in the same context. The string is clearly constant as are the static types of the arguments. The rest is not so clearly constant, so the prototype uses some tricks with MutableCallSite to make the evaluation mostly static. I think this needs scrutiny, and I would also like to consider other ways (without appealing to an MCS) to gain the required static evaluation hooks. Some of the use cases defer static validation until a database connection is opened and an SQL idiom is determined. In the more problematic case, the validation is not static because the database connection is not a constant, and the idiom may vary from call to call. The best you can do in such a circumstance is a cache. A MCS is the wrong tool in that circumstance; it is best to allow the SQL template designer to create whatever cache is most appropriate to the expected set of SQL idioms. The ST provider, per se, will in this case do minimal checking, or none at all, in its “static validation” hook. In any case, I think SQL idiom validation is very far from the central use case to design around. I think format strings and regular expressions are much more likely as use cases, and those have truly static validation stories that make sense. They may require static types to do the best job, but much validation can be done without argument types as well. Clearly, the design will succeed for regular expressions if and only if Pattern.compile can be executed reliably once before the first evaluation of the template as a whole. To me this suggests that we should be thinking about what it means to execute a “static hook” for an expression, which prepares for the subsequent execution of a method call that finishes the call. Maybe this is just a design pattern, but there is evidence that it needs language support. The language support come in when the compiler separates arguments meant only for the static hook from arguments used to finish the whole expression evaluation. It would seem that we need a notion of “static arguments” as opposed to regular “dynamic arguments”, for expressions that have a “static hook”. I don’t want to dilute the S.T. discussion any more than I already have, so I’ll just say that S.T.’s have static arguments that are (a) the string itself with holes marked and (b) maybe the argument types for the expressions for those holes. I suggest that, until we roll out more of the machinery we intend to roll out, such as type classes, that we restrict the operand x (the receiver LHS of the S.T.) to be a statically constant expression. If we do that, then we can hand three things to a bootstrap method that can do static validation: 1. the (constant) receiver 2. the string body (with holes marked) 3. maybe the static types of the arguments (this is very natural for indy) If we allow the receiver to vary dynamically, we have boxed ourselves into a corner, regarding validation. By “constant x” I simply mean the name of a static final field. There are not many other reference-valued expressions which are “constant” enough to permit static validation. This would give us a story for validation from day one (using indy) and would also preserve room to grow to more complex receivers, though not all at once. If we roll out a story for constant folding, the set of possible x naturally grows, without further trouble. And when we roll out type classes, then we can (again without much more trouble) support non-constant “x” receivers, if their type is able to nominate the appropriate S.T. handler witness. In this I am assuming that witnesses will always be constants relative to a given request for a witness. The Parametric VM design provides a way to do this even when the witnessed type is a type parameter.