Translating Modula2 into D: variant records, pointer
Frits van Bommel
fvbommel at REMwOVExCAPSs.nl
Tue Jan 9 10:17:47 PST 2007
BLS wrote:
> Hi Frits,
>> I think you can mostly fake this in D using private
>> (differently-named) union members and property methods that assert if
>> 'terminal' has the wrong value.
>> You can even make it so that the original names directly alias the
>> private names in a non-debug build, and only use the checking version
>> in a debug build[1].
> Can you please offer an example based on ...
> Modula
>
> TYPE NodePtr = POINTER TO Node;
> Node = RECORD suc, alt: NodePtr;
> CASE terminal: BOOLEAN OF
> TRUE: tsym: CHAR |
> FALSE: nSym: HeadPtr
> END
> END;
-----
struct Header{}; // to make it compile as-is
struct Node
{
Node* suc;
Node* alt;
bool terminal;
union
{
private char tsym_;
private Header* nSym_;
}
debug
{
// Property versions, with full error checking
// (This block is used if -debug is passed to the compiler)
char tsym()
in
{
assert(terminal == false);
}
body
{
return tsym_;
}
char tsym(char newval)
out
{
assert(terminal == false);
}
body
{
terminal = false;
return tsym_ = newval;
}
Header* nSym()
in
{
assert(terminal == true);
}
body
{
return nSym_;
}
Header* nSym(Header* newval)
out
{
assert(terminal == true);
}
body
{
terminal = true;
return nSym_ = newval;
}
} else {
// Hmm.. No way to automatically set 'terminal' in this
// implementation. Damn.
// (This block is used if -debug is NOT passed to the compiler)
alias tsym_ tsym;
alias nSym_ nSym;
}
}
-----
It's unfortunately a bit wordy. It's also completely untested beyond the
fact that it compiles ;).
I noticed a limitation of the optimization opportunity I mentioned:
In the debug version (with property setters) you can automatically
adjust the value of 'terminal' depending on the last-set property.
This isn't possible with direct aliasing as far as I can see.
If this is a problem, you might want to always use the code in the first
block. I see no reason the compiler can't inline the functions if passed
the appropriate optimization flags, so it shouldn't really matter much.
Some notes:
* The first block of code (right after 'debug') is compiled in if -debug
is passed to the compiler. Otherwise, the second (short) block is compiled.
* The 'in' and 'out' blocks are removed by the compiler if -release is
present on the compiler command line.
* As mentioned in my previous post, tsym_ and nSym_ are accessible from
code in the same module even though they are private.
* Another implementation option is to also rename 'terminal' and make it
private, and then only provide a property getter function so the code
using the Node type can't set it without also setting the appropriate
union member.
* If you only ever set the union members right after constructing the
Node instance, you may also want to think about classes and inheritance
if you're OOP-inclined.
More information about the Digitalmars-d-learn
mailing list