www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - CTFE implementation

reply Frank Benoit <keinfarbton googlemail.com> writes:
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?
Feb 08 2008
next sibling parent reply Bjoern <nanali nospam-wanadoo.fr> writes:
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.
Feb 08 2008
parent reply Frank Benoit <keinfarbton googlemail.com> writes:
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.
Feb 08 2008
parent BCS <ao pathlink.com> writes:
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 = ....; }
Feb 08 2008
prev sibling next sibling parent John C <johnch_atms hotmail.com> writes:
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.
Feb 08 2008
prev sibling next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"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.
Feb 08 2008
parent reply Frank Benoit <keinfarbton googlemail.com> writes:
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?
Feb 08 2008
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"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.
Feb 09 2008
prev sibling parent reply Don Clugston <dac nospam.com.au> writes:
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]] );
Feb 11 2008
parent reply Frank Benoit <keinfarbton googlemail.com> writes:
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]); }
Feb 11 2008
next sibling parent Don Clugston <dac nospam.com.au> writes:
Frank Benoit wrote:
 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:
opCall definitely won't work with CTFE yet. But struct constructors work in every case I've ever tried.
 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]);
 }
 
 
 
Feb 11 2008
prev sibling parent Don Clugston <dac nospam.com.au> writes:
Frank Benoit wrote:
 Don Clugston schrieb:
 Looks like a CTFE bug.
 Try creating the GUID struct in place, that often works better.
This works. I reduced the size of Data4 bcos I was lazy -- you'll need to add the other 4 members 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 '}' ); return GUID(HexToInt( str[1 .. 9] ), HexToInt( str[10 .. 14] ), HexToInt( str[15 .. 19]), [cast(ubyte)HexToInt( str[20 .. 22] ), HexToInt( str[22 .. 24] ), HexToInt( str[25+2 .. 25+1*2]),HexToInt( str[25+1*2 .. 25+2*2]), // other 4 entries...]); } const GUID IIDJavaBeansBridge = IIDFromString("{8AD9C840-044E-11D1-B3E9-00805F499D93}");
Feb 12 2008