On Thursday, 20 July 2017 at 21:17:45 UTC, Walter Bright wrote:
Some time ago, I wrote about the X Macro in C:

  https://digitalmars.com/articles/b51.html

I used it from time to time in C code. It's one of the things I actually like about the C preprocessor. But in translating the aged C code to D it was time to make X work in D. Here's the C code, followed by the D translation.

(I suppose it could be done with C++ templates, but I'll leave that to Andrei or Eric Niebler <g>.)

================ C Version ================

// Macro trick to generate several parallel tables

#define Y \
        X("AH",4,mAX,TYuchar)   \
        X("AL",0,mAX,TYuchar)   \
        X("AX",8,mAX,TYushort)  \
        X("BH",7,mBX,TYuchar)   \
        X("BL",3,mBX,TYuchar)   \
        X("BP",13,0,TYushort)   \
        X("BX",11,mBX,TYushort) \
        X("CH",5,mCX,TYuchar)   \
        X("CL",1,mCX,TYuchar)   \
        X("CX",9,mCX,TYushort)  \
        X("DH",6,mDX,TYuchar)   \
        X("DI",15,mDI,TYushort) \
        X("DL",2,mDX,TYuchar)   \
        X("DX",10,mDX,TYushort) \
        X("EAX",16,mAX,TYulong) \
        X("EBP",21,0,TYulong)   \
        X("EBX",19,mBX,TYulong) \
        X("ECX",17,mCX,TYulong) \
        X("EDI",23,mDI,TYulong) \
        X("EDX",18,mDX,TYulong) \
        X("ESI",22,mSI,TYulong) \
        X("ESP",20,0,TYulong)   \
        X("SI",14,mSI,TYushort) \
        X("SP",12,0,TYushort)

// Table for identifiers
static const char *pseudotab[] =
{
#define X(id,reg,m,ty)  id,
        Y
#undef X
};

// Register number to use in addressing mode
unsigned char pseudoreg[] =
{
#define X(id,reg,m,ty)  reg,
        Y
#undef X
};

// Mask to use for registers affected
regm_t pseudomask[] =
{
#define X(id,reg,m,ty)  m,
        Y
#undef X
};

// Table for type of pseudo register variable
static unsigned char pseudoty[] =
{
#define X(id,reg,m,ty)  mTYvolatile | ty,
        Y
#undef X
};

================ D Version ================

/* 4 parallel tables using "X Macro" technique
 */

template Y(alias X)
{
    enum Y =
    [
        //  id   reg  mask   ty
        X!("AH",   4, mAX, TYuchar),
        X!("AL",   0, mAX, TYuchar),
        X!("AX",   8, mAX, TYushort),
        X!("BH",   7, mBX, TYuchar),
        X!("BL",   3, mBX, TYuchar),
        X!("BP",  13,   0, TYushort),
        X!("BX",  11, mBX, TYushort),
        X!("CH",   5, mCX, TYuchar),
        X!("CL",   1, mCX, TYuchar),
        X!("CX",   9, mCX, TYushort),
        X!("DH",   6, mDX, TYuchar),
        X!("DI",  15, mDI, TYushort),
        X!("DL",   2, mDX, TYuchar),
        X!("DX",  10, mDX, TYushort),
        X!("EAX", 16, mAX, TYulong),
        X!("EBP", 21,   0, TYulong),
        X!("EBX", 19, mBX, TYulong),
        X!("ECX", 17, mCX, TYulong),
        X!("EDI", 23, mDI, TYulong),
        X!("EDX", 18, mDX, TYulong),
        X!("ESI", 22, mSI, TYulong),
        X!("ESP", 20,   0, TYulong),
        X!("SI",  14, mSI, TYushort),
        X!("SP",  12,   0, TYushort),
    ];
}

// Table for identifiers

template Xtab(alias A, alias B, alias C, alias D) { enum Xtab = A; }

private __gshared const(char)*[24] pseudotab = Y!Xtab;


// Register number to use in addressing mode

template Xreg(alias A, alias B, alias C, alias D) { enum Xreg = B; }

__gshared ubyte[24] pseudoreg = Y!Xreg;


// Mask to use for registers affected

template Xmask(alias A, alias B, alias C, alias D) { enum Xmask = C; }

__gshared regm_t[24] pseudomask = Y!Xmask;


// Table for type of pseudo register variable

template Xty(alias A, alias B, alias C, alias D) { enum Xty = mTYvolatile | D; }

private __gshared const(tym_t)[24] pseudoty = Y!Xty;

I wonder if you could use one of the SoA implementations (e.g from here: https://wiki.dlang.org/Transforming_slice_of_structs_into_struct_of_slices) to the same effect.

Reply via email to