Re: Is there an alternative to "__FUNCTION__" that gives the actual function symbol and not the name as a string?

2021-10-24 Thread Imperatorn via Digitalmars-d-learn

On Sunday, 24 October 2021 at 14:05:35 UTC, Simon wrote:

On Saturday, 23 October 2021 at 20:24:32 UTC, Tim wrote:

[...]


That worked! I needed to modify it a bit, since there is the 
"execution_count_to_log_reproduction_on"-template parameterto 
the enum. If I try to use that inside the token string, it just 
says it can't find the identifier, so I had to inject some 
non-token string in the middle that plays nice with the token 
string, where I can actually reference the parameter.


For completeness, here is how the code looks like now (I am 
completely horrified by the result):



[...]



and the usage just looks like this:


[...]


The "mixin(OUTPUT_REPRO_CASE!());" then expands to:


[...]



Thanks for your help!!!


Maybe core.reflect and codegen could help with this when it gets 
released


Re: Is there an alternative to "__FUNCTION__" that gives the actual function symbol and not the name as a string?

2021-10-24 Thread Simon via Digitalmars-d-learn

On Saturday, 23 October 2021 at 20:24:32 UTC, Tim wrote:

import std.traits, std.stdio;
string generateLogCode(alias func)()
{
string code = "writeln(";
code ~= "\"" ~ fullyQualifiedName!func ~ "(\"";
foreach(i, param; ParameterIdentifierTuple!func)
{
if(i)
code ~= ", \", \"";
code ~= ", " ~ param;
}
code ~= ", \");\");";
return code;
}
enum OUTPUT_REPRO_CASE = q{
pragma(msg, generateLogCode!(__traits(parent, {}))());
mixin(generateLogCode!(__traits(parent, {}))());
};
void test(int a, int[] b)
{
mixin(OUTPUT_REPRO_CASE);
}
void main()
{
test(1, [2, 3]);
}


That worked! I needed to modify it a bit, since there is the 
"execution_count_to_log_reproduction_on"-template parameterto the 
enum. If I try to use that inside the token string, it just says 
it can't find the identifier, so I had to inject some non-token 
string in the middle that plays nice with the token string, where 
I can actually reference the parameter.


For completeness, here is how the code looks like now (I am 
completely horrified by the result):



string generate_call_to_log_reproduction(alias func)(){
  string code = 
"dlog(generate_reproduction_for_current_function_call!("~fullyQualifiedName!func~", [get_string_argument_list_of_function!([ParameterIdentifierTuple!(__traits(parent, {}))])])(context.temp_allocator";


  foreach(i, param; ParameterIdentifierTuple!func)
code ~= "," ~ param;

  code ~= "));";
  return code;
}

string generate_call_to_log_execution_count(alias func)(){
  return "dlog(\""~fullyQualifiedName!(func)~" execution count: 
%lld\", execution_count);";

}

enum OUTPUT_REPRO_CASE(s64 
execution_count_to_log_reproduction_on = -1) = q{

  static s64 execution_count = 0;
  
if(context.settings.debug_.output_call_counts_for_reproducible_functions){

mixin(generate_call_to_log_execution_count!(__traits(parent, 
{})));

  }
} ~ "if(execution_count == 
"~execution_count_to_log_reproduction_on.stringof~")"~q{

  {
mixin(generate_call_to_log_reproduction!(__traits(parent, 
{}))());

trigger_breakpoint();
  }

  execution_count++;
};



and the usage just looks like this:


void some_function(int a, int b){
  mixin(OUTPUT_REPRO_CASE!());
  return a + b;
}


The "mixin(OUTPUT_REPRO_CASE!());" then expands to:


static s64 execution_count = 0;
if(context.settings.debug_.output_call_counts_for_reproducible_functions){
  mixin(generate_call_to_log_execution_count!(__traits(parent, 
{})));

}

if(execution_count == -1L){
  mixin(generate_call_to_log_reproduction!(__traits(parent, 
{}))());

  trigger_breakpoint();
}

execution_count++;



Thanks for your help!!!


Re: Is there an alternative to "__FUNCTION__" that gives the actual function symbol and not the name as a string?

2021-10-23 Thread Tim via Digitalmars-d-learn

On Saturday, 23 October 2021 at 19:52:19 UTC, Simon wrote:


Thanks for putting up with me! I tried a bunch and it seems 
like I left out too much code, because I can't get it working 
100%. I didn't even know about the q{} syntax, so I didn't 
think the stuff I left out would matter, but when using this 
approach it apparently does. I am going to show the full code 
here, just so that there are no more suprises.


Sorry for this becoming a "please do my homework" kind of 
question. I tried for half an hour with no idea how to fix the 
errors I'm seeing. Something always fails.


The full implementation of OUTPUT_REPRO_CASE looked like this:


enum MAKE_FUNCTION_REPRODUCIBLE(alias func, s64 
execution_count_to_log_reproduction_on = -1) =

  "static s64 execution_count = 0;
  
if(context.settings.debug_.output_call_counts_for_reproducible_functions)
dlog(\""~fullyQualifiedName!func~" call count: %lld\", 
execution_count);


  if(execution_count == 
"~execution_count_to_log_reproduction_on.stringof~"){

dlog(generate_reproduction_for_current_function_call!(
  "~fullyQualifiedName!func~",
  
["~get_string_argument_list_of_function!([ParameterIdentifierTuple!func])~"])(

  context.temp_allocator,
  
"~get_argument_list_of_function!([ParameterIdentifierTuple!func])~"));


  trigger_breakpoint();
}";

It calls the function

String generate_reproduction_for_current_function_call(alias 
func, string[] parameter_names, Parameter_Types...)(Allocator* 
allocator, Parameter_Types parameters);


that actually creates the code-string. I did a lot of trial and 
error getting the trait-calls to expand at the right time 
(become part of the mixin string or outside of it) and falling 
on my nose about when something is a type vs a string and so 
on, so this became really ugly. If you have a better suggestion 
I'm open to it.


I was testing this inside the function

Dynamic_Array!(Polygon) clip_polygons(Slice!Vector2 p0, 
Slice!Vector2 p1, bool return_difference_instead_of_union = 
true, Slice!(Slice!Vector2) p0_holes = Slice!(Slice!Vector2)(), 
bool debug_print = false);


in which the OUTPUT_REPRO_CASE expands to:

static s64 execution_count = 0;
  
if(context.settings.debug_.output_call_counts_for_reproducible_functions)

dlog("vbl.clip_polygons call count: %lld", execution_count);

  if(execution_count == -1L){
dlog(generate_reproduction_for_current_function_call!(
  vbl.clip_polygons,
  ["p0", "p1", "return_difference_instead_of_union", 
"p0_holes", "debug_print"])(

  context.temp_allocator,
  p0, p1, return_difference_instead_of_union, p0_holes, 
debug_print));


  trigger_breakpoint();
}

When I try to change the whole thing to be a token string, 
execution_count_to_log_reproduction_on was suddenly undefined. 
I changed this to be an abominational mix of token string and 
string literal and then it sort of worked, except then the 
whole business of making the parameter names expand as actual 
tokens and not strings failed for some reason.


I am super confused (this is a reccuring theme with D compile 
time stuff on my part :/). Can you show me how this can work 
with your token string solution?


Maybe you need another mixin in the mixin. The first mixin gets 
the symbol to the current function. Information from the symbol 
is used to generate the second mixin. It could be done like this:


import std.traits, std.stdio;
string generateLogCode(alias func)()
{
string code = "writeln(";
code ~= "\"" ~ fullyQualifiedName!func ~ "(\"";
foreach(i, param; ParameterIdentifierTuple!func)
{
if(i)
code ~= ", \", \"";
code ~= ", " ~ param;
}
code ~= ", \");\");";
return code;
}
enum OUTPUT_REPRO_CASE = q{
pragma(msg, generateLogCode!(__traits(parent, {}))());
mixin(generateLogCode!(__traits(parent, {}))());
};
void test(int a, int[] b)
{
mixin(OUTPUT_REPRO_CASE);
}
void main()
{
test(1, [2, 3]);
}


Re: Is there an alternative to "__FUNCTION__" that gives the actual function symbol and not the name as a string?

2021-10-23 Thread Adam D Ruppe via Digitalmars-d-learn

On Saturday, 23 October 2021 at 18:23:47 UTC, Simon wrote:
For debugging purposes, I have built a mixin that will, when 
declared inside a function, output code to the console that 
will reproduce the exact function call.


Sounds like what you really want is

https://github.com/dlang/dmd/pull/13071

but the PR there is not merged :(

the other way though is the string mixin with the parent {} thing 
it is pretty ugly.


Re: Is there an alternative to "__FUNCTION__" that gives the actual function symbol and not the name as a string?

2021-10-23 Thread Simon via Digitalmars-d-learn

On Saturday, 23 October 2021 at 19:03:41 UTC, Tim wrote:

On Saturday, 23 October 2021 at 18:56:48 UTC, Simon wrote:

And I tried to use your suggestion like this:

enum OUTPUT_REPRO_CASE(alias func = __traits(parent, {})) = 
"build the actual code stuff with"~fullyQualifiedName!func~" 
and so on";


Which doesn't work. In that case func seems to become the 
parent namespace. If I substitute fullyQualifiedName!func with 
fullyQualifiedName!(__traits(parent, {}))) I get a circular 
dependecy error.


How do I have to use this exactly?


This seems to work:

import std.traits, std.stdio;
enum OUTPUT_REPRO_CASE = q{
string name = fullyQualifiedName!(__traits(parent, {}));
writeln(name);
};
void test()
{
mixin(OUTPUT_REPRO_CASE);
}
void main()
{
test();
}


Thanks for putting up with me! I tried a bunch and it seems like 
I left out too much code, because I can't get it working 100%. I 
didn't even know about the q{} syntax, so I didn't think the 
stuff I left out would matter, but when using this approach it 
apparently does. I am going to show the full code here, just so 
that there are no more suprises.


Sorry for this becoming a "please do my homework" kind of 
question. I tried for half an hour with no idea how to fix the 
errors I'm seeing. Something always fails.


The full implementation of OUTPUT_REPRO_CASE looked like this:


enum MAKE_FUNCTION_REPRODUCIBLE(alias func, s64 
execution_count_to_log_reproduction_on = -1) =

  "static s64 execution_count = 0;
  
if(context.settings.debug_.output_call_counts_for_reproducible_functions)
dlog(\""~fullyQualifiedName!func~" call count: %lld\", 
execution_count);


  if(execution_count == 
"~execution_count_to_log_reproduction_on.stringof~"){

dlog(generate_reproduction_for_current_function_call!(
  "~fullyQualifiedName!func~",
  
["~get_string_argument_list_of_function!([ParameterIdentifierTuple!func])~"])(

  context.temp_allocator,
  
"~get_argument_list_of_function!([ParameterIdentifierTuple!func])~"));


  trigger_breakpoint();
}";

It calls the function

String generate_reproduction_for_current_function_call(alias 
func, string[] parameter_names, Parameter_Types...)(Allocator* 
allocator, Parameter_Types parameters);


that actually creates the code-string. I did a lot of trial and 
error getting the trait-calls to expand at the right time (become 
part of the mixin string or outside of it) and falling on my nose 
about when something is a type vs a string and so on, so this 
became really ugly. If you have a better suggestion I'm open to 
it.


I was testing this inside the function

Dynamic_Array!(Polygon) clip_polygons(Slice!Vector2 p0, 
Slice!Vector2 p1, bool return_difference_instead_of_union = true, 
Slice!(Slice!Vector2) p0_holes = Slice!(Slice!Vector2)(), bool 
debug_print = false);


in which the OUTPUT_REPRO_CASE expands to:

static s64 execution_count = 0;
  
if(context.settings.debug_.output_call_counts_for_reproducible_functions)

dlog("vbl.clip_polygons call count: %lld", execution_count);

  if(execution_count == -1L){
dlog(generate_reproduction_for_current_function_call!(
  vbl.clip_polygons,
  ["p0", "p1", "return_difference_instead_of_union", 
"p0_holes", "debug_print"])(

  context.temp_allocator,
  p0, p1, return_difference_instead_of_union, p0_holes, 
debug_print));


  trigger_breakpoint();
}

When I try to change the whole thing to be a token string, 
execution_count_to_log_reproduction_on was suddenly undefined. I 
changed this to be an abominational mix of token string and 
string literal and then it sort of worked, except then the whole 
business of making the parameter names expand as actual tokens 
and not strings failed for some reason.


I am super confused (this is a reccuring theme with D compile 
time stuff on my part :/). Can you show me how this can work with 
your token string solution?


Re: Is there an alternative to "__FUNCTION__" that gives the actual function symbol and not the name as a string?

2021-10-23 Thread Tim via Digitalmars-d-learn

On Saturday, 23 October 2021 at 18:56:48 UTC, Simon wrote:

And I tried to use your suggestion like this:

enum OUTPUT_REPRO_CASE(alias func = __traits(parent, {})) = 
"build the actual code stuff with"~fullyQualifiedName!func~" 
and so on";


Which doesn't work. In that case func seems to become the 
parent namespace. If I substitute fullyQualifiedName!func with 
fullyQualifiedName!(__traits(parent, {}))) I get a circular 
dependecy error.


How do I have to use this exactly?


This seems to work:

import std.traits, std.stdio;
enum OUTPUT_REPRO_CASE = q{
string name = fullyQualifiedName!(__traits(parent, {}));
writeln(name);
};
void test()
{
mixin(OUTPUT_REPRO_CASE);
}
void main()
{
test();
}



Re: Is there an alternative to "__FUNCTION__" that gives the actual function symbol and not the name as a string?

2021-10-23 Thread Simon via Digitalmars-d-learn

On Saturday, 23 October 2021 at 18:36:27 UTC, Tim wrote:

On Saturday, 23 October 2021 at 18:23:47 UTC, Simon wrote:
So what I am looking for then is the equivalent to 
__FUNCTION__ that evaluates to the actual symbol of the 
function instead of its name, so it can be used as a parameter 
to ParameterIdentifierTuple.


You could use the following:

alias F = __traits(parent, {});

The lambda {} is a symbol inside the function. F will be its 
parent, which is the function itself.


So before I had OUTPUT_REPRO_CASE defined like this:

enum OUTPUT_REPRO_CASE(alias func) = "build the actual code stuff 
with"~fullyQualifiedName!func~" and so on";


And I tried to use your suggestion like this:

enum OUTPUT_REPRO_CASE(alias func = __traits(parent, {})) = 
"build the actual code stuff with"~fullyQualifiedName!func~" and 
so on";


Which doesn't work. In that case func seems to become the parent 
namespace. If I substitute fullyQualifiedName!func with 
fullyQualifiedName!(__traits(parent, {}))) I get a circular 
dependecy error.


How do I have to use this exactly?





Re: Is there an alternative to "__FUNCTION__" that gives the actual function symbol and not the name as a string?

2021-10-23 Thread Tim via Digitalmars-d-learn

On Saturday, 23 October 2021 at 18:23:47 UTC, Simon wrote:
So what I am looking for then is the equivalent to __FUNCTION__ 
that evaluates to the actual symbol of the function instead of 
its name, so it can be used as a parameter to 
ParameterIdentifierTuple.


You could use the following:

alias F = __traits(parent, {});

The lambda {} is a symbol inside the function. F will be its 
parent, which is the function itself.


Is there an alternative to "__FUNCTION__" that gives the actual function symbol and not the name as a string?

2021-10-23 Thread Simon via Digitalmars-d-learn
For debugging purposes, I have built a mixin that will, when 
declared inside a function, output code to the console that will 
reproduce the exact function call.


So, as an example, for the following function

int reproducible_function(int a, int b){
  mixin(OUTPUT_REPRO_CASE!reproducible_function);
  return a + b;
}

called in the following way:

reproducible_function(5, 9);

the mixin OUTPUT_REPRO_CASE will output the exact same call. I 
can then take that code, paste it into the tests and tad - I 
have a repro case.


The only problem I have with this is that you still need to give 
the function as a template argument to OUTPUT_REPRO_CASE. In 
other cases, I have gotten around this by giving __FUNCTION__ as 
the default argument to that template parameter, but that doesn't 
work here because the mixin expands to something that calls 
ParameterIdentifierTuple. ParameterIdentifierTuple does not take 
a string as an argument, but needs the actual symbol (or an 
alias) to be passed.


So what I am looking for then is the equivalent to __FUNCTION__ 
that evaluates to the actual symbol of the function instead of 
its name, so it can be used as a parameter to 
ParameterIdentifierTuple. With this, I could then change the call 
to just be:


int reproducible_function(int a, int b){
   mixin(OUTPUT_REPRO_CASE!());
   return a + b;
}