1:- module(anti_subst, [
    2			  anti_subst/3,
    3			  anti_subst/4,
    4			  expand_clause/4,
    5	  		  expand_head/6,
    6			  expand_atomic_goal/6
    7					   ]).    8
    9:- use_module(reduce).   10
   11% :- module(anti_subst).
   12% some tiny for the reserved '.' for swi.
 period_args(+X, -A, -B) is det
True if X is of the form A.B.
   16period_args(X, A, B):- compound(X),
   17	compound_name_arguments(X, '.', [A, B]).
 is_role(+X, -Y, -Z) is det
True if X if of the form role(Y, Z) or Y.Z
   21is_role(role(X, Y), X, Y):-!.
   22is_role(X, A, B):- period_args(X, A, B).
   23
   24% for debugging  is_odict/1.
   25% ?- disable_odict.
   26% ?- enable_odict.
   27% ?- disable_pac_query.
   28% ?- enable_pac_query.
   29% ?- trace, is_odict({a:1, b:{2,3}}).
   30% ?- is_odict({X, b:{2,3}}).
   31% ?- mustbe_odict({X, b:{2,3}}).
   32% ?- trace, is_odict({a:X, b:{2,3}}).
   33% ?- mustbe_odict({a:X, b:{2,3}}).
 is_odict(+X) is det
True if X is instnatiated as {k1:_, ..., kn:_} for n >= 1, ground k_i (1=<k=<n), where commutativity of (,) is assumed.
   40is_odict(X):- nonvar(X), X = {X0}, nonvar(X0),
   41	key_value_pairs(X0).
   42%
   43key_value_pairs((X, Y)):- nonvar(X), nonvar(Y),
   44	key_value_pairs(X),
   45	key_value_pairs(Y).
   46key_value_pairs(K: _):- ground(K).
   47
   48%
   49mustbe_odict(X):- is_odict(X), !.
   50mustbe_odict(X):- writeln("Open dict expected found:"),  writeln(X).
   51
   52% ?- module(anti_subst).
   53% ?- disable_odict, disable_pac_query.
   54
   55% ?- expand_dict:btree_build({a:b}, R).
 anti_subst(+X, -A, -Y, -Z) is det
Difference list Y from Z is the minimum assoc list such that there is no expandable term appearing in A, and substitution of A with the assoc list is equal to X.
 anti_subst(+X, -A, -Y) is det
Is equatl to anti_subst(X, A, Y, []).
   66% ?- anti_subst(a, A, R).
   67% ?- anti_subst({a:b, c:d}, A, R).
   68% ?- anti_subst(f({a:b}), A, R).
   69% ?- anti_subst(f({a:g({b:c})}), A, R).
   70% ?- anti_subst({a:b,{d:e}, c:d}, A, R).
   71% ?- anti_subst(f({a:b,{d:e}, c:d}), A, R).
   72% ?- anti_subst(f({a:b,c:g({d:e}), c:d}), A, R).
   73% ?- anti_subst({a: pred([a]:-d), c:d}, A, R).
   74% ?- anti_subst({a: (@(b,c))}, A, R).
   75% ?- anti_subst(f({a: (@(b,c))}, {d:e}), A, R).
   76
   77anti_subst(X, A, R):- once(anti_subst(X, A, R, [])).
   78
   79anti_subst(X, X, P, P):- (var(X); atomic(X)), !.
   80anti_subst({X}, A, [{X0}-A|P], Q):- is_odict({X}), !, anti_subst(X, X0, P, Q).
   81anti_subst(quote(X), X, R, R).
   82anti_subst(nopac(X), X, R, R).
   83anti_subst((X, Y),  (X0, Y0), P, Q):-
   84	anti_subst(X, X0, P, P0),
   85	anti_subst(Y, Y0,  P0, Q).
   86anti_subst(M:X, M:A, P, Q):-	anti_subst(X, A, P, Q).
   87anti_subst(X, A, [Y-A|R], R):-	anti_subst_rule(X, Y), !.
   88anti_subst([X|Xs], [A|As], P, Q):- !,
   89	anti_subst(X, A, P, P0),
   90	anti_subst(Xs, As, P0, Q).
   91anti_subst(X, X, P, P):- compound_name_arity(X, _, 0), !.
   92anti_subst(X, A, P, Q):- X =..[H|Xs],
   93					anti_subst(Xs, As, P, Q),
   94					A =..[H|As].
   95
   96% anti_subst_rule(@(X,Y), @(X, Y)).
   97anti_subst_rule(is(X), arith_exp(X)).
   98anti_subst_rule(X, pac(X0)):- normal_pac(X, X0).
   99anti_subst_rule(X, Y):- period_args(X, A, B),
  100	(	user:chk_odict ->  Y = role(A, B)
  101	;   Y = X
  102	).
 normal_pac(+X, -Y) is det
True if Y is a normal form of an expandable term X.
  107normal_pac(pred(X),			pred(X)).
  108normal_pac(pred(Vs, X),		pred(Vs, X)).
  109normal_pac(rec(F, Cs),		rec(F,  Cs)).
  110normal_pac(rec(F, Vs, Cs),	rec(F, Vs, Cs)).
  111normal_pac(mrec(Defs),		mrec(Defs)).
  112normal_pac(mrec(Vs, Defs),	mrec(Vs, Defs)).
  113
  114 	/****************************************
  115	*   Expand CIL clauses, DCG rules,		*
  116	*	and queries.						*
  117	****************************************/
 expand_clause(+C, -D, -P, -Q) is det
Clauses in C are expanded to D with the difference list P from Q which consists of all generated auxiliary predicates.
  124% ?- anti_subst:expand_clause(a:-b, [], R, []).
  125% ?- anti_subst:expand_clause(a(1):-b, [], R, []).
  126% ?- anti_subst:expand_clause(a({x}):-b, [], R, []).
  127% ?- anti_subst:expand_clause(a({b:c}):-d, [], R, []).
  128
  129expand_clause(M:A, M0, P, Q):- M==[], !,
  130		expand_clause(A, M0, P, Q).
  131expand_clause(M:A, _, P, Q):- !, expand_clause(A, M, P, Q).
  132expand_clause(:-(H, B), M, [:-(H0, B0)|P], Q):-!,
  133		expand_head(H, M, H0, U, P, P0),
  134		pac:expand_goal(B, M, V, P0, Q),
  135		slim_goal((U, V), B0).
  136expand_clause(H-->B, M, [C|P], Q):- !,
  137		expand_head(H, M, H0, U, P, P0),
  138		pac:expand_phrase(B, M, B0, P0, Q),
  139		dcg_translate_rule((H0 --> {U}, B0), C).
  140expand_clause(H, M, P, Q):- expand_clause( H:-true, M, P, Q).
 expand_atomic_goal(+A, -D, -P, -Q) is det
Atomic goal A is expanded to D with the difference list P from Q which consists of all generated auxiliary predicates.
  146expand_atomic_goal(G, M, H, U, P, Q):-
  147		anti_subst(G, G0, Aux),
  148		attach_prefix(M, G0, H),
  149		expand_aux(Aux, M, U0, P, Q),
  150		slim_goal(U0, U).
 expand_head(+H, -D, -P, -Q) is det
Head H is expanded to D with the difference list P from Q which consists of all generated auxiliary predicates.
  157% ?- anti_subst:expand_head(a(pred([b])), [], H, G, P, []).
  158% ?- anti_subst:expand_head(a({b:pred([b])}), [], H, G, P, []).
  159% ?- anti_subst:expand_head(a(is(1+1)), [], H, G, P, []).
  160% ?- anti_subst:expand_head(a(is(role(X,A))), [], H, G, P, []).
  161% ?- anti_subst:expand_head(a(role(X,A)), [], H, G, P, []).
  162% ?- anti_subst:expand_head(a(is(role(X,A))), [], H, G, P, []).
  163
  164expand_head(H, M, NewH, U, P, Q):-
  165        anti_subst(H, H0, Aux),
  166		expand_aux(Aux, M, U, P, Q),
  167		attach_prefix(M, H0, NewH).
 expand_aux(+A, -D, -P, -Q) is det
Auxiliary term A is expanded possibly recursively to D with the difference list P from Q which consists of all generated auxiliary predicates. Note that open dicts are a recursive structure.
  175expand_aux([], _, true, P, P).
  176expand_aux([X|Xs], M, (G0, G), P, Q):-
  177	expand_aux_base(X, M, G0, P, P0),
  178	expand_aux(Xs, M, G, P0, Q).
 expand_aux_base(+B, -D, -P, -Q) is det
Auxiliary base B is expanded to D possibly recursively with the difference list P from Q which consists of all generated auxiliary predicates. Note that open dicts are a recursive structure.
  186expand_aux_base({X}-A, M, (G1, G0), P, Q):-
  187	anti_subst(X, X0, Aux),
  188	(	user:chk_odict
  189	->		expand_dict:expand_dict({X0}, A, G0)
  190	;		A = {X0}
  191	),
  192	expand_aux(Aux, M, G1, P, Q).
  193expand_aux_base(X-A, M, G, P, Q):- is_role(X, _, _), !,
  194	pac:expand_dict_access(X, =, A, M, G, P, Q).
  195expand_aux_base(pac(X)-A, M, true, P, Q):-
  196	pac:expand_core(X, M, A, P, Q).
  197expand_aux_base(arith_exp(E)-A, M, G, P, Q):-
  198	anti_subst(E, E0, Aux),
  199	expand_aux(Aux, M, G0, P, Q),
  200	slim_goal((G0, A is E0), G)