aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2021-12-04 13:47:19 -0500
committerStefan Monnier2021-12-04 13:47:35 -0500
commitde727b5886fb4a81df2dc17d9d094e915c1e9fb4 (patch)
treec7e1f3ae109eb8cc6c11abf9391b25bf8d15b8cf
parent63be97fb050545cc33ae5d857188ad45fbe27715 (diff)
downloademacs-de727b5886fb4a81df2dc17d9d094e915c1e9fb4.tar.gz
emacs-de727b5886fb4a81df2dc17d9d094e915c1e9fb4.zip
eieio-core.el: Allow assignment to cl-structs through `slot-value`
* lisp/emacs-lisp/eieio-core.el (eieio--validate-slot-value): Obey the `:read-only` property of the slot. (eieio-oset): Allow use on cl-structs as well. (eieio-read-only): New error. * test/lisp/emacs-lisp/eieio-tests/eieio-tests.el (eieio-test--struct): Make the last field read-only. (eieio-test-defstruct-slot-value): Test that cl-struct slots can be assigned via `slot-value`.
-rw-r--r--doc/misc/eieio.texi3
-rw-r--r--etc/NEWS2
-rw-r--r--lisp/emacs-lisp/eieio-core.el19
-rw-r--r--test/lisp/emacs-lisp/eieio-tests/eieio-tests.el7
4 files changed, 19 insertions, 12 deletions
diff --git a/doc/misc/eieio.texi b/doc/misc/eieio.texi
index 2b0b1f7fd67..8a4b914687c 100644
--- a/doc/misc/eieio.texi
+++ b/doc/misc/eieio.texi
@@ -703,8 +703,7 @@ This function retrieves the value of @var{slot} from @var{object}.
703It can also be used on objects defined by @code{cl-defstruct}. 703It can also be used on objects defined by @code{cl-defstruct}.
704 704
705This is a generalized variable that can be used with @code{setf} to 705This is a generalized variable that can be used with @code{setf} to
706modify the value stored in @var{slot}, tho not for objects defined by 706modify the value stored in @var{slot}.
707@code{cl-defstruct}.
708@xref{Generalized Variables,,,elisp,GNU Emacs Lisp Reference Manual}. 707@xref{Generalized Variables,,,elisp,GNU Emacs Lisp Reference Manual}.
709@end defun 708@end defun
710 709
diff --git a/etc/NEWS b/etc/NEWS
index 2b4eaaf8a1a..df5e6ef7904 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -423,7 +423,7 @@ representation as emojis.
423** EIEIO 423** EIEIO
424 424
425+++ 425+++
426*** 'slot-value' can now be used to read slots of 'cl-defstruct' objects. 426*** 'slot-value' can now be used to access slots of 'cl-defstruct' objects.
427 427
428** align 428** align
429 429
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el
index 7c5babcf54c..ca47ec77f76 100644
--- a/lisp/emacs-lisp/eieio-core.el
+++ b/lisp/emacs-lisp/eieio-core.el
@@ -450,7 +450,7 @@ See `defclass' for more information."
450 )) 450 ))
451 451
452 ;; Now that everything has been loaded up, all our lists are backwards! 452 ;; Now that everything has been loaded up, all our lists are backwards!
453 ;; Fix that up now and then them into vectors. 453 ;; Fix that up now and turn them into vectors.
454 (cl-callf (lambda (slots) (apply #'vector (nreverse slots))) 454 (cl-callf (lambda (slots) (apply #'vector (nreverse slots)))
455 (eieio--class-slots newc)) 455 (eieio--class-slots newc))
456 (cl-callf nreverse (eieio--class-initarg-tuples newc)) 456 (cl-callf nreverse (eieio--class-initarg-tuples newc))
@@ -704,11 +704,15 @@ an error."
704 nil 704 nil
705 ;; Trim off object IDX junk added in for the object index. 705 ;; Trim off object IDX junk added in for the object index.
706 (setq slot-idx (- slot-idx (eval-when-compile eieio--object-num-slots))) 706 (setq slot-idx (- slot-idx (eval-when-compile eieio--object-num-slots)))
707 (let ((st (cl--slot-descriptor-type (aref (eieio--class-slots class) 707 (let* ((sd (aref (eieio--class-slots class)
708 slot-idx)))) 708 slot-idx))
709 (if (not (eieio--perform-slot-validation st value)) 709 (st (cl--slot-descriptor-type sd)))
710 (signal 'invalid-slot-type 710 (cond
711 (list (eieio--class-name class) slot st value)))))) 711 ((not (eieio--perform-slot-validation st value))
712 (signal 'invalid-slot-type
713 (list (eieio--class-name class) slot st value)))
714 ((alist-get :read-only (cl--slot-descriptor-props sd))
715 (signal 'eieio-read-only (list (eieio--class-name class) slot)))))))
712 716
713(defun eieio--validate-class-slot-value (class slot-idx value slot) 717(defun eieio--validate-class-slot-value (class slot-idx value slot)
714 "Make sure that for CLASS referencing SLOT-IDX, VALUE is valid. 718 "Make sure that for CLASS referencing SLOT-IDX, VALUE is valid.
@@ -813,7 +817,7 @@ Fills in CLASS's SLOT with its default value."
813(defun eieio-oset (obj slot value) 817(defun eieio-oset (obj slot value)
814 "Do the work for the macro `oset'. 818 "Do the work for the macro `oset'.
815Fills in OBJ's SLOT with VALUE." 819Fills in OBJ's SLOT with VALUE."
816 (cl-check-type obj eieio-object) 820 (cl-check-type obj (or eieio-object cl-structure-object))
817 (cl-check-type slot symbol) 821 (cl-check-type slot symbol)
818 (let* ((class (eieio--object-class obj)) 822 (let* ((class (eieio--object-class obj))
819 (c (eieio--slot-name-index class slot))) 823 (c (eieio--slot-name-index class slot)))
@@ -1063,6 +1067,7 @@ method invocation orders of the involved classes."
1063;; 1067;;
1064(define-error 'invalid-slot-name "Invalid slot name") 1068(define-error 'invalid-slot-name "Invalid slot name")
1065(define-error 'invalid-slot-type "Invalid slot type") 1069(define-error 'invalid-slot-type "Invalid slot type")
1070(define-error 'eieio-read-only "Read-only slot")
1066(define-error 'unbound-slot "Unbound slot") 1071(define-error 'unbound-slot "Unbound slot")
1067(define-error 'inconsistent-class-hierarchy "Inconsistent class hierarchy") 1072(define-error 'inconsistent-class-hierarchy "Inconsistent class hierarchy")
1068 1073
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el b/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
index dfdfb63b584..6f6a1f4f19a 100644
--- a/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
+++ b/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
@@ -971,7 +971,7 @@ Subclasses to override slot attributes.")
971 971
972;;;; Interaction with defstruct 972;;;; Interaction with defstruct
973 973
974(cl-defstruct eieio-test--struct a b c) 974(cl-defstruct eieio-test--struct a b (c nil :read-only t))
975 975
976(ert-deftest eieio-test-defstruct-slot-value () 976(ert-deftest eieio-test-defstruct-slot-value ()
977 (let ((x (make-eieio-test--struct :a 'A :b 'B :c 'C))) 977 (let ((x (make-eieio-test--struct :a 'A :b 'B :c 'C)))
@@ -980,7 +980,10 @@ Subclasses to override slot attributes.")
980 (should (eq (eieio-test--struct-b x) 980 (should (eq (eieio-test--struct-b x)
981 (slot-value x 'b))) 981 (slot-value x 'b)))
982 (should (eq (eieio-test--struct-c x) 982 (should (eq (eieio-test--struct-c x)
983 (slot-value x 'c))))) 983 (slot-value x 'c)))
984 (setf (slot-value x 'a) 1)
985 (should (eq (eieio-test--struct-a x) 1))
986 (should-error (setf (slot-value x 'c) 3) :type 'eieio-read-only)))
984 987
985(provide 'eieio-tests) 988(provide 'eieio-tests)
986 989