10-Jan-2013 09:45, H. S. Teoh пишет:
On Thu, Jan 10, 2013 at 04:51:35AM +0100, Timon Gehr wrote:
On Wednesday, 9 January 2013 at 18:45:56 UTC, H. S. Teoh wrote:
[...]
Whoa!!! Now you really caught my interest!

Can it handle CTFE-computed mixins that declare and reference
variables?  If it can, I will finally be able to write a library AA
implementation that allows static AA literals (no runtime
init/allocation needed)!

Probably yes, but I am not sure what you mean. Can you provide an
example?

The basic idea behind static AA literals is to use CTFE to compute the
hashes of the keys, and therefore which slot(s) they will fall in, at
compile time.

Why not try to make an AA literal a universal entity for all kinds of user-defined associative arrays? Then the actual construction of AA is done via constructor taking some type like AALiteral!(Key, Value) which is a sequence of Key, Value pairs. It could be even presorted.

Armed with this information, we can create an array of
slots at compile-time that contains the AA entries by declaring each
slot as a static variable and using the slot assignment information to
initialize the hash table (array of pointers to slots) to point to these
slots.

Now, there are some challenges to be overcome here. For example, the
slots need to be declared as local variables, and therefore need unique
names (the hash table array needs to be able to refer to the addresses
of these variables), so the only way I can think of to do this at
compile-time is to have the CTFE code generate mixins to declare those
variables. So here's the tricky part. Suppose you have this CTFE code:

        // Not the real code, just a rough sketch to give the idea
        string aaComputeAASlots(K,V)(K[V] aaLiteral) {
                // Create slots
                string slotVars;
                foreach (key, value; aaLiteral) {
                        size_t slotNum = hashOf(key) % numKeys;
                        string slotName = "aaSlot" ~ slotNum;
                        slotVars ~= "immutable Slot " ~ slotName ~
                                " = Slot(" ~ key ~ ", " ~ value ~ ");";
                }

                string mainTable = q{
                        immutable Slot*[] aaTable = {
                                &aaSlot0,
                                &aaSlot1,
                                ... // generate these programmatically
                        };
                };

                return slotVars ~ mainTable;
        }

        // Instantiate AA here, at compile time.
        mixin(aaComputeAASlots(myLiteral));

The mixin string would look something like this:

        "immutable Slot aaSlot0 = Slot(..., ...);
         immutable Slot aaSlot1 = Slot(..., ...);
         immutable Slot*[] aaTable = {
                &aaSlot0, &aaSlot1, ...
         }"

The question is, will the compile be able to resolve &aaSlot0, &aaSlot1,
etc., at compile-time?

Obviously, this code works if you copy-n-paste it into a .d source file.
It also works if I write it as a string literal, then use mixin().
However, on DMD, if the string is returned by a CTFE function that
builds it using ~, for some reason all the pointers in aaTable are null.
Strangely enough, if I assign the returned string to a string variable
and print it out at runtime, the correct string is produced.


Seems like a bug.

So I concluded that somehow, DMD was unable to correctly interpret
&aaSlot0 inside a mixin string at compile-time.


--
Dmitry Olshansky

Reply via email to