scryer-prolog icon indicating copy to clipboard operation
scryer-prolog copied to clipboard

Infinitely many term expansions are unexpectedly defined

Open triska opened this issue 1 year ago • 4 comments

Motivated by what @rodrigosetti said in https://github.com/mthom/scryer-prolog/discussions/2450#discussioncomment-10076075, I looked again at https://github.com/mthom/scryer-prolog/issues/987#issuecomment-858886019 which mentions:

The term expansion rules of dcgs are loaded during bootstrapping ...

So I asked Scryer: Which term expansions are currently defined?

?- term_expansion(T, E).
   T = (:-op(_A,_B,[_C])), E = [(:-op(_A,_B,_C))]
;  T = (:-op(_A,_B,[_C,_D])), E = [(:-op(_A,_B,_C)),(:-op(_A,_B,_D))]
;  T = (:-op(_A,_B,[_C,_D,_E])), E = [(:-op(_A,_B,_C)),(:-op(_A,_B,_D)),(:-op(_A,_B,_E))]
;  T = (:-op(_A,_B,[_C,_D,_E,_F])), E = [(:-op(_A,_B,_C)),(:-op(_A,_B,_D)),(:-op(_A,_B,_E)),(:-op(_A,_B,_F))]
;  ... .

That's of course not the "correct" way to query this predicate so that it answers the above question. But still: The result is unexpected! And further:

?- term_expansion(T, E), false.
loops, unexpected.
false. % expected

And further: Even if such expansions are loaded during bootstrapping, what exactly prevents their elimination at the end of bootstrapping? After bootstrapping is completed, I would expect a freshly generated Prolog system where no term expansions are (yet) defined.

triska avatar Jul 17 '24 21:07 triska

Currently, I get:

?- term_expansion(T, E).
   error(instantiation_error,throw/1).

This seems reasonable I think? Certainly better than nontermination.

triska avatar Aug 24 '25 06:08 triska

There is a common pattern I observe in expansions:

term_expansion(A, B) :-
    nonvar(A),
    % Actual expansion code
    .

And I don't know if it should or shouldn't be used. Usage of this patern greatly influence output of your query.

hurufu avatar Aug 24 '25 14:08 hurufu

I started to think that Prolog runtime should take more control and not blindly execute user provided expansions. What do you think about predicate ´term_expansion_rule/2´, where second argument isn't the result of term expansion, but a list of clauses that upon execution will expand first argument? Then it will be possible to enumarate all (even missbehaving) term expansions.

hurufu avatar Aug 24 '25 15:08 hurufu

Regarding the test: I think a nonvar/1 test should not be necessary, since expand_term/2 should call term_expansion/2 only for non-variable terms? At least that's how GNU Prolog documents it:

http://www.gprolog.org/manual/gprolog.html#expand-term%2F2

triska avatar Aug 24 '25 17:08 triska