Skip to content

Commit 7ab8318

Browse files
committed
Introduce CHECKING-READER-CONDITIONALS
1 parent 98569b8 commit 7ab8318

File tree

7 files changed

+97
-91
lines changed

7 files changed

+97
-91
lines changed

Diff for: contrib/lispy.lisp

+5-4
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,11 @@ STREAM can be an interactive (REPL) stream"
274274
(when ch (unread-char ch stream)))))
275275
(should-unread-last-newline ()
276276
;; In some implementations, leaving the #\Newline triggers printing new prompt.
277-
#+allegro nil
278-
#+ccl nil
279-
#+sbcl t
280-
#-(or allegro ccl sbcl) nil)
277+
(checking-reader-conditionals
278+
#+allegro nil
279+
#+ccl nil
280+
#+sbcl t
281+
#-(or allegro ccl sbcl) nil))
281282

282283
(read-complete-input ()
283284
(check-type stream concatenated-stream) ;; as created by omnivore readtable

Diff for: contrib/repl.lisp

+7-6
Original file line numberDiff line numberDiff line change
@@ -363,12 +363,13 @@ KIND can be :ptime, :time, :space, :pspace or NIL."
363363
(locally (declare (special *stdout-softspace*))
364364
(setf *stdout-softspace* (py-bool nil)))
365365

366-
(unless #+(or allegro sbcl) (input-available-p)
367-
#-(or allegro sbcl) nil
368-
;; When copy-pasting multiple lines of Python source code into the REPL,
369-
;; prevent several prompts being printed below the copied code.
370-
(format t (nth (if acc 1 0) *prompts*))
371-
(force-output *standard-output*)) ;; stream T would mean *terminal-io*
366+
(unless (checking-reader-conditionals
367+
#+(or allegro sbcl) (input-available-p)
368+
#-(or allegro sbcl) nil)
369+
;; When copy-pasting multiple lines of Python source code into the REPL,
370+
;; prevent several prompts being printed below the copied code.
371+
(format t (nth (if acc 1 0) *prompts*))
372+
(force-output *standard-output*)) ;; stream T would mean *terminal-io*
372373

373374
(let ((x (read-line *standard-input* nil 'eof)))
374375
;; XXX Let future debugger interface use *debug-io*?

Diff for: package.lisp

+1
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@
204204
#:alist-remove-prop #:+dict-alist-to-hashtable-threshold+
205205
#:+max-char-code+ #:char-code-type
206206
#:derive-pathname #:ensure-path-is-directory #:careful-probe-file
207+
#:checking-reader-conditionals
207208
;; finalization
208209
#:schedule-finalization #:unschedule-finalization
209210
;; strings

Diff for: parser/lexer.lisp

+3-4
Original file line numberDiff line numberDiff line change
@@ -594,10 +594,9 @@ Used by compiler to generate 'forbidden' identfiers.")
594594
"PYTHON-NAME has spaces as dividers, e.g. 'latin capital letter l with stroke'.
595595
Returns character or NIL."
596596
(when (plusp (length python-name))
597-
(let* ((division-char #+(or allegro ccl sbcl) #\_
598-
#+lispworks #\-
599-
#-(or allegro ccl lispworks sbcl)
600-
(error "lisp-char-by-python-name not implemented"))
597+
(let* ((division-char (checking-reader-conditionals
598+
#+(or allegro ccl sbcl) #\_
599+
#+lispworks #\- ))
601600
(lisp-char-name (substitute division-char #\Space python-name)))
602601
(name-char lisp-char-name))))
603602

Diff for: runtime/classes.lisp

+28-24
Original file line numberDiff line numberDiff line change
@@ -414,11 +414,12 @@
414414
(make-instance cls))
415415

416416
(defun classp (x)
417-
#+allegro (excl::classp x)
418-
#+cmu (pcl::classp x)
419-
#+lispworks (clos::classp x)
420-
#+sbcl (sb-pcl::classp x)
421-
#-(or allegro cmu lispworks sbcl) (typep x 'class))
417+
(checking-reader-conditionals
418+
#+allegro (excl::classp x)
419+
#+cmu (pcl::classp x)
420+
#+lispworks (clos::classp x)
421+
#+sbcl (sb-pcl::classp x)
422+
#-(or allegro cmu lispworks sbcl) (typep x 'class)))
422423

423424
(def-py-method py-class-method.__get__ (x inst class)
424425
(let ((arg (if (classp inst) inst (py-class-of inst))))
@@ -613,10 +614,11 @@
613614
;; where instantiating a py-function leads to strange errors.
614615
;; See <http://common-lisp.net/pipermail/clpython-devel/2008-May/000048.html>
615616
(defparameter *create-simple-lambdas-for-python-functions*
616-
#+(or allegro lispworks) nil
617-
#+sbcl t
618-
#-(or allegro lispworks sbcl) t
619-
"Whether Python function are real CLOS funcallable instances, or just normal lambdas.
617+
(checking-reader-conditionals
618+
#+(or allegro lispworks) nil
619+
#+sbcl t
620+
#-(or allegro lispworks sbcl) t)
621+
"Whether Python function are real CLOS funcallable instances, or just normal lambdas.
620622
Note that in the latter case, functions miss their name and attribute dict, but should
621623
otherwise work well.")
622624

@@ -2252,11 +2254,12 @@ But if RELATIVE-TO package name is given, result may contains dots."
22522254
collect (make-tuple-from-list (list k v)))))
22532255

22542256
(defparameter *hash-table-iterator-indefinite-extent*
2255-
#+allegro t
2256-
#+lispworks nil
2257-
#+sbcl t
2258-
#-(or allegro lispworks sbcl) nil
2259-
"Whether the iterator created by WITH-HASH-TABLE-ITERATOR has indefinite extent.
2257+
(checking-reader-conditionals
2258+
#+allegro t
2259+
#+lispworks nil
2260+
#+sbcl t
2261+
#-(or allegro lispworks sbcl) nil)
2262+
"Whether the iterator created by WITH-HASH-TABLE-ITERATOR has indefinite extent.
22602263
ANSI states for WITH-HASH-TABLE-ITERATOR: \"It is unspecified what happens if any
22612264
of the implicit interior state of an iteration is returned outside the dynamic extent
22622265
of the with-hash-table-iterator form such as by returning some closure over the
@@ -3804,13 +3807,13 @@ finished; F will then not be called again."
38043807
"Return pointer address. This might change during the life time of the object,
38053808
e.g. due to moving by the GC. Python has reference counting, and guarantees a
38063809
fixed id during the object's lifetime."
3807-
(declare (ignorable x))
3808-
#+allegro (excl:lispval-to-address x)
3809-
#+ccl (ccl:%address-of x)
3810-
#+cmu (kernel:get-lisp-obj-address x)
3811-
#+lispworks (system:object-address x)
3812-
#+sbcl (sb-kernel:get-lisp-obj-address x)
3813-
#-(or allegro ccl cmu lispworks sbcl) (error "TODO: id() not implemented for this Lisp implementation"))
3810+
(checking-reader-conditionals
3811+
#+allegro (excl:lispval-to-address x)
3812+
#+ccl (ccl:%address-of x)
3813+
#+cmu (kernel:get-lisp-obj-address x)
3814+
#+ecl (error "py-id not implemented in :ecl")
3815+
#+lispworks (system:object-address x)
3816+
#+sbcl (sb-kernel:get-lisp-obj-address x)))
38143817

38153818
(defgeneric py-cmp (x y)
38163819
(:documentation
@@ -4083,9 +4086,10 @@ Returns one of (-1, 0, 1): -1 iff x < y; 0 iff x == y; 1 iff x > y")
40834086
;;; Printing with circle (recursion) detection
40844087

40854088
(defvar *circle-detection-mechanism*
4086-
#+allegro :hash-table
4087-
#+(or cmu sbcl lispworks) :level
4088-
#-(or allegro cmu lispworks sbcl) :level)
4089+
(checking-reader-conditionals
4090+
#+allegro :hash-table
4091+
#+(or cmu sbcl lispworks) :level
4092+
#-(or allegro cmu lispworks sbcl) :level))
40894093

40904094
(defvar *circle-print-abbrev* "...")
40914095

Diff for: runtime/dictattr.lisp

+14-15
Original file line numberDiff line numberDiff line change
@@ -65,29 +65,28 @@
6565
(class-slot-ix 'dict 'py-type 'py-meta-type))
6666

6767
(defconstant-once +py-class-classname-slot-name+
68-
#+allegro 'excl::name
69-
#+ccl 'ccl::name
70-
#+cmu 'pcl::name
71-
#+ecl 'clos::name
72-
#+lispworks 'clos::name
73-
#+sbcl 'sb-pcl::name
74-
#-(or allegro ccl cmu ecl lispworks sbcl)
75-
(break "Define slot name containing class name, for this implementation."))
68+
(checking-reader-conditionals
69+
#+allegro 'excl::name
70+
#+ccl 'ccl::name
71+
#+cmu 'pcl::name
72+
#+ecl 'clos::name
73+
#+lispworks 'clos::name
74+
#+sbcl 'sb-pcl::name))
7675

7776
(eval-when (:compile-toplevel :load-toplevel :execute)
7877

7978
(defconstant +use-standard-instance-access+
80-
#+ #1=ecl nil
81-
#+ #2=(or allegro ccl cmu lispworks sbcl) t
82-
#- (or #1# #2#) (break "Define +use-standard-instance-access+"))
79+
(checking-reader-conditionals
80+
#+ecl nil
81+
#+(or allegro ccl cmu lispworks sbcl) t))
8382

8483
(register-feature :clpython-use-standard-instance-access +use-standard-instance-access+)
8584

8685
(defconstant +use-standard-instance-access-setf+
87-
#+(or allegro ccl lispworks sbcl) t
88-
#+(or cmu ecl) nil ;; these lack (SETF STANDARD-INSTANCE-ACCESS)
89-
#-(or allegro ccl cmu ecl lispworks sbcl) (break "Define +use-standard-instance-access-setf+ ~
90-
for this implementation"))
86+
(checking-reader-conditionals
87+
#+(or allegro ccl lispworks sbcl) t
88+
#+(or cmu ecl) nil ;; these lack (SETF STANDARD-INSTANCE-ACCESS)
89+
))
9190

9291
(register-feature :clpython-use-standard-instance-access-setf +use-standard-instance-access-setf+))
9392

Diff for: util/utils.lisp

+39-38
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,20 @@ If the stream length can not be determined (e.g. for standard input), all availa
106106
((equal array-element-type '(unsigned-byte 8))
107107
(map 'string #'code-char vec))))))
108108

109+
(defmacro checking-reader-conditionals (&whole whole &body body)
110+
"Break unless the body contains exactly one form. Based on idea from Steve Haflich."
111+
(let ((num (length body)))
112+
(unless (= num 1)
113+
(break "A CHECKING-READER-CONDITIONALS expression returned ~r forms: ~s" num whole))
114+
(car body)))
115+
109116
(defmacro named-function (name lambda-form)
110117
(declare (ignorable name))
111118
(assert (eq (car lambda-form) 'lambda))
112-
#+allegro `(excl:named-function ,name ,lambda-form)
113-
#+sbcl `(sb-int:named-lambda ,name ,@(cdr lambda-form)) ;; skip 'lambda symbol
114-
#-(or allegro sbcl) lambda-form)
119+
(checking-reader-conditionals
120+
#+allegro `(excl:named-function ,name ,lambda-form)
121+
#+sbcl `(sb-int:named-lambda ,name ,@(cdr lambda-form)) ;; skip 'lambda symbol
122+
#-(or allegro sbcl) lambda-form))
115123

116124
(defmacro with-stack-list ((name &rest items) &body body)
117125
(check-type name symbol)
@@ -124,11 +132,12 @@ If the stream length can not be determined (e.g. for standard input), all availa
124132
,@body))
125133

126134
(defmacro without-redefinition-warnings (&body body)
127-
#+allegro `(excl:without-redefinition-warnings ,@body)
128-
#+lispworks `(system::without-warning-on-redefinition ,@body)
129-
#+sbcl `(handler-bind ((sb-kernel:redefinition-warning #'muffle-warning))
130-
,@body)
131-
#-(or allegro lispworks sbcl) `(progn ,@body))
135+
(checking-reader-conditionals
136+
#+allegro `(excl:without-redefinition-warnings ,@body)
137+
#+lispworks `(system::without-warning-on-redefinition ,@body)
138+
#+sbcl `(handler-bind ((sb-kernel:redefinition-warning #'muffle-warning))
139+
,@body)
140+
#-(or allegro lispworks sbcl) `(progn ,@body)))
132141

133142
(defmacro fast (&body body)
134143
`(locally (declare (optimize (speed 3)))
@@ -142,11 +151,12 @@ If the stream length can not be determined (e.g. for standard input), all availa
142151

143152

144153
(defconstant-once +max-char-code+
145-
;; On Allegro CHAR-CODE-LIMIT is the largest value across all
146-
;; implementations, while EXCL:REAL-CHAR-CODE-LIMIT. is "a better estimate".
147-
;; http://www.franz.com/support/documentation/8.1/doc/variables/excl/real-char-code-limit.htm
148-
#+allegro (progn (assert (<= excl:real-char-code-limit char-code-limit))
149-
excl:real-char-code-limit)
154+
#+allegro (progn
155+
;; On Allegro CHAR-CODE-LIMIT is the largest value across all
156+
;; implementations, while EXCL:REAL-CHAR-CODE-LIMIT. is "a better estimate".
157+
;; http://www.franz.com/support/documentation/8.1/doc/variables/excl/real-char-code-limit.htm
158+
(assert (<= excl:real-char-code-limit char-code-limit))
159+
excl:real-char-code-limit)
150160
#-allegro char-code-limit
151161
"Like CHAR-CODE-LIMIT, but possible lower.")
152162

@@ -235,26 +245,17 @@ See function ALIST-VS-HT.")
235245
;; Adapted from Rob Warnock's post "How to programmatically exit?"
236246
;; http://groups.google.nl/group/comp.lang.lisp/msg/94c9a579608dcd9a
237247
(declare (ignorable code))
238-
#+allegro (excl:exit code :quiet t) ;; added (:quiet t) -WB
239-
#+clisp (#+lisp=cl ext:quit #-lisp=cl lisp:quit code)
240-
#+cmu (ext:quit code)
241-
#+cormanlisp (win32:exitprocess code)
242-
#+gcl (lisp:bye code) ; XXX Or is it LISP::QUIT?
243-
#+lispworks (lw:quit :status code)
244-
#+lucid (lcl:quit code)
245-
#+sbcl (sb-ext:quit
246-
:unix-status (typecase code (number code)
247-
(null 0)
248-
(t 1)))
249-
#+kcl (lisp::bye) ; XXX Does this take an arg?
250-
#+scl (ext:quit code) ; XXX Pretty sure this *does*.
251-
#+(or openmcl mcl) (ccl::quit)
252-
#+abcl (cl-user::quit)
253-
#+ecl (si:quit)
254-
#+poplog (poplog::bye) ; XXX Does this take an arg?
255-
#-(or allegro clisp cmu cormanlisp gcl lispworks lucid sbcl
256-
kcl scl openmcl mcl abcl ecl poplog)
257-
(error "QUIT not-implemented in this implementation"))
248+
(checking-reader-conditionals
249+
#+allegro (excl:exit code :quiet t)
250+
#+cmu (ext:quit code)
251+
#+lispworks (lw:quit :status code)
252+
#+sbcl (sb-ext:quit :unix-status (typecase code (number code)
253+
(null 0)
254+
(t 1)))
255+
#+(or openmcl mcl) (ccl::quit)
256+
#+abcl (cl-user::quit)
257+
#+ecl (si:quit)
258+
))
258259

259260
(defun abbreviate-to-one-line (string)
260261
(loop for i from 0
@@ -287,10 +288,10 @@ See function ALIST-VS-HT.")
287288
#+(or)
288289
(defun directory-p (pathname)
289290
(check-type pathname pathname)
290-
#+allegro (excl:file-directory-p pathname)
291-
#+lispworks (lispworks:file-directory-p pathname)
292-
#+(or cmu sbcl) (null (pathname-type pathname))
293-
#-(or allegro cmu lispworks sbcl) (error "TODO: No DIRECTORY-P for this implementation."))
291+
(checking-reader-conditionals
292+
#+allegro (excl:file-directory-p pathname)
293+
#+lispworks (lispworks:file-directory-p pathname)
294+
#+(or cmu sbcl) (null (pathname-type pathname))))
294295

295296
(defmacro with-line-prefixed-output ((prefix) &body body)
296297
(check-type prefix string)
@@ -347,4 +348,4 @@ See function ALIST-VS-HT.")
347348
(defun careful-probe-file (pathspec)
348349
"Like PROBE-FILE, but this function never signals FILE-ERROR: that is mapped to NIL."
349350
(handler-case (probe-file pathspec)
350-
(file-error () nil)))
351+
(file-error () nil)))

0 commit comments

Comments
 (0)