Jump to page: 1 2 3
Thread overview
Complex (constant) C macros -> D
Feb 22, 2005
brad
Feb 22, 2005
Kris
Feb 22, 2005
brad
Feb 23, 2005
Kris
Feb 23, 2005
brad
Feb 23, 2005
Kris
Feb 23, 2005
Aleksey Bobnev
Feb 23, 2005
brad beveridge
Feb 23, 2005
Ben Hinkle
Feb 23, 2005
brad
Feb 23, 2005
Ben Hinkle
Feb 23, 2005
brad
Feb 23, 2005
Ben Hinkle
Feb 23, 2005
brad beveridge
Feb 23, 2005
brad beveridge
Feb 23, 2005
Ben Hinkle
Feb 23, 2005
brad beveridge
Feb 23, 2005
Ben Hinkle
Feb 23, 2005
brad
Feb 23, 2005
Kris
Feb 25, 2005
Walter
Feb 23, 2005
Derek Parnell
Feb 23, 2005
brad
Feb 23, 2005
xs0
Feb 23, 2005
Derek Parnell
Feb 26, 2005
Manfred Nowak
Feb 23, 2005
Georg Wrede
Feb 25, 2005
Andy Friesen
February 22, 2005
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
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
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
<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
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
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
> 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
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
> 
> 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
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