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!!!

Reply via email to