September 20, 2021

On 9/20/21 2:11 AM, Kagamin wrote:

>

On Sunday, 19 September 2021 at 11:55:04 UTC, Steven Schveighoffer wrote:

>

On 9/19/21 1:43 AM, Stefan Koch wrote:

>

What do you guys think?

I think an easier fix is just to change the call that does the AA literals to something that can be CTFEd. Right now it's an extern(C) hook that is opaque and takes void[] and TypeInfos.

Something like:

V[K] __aALiteral(V, K)(K[] keys, V[] values);

Then just lower the call to that, and if that is CTFEable, it works.

Isn't that already kinda possible?
A quick example:

struct StaticHashTable(TKey,TValue)
{
     struct Pair { TKey key, TValue value }
     Pair[] items;
     inout(TValue) opIndex(in TKey key) pure inout
     {
         foreach(i;items)if(i.key==key)return i.value;
         assert(false);
     }
}

StaticHashTable!(TKey,TValue) make(TKey,TValue)(in TValue[TKey] aa) pure
{
     StaticHashTable!(TKey,TValue) s;
     s.items.length=8;
     s.items[0].key="a";
     s.items[0].value=aa["a"];
     return s;
}

immutable s=make(["a":"b","c":"d"]);
static assert(s["a"]=="b");

That is, you can serialize a hashtable into anything with a relatively easy syntax.

A StaticHashTable is not a builtin AA. The idea is to allow AAs to be generated at compile time, and then moved into usable runtime AAs.

One thing that is horrific, but possible, is to generate something like:

struct FakeAA(K, V)
{
    // mimic the true AA impl
    struct FakeBucket {
        size_t hash;
        void * entry;
    }
    struct FakeAAImpl
    {
        FakeBucket[] buckets;
        uint used;
        uint deleted;
        TypeInfo_Struct entryTI;
        uint firstUsed;
        immutable uint keysz;
        immutable uint valsz;
        immutable uint valoff;
        ubyte flags;
    }
    FakeAAImpl *impl;
    V[K] __get() { return *(cast(V[K]*)&impl); }
    alias __get this;
}

And then build that thing at compile time based on the CTFE AA.

But I would still like to see the AA static initializer "just work".

-Steve

September 20, 2021

On 9/20/21 8:54 AM, Stefan Koch wrote:

>

On Monday, 20 September 2021 at 12:38:59 UTC, Steven Schveighoffer wrote:

>

On 9/19/21 9:38 AM, Stefan Koch wrote:

> > >

Also it introduces yet more templates, I cannot cache templates as effectively as I can runtime which I only have to generate once.

Only one template per AA type.

But that would be an interpreted/or some day JITed function call that has to do the hashing of the values and place them into the right buckets.
Which would be a different function per instance.

Whereas currently the only thing that has to be interpreted is the toHash function.
and it only has to be called once per element.

There exist ways to abstract out parts of templates that are the same for every instance.

What would have to happen is that the AA code would have to either be duplicated (or mostly duplicated), or made publicly accessible to the compiler.

-Steve

September 20, 2021

On 9/19/21 10:10 AM, Stefan Koch wrote:

>

On Sunday, 19 September 2021 at 11:39:15 UTC, pineapple wrote:

>

This could be nice. It's always been kind of annoying having to put AAs in static initializers and not being able to inspect them at compile time.

Be careful though.
The runtime does not know if an array is in static memory or not.
(Though it would be trivial to add a flag so it knows.)
And Therefore when you do this:

static mutable_ct_createdAA = mixin(["a","b"]);

and you mutate that array in any way.
The runtime will crash.
As it tries write into memory it is not supposed to write in.

How do statically initialized mutable dynamic arrays work? Should be the same thing.

-Steve

September 20, 2021

On Monday, 20 September 2021 at 13:02:22 UTC, Steven Schveighoffer wrote:

>
struct FakeAA(K, V)
{
    // mimic the true AA impl
    struct FakeBucket {
        size_t hash;
        void * entry;
    }
    struct FakeAAImpl
    {
        FakeBucket[] buckets;
        uint used;
        uint deleted;
        TypeInfo_Struct entryTI;
        uint firstUsed;
        immutable uint keysz;
        immutable uint valsz;
        immutable uint valoff;
        ubyte flags;
    }
    FakeAAImpl *impl;
    V[K] __get() { return *(cast(V[K]*)&impl); }
    alias __get this;
}

And then build that thing at compile time based on the CTFE AA.

But I would still like to see the AA static initializer "just work".

-Steve

In fact that is exactly what my implementation of AA literals does.
just that it does that internally to the "static initializer generation code"
except for evaluation of the hash-function it has nothing to do with CTFE ;)

And by the by that is exactly how all generation of static initalizers work.
They build up "fake" runtime structures and hope that the structures match the layout used at runtime.

Which is why cross-compilation is still a pain.

September 20, 2021

On Monday, 20 September 2021 at 13:08:53 UTC, Steven Schveighoffer wrote:

>

On 9/19/21 10:10 AM, Stefan Koch wrote:

>

On Sunday, 19 September 2021 at 11:39:15 UTC, pineapple wrote:

>

This could be nice. It's always been kind of annoying having to put AAs in static initializers and not being able to inspect them at compile time.

Be careful though.
The runtime does not know if an array is in static memory or not.
(Though it would be trivial to add a flag so it knows.)
And Therefore when you do this:

static mutable_ct_createdAA = mixin(["a","b"]);

and you mutate that array in any way.
The runtime will crash.
As it tries write into memory it is not supposed to write in.

How do statically initialized mutable dynamic arrays work? Should be the same thing.

-Steve

I just had a look to what druntime does.
writing into statically allocated memory is fine as long as it's allocated writable.
Which means assigning to a mutable array is fine.
And the only time when an array has to reallocate is on appending in shrinking.
At which point it is copied. Which is the same for statically allocated and dynamically allocated arrays.

However for an AA assigning to an index. may pr may not reallocate them.
which is why we would have to put a guard into the assignment code as well.

1 2
Next ›   Last »