www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Idea: Context sensitive attribute functions.

reply 12345swordy <alexanderheistermann gmail.com> writes:
Pseudocode:
void example()
{
static if(Context =  nogc)
{
//nogc implementation
}
else
{
//gc implementation
}
}

This is useful as it eliminate the need to create multiple 
functions for each possible system attribute hence reducing 
redundant code. There are advantages of having a gc/unsafe/throw 
code. Why not use them if given the opportunity based on its 
context?

- Alex
Jun 19 2018
parent reply Dennis <dkorpel gmail.com> writes:
On Tuesday, 19 June 2018 at 19:03:44 UTC, 12345swordy wrote:
 Why not use them if given the opportunity based on its context?
You can do that if you want ``` import std.stdio; import core.stdc.stdio; void main() nogc { int a = 8; static if (__traits(compiles, new int(0))) { writefln("writeln %d", a); } else { printf("printf %d", a); } } ```
Jun 19 2018
next sibling parent reply Dennis <dkorpel gmail.com> writes:
On Tuesday, 19 June 2018 at 21:06:16 UTC, Dennis wrote:
 On Tuesday, 19 June 2018 at 19:03:44 UTC, 12345swordy wrote:
 Why not use them if given the opportunity based on its context?
You can do that if you want
Although it doesn't seem to work in attribute interference of templates. ``` void main() nogc { example(); } void example()() { int a = 8; static if (__traits(compiles, new int(0))) { writefln("writeln %d", a); } else { printf("printf %d", a); } } ``` onlineapp.d(5): Error: nogc function D main cannot call non- nogc function onlineapp.example!().example Maybe there's some workaround?
Jun 19 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, June 19, 2018 21:11:10 Dennis via Digitalmars-d wrote:
 On Tuesday, 19 June 2018 at 21:06:16 UTC, Dennis wrote:
 On Tuesday, 19 June 2018 at 19:03:44 UTC, 12345swordy wrote:
 Why not use them if given the opportunity based on its context?
You can do that if you want
Although it doesn't seem to work in attribute interference of templates. ``` void main() nogc { example(); } void example()() { int a = 8; static if (__traits(compiles, new int(0))) { writefln("writeln %d", a); } else { printf("printf %d", a); } } ``` onlineapp.d(5): Error: nogc function D main cannot call non- nogc function onlineapp.example!().example Maybe there's some workaround?
Whether a function is nogc has nothing to do with where it's called from. It has to do with what it calls. As such, new int(0) compiles just fine inside of your example function, and that branch is compiled in, making it so that the function is not nogc. I am not aware of any way to make a function's attributes depend on what calls it. The closest would be if you changed what it did based on its template arguments - which would mean doing something like passing a bool or flag indicating whether the function should be compiled as nogc or not. I don't think that it's possible to have a function be compiled differently based on where it's called from. Attribute inference is all about inferring the attributes of the templated function based on its implementation, not adjusting its implementation based on where it's used. - Jonathan M Davis
Jun 19 2018
parent reply Dennis <dkorpel gmail.com> writes:
On Tuesday, 19 June 2018 at 21:38:14 UTC, Jonathan M Davis wrote:
 Attribute inference is all about inferring the attributes of 
 the templated function based on its implementation, not 
 adjusting its implementation based on where it's used.
Indeed, I realised that the same template instantiation can't possibly have both a nogc and gc version, so there has to be a template parameter. You can automatically set one however: ``` void main() nogc { example(); } void example(string callee = __FUNCTION__)() { int a = 8; static if (isNoGc!callee) { printf("printf %d", a); } else { writefln("writeln %d", a); } } bool isNoGc(string functionName)() { import std.algorithm; mixin(`return [__traits(getFunctionAttributes, `~functionName~`)].canFind(" nogc");`); } ``` This seems to work. I'm not sure how robust it is though. You might need an extra `mixin("import "~functionName~";");` in `isNoGc` when it's called from other modules (if that helps at all).
Jun 19 2018
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, June 19, 2018 22:22:23 Dennis via Digitalmars-d wrote:
 On Tuesday, 19 June 2018 at 21:38:14 UTC, Jonathan M Davis wrote:
 Attribute inference is all about inferring the attributes of
 the templated function based on its implementation, not
 adjusting its implementation based on where it's used.
Indeed, I realised that the same template instantiation can't possibly have both a nogc and gc version, so there has to be a template parameter. You can automatically set one however: ``` void main() nogc { example(); } void example(string callee = __FUNCTION__)() { int a = 8; static if (isNoGc!callee) { printf("printf %d", a); } else { writefln("writeln %d", a); } } bool isNoGc(string functionName)() { import std.algorithm; mixin(`return [__traits(getFunctionAttributes, `~functionName~`)].canFind(" nogc");`); } ``` This seems to work. I'm not sure how robust it is though. You might need an extra `mixin("import "~functionName~";");` in `isNoGc` when it's called from other modules (if that helps at all).
Hmm. That's clever, but that approach would not work very well with function overloads. Also, it falls apart on some level if the caller is a template function that relies on attribute inference to be nogc. In such cases, the caller would be infered as not being nogc, and example would be compiled with the GC version. In addition, even if it all worked perfectly, it would mean compiling a different instantation of the function for every function that calls it, which seems likely to cause an awful lot of bloat. It's not as bad as using __FILE__ and __LINE__ as template arguments, but it's close. Another problem here is that as long as we can't introspect on private members of other modules (which really should be fixed), this would likely fail to compile when the caller is private and in another module. But hopefully, that's just a temporary issue. Making it deal with overloads correctly is likely a far bigger issue long term. - Jonathan M Davis
Jun 19 2018
prev sibling parent 12345swordy <alexanderheistermann gmail.com> writes:
On Tuesday, 19 June 2018 at 21:06:16 UTC, Dennis wrote:
 On Tuesday, 19 June 2018 at 19:03:44 UTC, 12345swordy wrote:
 Why not use them if given the opportunity based on its context?
You can do that if you want ``` import std.stdio; import core.stdc.stdio; void main() nogc { int a = 8; static if (__traits(compiles, new int(0))) { writefln("writeln %d", a); } else { printf("printf %d", a); } } ```
No, it is not the same. You are testing one of the rules that is defined by the attribute, you are not testing the attribute itself that is derived by the context that you are in. You code can't take into account of custom attributes. Alexander
Jun 20 2018