1.0.25.8: fix sxhash bug
[sbcl.git] / src / code / early-extensions.lisp
index ac0552d..0612180 100644 (file)
 ;;; something not EQ to anything we might legitimately READ
 (defparameter *eof-object* (make-symbol "EOF-OBJECT"))
 
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defconstant max-hash sb!xc:most-positive-fixnum))
+
+(def!type hash ()
+  `(integer 0 ,max-hash))
+
 ;;; a type used for indexing into arrays, and for related quantities
 ;;; like lengths of lists
 ;;;
 ;;;   foo => 13, (constantp 'foo) => t
 ;;;
 ;;; ...in which case you frankly deserve to lose.
-(defun about-to-modify-symbol-value (symbol action)
+(defun about-to-modify-symbol-value (symbol action &optional (new-value nil valuep))
   (declare (symbol symbol))
   (multiple-value-bind (what continue)
       (when (eq :constant (info :variable :kind symbol))
     (when what
       (if continue
           (cerror "Modify the constant." what action symbol)
-          (error what action symbol))))
+          (error what action symbol)))
+    (when valuep
+      ;; :VARIABLE :TYPE is in the db only if it is declared, so no need to
+      ;; check.
+      (let ((type (info :variable :type symbol)))
+        (unless (sb!kernel::%%typep new-value type)
+          (let ((spec (type-specifier type)))
+            (error 'simple-type-error
+                   :format-control "Cannot ~@? to ~S (not of type ~S.)"
+                   :format-arguments (list action symbol new-value spec)
+                   :datum new-value
+                   :expected-type spec))))))
   (values))
 
 ;;; If COLD-FSET occurs not at top level, just treat it as an ordinary
           (unless (proper-list-of-length-p spec 2)
             (error "malformed ONCE-ONLY binding spec: ~S" spec))
           (let* ((name (first spec))
-                 (exp-temp (gensym (symbol-name name))))
+                 (exp-temp (gensym "ONCE-ONLY")))
             `(let ((,exp-temp ,(second spec))
-                   (,name (gensym "ONCE-ONLY-")))
+                   (,name (gensym ,(symbol-name name))))
                `(let ((,,name ,,exp-temp))
                   ,,(frob (rest specs) body))))))))
 \f
           (*print-length* (or (true *print-length*) 12)))
       (funcall function))))
 
+;;; 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)
+  (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)))))))
+
 ;;; Default evaluator mode (interpeter / compiler)
 
 (declaim (type (member :compile #!+sb-eval :interpret) *evaluator-mode*))
@@ -1214,53 +1241,19 @@ to :INTERPRET, an interpreter will be used.")
 
 ;;; Helper for making the DX closure allocation in macros expanding
 ;;; to CALL-WITH-FOO less ugly.
-;;;
-;;; This expands to something like
-;;;
-;;;  (flet ((foo (...) <body-of-foo>))
-;;;     (declare (optimize stack-allocate-dynamic-extent))
-;;;     (flet ((foo (...)
-;;;              (foo ...))
-;;;        (declare (dynamic-extent #'foo))
-;;;        <body-of-dx-flet>)))
-;;;
-;;; The outer FLETs are inlined into the inner ones, and the inner ones
-;;; are DX-allocated. The double-fletting is done to keep the bodies of
-;;; the functions in an environment with correct policy: we don't want
-;;; to force DX allocation in their bodies, which would be bad eg.
-;;; in safe code.
 (defmacro dx-flet (functions &body forms)
-  (let ((names (mapcar #'car functions)))
-    `(flet ,functions
-       #-sb-xc-host
-       (declare (optimize sb!c::stack-allocate-dynamic-extent))
-       (flet ,(mapcar
-               (lambda (f)
-                 (let ((args (cadr f))
-                       (name (car f)))
-                   (when (intersection args sb!xc:lambda-list-keywords)
-                     ;; No fundamental reason not to support them, but we
-                     ;; don't currently need them here.
-                     (error "Non-required arguments not implemented for DX-FLET."))
-                   `(,name ,args
-                      (,name ,@args))))
-               functions)
-         (declare (dynamic-extent ,@(mapcar (lambda (x) `(function ,x)) names)))
-         ,@forms))))
-
-;;; Another similar one -- but actually touches the policy of the body,
-;;; so take care with this one...
+  `(flet ,functions
+     (declare (#+sb-xc-host dynamic-extent #-sb-xc-host truly-dynamic-extent
+               ,@(mapcar (lambda (func) `(function ,(car func))) functions)))
+     ,@forms))
+
+;;; Another similar one.
 (defmacro dx-let (bindings &body forms)
-  `(locally
-       (declare (optimize #-sb-xc-host sb!c::stack-allocate-dynamic-extent
-                          #-sb-xc-host sb!c::stack-allocate-value-cells))
-     (let ,bindings
-       (declare (dynamic-extent ,@(mapcar (lambda (bind)
-                                            (if (consp bind)
-                                                (car bind)
-                                                bind))
-                                          bindings)))
-       ,@forms)))
+  `(let ,bindings
+     (declare (#+sb-xc-host dynamic-extent #-sb-xc-host truly-dynamic-extent
+               ,@(mapcar (lambda (bind) (if (consp bind) (car bind) bind))
+                         bindings)))
+     ,@forms))
 
 (in-package "SB!KERNEL")