]> git.eshelyaron.com Git - emacs.git/commitdiff
Minor simplifications and doc for records
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 4 Apr 2017 21:06:25 +0000 (14:06 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 4 Apr 2017 21:07:54 +0000 (14:07 -0700)
* doc/lispref/records.texi (Records): Mention size limit.
* etc/NEWS: Mention records.
* src/alloc.c (allocate_pseudovector, allocate_record):
Prefer 'PSEUDOVECTOR_SIZE_MASK' to its definiens.
(allocate_record): Check arg range here, not in callers, as this
simplifies the code.  Use allocate_vectorlike instead of
allocate_vector, to avoid duplicate runtime tests.
(Fmake_record, record): Don't mention PSEUDOVECTOR_SIZE_BITS in
the doc string, as it is not visible to the user.
(Fmake_record, record, Fcopy_record):
Prefer make_lisp_ptr to XSETVECTOR.
(record): Broaden memcpy to copy the type, too.

doc/lispref/records.texi
etc/NEWS
src/alloc.c

index 9a5d900cfc915d9f6db6f546fd32140e1126f0fd..a6c560cbcb9bff196b581fa030e03c8f4dd0a666 100644 (file)
@@ -14,8 +14,10 @@ instances.
 
   Internally, a record object is much like a vector; its slots can be
 accessed using @code{aref}.  However, the first slot is used to hold
-its type as returned by @code{type-of}.  Like arrays, records use
-zero-origin indexing: the first slot has index 0.
+its type as returned by @code{type-of}.  Also, in the current
+implementation records can have at most 4096 slots, whereas vectors
+can be much larger.  Like arrays, records use zero-origin indexing:
+the first slot has index 0.
 
   The printed representation of records is @samp{#s} followed by a
 list specifying the contents.  The first list element must be the
index fc076569862a8cd052f78be9e07d6b19b40d1a05..8b17f1648bf0f43f5ce6c2b57354b24e2d06e5d0 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -839,6 +839,12 @@ instead of its first.
 \f
 * Lisp Changes in Emacs 26.1
 
++++
+** Emacs now supports records for user-defined types, via the new
+functions 'copy-record', 'make-record', 'record', and 'recordp'.
+Records are now used internally to represent cl-defstruct and defclass
+instances, for example.
+
 +++
 ** 'save-some-buffers' now uses 'save-some-buffers-default-predicate'
 to decide which buffers to ask about, if the PRED argument is nil.
index 5024b1211e535f73e2db1c4dae289b46c7b7c5ec..a58824fb0f3eaf708e1f0934c1601170d3532860 100644 (file)
@@ -3371,7 +3371,7 @@ allocate_pseudovector (int memlen, int lisplen,
   eassert (0 <= tag && tag <= PVEC_FONT);
   eassert (0 <= lisplen && lisplen <= zerolen && zerolen <= memlen);
   eassert (memlen - lisplen <= (1 << PSEUDOVECTOR_REST_BITS) - 1);
-  eassert (lisplen <= (1 << PSEUDOVECTOR_SIZE_BITS) - 1);
+  eassert (lisplen <= PSEUDOVECTOR_SIZE_MASK);
 
   /* Only the first LISPLEN slots will be traced normally by the GC.  */
   memclear (v->contents, zerolen * word_size);
@@ -3393,16 +3393,17 @@ allocate_buffer (void)
 }
 
 
-/* Allocate a new record with COUNT slots.  Return NULL if COUNT is
-   too large.  */
+/* Allocate a record with COUNT slots.  COUNT must be positive, and
+   includes the type slot.  */
 
 static struct Lisp_Vector *
-allocate_record (int count)
+allocate_record (EMACS_INT count)
 {
-  if (count >= (1 << PSEUDOVECTOR_SIZE_BITS))
-    return NULL;
-
-  struct Lisp_Vector *p = allocate_vector (count);
+  if (count > PSEUDOVECTOR_SIZE_MASK)
+    error ("Attempt to allocate a record of %"pI"d slots; max is %d",
+          count, PSEUDOVECTOR_SIZE_MASK);
+  struct Lisp_Vector *p = allocate_vectorlike (count);
+  p->header.size = count;
   XSETPVECTYPE (p, PVEC_RECORD);
   return p;
 }
@@ -3411,53 +3412,29 @@ allocate_record (int count)
 DEFUN ("make-record", Fmake_record, Smake_record, 3, 3, 0,
        doc: /* Create a new record.
 TYPE is its type as returned by `type-of'.  SLOTS is the number of
-slots, each initialized to INIT.  The number of slots, including the
-type slot, must fit in PSEUDOVECTOR_SIZE_BITS.  */)
+non-type slots, each initialized to INIT.  */)
   (Lisp_Object type, Lisp_Object slots, Lisp_Object init)
 {
-  Lisp_Object record;
-  ptrdiff_t size, i;
-  struct Lisp_Vector *p;
-
   CHECK_NATNUM (slots);
-
-  size = XFASTINT (slots) + 1;
-  p = allocate_record (size);
-  if (p == NULL)
-    error ("Attempt to allocate a record of %"pD"d slots; max is %d",
-          size, (1 << PSEUDOVECTOR_SIZE_BITS) - 1);
-
+  EMACS_INT size = XFASTINT (slots) + 1;
+  struct Lisp_Vector *p = allocate_record (size);
   p->contents[0] = type;
-  for (i = 1; i < size; i++)
+  for (ptrdiff_t i = 1; i < size; i++)
     p->contents[i] = init;
-
-  XSETVECTOR (record, p);
-  return record;
+  return make_lisp_ptr (p, Lisp_Vectorlike);
 }
 
 
 DEFUN ("record", Frecord, Srecord, 1, MANY, 0,
        doc: /* Create a new record.
 TYPE is its type as returned by `type-of'.  SLOTS is used to
-initialize the record slots with shallow copies of the arguments.  The
-number of slots, including the type slot, must fit in
-PSEUDOVECTOR_SIZE_BITS.
+initialize the record slots with shallow copies of the arguments.
 usage: (record TYPE &rest SLOTS) */)
   (ptrdiff_t nargs, Lisp_Object *args)
 {
   struct Lisp_Vector *p = allocate_record (nargs);
-  if (p == NULL)
-    error ("Attempt to allocate a record of %"pD"d slots; max is %d",
-          nargs, (1 << PSEUDOVECTOR_SIZE_BITS) - 1);
-
-  Lisp_Object type = args[0];
-  Lisp_Object record;
-
-  p->contents[0] = type;
-  memcpy (p->contents + 1, args + 1, (nargs - 1) * sizeof *args);
-
-  XSETVECTOR (record, p);
-  return record;
+  memcpy (p->contents, args, nargs * sizeof *args);
+  return make_lisp_ptr (p, Lisp_Vectorlike);
 }
 
 
@@ -3466,17 +3443,11 @@ DEFUN ("copy-record", Fcopy_record, Scopy_record, 1, 1, 0,
   (Lisp_Object record)
 {
   CHECK_RECORD (record);
-  struct Lisp_Vector *src = XVECTOR (record);
   ptrdiff_t size = ASIZE (record) & PSEUDOVECTOR_SIZE_MASK;
   struct Lisp_Vector *new = allocate_record (size);
-  if (new == NULL)
-    error ("Attempt to allocate a record of %"pD"d slots; max is %d",
-          size, (1 << PSEUDOVECTOR_SIZE_BITS) - 1);
-
-  memcpy (&(new->contents[0]), &(src->contents[0]),
+  memcpy (new->contents, XVECTOR (record)->contents,
           size * sizeof (Lisp_Object));
-  XSETVECTOR (record, new);
-  return record;
+  return make_lisp_ptr (new, Lisp_Vectorlike);
 }