Thread overview
Compile time initialization of AA
Mar 23, 2018
Xavier Bigand
Mar 23, 2018
Ali Çehreli
Mar 23, 2018
Seb
Mar 24, 2018
Patrick Schluter
Mar 24, 2018
Xavier Bigand
March 23, 2018
I am trying to initialize an global immutable associative array of structs, but it doesn't compile.
I am getting the following error message : "Error: not an associative array initializer".

As I really need to store my data for a compile time purpose if we can't do that with AA, I'll use arrays instead.

Here is my code :
struct EntryPoint
{
    string  moduleName;
    string  functionName;
    bool    beforeForwarding = false;
}

immutable EntryPoint[string]  entryPoints = [
    "wglDescribePixelFormat": {moduleName:"opengl32.forward_initialization", functionName:"wglDescribePixelFormat"}
];
March 23, 2018
On 03/23/2018 03:43 PM, Xavier Bigand wrote:
> I am trying to initialize an global immutable associative array of
> structs, but it doesn't compile.

Current solution is to initialize the AA in a 'static this()' block or ('shared static this()').

> I am getting the following error message : "Error: not an associative
> array initializer".
>
> As I really need to store my data for a compile time purpose if we can't
> do that with AA, I'll use arrays instead.

You can create and use AAs at compile time, which may be an acceptable use for your case as well:

struct EntryPoint
{
    string  moduleName;
    string  functionName;
    bool    beforeForwarding = false;
}

EntryPoint[string] makeEntryPoints() {
    EntryPoint[string] entryPoints = [
        "wglDescribePixelFormat": EntryPoint("opengl32.forward_initialization", "wglDescribePixelFormat")
    ];
    return entryPoints;
}

string useEntryPoints(EntryPoint[string] aa) {
    return aa["wglDescribePixelFormat"].moduleName;
}

void main() {
    enum s = useEntryPoints(makeEntryPoints());
    static const s2 = s;
}

The computations of 's' and 's2' in main are performed at compile time. If you can getaway with that, great. :) Otherwise, you have to initialize at runtime in a 'shared static this()' block, which can still be 'immutable':

// NOTE the addition of 'pure':
EntryPoint[string] makeEntryPoints() pure {
    // Same as above...
}

immutable EntryPoint[string] entryPoints;
shared static this() {
    // Yes, can initialize immutable:
    entryPoints = makeEntryPoints();
}

Ali

March 23, 2018
On Friday, 23 March 2018 at 22:43:47 UTC, Xavier Bigand wrote:
> I am trying to initialize an global immutable associative array of structs, but it doesn't compile.
> I am getting the following error message : "Error: not an associative array initializer".
>
> As I really need to store my data for a compile time purpose if we can't do that with AA, I'll use arrays instead.
>
> Here is my code :
> struct EntryPoint
> {
>     string  moduleName;
>     string  functionName;
>     bool    beforeForwarding = false;
> }
>
> immutable EntryPoint[string]  entryPoints = [
>     "wglDescribePixelFormat": {moduleName:"opengl32.forward_initialization", functionName:"wglDescribePixelFormat"}
> ];

Try this:

https://run.dlang.io/is/b7VQVB

tl;dr: you can instantiate immutable data in the module constructors.

---
struct EntryPoint
{
    string moduleName;
    string functionName;
    bool beforeForwarding = false;
}

static immutable EntryPoint[string] entryPoints;

shared static this()
{
    EntryPoint p = {moduleName:"opengl32.forward_initialization", functionName:"wglDescribePixelFormat"};
    entryPoints = ["wglDescribePixelFormat" : p];
}

void main()
{
    import std.stdio;
    entryPoints.writeln;
}
---
March 24, 2018
On Friday, 23 March 2018 at 22:43:47 UTC, Xavier Bigand wrote:
> I am trying to initialize an global immutable associative array of structs, but it doesn't compile.
> I am getting the following error message : "Error: not an associative array initializer".
>
> As I really need to store my data for a compile time purpose if we can't do that with AA, I'll use arrays instead.
>
> Here is my code :
> struct EntryPoint
> {
>     string  moduleName;
>     string  functionName;
>     bool    beforeForwarding = false;
> }
>
> immutable EntryPoint[string]  entryPoints = [
>     "wglDescribePixelFormat": {moduleName:"opengl32.forward_initialization", functionName:"wglDescribePixelFormat"}
> ];

Another solution, radically different is to not use an AA but a simple array.
Instead of indexing on a string you could simply index on an enum type. As your array is compile time constant, the dynamic nature of AA is not really used and indexing on a enum value is faster and simpler anyway.
The trick here is to generate the enum type at compile time. This can be achieved by a string mixin built at compile time.

Here an example that I used to generate an enum from the values from another enum. In your case you can look where the "wglDescribePixelFormat" are defined and using imports or string building code.

mixin({
  string code = "enum LANBIT : ulong { "~
                        "init = 0,";      /* We set the dummy init value to 0 */
  foreach(lanCode; __traits(allMembers, LANIDX)) {
    static if(lanCode == "IN")
      code ~= "INVALID = LANIDX2LANID(LANIDX."~lanCode~"),";
    else
      code ~= lanCode~"= LANIDX2LANID(LANIDX."~lanCode~"),";
  }
  code ~= "
    ALL    =  INVALID-1,                     /**< All bits except the LANID_INVALID */
    OFFICIAL= BG|CS|DA|DE|EL|EN|ES|ET|FI|FR|GA|HR|HU|IT|LT|LV|MT|NL|PL|PT|RO|SK|SL|SV,  /**< Official languages of the EU */
    COOFFICIAL=CA|GL|EU|GD|CY             /**< Co-official languages of the EU */
  ";
  return code ~ "}";
}());


TL/DR
defining constant compile time AA is an oxymoron. AA are by nature dynamic runtime creatures. if the indexes are compile time, a normal array with fixed indexes is enough.

March 24, 2018
Le 23/03/2018 à 23:43, Xavier Bigand a écrit :
> I am trying to initialize an global immutable associative array of structs, but it doesn't compile.
> I am getting the following error message : "Error: not an associative array initializer".
>
> As I really need to store my data for a compile time purpose if we can't do that with AA, I'll use arrays instead.
>
> Here is my code :
> struct EntryPoint
> {
>     string  moduleName;
>     string  functionName;
>     bool    beforeForwarding = false;
> }
>
> immutable EntryPoint[string]  entryPoints = [
>     "wglDescribePixelFormat": {moduleName:"opengl32.forward_initialization", functionName:"wglDescribePixelFormat"}
> ];

I finally found something that works great:
enum  entryPoints = [
    "wglChoosePixelFormat": EntryPoint("opengl32.forward_initialization", "client_wglChoosePixelFormat"),
    "wglDescribePixelFormat": EntryPoint("opengl32.forward_initialization", "client_wglDescribePixelFormat")
];

I am able to use this enum like an AA.