Raymond Toy pushed to branch master at cmucl / cmucl
Commits:
-
1ca0a557
by Raymond Toy
at 2015-06-14T08:31:14Z
Fix #4: ELT signals error on invalid index on lists
code/seq.lisp:
o Define internal LIST-ELT* function that executes ELT on lists,
signaling an error if the index is invalid.
compiler/seqtran.lisp:
o Change the deftransform for ELT to use LIST-ELT* instead of NTH.
tests/issues.lisp:
o Add test for this issue.
3 changed files:
Changes:
src/code/seq.lisp
--- a/src/code/seq.lisp
+++ b/src/code/seq.lisp
@@ -138,6 +138,16 @@
(t
(make-sequence-of-type (result-type-or-lose type) length))))
+(defun list-elt* (sequence index)
+ (declare (type list sequence))
+ (do ((count index (1- count))
+ (list sequence (cdr list)))
+ ((= count 0)
+ (if (endp list)
+ (signal-index-too-large-error sequence index)
+ (car list)))
+ (declare (type (integer 0) count))))
+
(defun elt (sequence index)
"Returns the element of SEQUENCE specified by INDEX."
(etypecase sequence
src/compiler/seqtran.lisp
--- a/src/compiler/seqtran.lisp
+++ b/src/compiler/seqtran.lisp
@@ -107,8 +107,8 @@
(deftransform elt ((s i) ((simple-array * (*)) *) * :when :both)
'(aref s i))
-(deftransform elt ((s i) (list *) * :when :both :policy (< safety 3))
- '(nth i s))
+(deftransform elt ((s i) (list *) * :when :both)
+ '(lisp::list-elt* s i))
(deftransform %setelt ((s i v) ((simple-array * (*)) * *) * :when :both)
'(%aset s i v))
tests/issues.lisp
--- a/tests/issues.lisp
+++ b/tests/issues.lisp
@@ -23,3 +23,18 @@
(assert-equal
'(square x)
(funcall (compiler-macro-function 'square) '(funcall #'square x) nil)))
+
+(define-test issue.5
+ (:tag :issues)
+ (assert-true
+ (handler-case
+ (let ((f (compile nil '(lambda (list)
+ (declare (type list list)
+ (optimize (speed 1) (safety 1) (compilation-speed 1) (space 1) (debug 1)))
+ (elt list 3)))))
+ (funcall f (list 0 1 2)))
+ ;; ELT should signal an error in this case.
+ (lisp::index-too-large-error ()
+ t)
+ (t ()
+ nil))))