Thread overview | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 22, 2005 Complex (constant) C macros -> D | ||||
---|---|---|---|---|
| ||||
I'm just looking at a couple of projects, and wondering how I can convert them to D. The point of these macros to to translate a human readable value to something that is hardware specific. The details aren't too specific, but the macros convert from one constant form to another, here is the C code. #define INVERT_COMMANDS #ifdef INVERT_COMMANDS #define INVERT ~ #else #define INVERT #endif #define FLIP_COMMANDS #ifdef FLIP_COMMANDS #define FLIP(x) ( ((x & 0x80) >> 7) | \ ((x & 0x40) >> 5) | \ ((x & 0x20) >> 3) | \ ((x & 0x10) >> 1) | \ ((x & 0x08) << 1) | \ ((x & 0x04) << 3) | \ ((x & 0x02) << 5) | \ ((x & 0x01) << 7) ) #else #define FLIP(x) (x) #endif #define SOME_COMMAND ((INVERT (FLIP (0xE0)) & 0xFF )) Now, yes I know this is ugly, but for this project we were reverse engineering a legacy interface and were not certain of a lot of things, being able to transform the value E0, which was what the documentation said, to what the hardware expected was essential. If you notice, a decent pre-processor will fold all of those operations into a single new constant that is inverted and bit fliped. Is there anyway to do this with D? I suspect that the cleanest, and most D like way would be along the lines of: version (flip_commands) { static uint flip(uint x) { return ((x & 0x80) >> 7) | ((x & 0x40) >> 5) | ((x & 0x20) >> 3) | ((x & 0x10) >> 1) | ((x & 0x08) << 1) | ((x & 0x04) << 3) | ((x & 0x02) << 5) | ((x & 0x01) << 7) ) } } else { static uint flip (uint x) { return x; } } const uint SOME_COMMAND = flip (0xE0); Where SOME_COMMAND is evalutated once at runtime, before the main function gets called. I really feel like this would be a powerful addition to D (if it doesn't already support it). If it does support it - how can I do it? Hmm, just thinking about it some more, I can use a static module constructor to assign the value, ie static this () { SOME_COMMAND = flip (0xE0); } But that feels a little ugly. Cheers Brad PS - sorry if the formatting sucks :) |
February 22, 2005 Re: Complex (constant) C macros -> D | ||||
---|---|---|---|---|
| ||||
Posted in reply to brad | One way to do it is to use the PP on the D source code. There's nothing stopping you using a C compiler (with PP output only!) to handle macros within D. However, you can likely do the equivalent thing using templates: template Flip (T : int) { T swizzle (T i) { // your stuff here ... return (i << 1) | (i >> 7); } } void test() { int flipped = Flip!(int).swizzle(0xEB30); } And then use 'alias' to clean up the syntax a bit. - Kris In article <cvg7sd$1d4k$1@digitaldaemon.com>, brad@domain.invalid says... > >I'm just looking at a couple of projects, and wondering how I can >convert them to D. The point of these macros to to translate a human >readable value to something that is hardware specific. The details >aren't too specific, but the macros convert from one constant form to >another, here is the C code. >#define INVERT_COMMANDS >#ifdef INVERT_COMMANDS >#define INVERT ~ >#else >#define INVERT >#endif > >#define FLIP_COMMANDS >#ifdef FLIP_COMMANDS > #define FLIP(x) ( ((x & 0x80) >> 7) | \ > ((x & 0x40) >> 5) | \ > ((x & 0x20) >> 3) | \ > ((x & 0x10) >> 1) | \ > ((x & 0x08) << 1) | \ > ((x & 0x04) << 3) | \ > ((x & 0x02) << 5) | \ > ((x & 0x01) << 7) ) >#else >#define FLIP(x) (x) >#endif >#define SOME_COMMAND ((INVERT (FLIP (0xE0)) & 0xFF )) > >Now, yes I know this is ugly, but for this project we were reverse engineering a legacy interface and were not certain of a lot of things, being able to transform the value E0, which was what the documentation said, to what the hardware expected was essential. If you notice, a decent pre-processor will fold all of those operations into a single new constant that is inverted and bit fliped. > >Is there anyway to do this with D? I suspect that the cleanest, and most D like way would be along the lines of: > >version (flip_commands) >{ >static uint flip(uint x) { > return ((x & 0x80) >> 7) | > ((x & 0x40) >> 5) | > ((x & 0x20) >> 3) | > ((x & 0x10) >> 1) | > ((x & 0x08) << 1) | > ((x & 0x04) << 3) | > ((x & 0x02) << 5) | > ((x & 0x01) << 7) ) >} >} >else >{ >static uint flip (uint x) { > return x; >} >} > >const uint SOME_COMMAND = flip (0xE0); > >Where SOME_COMMAND is evalutated once at runtime, before the main >function gets called. >I really feel like this would be a powerful addition to D (if it doesn't >already support it). If it does support it - how can I do it? >Hmm, just thinking about it some more, I can use a static module >constructor to assign the value, ie >static this () >{ > SOME_COMMAND = flip (0xE0); >} >But that feels a little ugly. > >Cheers >Brad > >PS - sorry if the formatting sucks :) |
February 22, 2005 Re: Complex (constant) C macros -> D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kris | Kris wrote:
> One way to do it is to use the PP on the D source code. There's nothing stopping
> you using a C compiler (with PP output only!) to handle macros within D.
>
> However, you can likely do the equivalent thing using templates:
>
> template Flip (T : int)
> {
> T swizzle (T i)
> { // your stuff here ...
> return (i << 1) | (i >> 7); }
> }
>
> void test()
> {
> int flipped = Flip!(int).swizzle(0xEB30);
> }
>
> And then use 'alias' to clean up the syntax a bit.
>
Ugh! You're not really suggesting that I re-use C's pre-processor with D? Shame on you! :)
I don't think that the template really solves my problem, because it still doesn't let me assign to a const variable, or outside of any functions.
Brad
|
February 23, 2005 Re: Complex (constant) C macros -> D | ||||
---|---|---|---|---|
| ||||
Posted in reply to brad | <brad@domain.invalid> wrote in message news:cvg7sd$1d4k$1@digitaldaemon.com... > I'm just looking at a couple of projects, and wondering how I can convert them to D. The point of these macros to to translate a human readable value to something that is hardware specific. [snip] > const uint SOME_COMMAND = flip (0xE0); > > Where SOME_COMMAND is evalutated once at runtime, before the main function gets called. [snip] Does SOME_COMMAND really have to be const? Can it be an inlined function call instead? I'm thinking something like uint flip(uint x){ compute and return flipped x } uint SOME_COMMAND(){ return flip(0xE0); } Then if you compile with -inline -O the call to SOME_COMMAND() and flip() should be inlined and the constant folding logic in the optimizer should evaluate the resulting expression at compile time. The down-sides of this approach are 1) assumes inlining and constant folding are enabled 2) you can't take the address of SOME_COMMAND and get a uint* 3) you have to write SOME_COMMAND() in code instead of SOME_COMMAND I think it's worth a shot, though. -Ben |
February 23, 2005 Re: Complex (constant) C macros -> D | ||||
---|---|---|---|---|
| ||||
Posted in reply to brad | On Wed, 23 Feb 2005 10:23:43 +1300, brad@domain.invalid wrote: > I'm just looking at a couple of projects, and wondering how I can > convert them to D. The point of these macros to to translate a human > readable value to something that is hardware specific. The details > aren't too specific, but the macros convert from one constant form to > another, here is the C code. > #define INVERT_COMMANDS > #ifdef INVERT_COMMANDS > #define INVERT ~ > #else > #define INVERT > #endif > > #define FLIP_COMMANDS > #ifdef FLIP_COMMANDS > #define FLIP(x) ( ((x & 0x80) >> 7) | \ > ((x & 0x40) >> 5) | \ > ((x & 0x20) >> 3) | \ > ((x & 0x10) >> 1) | \ > ((x & 0x08) << 1) | \ > ((x & 0x04) << 3) | \ > ((x & 0x02) << 5) | \ > ((x & 0x01) << 7) ) > #else > #define FLIP(x) (x) > #endif > #define SOME_COMMAND ((INVERT (FLIP (0xE0)) & 0xFF )) > > Now, yes I know this is ugly, but for this project we were reverse engineering a legacy interface and were not certain of a lot of things, being able to transform the value E0, which was what the documentation said, to what the hardware expected was essential. If you notice, a decent pre-processor will fold all of those operations into a single new constant that is inverted and bit fliped. > > Is there anyway to do this with D? I suspect that the cleanest, and most D like way would be along the lines of: > > version (flip_commands) > { > static uint flip(uint x) { > return ((x & 0x80) >> 7) | > ((x & 0x40) >> 5) | > ((x & 0x20) >> 3) | > ((x & 0x10) >> 1) | > ((x & 0x08) << 1) | > ((x & 0x04) << 3) | > ((x & 0x02) << 5) | > ((x & 0x01) << 7) ) > } > } > else > { > static uint flip (uint x) { > return x; > } > } > > const uint SOME_COMMAND = flip (0xE0); > > Where SOME_COMMAND is evalutated once at runtime, before the main > function gets called. > I really feel like this would be a powerful addition to D (if it doesn't > already support it). If it does support it - how can I do it? > Hmm, just thinking about it some more, I can use a static module > constructor to assign the value, ie > static this () > { > SOME_COMMAND = flip (0xE0); > } > But that feels a little ugly. > It might "feel a little ugly" to you, but that is exactly what module constructors are for ... "SOME_COMMAND is evaluated once at runtime, before the main function gets called". In fact, I'd even make the flip() function a nested function within the module constructor if it's not needed elsewhere in the program. -- Derek Melbourne, Australia 23/02/2005 11:06:35 AM |
February 23, 2005 Re: Complex (constant) C macros -> D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | Ben Hinkle wrote:
> <brad@domain.invalid> wrote in message news:cvg7sd$1d4k$1@digitaldaemon.com...
>
>>I'm just looking at a couple of projects, and wondering how I can convert them to D. The point of these macros to to translate a human readable value to something that is hardware specific.
>
> [snip]
>
>>const uint SOME_COMMAND = flip (0xE0);
>>
>>Where SOME_COMMAND is evalutated once at runtime, before the main function gets called.
>
> [snip]
>
> Does SOME_COMMAND really have to be const? Can it be an inlined function call instead? I'm thinking something like
>
> uint flip(uint x){ compute and return flipped x }
> uint SOME_COMMAND(){ return flip(0xE0); }
>
> Then if you compile with -inline -O the call to SOME_COMMAND() and flip() should be inlined and the constant folding logic in the optimizer should evaluate the resulting expression at compile time. The down-sides of this approach are
> 1) assumes inlining and constant folding are enabled
> 2) you can't take the address of SOME_COMMAND and get a uint*
> 3) you have to write SOME_COMMAND() in code instead of SOME_COMMAND
>
> I think it's worth a shot, though.
> -Ben
>
>
That is probably a good choice. It doesn't need to be a constant (in my case), though it is a little more code than in the C case. It does also make assumptions about the inliner/optimiser - but that is easily verified with an assembler check. I guess I was hoping that I would be able to control constant munging in D just as well as I can in C with the preprocessor. I mean, with the C code I know that it will fold down to just another constant - I'll need to check the assembler output with the D method :)
Brad
|
February 23, 2005 Re: Complex (constant) C macros -> D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell |
> It might "feel a little ugly" to you, but that is exactly what module
> constructors are for ... "SOME_COMMAND is evaluated once at runtime, before
> the main function gets called".
>
> In fact, I'd even make the flip() function a nested function within the
> module constructor if it's not needed elsewhere in the program.
>
The only remaining difference is that I can't assign a value to a const variable with the static module constructor method.
I'm not particularly concerned, just found a little corner that I think C does better than D, and I'd like D to be better than C everywhere :)
Is there a reason why D the following couldn't be valid D?
static int foo(int i) { return i/2; };
const int myVar = foo(10);
Brad
|
February 23, 2005 Re: Complex (constant) C macros -> D | ||||
---|---|---|---|---|
| ||||
Posted in reply to brad | In article <cvgcip$1l9p$1@digitaldaemon.com>, brad@domain.invalid says... > >Kris wrote: >> One way to do it is to use the PP on the D source code. There's nothing stopping you using a C compiler (with PP output only!) to handle macros within D. >> >> However, you can likely do the equivalent thing using templates: >> >> template Flip (T : int) >> { >> T swizzle (T i) >> { >> // your stuff here ... >> return (i << 1) | (i >> 7); >> } >> } >> >> void test() >> { >> int flipped = Flip!(int).swizzle(0xEB30); >> } >> >> And then use 'alias' to clean up the syntax a bit. >> > >Ugh! You're not really suggesting that I re-use C's pre-processor with D? Shame on you! :) It's what one has to do to get _Line_ and _File_ info at this time. Shame on Walter ... :-) >I don't think that the template really solves my problem, because it still doesn't let me assign to a const variable, or outside of any functions. Hmm. Walter shows a trick-pony via a recursive "compile time" template example near the bottom of this page: http://digitalmars.com/d/index.html One would hope that beast could be 'persuaded' to do what you need. - Kris |
February 23, 2005 Re: Complex (constant) C macros -> D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kris |
>
> Hmm. Walter shows a trick-pony via a recursive "compile time" template example
> near the bottom of this page: http://digitalmars.com/d/index.html
>
> One would hope that beast could be 'persuaded' to do what you need.
>
> - Kris
>
>
Thanks for the suggestion. I've managed to get this code working, which presumably could be extended to any other constant folding exercise.
template Foo(int n)
{
const int val = n - 1;
}
const int test = Foo!(10).val;
Though I think the syntax is on the clunky side :)
Brad
|
February 23, 2005 Re: Complex (constant) C macros -> D | ||||
---|---|---|---|---|
| ||||
Posted in reply to brad | In article <cvgjed$20sn$1@digitaldaemon.com>, brad@domain.invalid says... > > >> >> Hmm. Walter shows a trick-pony via a recursive "compile time" template example near the bottom of this page: http://digitalmars.com/d/index.html >> >> One would hope that beast could be 'persuaded' to do what you need. >> >> - Kris >> >> >Thanks for the suggestion. I've managed to get this code working, which presumably could be extended to any other constant folding exercise. > >template Foo(int n) >{ > const int val = n - 1; >} > >const int test = Foo!(10).val; > >Though I think the syntax is on the clunky side :) > >Brad I tried it with mixins: template Flip(int b) { const int swizzle = (b << 7) | (b >> 2); } void main() { mixin Flip!(0x4566) a; mixin Flip!(0xfee1) b; printf ("%x, %x\n", a.swizzle, b.swizzle); } Would be great to get 'regular' functions evaluated at compile time. Templates are indeed klunky for such things, and terribly non-intuitive. That aside, the biggest issue with templates is that they are nigh impossible to use with a source-code debugger. - Kris |
Copyright © 1999-2021 by the D Language Foundation