Build interface from abstract class
DigitalDesigns
DigitalDesigns at gmail.com
Wed May 30 00:00:57 UTC 2018
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.
More information about the Digitalmars-d-learn
mailing list