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

Tim tim.dlang at t-online.de
Sat Oct 23 20:24:32 UTC 2021


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]);
}


More information about the Digitalmars-d-learn mailing list