DeRailed DSL (was Re: compile-time regex redux)
Bill Baxter
dnewsgroup at billbaxter.com
Fri Feb 9 17:56:12 PST 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Tom S wrote:
>> Therefore, I'd like to see a case when a compile-time DSL processing
>> is going to be really useful in the real world, as to provoke further
>> complication of the compiler and its usage patterns.
>
> I can't parse this sentence. Did you mean "as opposed to provoking"
> instead of "as to provoke"?
I think he just meant he wants to see some real world examples that
justify the additional complexity that will be added to the compiler and
language.
>> The other aspect I observed in the discussions following the new dmd
>> release, is that folks are suggesting writing full language parsers, D
>> preprocessors and various sort of operations on complex languages,
>> notably extended-D parsing... This may sound weird in my lips, but
>> that's clearly abuse. What these people really want is a way to extend
>> the language's syntax, pretty much as Nemerle does it. And frankly, if
>> D is going to be a more powerful language, built-in text preprocessing
>> won't cut it. Full fledged macro support and syntax extension
>> mechanics are something that we should look at.
>
> This is a misunderstanding. The syntax is not to be extended. It stays
> fixed, and that is arguably a good thing. The semantics become more
> flexible. For example, they will make it easy to write a matrix operation:
>
> A = (I - B) * C + D
>
> and generate highly performant code from it. (There are many reasons for
> which that's way harder than it looks.)
This is one thing I haven't really understood in the discussion. How do
the current proposals help that case? From what I'm getting you're
going to have to write every statement like the above as something like:
mixin {
ProcessMatrixExpr!( "A = (I - B) * C + D;" );
}
How do you get from this mixin/string processing stuff to an API that I
might actually be willing to use for common operations?
> I think there is a lot of apprehension and misunderstanding surrounding
> what metacode is able and supposed to do or simplify. Please, let's
> focus on understanding _before_ forming an opinion.
I think that's exactly what Tom's getting at. He's asking for examples
of how this would make like better for him and others. I think given
your background you take it for granted that metaprogramming is the
future. But D is attracts folks from all kinds of walks of life,
because it promises to be a kinder, gentler C++. So some people here
aren't even sure why D needs templates at all. Fortran doesn't have 'em
after all. And Java just barely does.
Anyway, I think it would help get everyone on board if some specific and
useful examples were given of how this solves real problems (and no I
don't really consider black and white holes as solving real problems. I
couldn't even find any non-astronomical uses of the terms in a google
search.)
For instance, it would be nice to see some more concrete discussion about
* the "rails" case.
* the X = A*B + C matrix/vector expressions case.
* the case of generating bindings to scripting langauges / ORB stubs
* the Spirit/parser generator case
So here's my take on vector expressions since that's the only one I know
anything about.
*Problem statement*:
Make the expression A=(I-B)*C+D efficient, where the variables are large
vectors (I'll leave out matrices for now).
*Why it's hard*:
The difficulty is that (ignoring SSE instruction etc) the most efficient
way to compute that is do all operations component-wise. So instead of
computing I-B then multiplying by C, you compute
A[i] = (I[i]-B[i])*C[i]+D[i];
for each i. This eliminates the need to allocate large intermediate
vectors.
*Existing solutions*:
Expression templates in C++, e.g. The Blitz++ library. Instead of
making opSub in I-B return a new Vector object, you make opSub return an
ExpressionTemplate object. This is a little template struct that
contains a reference to I and to B, and knows how to subtract the two in
a component-wise manner. The types of I and B are template parameters,
LeftT and RightT. Its interface also allows it to be treated just like a
Vector. You can add a vector to it, subtract a Vector from it etc.
Now we go and try to multiply that result times C. The result of that
is a new MultExpressionTemplate with two paramters, the LeftT being our
previous SubExpressionTemplate!(Vector,Vector) and the RightT being Vector.
Proceeding on in this way eventually the result of the math is of type:
AddExpressionTemplate!(
MultExpressionTemplate!(
SubExpressionTemplate!(Vector,Vector),
Vector),
Vector)
And you can see that we basically have a parse tree expressed as nested
templates. The final trick is that a Vector.opAssign that takes an
ExpressionTemplate is provided and that method calls a method of the
expression template to finally trigger the calculation, like
expr.eval(this). eval() has the top-level loop over the components of
the answer.
*Why Existing solutions are insufficient*
For that all that effort to actually be useful the compiler has to be
pretty agressive about inlining everything so that in the end all the
temporary template structs and function calls go away and you're just
left with one eval call. It can be tricky to get the code into just the
right configuration so that the compiler will do the inlining. And even
then results will depend on the quality of the compiler. My attempts
using MSVC++ several years ago always came out to be slower than the
naive version, but with about 10x the amount of code. The code is also
pretty difficult to follow because of all those different types of
expression templates that have to be created.
If you include matrices things are even trickier because there are
special cases like "A*B+a*C" that can be computed efficiently by a
single optimized routine. You'd like to recognize such cases and turn
them into single calls to that fast routine. You might also want to
recognize "A*B+C" as a special case of that with a==1.
*How it could be improved*:
??? this is what I'd like to see explained better.
--bb
More information about the Digitalmars-d
mailing list