Retaining meaningful variable names with term_expansion/2

When I rewrite a term into a rule using term_expansion/2, my “meaningful” variable names seem to be lost. So, when I later debug, I get A, B, etc instead of the variable names in my term_expansion/2 rule:

term_expansion(createWritelnPredicate(PredicateName),
    [
        (NewPredicateHead :- writeln(TextToWriteln))
    ]) :-
        NewPredicateHead =.. [PredicateName, TextToWriteln]
    .
createWritelnPredicate(test99).

if I gtrace/0:

?- gtrace, test99(1).

In the debugger I see:

user:test99(A) :-
    writeln(A).

Is there a way to keep the variable names for easier debugging?

In this case I’m close to saying “no” as you cannot find TextToWriteln in the term to be expanded. What you can do is to use term_expansion/4 to rewrite both the term itself and the layout information. That normally gives correct source code information.

You can also add rules for the hooks in library(prolog_clause) to learn the debugger how to match the source term to the clause. With this type of transformations, i.e., transforming a fact into a rule, the overall result is unlikely to look good.

You can achieve fairly reasonable results under significant rewriting as illustrated by DCGs, CHR and Logtalk as long as each actually executed goal can be related to some location in the source text and, for variables, for the variables that are both in the source and executable code.

Thanks @jan. I was seeing if I could use the term expansion system to build a DSL that does some pretty radical rewrites of boilerplate code I have. I suspect now that this is more an abuse than a proper use of the system as intended since it converts a single goal into up to 5 different rules, all with lots of interesting logic, etc.

I suspect just creating a mini compiler that I use to “build” the files first will probably give a better overall debugging experience.