;;;; code analysis stuff
(defun loop-constant-fold-if-possible (form &optional expected-type)
- (let ((new-form form) (constantp nil) (constant-value nil))
- (when (setq constantp (constantp new-form))
- (setq constant-value (eval new-form)))
+ (let* ((constantp (sb!xc:constantp form))
+ (value (and constantp (sb!int:constant-form-value form))))
(when (and constantp expected-type)
- (unless (sb!xc:typep constant-value expected-type)
+ (unless (sb!xc:typep value expected-type)
(loop-warn "~@<The form ~S evaluated to ~S, which was not of ~
the anticipated type ~S.~:@>"
- form constant-value expected-type)
- (setq constantp nil constant-value nil)))
- (values new-form constantp constant-value)))
-
-(defun loop-constantp (form)
- (constantp form))
+ form value expected-type)
+ (setq constantp nil value nil)))
+ (values form constantp value)))
\f
;;;; LOOP iteration optimization
-(defvar *loop-duplicate-code*
- nil)
+(defvar *loop-duplicate-code* nil)
-(defvar *loop-iteration-flag-var*
- (make-symbol "LOOP-NOT-FIRST-TIME"))
+(defvar *loop-iteration-flag-var* (make-symbol "LOOP-NOT-FIRST-TIME"))
(defun loop-code-duplication-threshold (env)
(declare (ignore env))
(t (error "invalid LOOP variable passed in: ~S" name))))
(defun loop-maybe-bind-form (form data-type)
- (if (loop-constantp form)
+ (if (constantp form)
form
(loop-make-var (gensym "LOOP-BIND-") form data-type)))
\f
(setq step-hack
`(,variable ,step-hack)))
(let ((first-test test) (remaining-tests test))
+ ;; As far as I can tell, the effect of the following code is
+ ;; to detect cases where we know statically whether the first
+ ;; iteration of the loop will be executed. Depending on the
+ ;; situation, we can either:
+ ;; a) save one jump and one comparison per loop (not per iteration)
+ ;; when it will get executed
+ ;; b) remove the loop body completely when it won't be executed
+ ;;
+ ;; Noble goals. However, the code generated in case a) will
+ ;; fool the loop induction variable detection, and cause
+ ;; code like (LOOP FOR I TO 10 ...) to use generic addition
+ ;; (bug #278a).
+ ;;
+ ;; Since the gain in case a) is rather minimal and Python is
+ ;; generally smart enough to handle b) without any extra
+ ;; support from the loop macro, I've disabled this code for
+ ;; now. The code and the comment left here in case somebody
+ ;; extends the induction variable bound detection to work
+ ;; with code where the stepping precedes the test.
+ ;; -- JES 2005-11-30
+ #+nil
(when (and stepby-constantp start-constantp limit-constantp
(realp start-value) (realp limit-value))
(when (setq first-test
'((:from :upfrom :downfrom) (:to :upto :downto :above :below) (:by))
nil (list (list kwd val)))))
-(defun loop-sequence-elements-path (variable data-type prep-phrases
- &key
- fetch-function
- size-function
- sequence-type
- element-type)
- (multiple-value-bind (indexv) (loop-named-var 'index)
- (let ((sequencev (loop-named-var 'sequence)))
- (list* nil nil ; dummy bindings and prologue
- (loop-sequencer
- indexv 'fixnum
- variable (or data-type element-type)
- sequencev sequence-type
- `(,fetch-function ,sequencev ,indexv)
- `(,size-function ,sequencev)
- prep-phrases)))))
\f
;;;; builtin LOOP iteration paths