Print_term/2: mystery bug!

This is one of the strangest bugs I have run into! Happens only in the new git branch.

pp1 :-
    T =[longishftor(s,[v=1,i=kk,ll=vv,x=xx,f=ff,e=e],[longishftor(s,[],[longishftor(r,[x=h],[]),longishftor(m,[x=somelongishatomwithalotofletters],[longishftor(m,[],[s]),longishftor(m,[],[l])])])])],
    pp_str(T,_Str).

pp2 :-
    T =[longishftor(s,[v=1,i=kk,ll=vv,x=xx,f=ff,e=e],[longishftor(s,[],[longishftor(r,[x=h],[]),longishftor(m,[x=somelongishatomwithalotofletters],[longishftor(m,[],[s]),longishftor(m,[],[l])])])])],
    pp_no_with_output_to(T).

pp_str(In,Str) :-
   with_output_to(string(Str),
      print_term(In,[output(current_output),left_margin(3)])).

pp_no_with_output_to(In) :-
      print_term(In,[output(current_output),left_margin(3)]).

Now for the results:

Welcome to SWI-Prolog (threaded, 64 bits, version 8.5.4-20-gb7dce0b1b [...]

1 ?- pp1.
ERROR: Stack limit (1.0Gb) exceeded
ERROR:   Stack sizes: local: 0.5Gb, global: 0.2Gb, trail: 7.1Mb
ERROR:   Stack depth: 1,725,526, last-call: 0%, Choice points: 7
ERROR:   In:
ERROR:     [1,725,526] system:functor(_576, portray, 1)
ERROR:     [1,725,525] swi_option:option(<compound portray/1>, [length:4])
ERROR:     [1,725,524] prolog_pretty_print:pp(<compound (=)/2>, <compound C'dict'/23>, [length:9])
ERROR:     [1,725,523] prolog_pretty_print:pp_infix_list([length:1], =, 0, <compound C'dict'/23>, [length:9])
ERROR:     [1,725,522] prolog_pretty_print:pp(<compound (=)/2>, <compound C'dict'/23>, [length:9])
ERROR: 
ERROR: Use the --stack_limit=size[KMG] command line option or
ERROR: ?- set_prolog_flag(stack_limit, 2_147_483_648). to double the limit.
2 ?- pp2.
[ longishftor(s,
	     [v=1,i=kk,ll=vv,x=xx,f=ff,e=e],
	     [ longishftor(s,
			   [],
			   [ longishftor(r,[x=h],[]),
			     longishftor(m,
					 [x=somelongishatomwithalotofletters],
					 [longishftor(m,[],[s]),longishftor(m,[],[l])])
			   ])
	     ])
]
true.

3 ?- 

pp1 causes a stack overflow, and pp2 works fine, the only difference is using with_output_to/2 in pp2.

EDIT: if you change the longishftor or the somelongishatomwithalotofletters to something shorter you can make the bug disappear.

Should be fixed now. There are some recent fixes and enhancements to print_term/2. One of them is to find the with of the tty and use that. Using with_output_to(string(S), …) this doesn’t work, so the width is assumed to be 80. At certain widths the code went into infinite recursion. A good test suite would do miracles :frowning: A general rethinking of this module even more so …

Yes, it would be nice to have fuzzy testing. This would be a nice addition to plunit. One of these days :slight_smile:

We have the forall construct in tests. The only thing you need are good generators. I’ve written several term and graph generators. Most seem pretty dedicated to what needs to be tested. Like in this case. Length of atomic data, number of arguments and operator aspects are important.

Indeed, I had not considered using forall for this; amazing what we already have in the infrastructure.

This is one of the most useful aspects of prolog in general, often you have what you need, it just needs to be used from a different angle or in a different way. This is, for example, what happened with DCGs, it simply relies on unification and the proper data model (difference lists).