\f
;;;; DO-related stuff which needs to be visible on the cross-compilation host
-(eval-when (:compile-toplevel :load-toplevel :execute)
+(eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
(defun frob-do-body (varlist endlist decls-and-code bind step name block)
(let* ((r-inits nil) ; accumulator for reversed list
(r-steps nil) ; accumulator for reversed list
(t (illegal-varlist)))))
(t (illegal-varlist)))))
;; Construct the new form.
- (multiple-value-bind (code decls) (parse-body decls-and-code nil)
+ (multiple-value-bind (code decls)
+ (parse-body decls-and-code :doc-string-allowed nil)
`(block ,block
(,bind ,(nreverse r-inits)
,@decls
(tagbody
- (go ,label-2)
- ,label-1
- ,@code
- (,step ,@(nreverse r-steps))
- ,label-2
- (unless ,(first endlist) (go ,label-1))
- (return-from ,block (progn ,@(rest endlist))))))))))
+ (go ,label-2)
+ ,label-1
+ (tagbody ,@code)
+ (,step ,@(nreverse r-steps))
+ ,label-2
+ (unless ,(first endlist) (go ,label-1))
+ (return-from ,block (progn ,@(rest endlist))))))))))
;;; This is like DO, except it has no implicit NIL block. Each VAR is
;;; initialized in parallel to the value of the specified INIT form.
(defmacro do-anonymous (varlist endlist &rest body)
(frob-do-body varlist endlist body 'let 'psetq 'do-anonymous (gensym)))
\f
+;;;; GENSYM tricks
+
+;;; Automate an idiom often found in macros:
+;;; (LET ((FOO (GENSYM "FOO"))
+;;; (MAX-INDEX (GENSYM "MAX-INDEX-")))
+;;; ...)
+;;;
+;;; "Good notation eliminates thought." -- Eric Siggia
+;;;
+;;; Incidentally, this is essentially the same operator which
+;;; _On Lisp_ calls WITH-GENSYMS.
+(defmacro with-unique-names (symbols &body body)
+ `(let ,(mapcar (lambda (symbol)
+ (let* ((symbol-name (symbol-name symbol))
+ (stem (if (every #'alpha-char-p symbol-name)
+ symbol-name
+ (concatenate 'string symbol-name "-"))))
+ `(,symbol (gensym ,stem))))
+ symbols)
+ ,@body))
+
+;;; Return a list of N gensyms. (This is a common suboperation in
+;;; macros and other code-manipulating code.)
+(declaim (ftype (function (index) list) make-gensym-list))
+(defun make-gensym-list (n)
+ (loop repeat n collect (gensym)))
+\f
;;;; miscellany
;;; Lots of code wants to get to the KEYWORD package or the
;;; Concatenate together the names of some strings and symbols,
;;; producing a symbol in the current package.
-(eval-when (:compile-toplevel :load-toplevel :execute)
+(eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
(defun symbolicate (&rest things)
(let ((name (case (length things)
- ;; why isn't this just the value in the T branch?
+ ;; Why isn't this just the value in the T branch?
;; Well, this is called early in cold-init, before
;; the type system is set up; however, now that we
;; check for bad lengths, the type system is needed
;; for calls to CONCATENATE. So we need to make sure
;; that the calls are transformed away:
- (1 (concatenate 'string (the simple-string (string (car things)))))
+ (1 (concatenate 'string
+ (the simple-base-string
+ (string (car things)))))
(2 (concatenate 'string
- (the simple-string (string (car things)))
- (the simple-string (string (cadr things)))))
+ (the simple-base-string
+ (string (car things)))
+ (the simple-base-string
+ (string (cadr things)))))
(3 (concatenate 'string
- (the simple-string (string (car things)))
- (the simple-string (string (cadr things)))
- (the simple-string (string (caddr things)))))
+ (the simple-base-string
+ (string (car things)))
+ (the simple-base-string
+ (string (cadr things)))
+ (the simple-base-string
+ (string (caddr things)))))
(t (apply #'concatenate 'string (mapcar #'string things))))))
(values (intern name)))))