www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - checking if template arg is literal, possible ER for compiler change


disclaimer: please, ignore compiler inlining abilities while you are
reading this post. i'll give some reasoning later.

let's imagine that we have such function:

  void putPixel (int x, int y, uint color) {
    if ((color&0xff) =3D=3D 0) {
      // replace pixel
    } else if ((color&0xff) !=3D 0xff) {
      // do color blending
    } // and do nothing for transparent pixels

and it's often calling like this: `putPixel(x, y, Color.White);` (or
another color constant). `Color.White` is not transparent.

but why we should do all the checks if we know the argument value at
compile time? it would be wonderful if we'll be able to do something
like this:

  void putPixel() (int x, int y, uint color) {
    static if (isLiteralArg!color) {
      static if ((literalArgValue!color&0xff) =3D=3D 0) {
        // replace pixel
      } else static if ((literalArgValue!color&0xff) !=3D 0xff) {
        // do color blending with code
        // optimised for the given color
      } // and do nothing for transparent pixels
    } else {
      if ((color&0xff) =3D=3D 0) {
        // replace pixel
      } else if ((color&0xff) !=3D 0xff) {
        // do color blending
      } // and do nothing for transparent pixels

i named new traits `isLiteralArg` and `literalArgValue` here. yes, we
see code duplication here, but this is another story. what is important
is that we can generate specialised versions of `putPixel` based on
argument value which is known in compile time.

sure, for easy cases like this we can rely on compiler inlining
abilities. yet inlining may fail without warning (having warning about
failing inlines is nice, but this is completely different story).

and what is much more important is that we can specialise `putPixel`
with known color value. we can, for example, generate different code
for different opacities and so on.

we can introduce range checking for `x` and `y` and omit that if we
know their values at compile time.

the thing is that we have "controlled inlining" here without resorting
to something like this:

  void putPixel(alias x, alias y, alias color) ()
  if (isIntegral!(typeof(x)) && isIntegral!(typeof(y)) &&
    static if (!is(color)) {
      // color is literal
    } else {
      // color is not known in compile time

besides looking ugly with all those `isIntegral!` checks, which makes
signature unreadable, we now forced to call it like
`putPixel!(x, y, c);` instead of `putPixel(x, y, c);`.
ah, and compiler error messages are not really readable in this case.

what i want to say here is that having a way to check if *function*
args for templated function are literals (and get their values) can be
useful for various patterns of compile-time code generation and
parameterization without resorting to ugly signatures and unnatural
"bang calling".

this can break template instantiation though, as we cannot assume that
template with identical argument types will instantiate to identical
functions, but i don't think that this is of great importance: compiler
can do AST comparisons on various instances later.

this will change some instantiated function signatures too, as they now
will depend of literal arguments. so it will be wise to do this only
for templates that explicitly used `isLiteralArg` and `literalArgValue`

this seems to be a not-so-small change of compiler internals, so i want
to know if i'm completely insane here or there are more people that see
a sane practical value in such feature.
Jan 08 2015