digitalmars.D - Need runtime reflection?
- lijie (57/57) Jul 16 2012 I want to imitate golang's interface in D, to study D's template. I wrot...
- David Piepgrass (27/85) Jul 17 2012 I, too, was enamored with Go Interfaces and implemented them for
- lijie (53/76) Jul 17 2012 Interesting, good article and project, thanks.
- Jacob Carlborg (10/17) Jul 17 2012 It's possibly to implement runtime reflection by loading the running
- lijie (3/20) Jul 18 2012 I didn't know this usage, I will try it. Thanks.
- Jacob Carlborg (4/5) Jul 18 2012 You can do this in D.
- lijie (18/21) Jul 18 2012 Have a problem.
- Jacob Carlborg (5/27) Jul 18 2012 Seems like it.
- Paulo Pinto (5/76) Jul 17 2012 Interesting article, but why not just make use of "dynamic"
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 =3D new Foo; f.foo(3, "abc", 2.2); f =3D 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 =3D NewB(10) p2, ok :=3D p.(IReadWriter) -- Seems [p.(IReadWriter)] dynamically build a virtual table *[3]*=EF=BC=8Cbec= ause 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 =3D 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/inter= face.go [3] /path/of/go/src/pkg/runtime/iface.c: static Itab* itab(InterfaceType *inter, Type *type, int32 canfail) Best regards, -- Li Jie
Jul 16 2012
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?
Jul 17 2012
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 libraryfor .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.
Jul 17 2012
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
Jul 17 2012
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 compileIt is an optional way. I want to do all thing in D code.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,I didn't know this usage, I will try it. Thanks.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).
Jul 18 2012
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
Jul 18 2012
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?
Jul 18 2012
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
Jul 18 2012
On Tuesday, 17 July 2012 at 15:08:18 UTC, David Piepgrass wrote:Interesting article, but why not just make use of "dynamic" interfaces? -- PauloI 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
Jul 17 2012