On 02.11.2010 0:24, bearophile wrote:
To answer the recent D.learn thread "How would I optimize this parser?", I have
tried to find a more efficient way to build the parse tree, so I have used tagged
structs, something like this:
enum NodeType { node, text, tag }
struct Node {
/*immutable*/ NodeType type = NodeType.node;
Node* parent;
}
struct TextNode {
/*immutable*/ NodeType type = NodeType.text;
Node* parent;
string content;
public nothrow this(string content) {
this.content = content;
}
}
struct TagNode {
/*immutable*/ NodeType type = NodeType.tag;
Node* parent;
string name;
Node*[] children;
public nothrow this(string name) {
this.name = name;
}
public nothrow void addChild(Node* newChild) {
children ~= newChild;
newChild.parent = cast(Node*)&this;
}
}
Each struct instance contains a "type" tag that at runtime tells what kind of
node it is. This tag never changes in the life of a node, so it's better for it to be
immutable, to use the type system to avoid changing it by mistake.
But unfortunately it doesn't work, this is a reduced example:
struct Foo {
immutable int x = 1;
}
struct Bar {
immutable int x = 2;
}
static assert(Foo.sizeof == 4);
void main() {
Foo f;
assert(f.x == 1);
assert((cast(Bar)f).x == 1);
}
It seems that immutable fields act like static const fields or enum fields,
they have no storage. This seems a little weird to me. Do you know a way to put
immutable storage in a struct instance?
Using this doesn't work:
this(int) { type = NodeType.tag; }
And a static this() doesn't seem to work. So in the program I have just used a
mutable type field, but it looks silly...
Bye,
bearophile
Wierd indeed, best workaround I can come up with:
struct Foo {
immutable int x;
private this(int val){ x = val; }
public static Foo opCall(){
return Foo(1);
}
}
struct Bar {
immutable int x;
private this(int val){ x = val; }
public static Bar opCall(){
return Bar(2);
}
}
static assert(Foo.sizeof == 4);
void main() {
Foo f = Foo();
assert(f.x == 1);
assert((cast(Bar*)&f).x == 1);
}
works, and the fact that static opCall is deprecated(?) makes me wish
it's a compiler bug.
And you still could shoot yourself in the leg, but only explicitly (that
is "Foo f = Foo(42)" ) and only in the same module.
--
Dmitry Olshansky