www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Figuring out the returntype opDipatch

reply "TheFlyingFiddle" <theflyingfiddle gmail.com> writes:
I'm currently working on a IReflectionable interface

Currently the usage is as follows

class Foo : IReflectionable
{
   mixin ReflectionImpl;

   void bar(int a) { /* do something */ }
   int baz(string a) { return a.length; }

}

unittest
{
    IReflectionable foo = new Foo();

    alias void delegate(int) bar_t;

    auto bar = foo.funcPtr!(bar_t, "bar"); //Gets a delegate to 
foo.bar
    bar(1); //Calls foo.bar(1);

    alias int delegate(string) baz_t;
    auto baz = foo.funcPtr!(baz_t, "baz");
    int a = baz("Hello");
}

Now this works and is all well and good. However i would like to 
improve on the
syntax a bit.

This is how i would like to call the code.

unittest
{
   IReflectionable foo = new FooService();

   foo.bar(1); //Now this becomes foo.opDispatch!("bar", int)(1);

   int a = foo.baz("Hello"); //This does NOT work. Cannot figure 
out returntype
}

The problem i am faced with is that i need a way to figure out 
the return value of opDispatch by the invokation call.

all the information i need is here

int a = foo.baz("hello");

This gives returntype int.

So is there a way to gain this information in opDspatch? Is it 
possible to do something like this?

auto a = foo.baz!(int)("hello");
Nov 02 2013
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/02/2013 03:41 PM, TheFlyingFiddle wrote:
 I'm currently working on a IReflectionable interface

 Currently the usage is as follows

 class Foo : IReflectionable
 {
    mixin ReflectionImpl;

    void bar(int a) { /* do something */ }
    int baz(string a) { return a.length; }

 }

 unittest
 {
     IReflectionable foo = new Foo();

     alias void delegate(int) bar_t;

     auto bar = foo.funcPtr!(bar_t, "bar"); //Gets a delegate to foo.bar
     bar(1); //Calls foo.bar(1);

     alias int delegate(string) baz_t;
     auto baz = foo.funcPtr!(baz_t, "baz");
     int a = baz("Hello");
 }

 Now this works and is all well and good. However i would like to improve
 on the
 syntax a bit.

 This is how i would like to call the code.

 unittest
 {
    IReflectionable foo = new FooService();

    foo.bar(1); //Now this becomes foo.opDispatch!("bar", int)(1);

    int a = foo.baz("Hello"); //This does NOT work. Cannot figure out
 returntype
 }

 The problem i am faced with is that i need a way to figure out the
 return value of opDispatch by the invokation call.

 all the information i need is here

 int a = foo.baz("hello");

 This gives returntype int.

 So is there a way to gain this information in opDspatch? Is it possible
 to do something like this?

 auto a = foo.baz!(int)("hello");
Can you provide a little more complete code please. Otherwise, the return type is available to typeof: import std.stdio; struct S { auto opDispatch(string name, T...)(T parameters) { writef("S.%s:", name); foreach (parameter; parameters) { writef(" %s", parameter); } writeln(); return parameters[$/2]; } } void main() { auto s = S(); auto r0 = s.foo(42, 1.5, "hi"); auto r1 = s.bar("hello", 'a', 100); static assert (is (typeof(r0) == double)); static assert (is (typeof(r1) == char)); } Ali
Nov 02 2013
parent reply "TheFlyingFiddle" <theflyingfiddle gmail.com> writes:
 Can you provide a little more complete code please. Otherwise, 
 the return type is available to typeof:

 import std.stdio;

 struct S
 {
     auto opDispatch(string name, T...)(T parameters)
     {
         writef("S.%s:", name);
         foreach (parameter; parameters) {
             writef(" %s", parameter);
         }
         writeln();

         return parameters[$/2];
     }
 }

 void main()
 {
     auto s = S();

     auto r0 = s.foo(42, 1.5, "hi");
     auto r1 = s.bar("hello", 'a', 100);

     static assert (is (typeof(r0) == double));
     static assert (is (typeof(r1) == char));
 }

 Ali
In the IReflectionable interface: interface IReflectionable { final P funcPtr(P)(string fun) if (is(P == delegate)) { //Using mangeling for overloads and type safety auto ptr = delPtr_impl(mangle!P(fun)); P del; del.ptr = cast(typeof(del.ptr))ptr[0]; del.funcptr = cast(typeof(del.funcptr))ptr[1]; return del; } final P funcPtr(P)(string fun) if (is(P == function)) { //Using mangeling for overloads and type safety auto ptr = funcPtr_impl(mangle!(P)(fun)); return cast(P)ptr; } final ?? opDispatch(string name, Params...)(Params params) { alias ?? delegate(Params) del_type; auto del = funcPtr!(del_type)(name); static if(?? == void) del(params); else return del(params); } protected Tuple!(void*, void*) delPtr_impl(string s); protected void* funcPtr_impl(string s); } What i'm interested in is determining what type ?? should be. Variant works but if possible i would like to avoid it. This would require me to know about the code at the invokation site. (So i'm guessing it might not be possible)
Nov 02 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-11-03 03:15, TheFlyingFiddle wrote:

 In the IReflectionable interface:

 interface IReflectionable
 {
      final P funcPtr(P)(string fun) if (is(P == delegate))
      {
          //Using mangeling for overloads and type safety
      auto ptr = delPtr_impl(mangle!P(fun));

      P del;
      del.ptr = cast(typeof(del.ptr))ptr[0];
      del.funcptr = cast(typeof(del.funcptr))ptr[1];
      return del;
      }

      final P funcPtr(P)(string fun) if (is(P == function))
      {
          //Using mangeling for overloads and type safety
      auto ptr = funcPtr_impl(mangle!(P)(fun));
      return cast(P)ptr;
      }

      final ?? opDispatch(string name, Params...)(Params params)
      {
         alias ?? delegate(Params) del_type;
         auto del = funcPtr!(del_type)(name);

         static if(?? == void)
            del(params);
         else
            return del(params);
      }

      protected Tuple!(void*, void*) delPtr_impl(string s);
      protected void* funcPtr_impl(string s);
 }

 What i'm interested in is determining what type ?? should be. Variant
 works but if possible i would like to avoid it. This would require me to
 know about the code at the invokation site. (So i'm guessing it might
 not be possible)
I have the same problem as well. I haven't figured out the best way to solve this yet. -- /Jacob Carlborg
Nov 03 2013
parent reply "TheFlyingFiddle" <theflyingfiddle gmail.com> writes:
On Sunday, 3 November 2013 at 10:48:45 UTC, Jacob Carlborg wrote:
 On 2013-11-03 03:15, TheFlyingFiddle wrote:

 In the IReflectionable interface:

 interface IReflectionable
 {
     final P funcPtr(P)(string fun) if (is(P == delegate))
     {
         //Using mangeling for overloads and type safety
     auto ptr = delPtr_impl(mangle!P(fun));

     P del;
     del.ptr = cast(typeof(del.ptr))ptr[0];
     del.funcptr = cast(typeof(del.funcptr))ptr[1];
     return del;
     }

     final P funcPtr(P)(string fun) if (is(P == function))
     {
         //Using mangeling for overloads and type safety
     auto ptr = funcPtr_impl(mangle!(P)(fun));
     return cast(P)ptr;
     }

     final ?? opDispatch(string name, Params...)(Params params)
     {
        alias ?? delegate(Params) del_type;
        auto del = funcPtr!(del_type)(name);

        static if(?? == void)
           del(params);
        else
           return del(params);
     }

     protected Tuple!(void*, void*) delPtr_impl(string s);
     protected void* funcPtr_impl(string s);
 }

 What i'm interested in is determining what type ?? should be. 
 Variant
 works but if possible i would like to avoid it. This would 
 require me to
 know about the code at the invokation site. (So i'm guessing 
 it might
 not be possible)
I have the same problem as well. I haven't figured out the best way to solve this yet.
Might this be something you could solve using the DIP50 AST macros? Something like interface IRefectionable { //I'm assuming you can use a macro as opDispatch macro opDispatch(string s, Params...)(Context context, Ast!(Params) ast) { //The name is sort of bad enum returnType = context.?? //Look at the stuff in the context to figure out what the returnType would be. return <| alias ?? delegate(Params) del_type; auto del = funcPtr!(del_type)(name); static if(?? == void) del(params); else return del(params); } } unittest { IReflectionable refl = new Foo(); refl.bar(1); //void is infered since not setting any value. int baz = refl.baz("Hello"); auto baz2 = refl.baz("hello"); //Can't work. }
Nov 14 2013
next sibling parent reply "TheFlyingFiddle" <theflyingfiddle gmail.com> writes:
On Thursday, 14 November 2013 at 20:39:35 UTC, TheFlyingFiddle 
wrote:
 On Sunday, 3 November 2013 at 10:48:45 UTC, Jacob Carlborg 
 wrote:
 On 2013-11-03 03:15, TheFlyingFiddle wrote:

 In the IReflectionable interface:

 interface IReflectionable
 {
    final P funcPtr(P)(string fun) if (is(P == delegate))
    {
        //Using mangeling for overloads and type safety
    auto ptr = delPtr_impl(mangle!P(fun));

    P del;
    del.ptr = cast(typeof(del.ptr))ptr[0];
    del.funcptr = cast(typeof(del.funcptr))ptr[1];
    return del;
    }

    final P funcPtr(P)(string fun) if (is(P == function))
    {
        //Using mangeling for overloads and type safety
    auto ptr = funcPtr_impl(mangle!(P)(fun));
    return cast(P)ptr;
    }

    final ?? opDispatch(string name, Params...)(Params params)
    {
       alias ?? delegate(Params) del_type;
       auto del = funcPtr!(del_type)(name);

       static if(?? == void)
          del(params);
       else
          return del(params);
    }

    protected Tuple!(void*, void*) delPtr_impl(string s);
    protected void* funcPtr_impl(string s);
 }

 What i'm interested in is determining what type ?? should be. 
 Variant
 works but if possible i would like to avoid it. This would 
 require me to
 know about the code at the invokation site. (So i'm guessing 
 it might
 not be possible)
I have the same problem as well. I haven't figured out the best way to solve this yet.
Might this be something you could solve using the DIP50 AST macros? Something like interface IRefectionable { //I'm assuming you can use a macro as opDispatch macro opDispatch(string s, Params...)(Context context, Ast!(Params) ast) { //The name is sort of bad enum returnType = context.?? //Look at the stuff in the context to figure out what the returnType would be. return <| alias ?? delegate(Params) del_type; auto del = funcPtr!(del_type)(name); static if(?? == void) del(params); else return del(params); } } unittest { IReflectionable refl = new Foo(); refl.bar(1); //void is infered since not setting any value. int baz = refl.baz("Hello"); auto baz2 = refl.baz("hello"); //Can't work. }
Edit: ?? should be replaced with $returnType
Nov 14 2013
parent reply "TheFlyingFiddle" <theflyingfiddle gmail.com> writes:
After looking at the DIP some more i can see that my suggestion 
implementation does not make any sense (and i missed some of the 
syntax). If it can be done with AST's i don't have a sugestion 
for it.
Nov 14 2013
parent Jacob Carlborg <doob me.com> writes:
On 2013-11-14 22:02, TheFlyingFiddle wrote:
 After looking at the DIP some more i can see that my suggestion
 implementation does not make any sense (and i missed some of the
 syntax). If it can be done with AST's i don't have a sugestion for it.
If you have the an example like: int a = foo.baz("Hello"); And the context parameter allows you do determine the type of "a", then it would be possible. But you would still have problems with usages like these: auto a = foo.baz("Hello"); And: void bar (T) (T t) { } bar(foo.baz("Hello")); Both of these requires some fallback type. -- /Jacob Carlborg
Nov 15 2013
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-11-14 21:39, TheFlyingFiddle wrote:

 Might this be something you could solve using the DIP50 AST macros?
Possibly, if the context parameter provides enough information about where the macro is used. -- /Jacob Carlborg
Nov 15 2013
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/02/2013 03:41 PM, TheFlyingFiddle wrote:

 The problem i am faced with is that i need a way to figure out the
 return value of opDispatch by the invokation call.
If I now understand you correctly, what initially confused my was "invocation call." Because "invocation" makes me think about the actual arguments of the functino call.
 all the information i need is here

 int a = foo.baz("hello");

 This gives returntype int.
So, what you are trying to do is to get the return type from the left-hand side of the assignment operator.
 So is there a way to gain this information in opDspatch?
I don't think so. You can always return a special (similar to Variant that you mentioned) and play with automatic type conversions no that type.
 Is it possible to do something like this?

 auto a = foo.baz!(int)("hello");
Hmmm. I don't think so. "baz" itself becomes the first argument of opDispatch. So I tried the following ugly thing but it does not work either: import std.stdio; struct S { R opDispatch(string name, R, T...)(T parameters) { return R.init; } } void main() { auto s = S(); auto r0 = s.foo!("foo", int)("hello"); // does not compile auto r1 = s.bar!("bar", double)(100); static assert (is (typeof(r0) == int)); static assert (is (typeof(r1) == double)); } Ali
Nov 02 2013
parent "TheFlyingFiddle" <theflyingfiddle gmail.com> writes:
 struct S
 {
     R opDispatch(string name, R, T...)(T parameters)
     {
         return R.init;
     }
 }

 void main()
 {
     auto s = S();

     auto r0 = s.foo!("foo", int)("hello");    // does not 
 compile
     auto r1 = s.bar!("bar", double)(100);

     static assert (is (typeof(r0) == int));
     static assert (is (typeof(r1) == double));
 }

 Ali
I decided to go with the following: interface IReflectionable { final void call(string name, Params...)(Params params) { //code for getting pointer. } final void call(Params...)(string name, Params params) { //code for getting pointer. } final R call(R, Params...)(string name, Params params) { //code for getting pointer. return R.init; } final R call(R, string method, Params...)(Params params) { //code for getting pointer. return R.init; } } unittest { auto foo = new Foo(); string hello = "Hello"; int a = 10; foo.call!("bar")(a); //Infers void return type and int parameter. auto r1 = foo.call!(int, "baz")(hello); //Return type is int and infers string parameter. foo.call("bar", a); //Infers void return type and int parameter. foo.call!(int)("baz", hello); //Return type is int and infers sting parameter. } Sadly i could not get opDispatch to work either :( Idealy i would like to have foo.baz!(int)(hello) working but i guess since it's a template the compiler is unable to convert it into foo.opDispatch!("baz", int)(hello); Thanks for all the help Ali.
Nov 02 2013