www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - non-global template fix POC WIP

reply Suleyman <sahmi.soulaimane gmail.com> writes:
Hello everyone.

I started working on a fix for the non-global template issue.
Progress at https://github.com/dlang/dmd/pull/9282

currently the following POC works:
```
struct S
{
     int m;

     auto add(alias a)(int b)
     {
         return a + m + b;
     }

     auto exec(alias f)()
     {
         f(m);
     }
}

void main()
{
     int a = 4;
     auto o = S(3);

     assert(o.add!a(2) == 4+3+2);

     auto dg = &o.add!a;
     assert(dg(7) == 4+3+7);

     int b;
     auto bSetter(int i) { b = i; }

     o.exec!bSetter();
     assert(b == 3);

     /* S.add instantiated to:

         auto add(int b)
         {
             return main.a + main.o.m + b;
         }

         thus only requires the frame pointer of `main`
     */
}
```

The strategy is to access the `this` variable through the frame 
pointer of the caller.
Jan 22 2019
next sibling parent reply Suleyman <sahmi.soulaimane gmail.com> writes:
I think it's ready for use. I would appreciate it if someone can 
break it and produce a test case.
Jan 26 2019
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Saturday, 26 January 2019 at 12:06:48 UTC, Suleyman wrote:
 I think it's ready for use. I would appreciate it if someone 
 can break it and produce a test case.
I downloaded your branch and created this example that doesn't work: --------------------------------------------------------- import core.stdc.stdio : printf; struct Adder { int base; // works uint addBaseCallFunc(alias func)(uint value) { return func(base + value); } // these 2 don't work uint willNeedThreeContextPtrs(alias func)(uint value) { int localVar = func(value); uint localFunc(uint subValue) { return localVar + subValue; } return addBaseCallFuncs!(func, localFunc)(value); } uint addBaseCallFuncs(alias func1, alias func2)(uint value) { return func2(func1(base + value)); } } void main() { auto adder = Adder(3); int offset = 6; uint doOffset(uint value) { return offset + value; } // works printf("%d\n", adder.addBaseCallFunc!doOffset(4)); // need 3 context pointers (doesn't work) printf("%d\n", adder.willNeedThreeContextPtrs!doOffset(4)); }
Jan 27 2019
next sibling parent Jonathan Marler <johnnymarler gmail.com> writes:
On Sunday, 27 January 2019 at 18:13:49 UTC, Jonathan Marler wrote:
 On Saturday, 26 January 2019 at 12:06:48 UTC, Suleyman wrote:
 I think it's ready for use. I would appreciate it if someone 
 can break it and produce a test case.
I downloaded your branch and created this example that doesn't work: --------------------------------------------------------- import core.stdc.stdio : printf; struct Adder { int base; // works uint addBaseCallFunc(alias func)(uint value) { return func(base + value); } // these 2 don't work uint willNeedThreeContextPtrs(alias func)(uint value) { int localVar = func(value); uint localFunc(uint subValue) { return localVar + subValue; } return addBaseCallFuncs!(func, localFunc)(value); } uint addBaseCallFuncs(alias func1, alias func2)(uint value) { return func2(func1(base + value)); } } void main() { auto adder = Adder(3); int offset = 6; uint doOffset(uint value) { return offset + value; } // works printf("%d\n", adder.addBaseCallFunc!doOffset(4)); // need 3 context pointers (doesn't work) printf("%d\n", adder.willNeedThreeContextPtrs!doOffset(4)); }
Here's another one that seems to compile, but fails at runtime (it doesn't print anything): import core.stdc.stdio : printf; struct Adder { int base; uint addBaseCallFuncs(alias func1, alias func2)(uint value) { return func2(func1(base + value)); } } void main() { auto adder = Adder(3); int offset = 6; uint doOffset1(uint value) { return offset + value; } void anotherFunc() { int anotherVar = 11; uint doOffset2(uint value) { return anotherVar + value; } printf("%d\n", adder.addBaseCallFuncs!(doOffset1, doOffset2)(4)); } }
Jan 27 2019
prev sibling parent Suleyman <sahmi.soulaimane gmail.com> writes:
On Sunday, 27 January 2019 at 18:13:49 UTC, Jonathan Marler wrote:

 I downloaded your branch and created this example that doesn't 
 work:
 ...
Good catch! try again it should work now. Thanks. Looking forward to your next case.
Jan 27 2019
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 22.01.19 23:26, Suleyman wrote:
 
 
 I started working on a fix for the non-global template issue.
Thank you!
Jan 27 2019
parent reply Suleyman <sahmi.soulaimane gmail.com> writes:
On Sunday, 27 January 2019 at 22:25:20 UTC, Timon Gehr wrote:
 Thank you!
The pleasure is mine. This was number one on my list of the most irritating limitations.
Jan 29 2019
parent Suleyman <sahmi.soulaimane gmail.com> writes:
Hello,

I finished working on my solution I should be pretty solid now 
with a good number of unitests and corner cases covered. waiting 
for your replies.

link: https://github.com/dlang/dmd/pull/9282

I dropped the initial strategy instead I decided to use a static 
array of two pointer `void*[2]*` and making this one a closure 
variable thus it will be GC-allocated only when the function 
escapes.

example:
```
struct S
{
     auto func(alias a)() { ++a; }
}

void noClosure()
{
     int a;       // stack allocated
     auto s = S();
                 // v implicit var `void*[2] __this;` stack 
allocated
     s.func!a(); // no closure made
}

void withClosure()
{
     int a;               // closure var GC allocated
     auto s = S();
                          // v implicit closure var `void*[2] 
__this;` GC allocated
     auto dg = &s.func!a; // closure made
}
```
Apr 12 2019