On Tuesday, 29 May 2018 at 20:53:14 UTC, DigitalDesigns wrote:
On Tuesday, 29 May 2018 at 20:26:52 UTC, arturg wrote:
On Tuesday, 29 May 2018 at 19:06:24 UTC, DigitalDesigns wrote:
On Monday, 28 May 2018 at 22:15:40 UTC, arturg wrote:
this might help you,
https://dpaste.dzfl.pl/2cf844a11e3f

you can use them to generate the functions as strings.

Thanks,

So, the problem I'm having is that I cannot use the generated interface for the abstract class because the abstract class needs the interface defined. I need to be able to forward define the interface then extend it.

D doesn't like this

main.d(10): Error: interface `main.B` base `A` is forward referenced

interface A;
mixin(Generate!(B,A));
interface B : A
{

}

abstract class C : B
{

}


would it work if you define the interface but mixin the members?

interface A
{
    mixin(InterfaceFromClass!C);
}

Yes, I made a post about it but it didn't get through or I forgot to send ;/

Doing it this way solves the original problems but creates a new problem in that any class that inherits from an abstract class that implements A doesn't work.

interface A
{
    mixin(InterfaceFromClass!C);
}

abstract class B : A
{
    A foo() { return this; }
    int bar() { return 3; }
}


class C : B
{
    // compiler says foo, bar not implemented
}


so, instead

interface A
{
    mixin(InterfaceFromClass!C);
}

abstract class B
{
    A foo() { return this; } // requires cast
    int bar() { return 3; }
}


class C : B, A
{

}


works but requires casting this in B which happens to work in C. So It is a fessible solution but I'm not sure why the compiler things the first case doesn't implement the methods when it clearly does. I think it looks at A and doesn't compute the mixin first when parsing C because if I put the output of the mixin directly it works. Probably a bug...



This method, which imports the source code and extracts the members works but is very fragile and requires using -J:



// Directly copies the data to the interface with a few hacks to fix the bug from the original, it excepts a well formatted input


template InterfaceFromClass(alias T)
{

        string InterfaceFromClass(string file = __FILE_FULL_PATH__)()
        {
                string res;
                import std.path, std.string, std.algorithm;
                enum data = import(file.baseName);
                enum mc = "abstract class "~T.stringof~" : ";
                enum im = `@("InterfaceMembers")`;
                int level = 0;
                auto baseIndentLevel = -1;
                int funcIndentLevel = -1;
                foreach(v; data.splitLines)
                {
                        string l = v;
                        auto indentLevel = l.length - l.stripLeft().length;
                        auto ll = l.strip();
                        if (ll.length == 0) continue;
                        
//res ~= to!string(l.length) ~"\n" ~ l[0..min(mc.length, l.length)] ~ "\n"; if (level == 0 && ll.length >= mc.length && ll[0..min(mc.length, ll.length)] == mc) { baseIndentLevel = indentLevel; level = 1; continue; } // Finds "abstract class <T> : " if (level == 1 && ll.length >= im.length && ll[0..min(im.length, ll.length)] == im) { level = 2; continue; } // Finds "@("InterfaceMembers))" near by
                        if (level >= 2 && l == "}") break;
                        if (level == 2 && ll.length > 1)
                        {
                                if (funcIndentLevel < 0) funcIndentLevel = 
indentLevel;
                                if (funcIndentLevel < indentLevel) continue;

                                // A simple function definition(ends with a 
');')
if (!ll.canFind("=") && l.length > 2 && l[$-2..$] == ");") { res ~= l ~ "\n"; continue; }
                                // ignore fields(assumes it has no {, } but 
ends with a ';')
if (!ll.canFind("{") && l[$-1] == ';' && ll[$-2..$] != "};") continue;

                                // ignore functions with inline blocks
if (ll.canFind(") {")) { l = l[0..$ - ll.find(") {").length] ~ ")"; }
                                
                                // must get function signature only(ignore 
body)                                
                                res ~= l ~ ((ll[$] != ';') ? ";" : "") ~ "\n";

                        }
                }
                

                return res;
        }
}


Why the original code is being broke by using D's traits to build the functions properly is beyond me. I'm pretty sure it is a bug given the example I gave earlier.


Reply via email to