diff src/lisp.h @ 5560:58b38d5b32d0

Implement print-circle, allowing recursive and circular structures to be read. src/ChangeLog addition: 2011-09-04 Aidan Kehoe <kehoea@parhasard.net> * alloc.c: * alloc.c (ALLOC_FROB_BLOCK_LISP_OBJECT_1): * alloc.c (ALLOC_FROB_BLOCK_LISP_OBJECT): * alloc.c (cons_print_preprocess): * alloc.c (vector_print_preprocess): * alloc.c (vector_nsubst_structures_descend): * alloc.c (Fmake_symbol): * alloc.c (UNMARK_symbol): * alloc.c (sweep_symbols): * alloc.c (reinit_alloc_objects_early): * alloc.c (reinit_alloc_early): * bytecode.c: * bytecode.c (compiled_function_print_preprocess): * bytecode.c (compiled_function_nsubst_structures_descend): * bytecode.c (set_compiled_function_arglist): * bytecode.c (set_compiled_function_interactive): * bytecode.c (bytecode_objects_create): * chartab.c: * chartab.c (print_preprocess_mapper): * chartab.c (nsubst_structures_mapper): * chartab.c (char_table_nsubst_structures_descend): * chartab.c (chartab_objects_create): * elhash.c: * elhash.c (nsubst_structures_map_hash_table): * elhash.c (hash_table_nsubst_structures_descend): * elhash.c (print_preprocess_mapper): * elhash.c (hash_table_print_preprocess): * elhash.c (inchash_eq): * elhash.c (hash_table_objects_create): * elhash.c (syms_of_elhash): * elhash.h: * emacs.c (main_1): * fns.c: * fns.c (check_eq_nokey): * fns.c (Fnsubst): * fns.c (syms_of_fns): * lisp.h: * lisp.h (struct Lisp_Symbol): * lisp.h (IN_OBARRAY): * lisp.h (struct): * lisp.h (PRINT_PREPROCESS): * lread.c (read1): * lrecord.h: * lrecord.h (struct lrecord_implementation): * lrecord.h (DEFINE_DUMPABLE_MODULE_LISP_OBJECT): * print.c: * print.c (PRINT_CIRCLE_LIMIT): * print.c (print_continuous_numbering_changed): * print.c (print_prepare): * print.c (print_finish): * print.c (Fprin1_to_string): * print.c (print_cons): * print.c (print_preprocess_inchash_eq): * print.c (print_preprocess): * print.c (print_sort_get_numbers): * print.c (print_sort_compare_ordinals): * print.c (print_gensym_or_circle): * print.c (nsubst_structures_descend): * print.c (nsubst_structures): * print.c (print_internal): * print.c (print_symbol): * print.c (vars_of_print): * rangetab.c: * rangetab.c (range_table_print_preprocess): * rangetab.c (range_table_nsubst_structures_descend): * rangetab.c (rangetab_objects_create): * rangetab.c (syms_of_rangetab): * symbols.c: * symbols.c (symbol_print_preprocess): * symbols.c (Fintern): * symbols.c (Funintern): * symbols.c (reinit_symbol_objects_early): * symbols.c (init_symbols_once_early): * symsinit.h: Implement print-circle, printing circular structures in a readable fashion, and treating them appropriately on read. This is by means of two new object methods, print_preprocess (detecting circularities), and nsubst_structures_descend (replacing placeholders with the read objects). Expose the substitution to Lisp via #'nsubst and its new :descend-structures keyword. Store information as to whether symbols are interned in obarray or not in their header, making checking for keywords and uninterned symbols (and thus printing) cheaper. Default print_gensym to t, as Common Lisp does, and as a more-than-decade old comment suggests. lisp/ChangeLog addition: 2011-09-04 Aidan Kehoe <kehoea@parhasard.net> * bytecomp.el (byte-compile-output-file-form): * bytecomp.el (byte-compile-output-docform): Bind print-circle, print-continuous-numbering in these functions, now those variables are available. * lisp.el (forward-sexp): * lisp.el (backward-sexp): Recognise leading #N= as being part of an expression. tests/ChangeLog addition: 2011-09-04 Aidan Kehoe <kehoea@parhasard.net> * automated/lisp-reader-tests.el: * automated/lisp-tests.el (literal-with-uninterned): * automated/symbol-tests.el (foo): Test print-circle, for printing (mutually-)recursive and circular structures. Bind print-continuous-numbering where appropriate.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 04 Sep 2011 19:51:35 +0100
parents 3d1f8f0e690f
children 56144c8593a8
line wrap: on
line diff
--- a/src/lisp.h	Sun Aug 28 10:34:54 2011 +0100
+++ b/src/lisp.h	Sun Sep 04 19:51:35 2011 +0100
@@ -2816,7 +2816,37 @@
 typedef struct Lisp_Symbol Lisp_Symbol;
 struct Lisp_Symbol
 {
-  FROB_BLOCK_LISP_OBJECT_HEADER lheader;
+  union
+  {
+    FROB_BLOCK_LISP_OBJECT_HEADER lheader;
+    struct
+    {
+      /* Everything before package_count must agree exactly with struct
+         lrecord_header. */
+      unsigned int type :8;
+#ifdef NEW_GC
+      unsigned int lisp_readonly :1;
+      unsigned int free :1;
+      /* Number of packages this symbol is interned in, zero, one, or many.
+         Packages aren't yet implemented, but we have a design in Common
+         Lisp's. */
+      unsigned int package_count :2;
+      /* ID of the first package this symbol was interned in. Zero is
+         uninterned, one is obarray. */
+      unsigned int first_package_id :20;
+#else /* not NEW_GC */
+      unsigned int mark :1;
+      unsigned int c_readonly :1;
+      unsigned int lisp_readonly :1;
+      /* Number of packages this symbol is interned in, zero, one, or many. */
+      unsigned int package_count :2;
+      /* ID of the first package this symbol was interned in. Zero is
+         uninterned, one is obarray. */
+      unsigned int first_package_id :19;
+#endif /* not NEW_GC */
+    } v;
+  } u;
+
   /* next symbol in this obarray bucket */
   Lisp_Symbol *next;
   Lisp_Object name;
@@ -2825,11 +2855,12 @@
   Lisp_Object plist;
 };
 
-#define SYMBOL_IS_KEYWORD(sym)						\
-  ((string_byte (symbol_name (XSYMBOL (sym)), 0) == ':')		\
-   && EQ (sym, oblookup (Vobarray,					\
-			 XSTRING_DATA (symbol_name (XSYMBOL (sym))),	\
-			 XSTRING_LENGTH (symbol_name (XSYMBOL (sym))))))
+#define IN_OBARRAY(symbol) ((XSYMBOL (symbol)->u.v.first_package_id) == 1)
+
+#define SYMBOL_IS_KEYWORD(sym) (IN_OBARRAY (sym) &&                     \
+                                (string_byte (symbol_name (XSYMBOL (sym)), \
+                                              0) == ':'))
+
 #define KEYWORDP(obj) (SYMBOLP (obj) && SYMBOL_IS_KEYWORD (obj))
 
 DECLARE_MODULE_API_LISP_OBJECT (symbol, Lisp_Symbol);
@@ -2852,6 +2883,7 @@
 #define XSYMBOL_PLIST(s) (XSYMBOL (s)->plist)
 
 
+
 /*------------------------------- subr ---------------------------------*/
 
 /* A function that takes no arguments and returns a Lisp_Object.
@@ -5267,6 +5299,8 @@
 EXFUN (Fsubseq, 3);
 EXFUN (Fvalid_plist_p, 1);
 
+extern Boolint check_eq_nokey (Lisp_Object, Lisp_Object, Lisp_Object,
+                               Lisp_Object);
 extern Boolint check_lss_key_car (Lisp_Object, Lisp_Object, Lisp_Object,
 				  Lisp_Object);
 extern Boolint check_string_lessp_nokey (Lisp_Object, Lisp_Object,
@@ -5275,6 +5309,20 @@
 typedef Boolint (*check_test_func_t) (Lisp_Object test, Lisp_Object key,
 				      Lisp_Object item, Lisp_Object elt);
 
+typedef struct
+{
+  Lisp_Object number_table;
+  Lisp_Object new_;
+  Lisp_Object old;
+  Lisp_Object current_object;
+  Boolint test_not_unboundp;
+} nsubst_structures_info_t;
+
+Lisp_Object nsubst_structures (Lisp_Object new_, Lisp_Object old,
+                               Lisp_Object tree, check_test_func_t check_test,
+                               Boolint test_not_unboundp,
+                               Lisp_Object test, Lisp_Object key);
+
 Lisp_Object list_merge (Lisp_Object org_l1, Lisp_Object org_l2,
 			check_test_func_t check_merge,
                         Lisp_Object predicate, Lisp_Object key_func);
@@ -5617,6 +5665,31 @@
 DECLARE_DOESNT_RETURN (printing_unreadable_lisp_object (Lisp_Object obj,
 						     const Ibyte *name));
 
+#define PRINT_PREPROCESS(obj, print_number_table, seen_object_count)	\
+  do if (LRECORDP (obj)							\
+	 && XRECORD_LHEADER_IMPLEMENTATION (obj)->print_preprocess)	\
+    {									\
+      print_preprocess (obj, print_number_table, seen_object_count);	\
+    } while (0)
+
+typedef struct { Lisp_Object table; Elemcount *count; } preprocess_info_t;
+
+void print_preprocess (Lisp_Object obj, Lisp_Object print_number_table,
+                       Elemcount *seen_object_count);
+
+/* These is in print.c because they use the print_preprocess
+   infrastructure. */
+Lisp_Object nsubst_structures_descend (Lisp_Object new_, Lisp_Object old,
+                                       Lisp_Object object,
+                                       Lisp_Object number_table,
+                                       Boolint test_not_unboundp);
+
+Lisp_Object nsubst_structures (Lisp_Object new_, Lisp_Object old,
+                               Lisp_Object tree,
+                               check_test_func_t check_test,
+                               Boolint test_not_unboundp,
+                               Lisp_Object test, Lisp_Object key);
+
 extern Lisp_Object Qexternal_debugging_output;
 extern Lisp_Object Qprint_length;
 extern Lisp_Object Qprint_string_length;