Re: How can I do that in @nogc?

2015-02-25 Thread Ivan Timokhin via Digitalmars-d-learn
On Wed, Feb 25, 2015 at 07:32:48PM +, Namespace wrote:
 
 void glCheck(lazy void func, string file = __FILE__, uint line = 
 __LINE__) {
   func();
   glCheckError(file, line);
 }
 
 
 How can I specify that 'func' is @nogc? Or can define the 
 function otherwise?

Try

void glCheck(scope void delegate() @nogc func,...)


How can I do that in @nogc?

2015-02-25 Thread Namespace via Digitalmars-d-learn


void glCheck(lazy void func, string file = __FILE__, uint line = 
__LINE__) {

func();
glCheckError(file, line);
}


How can I specify that 'func' is @nogc? Or can define the 
function otherwise?


Re: How can I do that in @nogc?

2015-02-25 Thread Namespace via Digitalmars-d-learn
On Wednesday, 25 February 2015 at 19:53:16 UTC, Ivan Timokhin 
wrote:

On Wed, Feb 25, 2015 at 07:32:48PM +, Namespace wrote:


void glCheck(lazy void func, string file = __FILE__, uint line 
= __LINE__) {

func();
glCheckError(file, line);
}


How can I specify that 'func' is @nogc? Or can define the 
function otherwise?


Try

void glCheck(scope void delegate() @nogc func,...)


That seems not to work:

Error: function test.glCheck (scope void delegate() @nogc func, 
...) is not callable using argument types (void)




Re: How can I do that in @nogc?

2015-02-25 Thread Namespace via Digitalmars-d-learn

On Wednesday, 25 February 2015 at 20:15:10 UTC, anonymous wrote:

On Wednesday, 25 February 2015 at 19:32:50 UTC, Namespace wrote:


void glCheck(lazy void func, string file = __FILE__, uint line 
= __LINE__) {

func();
glCheckError(file, line);
}


How can I specify that 'func' is @nogc? Or can define the 
function otherwise?


First of all, if glCheck always uses/evaluates func, then there 
is no point in making it lazy.


On to the @nogc vs. lazy issue.

Simpler test case:
---
void glCheck(scope lazy int thing) @nogc {auto x = thing;}
int costly() @nogc {return 42;}
void main() @nogc
{
glCheck(costly()); /* A */
int x; glCheck(x); /* B */
}
---

I guess, the compiler could see that the delegate made for the 
lazy parameter must be @nogc. But it doesn't. So it tries to 
call a non-@nogc delegate in a @nogc function which fails of 
course.


You can make the delegate explicit so that you can tag the 
delegate as @nogc yourself:

---
void glCheck(scope int delegate() @nogc thing) @nogc {auto x = 
thing();}

int costly() @nogc {return 42;}
void main() @nogc
{
glCheck(()=costly());
int x; glCheck(()=x);
}
---

The calls are not as nice, requiring an explicit delegate 
(()=), but it works.


It may be possible to hack through this limitation - NOT 
THOUGHT-OUT, NOT TESTED, NOT RECOMMENDED:

---
void glCheck(scope lazy int thing) @nogc;
pragma(mangle, glCheck.mangleof) void glCheckImpl(scope int 
delegate() @nogc thing) @nogc {auto x = thing();}

int costly() @nogc {return 42;}
void main() @nogc
{
glCheck(costly());
int x; glCheck(x);
}
---


That last thing works. But I have no clue why. o.O
Anyway, thanks a lot!


Re: How can I do that in @nogc?

2015-02-25 Thread ketmar via Digitalmars-d-learn
On Wed, 25 Feb 2015 20:36:32 +, Namespace wrote:

 That last thing works. But I have no clue why. o.O Anyway, thanks a lot!

this is a smart hack. that should be NEVER used in production code.

anyway, it's good that you don't understand it. your code will crash 
sooner or later, and you will be forced to remove that trick.

signature.asc
Description: PGP signature


Re: How can I do that in @nogc?

2015-02-25 Thread anonymous via Digitalmars-d-learn

On Wednesday, 25 February 2015 at 19:32:50 UTC, Namespace wrote:


void glCheck(lazy void func, string file = __FILE__, uint line 
= __LINE__) {

func();
glCheckError(file, line);
}


How can I specify that 'func' is @nogc? Or can define the 
function otherwise?


First of all, if glCheck always uses/evaluates func, then there 
is no point in making it lazy.


On to the @nogc vs. lazy issue.

Simpler test case:
---
void glCheck(scope lazy int thing) @nogc {auto x = thing;}
int costly() @nogc {return 42;}
void main() @nogc
{
glCheck(costly()); /* A */
int x; glCheck(x); /* B */
}
---

I guess, the compiler could see that the delegate made for the 
lazy parameter must be @nogc. But it doesn't. So it tries to call 
a non-@nogc delegate in a @nogc function which fails of course.


You can make the delegate explicit so that you can tag the 
delegate as @nogc yourself:

---
void glCheck(scope int delegate() @nogc thing) @nogc {auto x = 
thing();}

int costly() @nogc {return 42;}
void main() @nogc
{
glCheck(()=costly());
int x; glCheck(()=x);
}
---

The calls are not as nice, requiring an explicit delegate 
(()=), but it works.


It may be possible to hack through this limitation - NOT 
THOUGHT-OUT, NOT TESTED, NOT RECOMMENDED:

---
void glCheck(scope lazy int thing) @nogc;
pragma(mangle, glCheck.mangleof) void glCheckImpl(scope int 
delegate() @nogc thing) @nogc {auto x = thing();}

int costly() @nogc {return 42;}
void main() @nogc
{
glCheck(costly());
int x; glCheck(x);
}
---


Re: How can I do that in @nogc?

2015-02-25 Thread Namespace via Digitalmars-d-learn

On Wednesday, 25 February 2015 at 20:46:32 UTC, ketmar wrote:

On Wed, 25 Feb 2015 20:36:32 +, Namespace wrote:

That last thing works. But I have no clue why. o.O Anyway, 
thanks a lot!


this is a smart hack. that should be NEVER used in production 
code.


anyway, it's good that you don't understand it. your code will 
crash

sooner or later, and you will be forced to remove that trick.


Instead of some wise talk, you could simply explain it. ;)
The code is only used for debugging purposes.


Re: How can I do that in @nogc?

2015-02-25 Thread TheFlyingFiddle via Digitalmars-d-learn

On Wednesday, 25 February 2015 at 19:32:50 UTC, Namespace wrote:
How can I specify that 'func' is @nogc? Or can define the 
function otherwise?


An alternative solution would be to use function
templated on an alias.

import std.traits;
void glCheck(alias func)(string file = __FILE__,
 size_t line = __LINE__) @nogc
if(isCallable!func)
{
func();
glCheckError(file, line);
}


void foo() { new int(5); } //Uses GC
void bar() @nogc { /* ... */ } //Does not use GC

unittest
{
//Calling is a little different
glCheck!foo; //Does not compile not @nogc
glCheck!bar; //Works like a charm.
}


//If you wanted to take arguments to func
//it can be done like this.
void glCheck(alias func,
 string file = __FILE__,
 size_t line = __LINE__,
 Args...)(auto ref Args args) @nogc
 if(isCallable!func)
{
func(args);
glCheckError(file, line);
}

void buz(string a, uint b, float c) @nogc { /* ... */ }

unittest
{
   //Calling looks like this.
   glCheck!buz(foobar, 0xBAADF00D, 42.0f);
}



Re: How can I do that in @nogc?

2015-02-25 Thread ketmar via Digitalmars-d-learn
On Wed, 25 Feb 2015 21:32:02 +, Namespace wrote:

 Instead of some wise talk, you could simply explain it. ;)

i can, but i certainly don't want to. many people are reading this forum, 
and i don't want to teach 'em something like this.

signature.asc
Description: PGP signature


Re: How can I do that in @nogc?

2015-02-25 Thread ketmar via Digitalmars-d-learn
On Wed, 25 Feb 2015 21:32:02 +, Namespace wrote:

 The code is only used for debugging purposes.

the best way to make your program undebugable is to use debugging code 
that will be turned off in production. this way you aren't debugging the 
code that will go into production, you debugging something different.

signature.asc
Description: PGP signature


Re: How can I do that in @nogc?

2015-02-25 Thread anonymous via Digitalmars-d-learn

On Wednesday, 25 February 2015 at 20:36:33 UTC, Namespace wrote:

On Wednesday, 25 February 2015 at 20:15:10 UTC, anonymous wrote:

[...]
It may be possible to hack through this limitation - NOT 
THOUGHT-OUT, NOT TESTED, NOT RECOMMENDED:

---
void glCheck(scope lazy int thing) @nogc;
pragma(mangle, glCheck.mangleof) void glCheckImpl(scope int 
delegate() @nogc thing) @nogc {auto x = thing();}

int costly() @nogc {return 42;}
void main() @nogc
{
   glCheck(costly());
   int x; glCheck(x);
}
---


That last thing works. But I have no clue why. o.O
Anyway, thanks a lot!


I advise you to not use it. It's a hack that relies on 
implementation details of the compiler.


As for how it works:

pragma(mangle, ...) sets the mangled name of the following 
symbol. The mangled name is similar to the fully qualified 
name, but it includes parameter types and such. So different 
overloads of a function have different mangled names, while 
sharing one fully qualified name.


Giving glCheckImpl the same mangled name as glCheck means they 
then refer to the same code despite having different signatures. 
This bypasses the type system. DON'T DO THIS.


So, whenever glCheck is called, really glCheckImpl is called, and 
the `scope lazy int` argument is interpreted as a `scope int 
delegate() @nogc` argument.


This works, because currently the compiler creates delegates for 
lazy arguments and calls those delegates when the arguments are 
accessed. So right now, `lazy int` is the same as `int 
delegate()` under the hood. But this is not guaranteed. The 
compiler is free to do this differently. It may depend on 
compiler flags, etc. SO DON'T DO THIS.