View mode: basic / threaded / horizontal-split · Log in · Help
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
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
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
<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
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
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
> 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
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
> 
> 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
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
« First   ‹ Prev
1 2 3
Top | Discussion index | About this forum | D home