Variable references in strings (Was: Structs implementing interfaces in D1)
Ary Borenszweig
ary at esperanto.org.ar
Tue Feb 10 03:14:07 PST 2009
Tom S escribió:
> /** Just a simple hack to have interfaces implemented by structs ...
> because I can :P
> Tested on DMD 1.039 [win32], GDC (various versions) [linux32] and
> codepad.org
>
> Output:
>
> Entering main
> Foo.func1 called ; val1 = 3.141590, val2 = Hello, world!
> Foo.func2 called ; val1 = 3.141590, val2 = Hello, world!
> Foo.func2 called ; val1 = 3.141590, val2 = Hello, world!
> Foo.func3 called ; val1 = 3.141590, val2 = Hello, world! ; p1 = 123, p2
> = some parameter
> Leaving main
> */
>
>
> module structIface;
>
> extern (C) int printf(char*, ...);
>
>
>
> // ---- evil implementation
> char[] structImplementInterface(char[] iface, char[][] funcs) {
> char[] res = "private {";
> res ~= \n"alias typeof(*this) _iface_"~iface~"_ThisType;";
>
> foreach (func; funcs) {
> res ~= \n"static assert (is(typeof(&"~iface~".init."~func~")),
> `The interface "~iface~" doesn't declare a '"~func~"'
> function, `
> `thus struct `~_iface_"~iface~"_ThisType.stringof~` cannot
> implement it`);";
> res ~= \n"static void _iface_" ~ iface ~ "_func_" ~ func ~ "() {";
> version (GNU) {
> res ~= \n\t"asm { naked; sub dword ptr 4[ESP], _iface_" ~
> iface ~ "_vtbl.offsetof; jmp " ~ func ~ "; }";
> } else {
> res ~= \n\t"asm { naked; sub EAX, _iface_" ~ iface ~
> "_vtbl.offsetof; jmp " ~ func ~ "; }";
> }
> res ~= \n"}";
> }
> res ~= \n ~ iface ~ " as" ~ iface ~ "() {";
> res ~= \n\t"return cast("~iface~")cast(void*)&_iface_" ~ iface ~
> "_vtbl;";
> res ~= \n"}";
>
> res ~= \n"void** _iface_" ~ iface ~ "_vtbl = cast(void**)([";
> res ~= \n\t"null"; // for classinfo
> foreach (func; funcs) {
> res ~= ",\n\tcast(void*)&Foo._iface_" ~ iface ~ "_func_" ~ func;
> }
> res ~= \n"]).ptr;";
> res ~= "}";
>
> return res;
> }
> // ---- end of the evil implementation
Since a lot of compile stuff is done via strings, I wish you could do
somehing like this in D (like in PHP):
res ~= res ~= "\n\treturn cast(${iface})cast(void*)&_iface_${iface}_vtbl;";
Much nicer and understandable. And I think it's not hard to implement:
when doing semantic for a string like that, parse it and search the
variables in the current scope and upwards (as a usual search). For this
to work, primitives should have a string representation, and if it's a
class or struct, then toString() is invoked.
It's really hard to follow a code like that, with thousands of "~".
And maybe this should only be done for strings enclosed in `, so that
the search is not always done.
More information about the Digitalmars-d
mailing list