Quasiquotations dictionaries not grounded

I’m trying to implement a quasiquotation that will effectively produce a list of string commands with embedded prolog variable terms, however it appears that the prolog variables are unground at parse time.

As a contrived simpler example that parse a list of Name=Value arguments:

:- use_module(library(dcg/basics)).
:- use_module(library(dcg/high_order)).
:- use_module(library(quasi_quotations)).

:- quasi_quotation_syntax(assignments).

assignments(Content, Vars, Dict, Result) :-
   format("Vars=~w, Dict=~w~n", [Vars, Dict]),
   phrase_from_quasi_quotation(sequence(assignment(Dict),",",Result), Content).

assignment(_,[]) --> [].
assignment(Dict,[SVar,"=",V]) --> string_without("=",Var), "=", number_or_var(Dict,V), { string_chars(SVar,Var) }.

number_or_var(_Dict,S) --> number(N), { number_string(N,S) }.
number_or_var(Dict,SV) --> prolog_var_name(S), { member(S=V, Dict), freeze(V, atom_string(V,SV)) }.

If I enter the following query:

?- X = 5, Y = {|assignments(X)||A=1,B=X|}.
Vars=[_1732], Dict=[X=_1732,Y=_1766]
X = 5,
Y = [["A", "=", "1"], ["B", "=", "5"]].

As can be seen, at parse time, the Dict shows X, but it doesn’t appear to have a grounded value, and hence I have froze the goal that adds the string value of X to the output, to prevent an

ERROR: atom_string/2: Arguments are not sufficiently instantiated

Is there a reason the value of X in the above example isn’t available during parse?

I could change the parser to just return the value instead of attempting a conversion:

number_or_var(Dict,V) --> prolog_var_name(S), { member(S=V, Dict) }.
?- X = 5, Y = {|assignments(X)||A=1,B=X|}.
Vars=[_1732], Dict=[X=_1732,Y=_1766]
X = 5,
Y = [["A", "=", "1"], ["B", "=", 5]].

But now I have to traverse the output to convert numbers to strings.

I’m thinking that the variable values are not available during parse time since the parser also executes at compile time, but in that case why provide the dictionary to the parser?

Yes. The quasi quotation is evaluated by read/1. X=5 is a unification that happens if you handle the term that is read as a goal (and thus call it).

Not sure I understand this, but if you bind Y to [["A", "=", "1"], ["B", "=", X]] when evaluating the quasi quotation, running the goal will bind X to 5.