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
Top | Discussion index | About this forum | D home