On Thursday, 10 January 2013 at 05:47:01 UTC, H. S. Teoh wrote:
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. 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.

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


T

Reply via email to