Jump to page: 1 2
Thread overview
CTFE implementation
Feb 08, 2008
Frank Benoit
Feb 08, 2008
Bjoern
Feb 08, 2008
Frank Benoit
Feb 08, 2008
BCS
Feb 08, 2008
John C
Feb 08, 2008
Frank Benoit
Feb 11, 2008
Don Clugston
Feb 11, 2008
Frank Benoit
Feb 12, 2008
Don Clugston
Feb 12, 2008
Don Clugston
February 08, 2008
I want to initialize constant GUID structure instanzes in D1. This is part of doing a port, so i want to keep most of the original code unchanged.

In Java:
public static const GUID IIDJavaBeansBridge = IIDFromString("{8AD9C840-044E-11D1-B3E9-00805F499D93}");

This is in Java no problem, IIDFromString is executed at startup.
In D i could change it too this:
public static const GUID IIDJavaBeansBridge = { 0x8AD9C840, 0x044E, 0x11D1, [0xB3, 0xE9, 0x00, 0x80, 0x5F, 0x49, 0x9D, 0x93]};

This compiles, but there are many of these GUID constants and for later merges and diffs, i really would like to keep the Java form. So i thought CTFE might do the trick.

// struct GUID { // size is 16
// align(1):
//     DWORD   Data1;
//     WORD    Data2;
//     WORD    Data3;
//     BYTE[8] Data4;
// }

int HexToInt( char[] str ){
    uint i = 0;
    foreach( c; str ){
        i <<= 4;
        int v = -1;
        if( c >= 'A' && c <= 'F' ){
            v = c - 'A' + 10;
        }
        else if( c >= '0' && c <= '9' ){
            v = c - '0';
        }
        assert( v >= 0 && v < 16, "for "~str~" char "~c );
        i |= v;
    }
    return i;
}

private static GUID IIDFromString( char[] str ){
    assert( str.length is 38 );
    assert( str[0] is '{' );
    assert( str[9] is '-' );
    assert( str[14] is '-' );
    assert( str[19] is '-' );
    assert( str[24] is '-' );
    assert( str[37] is '}' );
    GUID res;
    res.Data1 = HexToInt( str[1 .. 9] );
    res.Data2 = HexToInt( str[10 .. 14] );
    res.Data3 = HexToInt( str[15 .. 19] );
    //res.Data4[0] = HexToInt( str[20 .. 22] );
    //res.Data4[1] = HexToInt( str[22 .. 24] );
    //for( int i = 0; i < 5; i++ ){
    //    res.Data4[i+2] = HexToInt( str[25+2*i .. 25+2*i] );
    //}
    return res;
}

This works for the member Data1, Data2, Data3. But not for the Data4 member, which is a static array. Uncommenting those lines yield the "cannot evaluate at compile time" error.

I tried to do a union, also without luck.

Does someone have a solution for this?




February 08, 2008
Frank Benoit schrieb:
> I want to initialize constant GUID structure instanzes in D1. This is part of doing a port, so i want to keep most of the original code unchanged.
> 
> In Java:
> public static const GUID IIDJavaBeansBridge = IIDFromString("{8AD9C840-044E-11D1-B3E9-00805F499D93}");
> 



> This is in Java no problem, IIDFromString is executed at startup.


Why not using a module constructor
module dwx.guid;
static this()
{
  // all GUID init stuff (*IIDFromString ) goes here
}
...
I am very afraid I miss something. so it's just an idea.

February 08, 2008
Bjoern schrieb:
> I am very afraid I miss something. so it's just an idea.

Because then i need to have the constant declaration/initialization split into two different places.
I just wonder if it could be done in a nice way with CTFE. Then a diff-tool could find matching lines by comparing the java and the ported version.

February 08, 2008
Frank Benoit wrote:
> I want to initialize constant GUID structure instanzes in D1. This is part of doing a port, so i want to keep most of the original code unchanged.
> 
> In Java:
> public static const GUID IIDJavaBeansBridge = IIDFromString("{8AD9C840-044E-11D1-B3E9-00805F499D93}");
> 
> This is in Java no problem, IIDFromString is executed at startup.
> In D i could change it too this:
> public static const GUID IIDJavaBeansBridge = { 0x8AD9C840, 0x044E, 0x11D1, [0xB3, 0xE9, 0x00, 0x80, 0x5F, 0x49, 0x9D, 0x93]};
> 
> This compiles, but there are many of these GUID constants and for later merges and diffs, i really would like to keep the Java form. So i thought CTFE might do the trick.
> 
> // struct GUID { // size is 16
> // align(1):
> //     DWORD   Data1;
> //     WORD    Data2;
> //     WORD    Data3;
> //     BYTE[8] Data4;
> // }
> 
> int HexToInt( char[] str ){
>     uint i = 0;
>     foreach( c; str ){
>         i <<= 4;
>         int v = -1;
>         if( c >= 'A' && c <= 'F' ){
>             v = c - 'A' + 10;
>         }
>         else if( c >= '0' && c <= '9' ){
>             v = c - '0';
>         }
>         assert( v >= 0 && v < 16, "for "~str~" char "~c );
>         i |= v;
>     }
>     return i;
> }
> 
> private static GUID IIDFromString( char[] str ){
>     assert( str.length is 38 );
>     assert( str[0] is '{' );
>     assert( str[9] is '-' );
>     assert( str[14] is '-' );
>     assert( str[19] is '-' );
>     assert( str[24] is '-' );
>     assert( str[37] is '}' );
>     GUID res;
>     res.Data1 = HexToInt( str[1 .. 9] );
>     res.Data2 = HexToInt( str[10 .. 14] );
>     res.Data3 = HexToInt( str[15 .. 19] );
>     //res.Data4[0] = HexToInt( str[20 .. 22] );
>     //res.Data4[1] = HexToInt( str[22 .. 24] );
>     //for( int i = 0; i < 5; i++ ){
>     //    res.Data4[i+2] = HexToInt( str[25+2*i .. 25+2*i] );
>     //}
>     return res;
> }
> 
> This works for the member Data1, Data2, Data3. But not for the Data4 member, which is a static array. Uncommenting those lines yield the "cannot evaluate at compile time" error.
> 
> I tried to do a union, also without luck.
> 
> Does someone have a solution for this?
> 
> 
> 
> 

This is what I use:

template defIID(string g) {
  static if (g.length == 38)
    const GUID defIID = defIID!(g[1..$-1]);
  else static if (g.length == 36)
    const GUID defIID = { mixin("0x" ~ g[0..8]), mixin("0x" ~ g[9..13]), mixin("0x" ~ g[14..18]), [ mixin("0x" ~ g[19..21]), mixin("0x" ~ g[21..23]), mixin("0x" ~ g[24..26]), mixin("0x" ~ g[26..28]), mixin("0x" ~ g[28..30]), mixin("0x" ~ g[30..32]), mixin("0x" ~ g[32..34]), mixin("0x" ~ g[34..36]) ] };
  else
    static assert(false, "Incorrect format for GUID.");
}

const GUID IIDJavaBeansBridge = defIID!("{8AD9C840-044E-11D1-B3E9-00805F499D93}");

John.
February 08, 2008
"Frank Benoit" <keinfarbton@googlemail.com> wrote in message news:foi6sn$1kb4$1@digitalmars.com...

> Does someone have a solution for this?

private template IIDFromString(char[] str)
{
    static assert(str.length is 38);
    static assert(str[0] is '{');
    static assert(str[9] is '-');
    static assert(str[14] is '-');
    static assert(str[19] is '-');
    static assert(str[24] is '-');
    static assert(str[37] is '}');

    const GUID IIDFromString =
    {
        Data1: HexToInt(str[1 .. 9]),
        Data2: HexToInt(str[10 .. 14]),
        Data3: HexToInt(str[15 .. 19]),
        Data4:
        [
            HexToInt(str[20 .. 22]),
            HexToInt(str[22 .. 24]),
            HexToInt(str[25 .. 27]),
            HexToInt(str[27 .. 29]),
            HexToInt(str[29 .. 31]),
            HexToInt(str[31 .. 33]),
            HexToInt(str[33 .. 35]),
            HexToInt(str[35 .. 37])
        ]
    };
}

const IIDJavaBeansBridge =
IIDFromString!("{8AD9C840-044E-11D1-B3E9-00805F499D93}");

CTFE is terribly buggy, I tend to stay away from it as much as I can.


February 08, 2008
Reply to Frank,

> Bjoern schrieb:
> 
>> I am very afraid I miss something. so it's just an idea.
>> 
> Because then i need to have the constant declaration/initialization
> split into two different places.
> I just wonder if it could be done in a nice way with CTFE. Then a
> diff-tool could find matching lines by comparing the java and the
> ported
> version.

have you considered a template?

template GUID(char[GUID_LEN] str)
{
  const GUID_str GUID = ....;
}


February 08, 2008
Thanks all the answers.
Using template/mixin works.

Is the my not working example a showcase for a bug, or should it behave like this?
February 09, 2008
"Frank Benoit" <keinfarbton@googlemail.com> wrote in message news:foign0$288v$1@digitalmars.com...
> Thanks all the answers.
> Using template/mixin works.
>
> Is the my not working example a showcase for a bug, or should it behave like this?

It's probably a bug, but it might already have been reported, and a bug in CTFE is kind of like saying a bee in a bee hive.  I think that portion of the frontend just needs to be rewritten from scratch, since I wonder if it's really within reason to fix it.


February 11, 2008
Frank Benoit wrote:
> I want to initialize constant GUID structure instanzes in D1. This is part of doing a port, so i want to keep most of the original code unchanged.
> 
> In Java:
> public static const GUID IIDJavaBeansBridge = IIDFromString("{8AD9C840-044E-11D1-B3E9-00805F499D93}");
> 
> This is in Java no problem, IIDFromString is executed at startup.
> In D i could change it too this:
> public static const GUID IIDJavaBeansBridge = { 0x8AD9C840, 0x044E, 0x11D1, [0xB3, 0xE9, 0x00, 0x80, 0x5F, 0x49, 0x9D, 0x93]};
> 
> This compiles, but there are many of these GUID constants and for later merges and diffs, i really would like to keep the Java form. So i thought CTFE might do the trick.
> 
> // struct GUID { // size is 16
> // align(1):
> //     DWORD   Data1;
> //     WORD    Data2;
> //     WORD    Data3;
> //     BYTE[8] Data4;
> // }
> 
> int HexToInt( char[] str ){
>     uint i = 0;
>     foreach( c; str ){
>         i <<= 4;
>         int v = -1;
>         if( c >= 'A' && c <= 'F' ){
>             v = c - 'A' + 10;
>         }
>         else if( c >= '0' && c <= '9' ){
>             v = c - '0';
>         }
>         assert( v >= 0 && v < 16, "for "~str~" char "~c );
>         i |= v;
>     }
>     return i;
> }
> 
> private static GUID IIDFromString( char[] str ){
>     assert( str.length is 38 );
>     assert( str[0] is '{' );
>     assert( str[9] is '-' );
>     assert( str[14] is '-' );
>     assert( str[19] is '-' );
>     assert( str[24] is '-' );
>     assert( str[37] is '}' );
>     GUID res;
>     res.Data1 = HexToInt( str[1 .. 9] );
>     res.Data2 = HexToInt( str[10 .. 14] );
>     res.Data3 = HexToInt( str[15 .. 19] );
>     //res.Data4[0] = HexToInt( str[20 .. 22] );
>     //res.Data4[1] = HexToInt( str[22 .. 24] );
>     //for( int i = 0; i < 5; i++ ){
>     //    res.Data4[i+2] = HexToInt( str[25+2*i .. 25+2*i] );
>     //}
>     return res;
> }
> 
> This works for the member Data1, Data2, Data3. But not for the Data4 member, which is a static array. Uncommenting those lines yield the "cannot evaluate at compile time" error.
> 
> I tried to do a union, also without luck.
> 
> Does someone have a solution for this?

Looks like a CTFE bug.
Try creating the GUID struct in place, that often works better.

return GUID(HexToInt( str[1 .. 9] ), ...
[HexToInt( str[25+2*0 .. 25+2*0], ...
,HexToInt( str[25+2*5 .. 25+2*5]] );
February 11, 2008
Don Clugston schrieb:
> Looks like a CTFE bug.
> Try creating the GUID struct in place, that often works better.
> 
> return GUID(HexToInt( str[1 .. 9] ), ...
> [HexToInt( str[25+2*0 .. 25+2*0], ...
> ,HexToInt( str[25+2*5 .. 25+2*5]] );

I tried this without luck:
struct __GUID{
static __GUID opCall( uint Data1_, ushort Data2_, ushort Data3_, ubyte[8] Data4_ ){
    __GUID s;
    s.Data1 = Data1_;
    s.Data2 = Data2_;
    s.Data3 = Data3_;
    s.Data4[0..8] = Data4_[0..8];
    return s;
}
align(1):
uint Data1;
ushort Data2;
ushort Data3;
ubyte[8] Data4;
}
alias __GUID GUID;

GUID IIDFromString(char[] d) {
    return GUID(1,2,3,[0,1,2,3,4,5,6,7]);
}



« First   ‹ Prev
1 2