Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
July 16, 2012 Need runtime reflection? | ||||
---|---|---|---|---|
| ||||
Attachments:
| I want to imitate golang's interface in D, to study D's template. I wrote some code: https://gist.github.com/3123593 Now we can write code like golang: -- interface IFoo { void foo(int a, string b, float c); } struct Foo { void foo(int a, string b, float c) { writeln("Foo.foo: ", a, ", ", b, ", ", c); } } struct FooFoo { void foo(int a, string b, float c) { writeln("FooFoo.foo: ", a, ", ", b, ", ", c); } } GoInterface!(IFoo) f = new Foo; f.foo(3, "abc", 2.2); f = new FooFoo; f.foo(5, "def", 7.7); -- It is also very naive, does not support some features, like out/ref parameters, free functions *[1]* and so on. The biggest problem is downcast not supported. In golang, we can write code like*[2]*: -- var p IWriter = NewB(10) p2, ok := p.(IReadWriter) -- Seems [p.(IReadWriter)] dynamically build a virtual table *[3]*,because the type of "p" is IWriter, it is *smaller* than IReadWriter, the cast operation must search methods and build vtbl at run time. In D, GoInterface(T).opAssign!(V)(V v) can build a rich runtime information to *V* if we need. But if *V* is interface or base class, the type information not complete. So, seems like I need runtime reflection? and how can I do this in D? I did not find any useful information in the TypeInfo*. ------ [1] free functions support, e.g. -- interface IFoo { void foo(int a, string b, float c); } void foo(int self, int a, string b, float c) { writefln("..."); } GoInterface!(int) p = 1; p.foo(4, "ccc", 6.6); -- In theory no problem. [2] example from https://github.com/xushiwei/gobook/blob/master/dive-into/interface/03/interface.go [3] /path/of/go/src/pkg/runtime/iface.c: static Itab* itab(InterfaceType *inter, Type *type, int32 canfail) Best regards, -- Li Jie |
July 17, 2012 Re: Need runtime reflection? | ||||
---|---|---|---|---|
| ||||
Posted in reply to lijie | > I want to imitate golang's interface in D, to study D's template. I wrote > some code: https://gist.github.com/3123593 > > Now we can write code like golang: > -- > interface IFoo { > void foo(int a, string b, float c); > } > > struct Foo { > void foo(int a, string b, float c) { > writeln("Foo.foo: ", a, ", ", b, ", ", c); > } > } > > struct FooFoo { > void foo(int a, string b, float c) { > writeln("FooFoo.foo: ", a, ", ", b, ", ", c); > } > } > > GoInterface!(IFoo) f = new Foo; > f.foo(3, "abc", 2.2); > > f = new FooFoo; > f.foo(5, "def", 7.7); > -- > > It is also very naive, does not support some features, like out/ref > parameters, free functions *[1]* and so on. The biggest problem is downcast > not supported. In golang, we can write code like*[2]*: > -- > var p IWriter = NewB(10) > p2, ok := p.(IReadWriter) > -- > > Seems [p.(IReadWriter)] dynamically build a virtual table *[3]*,because the > type of "p" is IWriter, it is *smaller* than IReadWriter, the cast > operation must search methods and build vtbl at run time. > > In D, GoInterface(T).opAssign!(V)(V v) can build a rich runtime information > to *V* if we need. But if *V* is interface or base class, the type > information not complete. So, seems like I need runtime reflection? and how > can I do this in D? I did not find any useful information in the TypeInfo*. > > ------ > [1] free functions support, e.g. > -- > interface IFoo { > void foo(int a, string b, float c); > } > void foo(int self, int a, string b, float c) { > writefln("..."); > } > > GoInterface!(int) p = 1; > p.foo(4, "ccc", 6.6); > -- > In theory no problem. I, too, was enamored with Go Interfaces and implemented them for .NET: http://www.codeproject.com/Articles/87991/Dynamic-interfaces-in-any-NET-language And I wasn't the only one; later, someone else published another library for .NET with the exact same goal. This is definitely a feature I would want to see in D, preferably as a first-class feature, although sadly that would break any code that relies on ISomething being pointer-sized; Go uses fat pointers, and we use a thin-pointer implementation in .NET but it's inefficient (as every cast creates a heap-allocated wrapper, and double-indirection is needed to reach the real method.) Anyway, they say it's possible to build runtime reflection in D but I've no idea how... has it never been done before? Of course, runtime template instantiation won't be possible. Therefore, run-time casting will have to be more limited than compile-time casting. Reflection to free functions would be really nice, but it might be less capable at run-time. Consider if you there is a class A in third-party module MA that you want to cast to interface I, but class A is missing a function F() from I. So in your module (module MB) you define a free function F(B) and now you can do the cast. I guess realistically this can only happen at compile-time, since a run-time cast would naturally only look in module MA, not MB, for functions it could use to perform the cast. Presumably, it also requires that MA requested a run-time reflection table to be built, and is it possible to build a reflection table for a module over which you have no control? |
July 18, 2012 Re: Need runtime reflection? | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Piepgrass Attachments:
| On Tue, Jul 17, 2012 at 11:08 PM, David Piepgrass <qwertie256@gmail.com>wrote: > > I, too, was enamored with Go Interfaces and implemented them for .NET: > > http://www.codeproject.com/**Articles/87991/Dynamic-** interfaces-in-any-NET-language<http://www.codeproject.com/Articles/87991/Dynamic-interfaces-in-any-NET-language> Interesting, good article and project, thanks. And I wasn't the only one; later, someone else published another library > for .NET with the exact same goal. This is definitely a feature I would want to see in D, preferably as a first-class feature, although sadly that would break any code that relies on ISomething being pointer-sized; Go uses fat pointers, and we use a thin-pointer implementation in .NET but it's inefficient (as every cast creates a heap-allocated wrapper, and double-indirection is needed to reach the real method.) > D has powerful template and CTFE, seems we have more choices, fat pointer or thin pointer. I didn't think seriously about the performance differences. About every cast creates a heap-allocated wrapper, I think we can try to use lower cost way in D. In my code: -- void opAssign(V)(GoInterface!(V) v) if (is(V == interface)) { //pragma(msg, "assign for GoInterface"); static if (isImplicitlyConvertible!(V, T)) { //pragma(msg, V.stringof ~ " can implicitly convert to " ~ T.stringof); m_impl = v.m_impl; } else static if (isImplicitlyConvertible!(T, V)) { //pragma(msg, T.stringof ~ " can implicitly convert to " ~ V.stringof ~ ", try dynamic cast"); if (v.m_impl is null) { m_impl = null; } else { m_impl = cast(T)(v.m_impl); if (m_impl is null) { // dynamic cast failed, try dynamic proxy m_impl = buildDynamicProxy!(V)(v); } } } else { //pragma(msg, "cannot implicitly between " ~ V.stringof ~ " and " ~ T.stringof); static if (isInterfaceConvertible!(V, T)) { //pragma(msg, "generate static proxy to convert " ~ V.stringof ~ " to " ~ T.stringof); m_impl = new StaticProxy!(V)(v.m_impl); } else { //pragma(msg, V.stringof ~ " not compatible " ~ T.stringof ~ ", must dynamic build call proxy"); m_impl = buildDynamicProxy!(V)(v); } } } -- Some cases we can directly do assignment, it also can be optimized to reduce heap allocation. > > Anyway, they say it's possible to build runtime reflection in D but I've no idea how... has it never been done before? > Of course, runtime template instantiation won't be possible. Therefore, run-time casting will have to be more limited than compile-time casting. > > Reflection to free functions would be really nice, but it might be less capable at run-time. Consider if you there is a class A in third-party module MA that you want to cast to interface I, but class A is missing a function F() from I. So in your module (module MB) you define a free function F(B) and now you can do the cast. I guess realistically this can only happen at compile-time, since a run-time cast would naturally only look in module MA, not MB, for functions it could use to perform the cast. Presumably, it also requires that MA requested a run-time reflection table to be built, and is it possible to build a reflection table for a module over which you have no control? > Free functions support is hard, with runtime cast, I just think compile time. I am trying to support free functions at compile time, is also hard, since the generator in gointerface module, but other modules are only visible in the module that used these modules. I have an ugly implementation used compile time string mixin, trying to simplify it. Fighting. |
July 18, 2012 Re: Need runtime reflection? | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Piepgrass | On Tuesday, 17 July 2012 at 15:08:18 UTC, David Piepgrass wrote:
>> I want to imitate golang's interface in D, to study D's template. I wrote
>> some code: https://gist.github.com/3123593
>>
>> Now we can write code like golang:
>> --
>> interface IFoo {
>> void foo(int a, string b, float c);
>> }
>>
>> struct Foo {
>> void foo(int a, string b, float c) {
>> writeln("Foo.foo: ", a, ", ", b, ", ", c);
>> }
>> }
>>
>> struct FooFoo {
>> void foo(int a, string b, float c) {
>> writeln("FooFoo.foo: ", a, ", ", b, ", ", c);
>> }
>> }
>>
>> GoInterface!(IFoo) f = new Foo;
>> f.foo(3, "abc", 2.2);
>>
>> f = new FooFoo;
>> f.foo(5, "def", 7.7);
>> --
>>
>> It is also very naive, does not support some features, like out/ref
>> parameters, free functions *[1]* and so on. The biggest problem is downcast
>> not supported. In golang, we can write code like*[2]*:
>> --
>> var p IWriter = NewB(10)
>> p2, ok := p.(IReadWriter)
>> --
>>
>> Seems [p.(IReadWriter)] dynamically build a virtual table *[3]*,because the
>> type of "p" is IWriter, it is *smaller* than IReadWriter, the cast
>> operation must search methods and build vtbl at run time.
>>
>> In D, GoInterface(T).opAssign!(V)(V v) can build a rich runtime information
>> to *V* if we need. But if *V* is interface or base class, the type
>> information not complete. So, seems like I need runtime reflection? and how
>> can I do this in D? I did not find any useful information in the TypeInfo*.
>>
>> ------
>> [1] free functions support, e.g.
>> --
>> interface IFoo {
>> void foo(int a, string b, float c);
>> }
>> void foo(int self, int a, string b, float c) {
>> writefln("...");
>> }
>>
>> GoInterface!(int) p = 1;
>> p.foo(4, "ccc", 6.6);
>> --
>> In theory no problem.
>
> I, too, was enamored with Go Interfaces and implemented them for .NET:
>
> http://www.codeproject.com/Articles/87991/Dynamic-interfaces-in-any-NET-language
>
Interesting article, but why not just make use of "dynamic" interfaces?
--
Paulo
|
July 18, 2012 Re: Need runtime reflection? | ||||
---|---|---|---|---|
| ||||
Posted in reply to lijie | On 2012-07-18 06:10, lijie wrote: > Free functions support is hard, with runtime cast, I just think compile > time. It's possibly to implement runtime reflection by loading the running executable and inspecting the symbol table. It's an ugly hack but it should work. http://flectioned.kuehne.cn/ > I am trying to support free functions at compile time, is also hard, > since the generator in gointerface module, but other modules are only > visible in the module that used these modules. I have an ugly > implementation used compile time string mixin, trying to simplify it. > Fighting. I think you can pass a module to a template via an alias parameter. Then the template should be able to inspect all free functions using something like __traits(allMembers). -- /Jacob Carlborg |
July 18, 2012 Re: Need runtime reflection? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg Attachments:
| On Wed, Jul 18, 2012 at 2:59 PM, Jacob Carlborg <doob@me.com> wrote: > On 2012-07-18 06:10, lijie wrote: > > Free functions support is hard, with runtime cast, I just think compile >> time. >> > > It's possibly to implement runtime reflection by loading the running executable and inspecting the symbol table. It's an ugly hack but it should work. > > http://flectioned.kuehne.cn/ It is an optional way. I want to do all thing in D code. > > > I am trying to support free functions at compile time, is also hard, >> since the generator in gointerface module, but other modules are only visible in the module that used these modules. I have an ugly implementation used compile time string mixin, trying to simplify it. Fighting. >> > > I think you can pass a module to a template via an alias parameter. Then the template should be able to inspect all free functions using something like __traits(allMembers). I didn't know this usage, I will try it. Thanks. |
July 18, 2012 Re: Need runtime reflection? | ||||
---|---|---|---|---|
| ||||
Posted in reply to lijie | On 2012-07-18 09:26, lijie wrote: > It is an optional way. I want to do all thing in D code. You can do this in D. -- /Jacob Carlborg |
July 18, 2012 Re: Need runtime reflection? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg Attachments:
| On Wed, Jul 18, 2012 at 2:59 PM, Jacob Carlborg <doob@me.com> wrote:
> I think you can pass a module to a template via an alias parameter. Then the template should be able to inspect all free functions using something like __traits(allMembers).
>
>
Have a problem.
--
// file: A.d
module A;
// functions and classes
--
--
// file: testtraits.d
import std.stdio;
import A;
void main() {
writeln(__traits(allMembers, A));
}
--
There is a compilation error:
testtraits.d(6): Error: import A has no members
If module is under a package name, it is OK, is that a bug?
|
July 18, 2012 Re: Need runtime reflection? | ||||
---|---|---|---|---|
| ||||
Posted in reply to lijie | On 2012-07-18 17:10, lijie wrote: > On Wed, Jul 18, 2012 at 2:59 PM, Jacob Carlborg <doob@me.com > <mailto:doob@me.com>> wrote: > > I think you can pass a module to a template via an alias parameter. > Then the template should be able to inspect all free functions using > something like __traits(allMembers). > > > Have a problem. > > -- > // file: A.d > > module A; > > // functions and classes > -- > > -- > // file: testtraits.d > > import std.stdio; > import A; > > void main() { > writeln(__traits(allMembers, A)); > } > -- > > There is a compilation error: > testtraits.d(6): Error: import A has no members > > If module is under a package name, it is OK, is that a bug? > Seems like it. http://d.puremagic.com/issues/ -- /Jacob Carlborg |
Copyright © 1999-2021 by the D Language Foundation