;;;; -*- coding: utf-8; fill-column: 78 -*-
+changes relative to sbcl-1.1.3:
+ * bug fix: very long (or infinite) constant lists in DOLIST do not result
+ in very long compile times or heap exhaustion anymore. (lp#1095488)
+
changes in sbcl-1.1.3 relative to sbcl-1.1.2:
* enhancement: warnings about bad locale settings, LANG, LC_CTYPE, etc.
(lp#727625)
;; var.
(multiple-value-bind (forms decls) (parse-body body :doc-string-allowed nil)
(let* ((n-list (gensym "N-LIST"))
- (start (gensym "START"))
- (tmp (gensym "TMP")))
+ (start (gensym "START")))
(multiple-value-bind (clist members clist-ok)
(cond ((sb!xc:constantp list env)
(let ((value (constant-form-value list env)))
- (multiple-value-bind (all dot) (list-members value)
- (when dot
+ (multiple-value-bind (all dot) (list-members value :max-length 20)
+ (when (eql dot t)
;; Full warning is too much: the user may terminate the loop
;; early enough. Contents are still right, though.
(style-warn "Dotted list ~S in DOLIST." value))
- (values value all t))))
+ (if (eql dot :maybe)
+ (values value nil nil)
+ (values value all t)))))
((and (consp list) (eq 'list (car list))
(every (lambda (arg) (sb!xc:constantp arg env)) (cdr list)))
(let ((values (mapcar (lambda (arg) (constant-form-value arg env)) (cdr list))))
(tagbody
,start
(unless (endp ,n-list)
- (let* (,@(if clist-ok
- `((,tmp (truly-the (member ,@members) (car ,n-list)))
- (,var ,tmp))
- `((,var (car ,n-list)))))
+ (let ((,var ,(if clist-ok
+ `(truly-the (member ,@members) (car ,n-list))
+ `(car ,n-list))))
,@decls
(setq ,n-list (cdr ,n-list))
(tagbody ,@forms))
;;; Returns a list of members of LIST. Useful for dealing with circular lists.
;;; For a dotted list returns a secondary value of T -- in which case the
;;; primary return value does not include the dotted tail.
-(defun list-members (list)
+;;; If the maximum length is reached, return a secondary value of :MAYBE.
+(defun list-members (list &key max-length)
(when list
(do ((tail (cdr list) (cdr tail))
- (members (list (car list)) (cons (car tail) members)))
- ((or (not (consp tail)) (eq tail list))
- (values members (not (listp tail)))))))
+ (members (list (car list)) (cons (car tail) members))
+ (count 0 (1+ count)))
+ ((or (not (consp tail)) (eq tail list)
+ (and max-length (>= count max-length)))
+ (values members (or (not (listp tail))
+ (and (>= count max-length) :maybe)))))))
;;; Default evaluator mode (interpeter / compiler)