Mercurial > core / lisp/std/named-readtables.lisp
changeset 698: |
96958d3eb5b0 |
parent: |
00d1c8afcdbb
|
author: |
Richard Westhaver <ellis@rwest.io> |
date: |
Fri, 04 Oct 2024 22:04:59 -0400 |
permissions: |
-rw-r--r-- |
description: |
fixes |
1 ;;; named-readtables.lisp --- named-readtables 3 ;; The standard readtable is controlled by the Lisp implementation and 4 ;; generally shouldn't be touched. There can be problems with 5 ;; 'stacking' multiple read-macros as can be seen in this SO post: 6 ;; https://stackoverflow.com/questions/73346051/how-can-i-modify-the-and-readtable-macros-in-lisp 8 ;; Instead, if you really want to change standard readtable behavior, 9 ;; it is better to define your own readtables and be aware of the 10 ;; context in which they are enabled. For example, loading a system 11 ;; definition before enabling the readtable may cause divergent 12 ;; behavior (using standard) versus your source code (custom). 15 (defpackage :std/named-readtables 21 :merge-readtables-into 29 :list-all-named-readtables 31 :named-readtable-designator 34 :reader-macro-conflict 35 :readtable-does-already-exist 36 :readtable-does-not-exist 39 (in-package :std/named-readtables) 40 (pushnew :named-readtables *features*) 42 (defmacro without-package-lock ((&rest package-names) &body body) 43 `(sb-ext:with-unlocked-packages (,@package-names) ,@body)) 45 ;;; Taken from SWANK (which is Public Domain.) 47 (defmacro destructure-case (value &body patterns) 48 "Dispatch VALUE to one of PATTERNS. 49 A cross between `case' and `destructuring-bind'. 50 The pattern syntax is: 51 ((HEAD . ARGS) . BODY) 52 The list of patterns is searched for a HEAD `eq' to the car of 53 VALUE. If one is found, the BODY is executed with ARGS bound to the 54 corresponding values in the CDR of VALUE." 55 (let ((operator (gensym "op-")) 56 (operands (gensym "rand-")) 57 (tmp (gensym "tmp-"))) 59 (,operator (car ,tmp)) 60 (,operands (cdr ,tmp))) 62 ,@(loop for (pattern . body) in patterns collect 65 (destructuring-bind (op &rest rands) pattern 66 `(,op (destructuring-bind ,rands ,operands 68 ,@(if (eq (caar (last patterns)) t) 70 `((t (error "destructure-case failed: ~S" ,tmp)))))))) 72 ;;; Taken from Alexandria (which is Public Domain, or BSD.) 74 (define-condition simple-style-warning (simple-warning style-warning) 77 (defun simple-style-warn (format-control &rest format-args) 78 (warn 'simple-style-warning 79 :format-control format-control 80 :format-arguments format-args)) 82 (define-condition simple-program-error (simple-error program-error) 85 (defun simple-program-error (message &rest args) 86 (error 'simple-program-error 87 :format-control message 88 :format-arguments args)) 90 (defun required-argument (&optional name) 91 "Signals an error for a missing argument of NAME. Intended for 92 use as an initialization form for structure and class-slots, and 93 a default value for required keyword arguments." 94 (error "Required argument ~@[~S ~]missing." name)) 96 (defun ensure-list (list) 97 "If LIST is a list, it is returned. Otherwise returns the list 103 (declaim (inline ensure-function)) ; to propagate return type. 104 (declaim (ftype (function (t) (values function &optional)) 106 (defun ensure-function (function-designator) 107 "Returns the function designated by FUNCTION-DESIGNATOR: 108 if FUNCTION-DESIGNATOR is a function, it is returned, otherwise 109 it must be a function name and its FDEFINITION is returned." 110 (if (functionp function-designator) 112 (fdefinition function-designator))) 114 (eval-when (:compile-toplevel :load-toplevel :execute) 115 (defun parse-body (body &key documentation whole) 116 "Parses BODY into (values remaining-forms declarations doc-string). 117 Documentation strings are recognized only if DOCUMENTATION is true. 118 Syntax errors in body are signalled and WHOLE is used in the signal 119 arguments when given." 125 (setf current (car body)) 126 (when (and documentation (stringp current) (cdr body)) 128 (error "Too many documentation strings in ~S." (or whole body)) 129 (setf doc (pop body))) 131 (when (and (listp current) (eql (first current) 'declare)) 132 (push (pop body) decls) 134 (values body (nreverse decls) doc))) 136 (defun parse-ordinary-lambda-list (lambda-list) 137 "Parses an ordinary lambda-list, returning as multiple values: 139 1. Required parameters. 140 2. Optional parameter specifications, normalized into form (NAME INIT SUPPLIEDP) 141 where SUPPLIEDP is NIL if not present. 142 3. Name of the rest parameter, or NIL. 143 4. Keyword parameter specifications, normalized into form ((KEYWORD-NAME NAME) INIT SUPPLIEDP) 144 where SUPPLIEDP is NIL if not present. 145 5. Boolean indicating &ALLOW-OTHER-KEYS presence. 146 6. &AUX parameter specifications, normalized into form (NAME INIT). 148 Signals a PROGRAM-ERROR is the lambda-list is malformed." 149 (let ((state :required) 150 (allow-other-keys nil) 157 (labels ((simple-program-error (format-string &rest format-args) 158 (error 'simple-program-error 159 :format-control format-string 160 :format-arguments format-args)) 162 (simple-program-error "Misplaced ~S in ordinary lambda-list:~% ~S" 164 (check-variable (elt what) 165 (unless (and (symbolp elt) (not (constantp elt))) 166 (simple-program-error "Invalid ~A ~S in ordinary lambda-list:~% ~S" 167 what elt lambda-list))) 168 (check-spec (spec what) 169 (destructuring-bind (init suppliedp) spec 170 (declare (ignore init)) 171 (check-variable suppliedp what))) 173 "Interns the string designated by NAME in the KEYWORD package." 174 (intern (string name) :keyword))) 175 (dolist (elt lambda-list) 178 (if (eq state :required) 182 (if (member state '(:required &optional)) 185 (break "state=~S" state) 188 (if (member state '(:required &optional :after-rest)) 193 (setf allow-other-keys t 197 (cond ((eq state '&rest) 200 (simple-program-error "Multiple ~S in ordinary lambda-list:~% ~S" 207 (when (member elt '#.(set-difference lambda-list-keywords 208 '(&optional &rest &key &allow-other-keys &aux))) 209 (simple-program-error 210 "Bad lambda-list keyword ~S in ordinary lambda-list:~% ~S" 214 (check-variable elt "required parameter") 218 (destructuring-bind (name &rest tail) elt 219 (check-variable name "optional parameter") 221 (check-spec tail "optional-supplied-p parameter") 222 (setf elt (append elt '(nil)))))) 224 (check-variable elt "optional parameter") 225 (setf elt (cons elt '(nil nil))))) 228 (check-variable elt "rest parameter") 233 (destructuring-bind (var-or-kv &rest tail) elt 234 (cond ((consp var-or-kv) 235 (destructuring-bind (keyword var) var-or-kv 236 (unless (symbolp keyword) 237 (simple-program-error "Invalid keyword name ~S in ordinary ~ 239 keyword lambda-list)) 240 (check-variable var "keyword parameter"))) 242 (check-variable var-or-kv "keyword parameter") 243 (setf var-or-kv (list (make-keyword var-or-kv) var-or-kv)))) 245 (check-spec tail "keyword-supplied-p parameter") 246 (setf tail (append tail '(nil)))) 247 (setf elt (cons var-or-kv tail)))) 249 (check-variable elt "keyword parameter") 250 (setf elt (list (list (make-keyword elt) elt) nil nil)))) 254 (destructuring-bind (var &optional init) elt 255 (declare (ignore init)) 256 (check-variable var "&aux parameter")) 257 (check-variable elt "&aux parameter")) 260 (simple-program-error "Invalid ordinary lambda-list:~% ~S" lambda-list))))))) 261 (values (nreverse required) (nreverse optional) rest (nreverse keys) 262 allow-other-keys (nreverse aux))))) 264 (defmacro define-api (name lambda-list type-list &body body) 265 (flet ((parse-type-list (type-list) 266 (let ((pos (position '=> type-list))) 267 (assert pos () "You forgot to specify return type (`=>' missing.)") 268 (values (subseq type-list 0 pos) 269 `(values ,@(nthcdr (1+ pos) type-list) &optional))))) 270 (multiple-value-bind (body decls docstring) 271 (parse-body body :documentation t :whole `(define-api ,name)) 272 (multiple-value-bind (arg-typespec value-typespec) 273 (parse-type-list type-list) 274 (multiple-value-bind (reqs opts rest keys) 275 (parse-ordinary-lambda-list lambda-list) 276 (declare (ignorable reqs opts rest keys)) 278 (declaim (ftype (function ,arg-typespec ,value-typespec) ,name)) 280 ;; Muffle the annoying "&OPTIONAL and &KEY found in 281 ;; the same lambda list" style-warning 282 #+sbcl (declare (sb-ext:muffle-conditions style-warning)) 283 (defun ,name ,lambda-list 287 #+sbcl (declare (sb-ext:unmuffle-conditions style-warning)) 288 ;; SBCL will interpret the ftype declaration as 289 ;; assertion and will insert type checks for us. 292 (defmacro define-cruft (name lambda-list &body (docstring . alternatives)) 293 (assert (typep docstring 'string) (docstring) "Docstring missing!") 294 (assert (not (null alternatives))) 296 (declaim (inline ,name)) 297 (defun ,name ,lambda-list ,docstring ,(first alternatives)))) 299 (eval-when (:compile-toplevel :execute) 300 #+sbcl (when (find-symbol "ASSERT-NOT-STANDARD-READTABLE" 301 (find-package "SB-IMPL")) 302 (pushnew :sbcl+safe-standard-readtable *features*))) 306 ;;;; Mapping between a readtable object and its readtable-name. 308 (defvar *readtable-names* (make-hash-table :test 'eq)) 310 (define-cruft %associate-readtable-with-name (name readtable) 311 "Associate READTABLE with NAME for READTABLE-NAME to work." 312 #+ :common-lisp (setf (gethash readtable *readtable-names*) name)) 314 (define-cruft %unassociate-readtable-from-name (name readtable) 315 "Remove the association between READTABLE and NAME." 316 #+ :common-lisp (progn (assert (eq name (gethash readtable *readtable-names*))) 317 (remhash readtable *readtable-names*))) 319 (define-cruft %readtable-name (readtable) 320 "Return the name associated with READTABLE." 321 #+ :common-lisp (values (gethash readtable *readtable-names*))) 323 (define-cruft %list-all-readtable-names () 324 "Return a list of all available readtable names." 325 #+ :common-lisp (list* :standard :current :modern 326 (loop for name being each hash-value of *readtable-names* 329 ;;;; Mapping READTABLE objects to docstrings. 331 (defvar *readtable-to-docstring* (make-hash-table :test 'eq)) 333 (defun %associate-docstring-with-readtable (readtable docstring) 334 (setf (gethash readtable *readtable-to-docstring*) docstring)) 336 (defun %unassociate-docstring-from-readtable (readtable) 337 (prog1 (gethash readtable *readtable-to-docstring*) 338 (remhash readtable *readtable-to-docstring*))) 340 ;;;; Specialized DOCUMENTATION for named readtables. 342 ;;; Lispworks, at least, forbids defining methods on DOCUMENTATION. 343 ;;; Wrapping these forms with WITHOUT-PACKAGE-LOCK (as for PRINT-OBJECT, 344 ;;; see below) allows this to compile on Lispworks. 346 (without-package-lock (:common-lisp #+lispworks :implementation) 348 (defmethod documentation ((name symbol) (doc-type (eql 'readtable))) 349 (let ((readtable (find-readtable name))) 350 (and readtable (gethash readtable *readtable-to-docstring*)))) 352 (defmethod documentation ((readtable readtable) (doc-type (eql 'readtable))) 353 (gethash readtable *readtable-to-docstring*)) 355 (defmethod (setf documentation) (docstring (name symbol) 356 (doc-type (eql 'readtable))) 357 (let ((readtable (find-readtable name))) 359 (error 'readtable-does-not-exist :readtable-name name)) 360 (setf (gethash readtable *readtable-to-docstring*) docstring))) 362 (defmethod (setf documentation) (docstring (readtable readtable) 363 (doc-type (eql 'readtable))) 364 (setf (gethash readtable *readtable-to-docstring*) docstring))) 367 ;;;; Mapping between a readtable-name and the actual readtable object. 369 ;;; On Allegro we reuse their named-readtable support so we work 370 ;;; nicely on their infrastructure. 372 (defvar *named-readtables* (make-hash-table :test 'eq)) 374 (define-cruft %associate-name-with-readtable (name readtable) 375 "Associate NAME with READTABLE for FIND-READTABLE to work." 376 #+ :common-lisp (setf (gethash name *named-readtables*) readtable)) 378 (define-cruft %unassociate-name-from-readtable (name readtable) 379 "Remove the association between NAME and READTABLE" 380 #+ :common-lisp (progn (assert (eq readtable (gethash name *named-readtables*))) 381 (remhash name *named-readtables*))) 383 (define-cruft %find-readtable (name) 384 "Return the readtable named NAME." 385 #+ :common-lisp (values (gethash name *named-readtables* nil))) 388 ;;;; Reader-macro related predicates 390 ;;; CLISP creates new function objects for standard reader macros on 391 ;;; each readtable copy. 392 (define-cruft function= (fn1 fn2) 393 "Are reader-macro function-designators FN1 and FN2 the same?" 394 (let ((fn1 (ensure-function fn1)) 395 (fn2 (ensure-function fn2))) 397 ;; After SBCL 1.1.18, for dispatch macro characters 398 ;; GET-MACRO-CHARACTER returns closures whose name is: 400 ;; (LAMBDA (STREAM CHAR) :IN SB-IMPL::%MAKE-DISPATCH-MACRO-CHAR) 402 ;; Treat all these closures equivalent. 403 (flet ((internal-dispatch-macro-closure-name-p (name) 404 (find "SB-IMPL::%MAKE-DISPATCH-MACRO-CHAR" name 405 :key #'prin1-to-string :test #'string-equal))) 406 (let ((n1 (sb-impl::%fun-name fn1)) 407 (n2 (sb-impl::%fun-name fn2))) 408 (and (listp n1) (listp n2) 409 (internal-dispatch-macro-closure-name-p n1) 410 (internal-dispatch-macro-closure-name-p n2)))))) 412 (eq (ensure-function fn1) (ensure-function fn2))) 414 (define-cruft dispatch-macro-char-p (char rt) 415 "Is CHAR a dispatch macro character in RT?" 417 (handler-case (locally 418 (get-dispatch-macro-character char #\x rt) 422 ;; (defun macro-char-p (char rt) 423 ;; (let ((reader-fn (%get-macro-character char rt))) 424 ;; (and reader-fn t))) 426 ;; (defun standard-macro-char-p (char rt) 427 ;; (multiple-value-bind (rt-fn rt-flag) (get-macro-character char rt) 428 ;; (multiple-value-bind (std-fn std-flag) (get-macro-character char *standard-readtable*) 429 ;; (and (eq rt-fn std-fn) 430 ;; (eq rt-flag std-flag))))) 432 ;; (defun standard-dispatch-macro-char-p (disp-char sub-char rt) 433 ;; (flet ((non-terminating-p (ch rt) (nth-value 1 (get-macro-character ch rt)))) 434 ;; (and (eq (non-terminating-p disp-char rt) 435 ;; (non-terminating-p disp-char *standard-readtable*)) 436 ;; (eq (get-dispatch-macro-character disp-char sub-char rt) 437 ;; (get-dispatch-macro-character disp-char sub-char *standard-readtable*))))) 440 ;;;; Readtables Iterators 442 (defmacro with-readtable-iterator ((name readtable) &body body) 444 `(let ((,it (%make-readtable-iterator ,readtable))) 445 (macrolet ((,name () `(funcall ,',it))) 448 (defun funcall-or (package-and-name-list &rest args) 449 (loop for (package name) in package-and-name-list 450 do (let ((symbol (find-symbol (string name) package))) 452 (return-from funcall-or (apply symbol args)))))) 454 (defun %make-readtable-iterator (readtable) 455 (let ((char-macro-array (funcall-or '((sb-impl base-char-macro-array) 456 (sb-impl character-macro-array)) 458 (char-macro-ht (funcall-or '((sb-impl extended-char-table) 459 (sb-impl character-macro-hash-table)) 461 (dispatch-tables (sb-impl::dispatch-tables readtable)) 463 (with-hash-table-iterator (ht-iterator char-macro-ht) 464 (labels ((grovel-base-chars () 465 (if (>= char-code sb-int:base-char-code-limit) 466 (grovel-unicode-chars) 467 (let ((reader-fn (svref char-macro-array char-code)) 468 (char (code-char (shiftf char-code (1+ char-code))))) 471 (grovel-base-chars))))) 472 (grovel-unicode-chars () 473 (multiple-value-bind (more? char) (ht-iterator) 475 (values nil nil nil nil nil) 478 (let ((disp-fn (get-macro-character char readtable)) 481 ((setq disp-ht (cdr (assoc char dispatch-tables))) 482 (let ((sub-char-alist)) 483 (maphash (lambda (k v) 484 (push (cons k v) sub-char-alist)) 486 (values t char disp-fn t sub-char-alist))) 488 (values t char disp-fn nil nil)))))) 489 #'grovel-base-chars)))) 491 (defmacro do-readtable ((entry-designator readtable &optional result) 493 "Iterate through a readtable's macro characters, and dispatch macro characters." 494 (destructuring-bind (char &optional reader-fn non-terminating-p disp? table) 495 (if (symbolp entry-designator) 496 (list entry-designator) 498 (let ((iter (gensym "ITER+")) 499 (more? (gensym "MORE?+")) 500 (rt (gensym "READTABLE+"))) 501 `(let ((,rt ,readtable)) 502 (with-readtable-iterator (,iter ,rt) 504 (multiple-value-bind (,more? 506 ,@(when reader-fn (list reader-fn)) 507 ,@(when disp? (list disp?)) 508 ,@(when table (list table))) 510 (unless ,more? (return ,result)) 511 (let ,(when non-terminating-p 512 ;; FIXME: N-T-P should be incorporated in iterators. 513 `((,non-terminating-p 514 (nth-value 1 (get-macro-character ,char ,rt))))) 519 ;;; This should return an implementation's actual standard readtable 520 ;;; object only if the implementation makes the effort to guard against 521 ;;; modification of that object. Otherwise it should better return a 523 (define-cruft %standard-readtable () 524 "Return the standard readtable." 525 #+ :sbcl+safe-standard-readtable sb-impl::*standard-readtable* 526 #+ :common-lisp (copy-readtable nil)) 528 ;;; On SBCL, SET-SYNTAX-FROM-CHAR does not get rid of a 529 ;;; readtable's dispatch table properly. 530 ;;; Same goes for Allegro but that does not seem to provide a 531 ;;; setter for their readtable's dispatch tables. Hence this ugly 533 (define-cruft %clear-readtable (readtable) 534 "Make all macro characters in READTABLE be constituents." 536 (do-readtable (char readtable) 537 (set-syntax-from-char char #\A readtable)) 538 (setf (sb-impl::dispatch-tables readtable) nil)) 540 (do-readtable (char readtable readtable) 541 (set-syntax-from-char char #\A readtable))) 543 (define-cruft %get-dispatch-macro-character (char subchar rt) 544 "Ensure ANSI behaviour for GET-DISPATCH-MACRO-CHARACTER." 545 #+ :common-lisp (get-dispatch-macro-character char subchar rt)) 547 (define-cruft %get-macro-character (char rt) 548 "Ensure ANSI behaviour for GET-MACRO-CHARACTER." 549 #+ :common-lisp (get-macro-character char rt)) 552 ;;;; Specialized PRINT-OBJECT for named readtables. 554 ;;; As per #19 in CLHS 11.1.2.1.2 defining a method for PRINT-OBJECT 555 ;;; that specializes on READTABLE is actually forbidden. It's quite 556 ;;; likely to work (modulo package-locks) on most implementations, 559 (without-package-lock (:common-lisp) 560 (defmethod print-object :around ((rt readtable) stream) 561 (let ((name (readtable-name rt))) 563 (print-unreadable-object (rt stream :type nil :identity t) 564 (format stream "~A ~S" :named-readtable name)) 565 (call-next-method))))) 568 ;;; ``This is enough of a foothold to implement a more elaborate 569 ;;; facility for using readtables in a localized way.'' 571 ;;; (X3J13 Cleanup Issue IN-SYNTAX) 574 ;;;;;; DEFREADTABLE &c. 575 (defmacro defreadtable (name &body options) 576 "Define a new named readtable, whose name is given by the symbol NAME. 577 Or, if a readtable is already registered under that name, redefine 580 The readtable can be populated using the following OPTIONS: 582 - If the first element of OPTIONS is a string then it is associated 583 with the readtable as in `(SETF (DOCUMENTATION NAME 'READTABLE) 586 - `(:MERGE READTABLE-DESIGNATORS+)` 588 Merge the macro character definitions from the readtables 589 designated into the new readtable being defined as per 590 MERGE-READTABLES-INTO. The copied options are 591 :DISPATCH-MACRO-CHAR, :MACRO-CHAR and :SYNTAX-FROM, but not 594 If no :MERGE clause is given, an empty readtable is used. See 597 - `(:FUSE READTABLE-DESIGNATORS+)` 601 Error conditions of type READER-MACRO-CONFLICT that are signaled 602 during the merge operation will be silently _continued_. It 603 follows that reader macros in earlier entries will be 604 overwritten by later ones. For backward compatibility, :FUZE is 605 accepted as an alias of :FUSE. 607 - `(:DISPATCH-MACRO-CHAR MACRO-CHAR SUB-CHAR FUNCTION)` 609 Define a new sub character `SUB-CHAR` for the dispatching macro 610 character `MACRO-CHAR`, per SET-DISPATCH-MACRO-CHARACTER. You 611 probably have to define `MACRO-CHAR` as a dispatching macro 612 character by the following option first. 614 - `(:MACRO-CHAR MACRO-CHAR FUNCTION [NON-TERMINATING-P])` 616 Define a new macro character in the readtable, per 617 SET-MACRO-CHARACTER. If [FUNCTION][argument] is the keyword 618 :DISPATCH, `MACRO-CHAR` is made a dispatching macro character, 619 per MAKE-DISPATCH-MACRO-CHARACTER. 621 - `(:SYNTAX-FROM FROM-READTABLE-DESIGNATOR FROM-CHAR TO-CHAR)` 623 Set the character syntax of TO-CHAR in the readtable being 624 defined to the same syntax as FROM-CHAR as per 625 SET-SYNTAX-FROM-CHAR. 627 - `(:CASE CASE-MODE)` 629 Defines the _case sensitivity mode_ of the resulting readtable. 631 Any number of option clauses may appear. The options are grouped by 632 their type, but in each group the order the options appeared 633 textually is preserved. The following groups exist and are executed 634 in the following order: :MERGE and :FUSE (one group), :CASE, 635 :MACRO-CHAR and :DISPATCH-MACRO-CHAR (one group), finally 640 The readtable is defined at load-time. If you want to have it 641 available at compilation time -- say to use its reader-macros in the 642 same file as its definition -- you have to wrap the DEFREADTABLE 643 form in an explicit EVAL-WHEN. 645 On redefinition, the target readtable is made empty first before 646 it's refilled according to the clauses. 648 NIL, :STANDARD, :COMMON-LISP, :MODERN, and :CURRENT are 649 preregistered readtable names." 650 (check-type name symbol) 651 (when (reserved-readtable-name-p name) 652 (error "~A is the designator for a predefined readtable. ~ 653 Not acceptable as a user-specified readtable name." name)) 654 (flet ((process-option (option var) 655 (destructure-case option 656 ((:merge &rest readtable-designators) 657 `(merge-readtables-into ,var ,@(mapcar #'(lambda (x) `',x) 658 readtable-designators))) 659 ((:fuse &rest readtable-designators) 660 `(handler-bind ((reader-macro-conflict #'continue)) 661 (merge-readtables-into ,var ,@(mapcar #'(lambda (x) `',x) 662 readtable-designators)))) 664 ((:fuze &rest readtable-designators) 665 `(handler-bind ((reader-macro-conflict #'continue)) 666 (merge-readtables-into ,var ,@(mapcar #'(lambda (x) `',x) 667 readtable-designators)))) 668 ((:dispatch-macro-char disp-char sub-char function) 669 `(set-dispatch-macro-character ,disp-char ,sub-char 671 ((:macro-char char function &optional non-terminating-p) 672 (if (eq function :dispatch) 673 `(make-dispatch-macro-character ,char ,non-terminating-p ,var) 674 `(set-macro-character ,char ,function 675 ,non-terminating-p ,var))) 676 ((:syntax-from from-rt-designator from-char to-char) 677 `(set-syntax-from-char ,to-char ,from-char 678 ,var (find-readtable ,from-rt-designator))) 680 `(setf (readtable-case ,var) ,mode)))) 681 (remove-clauses (clauses options) 682 (setq clauses (if (listp clauses) clauses (list clauses))) 683 (remove-if-not #'(lambda (x) (member x clauses)) 684 options :key #'first))) 685 (let* ((docstring (when (stringp (first options)) 687 (merge-clauses (remove-clauses '(:merge :fuze :fuse) options)) 688 (case-clauses (remove-clauses :case options)) 689 (macro-clauses (remove-clauses '(:macro-char :dispatch-macro-char) 691 (syntax-clauses (remove-clauses :syntax-from options)) 693 (set-difference options 694 (append merge-clauses case-clauses 695 macro-clauses syntax-clauses)))) 697 ((not (null other-clauses)) 698 (error "Bogus DEFREADTABLE clauses: ~/PPRINT-LINEAR/" other-clauses)) 700 `(eval-when (:load-toplevel :execute) 701 ;; The (FIND-READTABLE ...) is important for proper 702 ;; redefinition semantics, as redefining has to modify the 703 ;; already existing readtable object. 704 (let ((readtable (find-readtable ',name))) 705 (cond ((not readtable) 706 (setq readtable (make-readtable ',name))) 708 (setq readtable (%clear-readtable readtable)) 710 "Overwriting already existing readtable ~S." 712 (setf (documentation readtable 'readtable) ,docstring) 713 ,@(loop for option in merge-clauses 714 collect (process-option option 'readtable)) 715 ,@(loop for option in case-clauses 716 collect (process-option option 'readtable)) 717 ,@(loop for option in macro-clauses 718 collect (process-option option 'readtable)) 719 ,@(loop for option in syntax-clauses 720 collect (process-option option 'readtable)) 723 (defmacro in-readtable (name) 724 "Set *READTABLE* to the readtable referred to by the symbol NAME. 725 Return the readtable." 726 (check-type name symbol) 727 `(eval-when (:compile-toplevel :load-toplevel :execute) 728 ;; NB. The :LOAD-TOPLEVEL is needed for cases like (DEFVAR *FOO* 729 ;; (GET-MACRO-CHARACTER #\")) 730 (setf *readtable* (ensure-readtable ',name)) 731 (when (find-package :swank) 732 (%frob-swank-readtable-alist *package* *readtable*)) 735 ;;; KLUDGE: [interim solution] 737 ;;; We need support for this in Slime itself, because we want IN-READTABLE 738 ;;; to work on a per-file basis, and not on a per-package basis. 740 (defun %frob-swank-readtable-alist (package readtable) 741 (let ((readtable-alist (find-symbol (string '#:*readtable-alist*) 742 (find-package :swank)))) 743 (when (boundp readtable-alist) 744 (let ((new-item (cons (package-name package) readtable))) 745 (setf (symbol-value readtable-alist) 748 (remove new-item (symbol-value readtable-alist) 749 :test (lambda (entry1 entry2) 750 (string= (car entry1) (car entry2)))))))))) 752 (deftype readtable-designator () 753 `(or null readtable)) 755 (deftype named-readtable-designator () 756 "Either a symbol or a readtable itself." 757 `(or readtable-designator symbol)) 759 ;;;;; Compiler macros 761 ;;; Since the :STANDARD readtable is interned, and we can't enforce 762 ;;; its immutability, we signal a style-warning for suspicious uses 763 ;;; that may result in strange behaviour: 765 ;;; Modifying the standard readtable would, obviously, lead to a 766 ;;; propagation of this change to all places which use the :STANDARD 767 ;;; readtable (and thus rendering this readtable to be non-standard, 769 (eval-when (:compile-toplevel :load-toplevel :execute) 770 (defun constant-standard-readtable-expression-p (thing) 775 '((find-readtable nil) 776 (find-readtable :standard) 777 (ensure-readtable nil) 778 (ensure-readtable :standard)) 781 (defun signal-suspicious-registration-warning (name-expr readtable-expr) 782 (when (constant-standard-readtable-expression-p readtable-expr) 784 "Caution: ~<You're trying to register the :STANDARD readtable ~ 785 under a new name ~S. As modification of the :STANDARD readtable ~ 786 is not permitted, subsequent modification of ~S won't be ~ 787 permitted either. You probably want to wrap COPY-READTABLE ~ 789 (list name-expr name-expr) readtable-expr)))) 791 (define-compiler-macro register-readtable (&whole form name readtable) 792 (signal-suspicious-registration-warning name readtable) 795 (define-compiler-macro ensure-readtable (&whole form name &optional 796 (default nil default-p)) 798 (signal-suspicious-registration-warning name default)) 801 (declaim (special *standard-readtable* *empty-readtable*)) 803 (define-api make-readtable 804 (&optional (name nil name-supplied-p) &key merge) 805 (&optional named-readtable-designator &key (:merge list) => readtable) 806 "Creates and returns a new readtable under the specified 809 MERGE takes a list of NAMED-READTABLE-DESIGNATORs and specifies the 810 readtables the new readtable is created from. (See the :MERGE clause 811 of DEFREADTABLE for details.) 813 If MERGE is NIL, an empty readtable is used instead. 815 If NAME is not given, an anonymous empty readtable is returned. 819 An empty readtable is a readtable where each character's syntax is 820 the same as in the _standard readtable_ except that each macro 821 character has been made a constituent. Basically: whitespace stays 822 whitespace, everything else is constituent." 823 (cond ((not name-supplied-p) 824 (copy-readtable *empty-readtable*)) 825 ((reserved-readtable-name-p name) 826 (error "~A is the designator for a predefined readtable. ~ 827 Not acceptable as a user-specified readtable name." name)) 828 ((let ((rt (find-readtable name))) 830 (cerror "Overwrite existing entry." 831 'readtable-does-already-exist :readtable-name name) 832 ;; Explicitly unregister to make sure that we do 833 ;; not hold on of any reference to RT. 834 (unregister-readtable rt))))) 835 (t (let ((result (apply #'merge-readtables-into 836 ;; The first readtable specified in 837 ;; the :merge list is taken as the 838 ;; basis for all subsequent 839 ;; (destructive!) modifications (and 840 ;; hence it's copied.) 841 (copy-readtable (if merge 847 (register-readtable name result))))) 849 (define-api rename-readtable 851 (named-readtable-designator symbol => readtable) 852 "Replaces the associated name of the readtable designated by 853 OLD-NAME with NEW-NAME. If a readtable is already registered under 854 NEW-NAME, an error of type READTABLE-DOES-ALREADY-EXIST is 856 (when (find-readtable new-name) 857 (cerror "Overwrite existing entry." 858 'readtable-does-already-exist :readtable-name new-name)) 859 (let* ((readtable (ensure-readtable old-name)) 860 (readtable-name (readtable-name readtable))) 861 ;; We use the internal functions directly to omit repeated 863 (%unassociate-name-from-readtable readtable-name readtable) 864 (%unassociate-readtable-from-name readtable-name readtable) 865 (%associate-name-with-readtable new-name readtable) 866 (%associate-readtable-with-name new-name readtable) 867 (%associate-docstring-with-readtable 868 readtable (%unassociate-docstring-from-readtable readtable)) 871 (define-api merge-readtables-into 872 (result-readtable &rest named-readtables) 873 (named-readtable-designator &rest named-readtable-designator => readtable) 874 "Copy macro character definitions of each readtable in 875 NAMED-READTABLES into RESULT-READTABLE. 877 If a macro character appears in more than one of the readtables, 878 i.e. if a conflict is discovered during the merge, an error of type 879 READER-MACRO-CONFLICT is signaled. 881 The copied options are :DISPATCH-MACRO-CHAR, :MACRO-CHAR and 882 :SYNTAX-FROM, but not READTABLE-CASE." 883 (flet ((merge-into (to from) 884 (do-readtable ((char reader-fn non-terminating-p disp? table) from) 885 (check-reader-macro-conflict from to char) 887 (set-macro-character char reader-fn non-terminating-p to)) 889 (ensure-dispatch-macro-character char non-terminating-p to) 890 (loop for (subchar . subfn) in table do 891 (check-reader-macro-conflict from to char subchar) 892 (set-dispatch-macro-character char subchar 895 (let ((result-table (ensure-readtable result-readtable))) 896 (dolist (table (mapcar #'ensure-readtable named-readtables)) 897 (merge-into result-table table)) 900 (defun ensure-dispatch-macro-character (char &optional non-terminating-p 901 (readtable *readtable*)) 902 (if (dispatch-macro-char-p char readtable) 904 (make-dispatch-macro-character char non-terminating-p readtable))) 906 (define-api copy-named-readtable 908 (named-readtable-designator => readtable) 909 "Like COPY-READTABLE but takes a NAMED-READTABLE-DESIGNATOR as argument." 910 (copy-readtable (ensure-readtable named-readtable))) 912 (define-api list-all-named-readtables () (=> list) 913 "Returns a list of all registered readtables. The returned list is 914 guaranteed to be fresh, but may contain duplicates." 915 (mapcar #'ensure-readtable (%list-all-readtable-names))) 918 (define-condition readtable-error (error) ()) 920 (define-condition readtable-does-not-exist (readtable-error) 921 ((readtable-name :initarg :readtable-name 922 :initform (required-argument) 923 :accessor missing-readtable-name 924 :type named-readtable-designator)) 925 (:report (lambda (condition stream) 926 (format stream "A readtable named ~S does not exist." 927 (missing-readtable-name condition))))) 929 (define-condition readtable-does-already-exist (readtable-error) 930 ((readtable-name :initarg :readtable-name 931 :initform (required-argument) 932 :accessor existing-readtable-name 933 :type named-readtable-designator)) 934 (:report (lambda (condition stream) 935 (format stream "A readtable named ~S already exists." 936 (existing-readtable-name condition)))) 937 (:documentation "Continuable.")) 939 (define-condition reader-macro-conflict (readtable-error) 942 :initform (required-argument) 943 :accessor conflicting-macro-char 948 :accessor conflicting-dispatch-sub-char 949 :type (or null character)) 951 :initarg :from-readtable 952 :initform (required-argument) 953 :accessor from-readtable 956 :initarg :to-readtable 957 :initform (required-argument) 958 :accessor to-readtable 961 (lambda (condition stream) 962 (format stream "~@<Reader macro conflict while trying to merge the ~ 963 ~:[macro character~;dispatch macro characters~] ~ 964 ~@C~@[ ~@C~] from ~A into ~A.~@:>" 965 (conflicting-dispatch-sub-char condition) 966 (conflicting-macro-char condition) 967 (conflicting-dispatch-sub-char condition) 968 (from-readtable condition) 969 (to-readtable condition)))) 970 (:documentation "Continuable. 972 This condition is signaled during the merge process if a reader 973 macro (be it a macro character or the sub character of a dispatch 974 macro character) is present in the both source and the target 975 readtable and the two respective reader macro functions differ.")) 977 (defun check-reader-macro-conflict (from to char &optional subchar) 978 (flet ((conflictp (from-fn to-fn) 980 "Bug in readtable iterators or concurrent access?") 981 (and to-fn (not (function= to-fn from-fn))))) 983 (conflictp (%get-dispatch-macro-character char subchar from) 984 (%get-dispatch-macro-character char subchar to)) 985 (conflictp (%get-macro-character char from) 986 (%get-macro-character char to))) 987 (cerror (format nil "Overwrite ~@C in ~A." char to) 988 'reader-macro-conflict 992 :sub-char subchar)))) 995 ;;; Although there is no way to get at the standard readtable in 996 ;;; Common Lisp (cf. /standard readtable/, CLHS glossary), we make 997 ;;; up the perception of its existence by interning a copy of it. 999 ;;; We do this for reverse lookup (cf. READTABLE-NAME), i.e. for 1001 ;;; (equal (readtable-name (find-readtable :standard)) "STANDARD") 1005 ;;; We, however, inherit the restriction that the :STANDARD 1006 ;;; readtable _must not be modified_ (cf. CLHS 2.1.1.2), although it'd 1007 ;;; technically be feasible (as *STANDARD-READTABLE* will contain a 1008 ;;; mutable copy of the implementation-internal standard readtable.) 1009 ;;; We cannot enforce this restriction without shadowing 1010 ;;; CL:SET-MACRO-CHARACTER and CL:SET-DISPATCH-MACRO-FUNCTION which 1011 ;;; is out of scope of this library, though. So we just threaten 1012 ;;; with nasal demons. 1014 (defvar *standard-readtable* 1015 (%standard-readtable)) 1017 (defvar *empty-readtable* 1018 (%clear-readtable (copy-readtable nil))) 1020 (defvar *case-preserving-standard-readtable* 1021 (let ((readtable (copy-readtable nil))) 1022 (setf (readtable-case readtable) :preserve) 1025 (defparameter *reserved-readtable-names* 1026 '(nil :standard :common-lisp :modern :current)) 1028 (defun reserved-readtable-name-p (name) 1029 (and (member name *reserved-readtable-names*) t)) 1031 ;;; In principle, we could DEFREADTABLE some of these. But we do 1032 ;;; reserved readtable lookup seperately, since we can't register a 1033 ;;; readtable for :CURRENT anyway. 1035 (defun find-reserved-readtable (reserved-name) 1036 (cond ((eq reserved-name nil) *standard-readtable*) 1037 ((eq reserved-name :standard) *standard-readtable*) 1038 ((eq reserved-name :common-lisp) *standard-readtable*) 1039 ((eq reserved-name :modern) *case-preserving-standard-readtable*) 1040 ((eq reserved-name :current) *readtable*) 1041 (t (error "Bug: no such reserved readtable: ~S" reserved-name)))) 1043 (define-api find-readtable 1045 (named-readtable-designator => (or readtable null)) 1046 "Looks for the readtable specified by NAME and returns it if it is 1047 found. Returns NIL otherwise." 1048 (cond ((readtablep name) name) 1049 ((reserved-readtable-name-p name) 1050 (find-reserved-readtable name)) 1051 ((%find-readtable name)))) 1053 ;;; FIXME: This doesn't take a NAMED-READTABLE-DESIGNATOR, but only a 1054 ;;; STRING-DESIGNATOR. (When fixing, heed interplay with compiler 1056 (defsetf find-readtable register-readtable) 1058 (define-api ensure-readtable 1059 (name &optional (default nil default-p)) 1060 (named-readtable-designator &optional (or named-readtable-designator null) 1062 "Looks up the readtable specified by NAME and returns it if it's found. 1063 If it is not found, it registers the readtable designated by DEFAULT 1064 under the name represented by NAME; or if no default argument is 1065 given, it signals an error of type READTABLE-DOES-NOT-EXIST 1067 (cond ((find-readtable name)) 1069 (error 'readtable-does-not-exist :readtable-name name)) 1070 (t (setf (find-readtable name) (ensure-readtable default))))) 1073 (define-api register-readtable 1075 (symbol readtable => readtable) 1076 "Associate READTABLE with NAME. Returns the readtable." 1077 (assert (typep name '(not (satisfies reserved-readtable-name-p)))) 1078 (%associate-readtable-with-name name readtable) 1079 (%associate-name-with-readtable name readtable) 1082 (define-api unregister-readtable 1084 (named-readtable-designator => boolean) 1085 "Remove the association of NAMED-READTABLE. Returns T if successfull, 1087 (let* ((readtable (find-readtable named-readtable)) 1088 (readtable-name (and readtable (readtable-name readtable)))) 1089 (if (not readtable-name) 1092 (check-type readtable-name 1093 (not (satisfies reserved-readtable-name-p))) 1094 (%unassociate-readtable-from-name readtable-name readtable) 1095 (%unassociate-name-from-readtable readtable-name readtable) 1096 (%unassociate-docstring-from-readtable readtable))))) 1098 (define-api readtable-name 1100 (named-readtable-designator => symbol) 1101 "Returns the name of the readtable designated by NAMED-READTABLE, 1103 (let ((readtable (ensure-readtable named-readtable))) 1104 (cond ((%readtable-name readtable)) 1105 ((eq readtable *readtable*) :current) 1106 ((eq readtable *standard-readtable*) :common-lisp) 1107 ((eq readtable *case-preserving-standard-readtable*) :modern) 1110 (provide :readtables)