Ary Borenszweig wrote:
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.

Macros are supposed to solve that. D1.0 even has a "macro" keyword, but so far macros are just vaporware.

Reply via email to