emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Allow value of PRINT_CIRCLE to be modified from Elisp?


From: Toby Cubitt
Subject: Allow value of PRINT_CIRCLE to be modified from Elisp?
Date: Thu, 19 Apr 2012 15:09:13 +0200
User-agent: Mutt/1.5.21 (2010-09-15)

print.c defines an arbitrary fixed limit

  #define PRINT_CIRCLE 200

on the depth to which a lisp object can be printed, before it bails out
with the "Apparently circular structure being printed" error.

Apparently, no one anticipated wanting to print highly nested Elisp
structures. But this arbitrary limit is breaking some of the
functionality in Elisp packages I maintain (see below for a detailed
explanation).

Could the #define PRINT_CIRCLE constant be turned into a DEFVAR_INT
`max-lisp-print-depth' variable, so that it could be adjusted from Elisp
when more print depth is needed?


The motivation for this request is that I've been playing around with
implementing persistent storage of undo history in undo-tree.el. This is
trivial to implement these days thanks to recent Emacs' ability to `read'
back the output of non-nil print-circle `prin1' output.

Unfortunately, undo history typically grows very long, even in a
moderately heavily edited buffer, creating very deep undo-trees. For all
but the most trivial test buffers, saving undo-tree history to file using
prin1 hits the arbitrary PRINT_CIRCLE limit and fails.

I've hit exactly the same problem before in my predictive.el package
(actually, in dict-tree.el, which implements the trie-based dictionary
data structures I use there). If one stores long strings in the
dictionaries, persistent storage of the dictionaries (again just
implemented using the natural prin1 method) hits PRINT_CIRCLE and fails.

So I now have two real-world use cases where the PRINT_CIRCLE limit is
causing problems.

I know I could work-around the problem using a more complicated
persistent storage implementation than prin1. But this would effectively
mean writing my own data-structure-specific re-implementations of prin1.
And that just seems wrong when we have all the beauty of Lisp read/print
syntax to hand.


Because the depth of the dictionary trees is proportional to the longest
string they store, which is typically upper-bounded by some not-too-big
constant, it's quite rare to hit this issue at all in predictive.el. And
the simple solution of increasing the value of PRINT_CIRCLE in print.c
and recompiling avoids the problem in any real-world use. (Though the
average Emacs user probably wouldn't call this solution "simple"!)

But the depth of an undo-tree is proportional to the length of the undo
history. PRINT_CIRCLE would have to be very large to avoid the problem in
undo-tree.el, probably too big to usefully protect against infinite
recursion elsewhere. An Elisp-configurable limit would seem the better
way to go, so that it can temporarily be let-bound to a larger value when
printing the undo-trees.

eval.c has adjustable `max-lisp-eval-depth', with big scary warnings in
the docstring about potential stack overflows if it's increased too
much. Could we add a `max-lisp-print-depth', with similar warnings?


I looked into writing a patch for this myself, but print.c defines
being_printed as a global static array for use in print_preprocess and
print_object:

  static Lisp_Object being_printed[PRINT_CIRCLE];

This would have to be turned into a dynamically allocated array
(allocated in the print c function?), and I'm not familiar enough with
Emacs' c code memory management to know how to implement this correctly.

Toby
-- 
Dr T. S. Cubitt
Mathematics and Quantum Information group
Department of Mathematics
Complutense University
Madrid, Spain

email: address@hidden
web:   www.dr-qubit.org



reply via email to

[Prev in Thread] Current Thread [Next in Thread]