1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
|
;;;-*-Mode:LISP; Package:(PCL LISP 1000); Base:10; Syntax:Common-lisp -*-
;;;
;;; *************************************************************************
;;; Copyright (c) 1985, 1986, 1987, 1988, 1989, 1990 Xerox Corporation.
;;; All rights reserved.
;;;
;;; Use and copying of this software and preparation of derivative works
;;; based upon this software are permitted. Any distribution of this
;;; software or derivative works must comply with all applicable United
;;; States export control laws.
;;;
;;; This software is made available AS IS, and Xerox Corporation makes no
;;; warranty about the software, its performance or its conformity to any
;;; specification.
;;;
;;; Any person obtaining a copy of this software is requested to send their
;;; name and post office or electronic mail address to:
;;; CommonLoops Coordinator
;;; Xerox PARC
;;; 3333 Coyote Hill Rd.
;;; Palo Alto, CA 94304
;;; (or send Arpanet mail to CommonLoops-Coordinator.pa@Xerox.arpa)
;;;
;;; Suggestions, comments and requests for improvements are also welcome.
;;; *************************************************************************
;;;
;;; This file contains portable versions of low-level functions and macros
;;; which are ripe for implementation specific customization. None of the
;;; code in this file *has* to be customized for a particular Common Lisp
;;; implementation. Moreover, in some implementations it may not make any
;;; sense to customize some of this code.
;;;
;;; But, experience suggests that MOST Common Lisp implementors will want
;;; to customize some of the code in this file to make PCL run better in
;;; their implementation. The code in this file has been separated and
;;; heavily commented to make that easier.
;;;
;;; Implementation-specific version of this file already exist for:
;;;
;;; Symbolics Genera family genera-low.lisp
;;; Lucid Lisp lucid-low.lisp
;;; Xerox 1100 family xerox-low.lisp
;;; ExCL (Franz) excl-low.lisp
;;; Kyoto Common Lisp kcl-low.lisp
;;; Vaxlisp vaxl-low.lisp
;;; CMU Lisp cmu-low.lisp
;;; H.P. Common Lisp hp-low.lisp
;;; Golden Common Lisp gold-low.lisp
;;; Ti Explorer ti-low.lisp
;;;
;;;
;;; These implementation-specific files are loaded after this file. Because
;;; none of the macros defined by this file are used in functions defined by
;;; this file the implementation-specific files can just contain the parts of
;;; this file they want to change. They don't have to copy this whole file
;;; and then change the parts they want.
;;;
;;; If you make changes or improvements to these files, or if you need some
;;; low-level part of PCL re-modularized to make it more portable to your
;;; system please send mail to CommonLoops.pa@Xerox.com.
;;;
;;; Thanks.
;;;
(in-package :pcl)
(eval-when (compile load eval)
(defvar *optimize-speed* '(optimize (speed 3) (safety 0)))
)
(defmacro %svref (vector index)
`(locally (declare #.*optimize-speed*
(inline svref))
(svref (the simple-vector ,vector) (the fixnum ,index))))
(defsetf %svref %set-svref)
(defmacro %set-svref (vector index new-value)
`(locally (declare #.*optimize-speed*
(inline svref))
(setf (svref (the simple-vector ,vector) (the fixnum ,index))
,new-value)))
;;;
;;; without-interrupts
;;;
;;; OK, Common Lisp doesn't have this and for good reason. But For all of
;;; the Common Lisp's that PCL runs on today, there is a meaningful way to
;;; implement this. WHAT I MEAN IS:
;;;
;;; I want the body to be evaluated in such a way that no other code that is
;;; running PCL can be run during that evaluation. I agree that the body
;;; won't take *long* to evaluate. That is to say that I will only use
;;; without interrupts around relatively small computations.
;;;
;;; INTERRUPTS-ON should turn interrupts back on if they were on.
;;; INTERRUPTS-OFF should turn interrupts back off.
;;; These are only valid inside the body of WITHOUT-INTERRUPTS.
;;;
;;; OK?
;;;
(defmacro without-interrupts (&body body)
`(macrolet ((interrupts-on () ())
(interrupts-off () ()))
(progn ,.body)))
;;;
;;; Very Low-Level representation of instances with meta-class standard-class.
;;;
#-new-kcl-wrapper
(progn
#-cmu17
(defstruct (std-instance (:predicate std-instance-p)
(:conc-name %std-instance-)
(:constructor %%allocate-instance--class ())
(:print-function print-std-instance))
(wrapper nil)
(slots nil))
(defmacro %instance-ref (slots index)
`(%svref ,slots ,index))
(defmacro instance-ref (slots index)
`(svref ,slots ,index))
)
#+new-kcl-wrapper
(progn
(defvar *init-vector* (make-array 40 :fill-pointer 1 :adjustable t
:initial-element nil))
(defun get-init-list (i)
(declare (fixnum i)(special *slot-unbound*))
(loop (when (< i (fill-pointer *init-vector*))
(return (aref *init-vector* i)))
(vector-push-extend
(cons *slot-unbound*
(aref *init-vector* (1- (fill-pointer *init-vector*))))
*init-vector*)))
(defmacro %std-instance-wrapper (instance)
`(structure-def ,instance))
(defmacro %std-instance-slots (instance)
instance)
(defmacro std-instance-p (x)
`(structurep ,x))
)
(defmacro std-instance-wrapper (x) `(%std-instance-wrapper ,x))
(defmacro std-instance-slots (x) `(%std-instance-slots ,x))
(defmacro get-wrapper (inst)
`(cond ((std-instance-p ,inst) (std-instance-wrapper ,inst))
((fsc-instance-p ,inst) (fsc-instance-wrapper ,inst))
(t (error "What kind of instance is this?"))))
(defmacro get-instance-wrapper-or-nil (inst)
`(cond ((std-instance-p ,inst) (std-instance-wrapper ,inst))
((fsc-instance-p ,inst) (fsc-instance-wrapper ,inst))))
(defmacro get-slots (inst)
`(cond ((std-instance-p ,inst) (std-instance-slots ,inst))
((fsc-instance-p ,inst) (fsc-instance-slots ,inst))
(t (error "What kind of instance is this?"))))
(defmacro get-slots-or-nil (inst)
`(cond ((std-instance-p ,inst) (std-instance-slots ,inst))
((fsc-instance-p ,inst) (fsc-instance-slots ,inst))))
(defun print-std-instance (instance stream depth) ;A temporary definition used
(declare (ignore depth)) ;for debugging the bootstrap
(printing-random-thing (instance stream) ;code of PCL (See high.lisp).
(let ((class (class-of instance)))
(if (or (eq class (find-class 'standard-class nil))
(eq class (find-class 'funcallable-standard-class nil))
(eq class (find-class 'built-in-class nil)))
(format stream "~a ~a" (early-class-name class)
(early-class-name instance))
(format stream "~a" (early-class-name class))))))
;;;
;;; This is the value that we stick into a slot to tell us that it is unbound.
;;; It may seem gross, but for performance reasons, we make this an interned
;;; symbol. That means that the fast check to see if a slot is unbound is to
;;; say (EQ <val> '..SLOT-UNBOUND..). That is considerably faster than looking
;;; at the value of a special variable. Be careful, there are places in the
;;; code which actually use ..slot-unbound.. rather than this variable. So
;;; much for modularity
;;;
(defvar *slot-unbound* '..slot-unbound..)
(defmacro %allocate-static-slot-storage--class (no-of-slots)
#+new-kcl-wrapper (declare (ignore no-of-slots))
#-new-kcl-wrapper
`(make-array ,no-of-slots :initial-element *slot-unbound*)
#+new-kcl-wrapper
(error "don't call this"))
(defmacro std-instance-class (instance)
`(wrapper-class* (std-instance-wrapper ,instance)))
;;
;;;;;; FUNCTION-ARGLIST
;;
;;; Given something which is functionp, function-arglist should return the
;;; argument list for it. PCL does not count on having this available, but
;;; MAKE-SPECIALIZABLE works much better if it is available. Versions of
;;; function-arglist for each specific port of pcl should be put in the
;;; appropriate xxx-low file. This is what it should look like:
;(defun function-arglist (function)
; (<system-dependent-arglist-function> function))
(defun function-pretty-arglist (function)
(declare (ignore function))
())
(defsetf function-pretty-arglist set-function-pretty-arglist)
(defun set-function-pretty-arglist (function new-value)
(declare (ignore function))
new-value)
;;;
;;; set-function-name
;;; When given a function should give this function the name <new-name>.
;;; Note that <new-name> is sometimes a list. Some lisps get the upset
;;; in the tummy when they start thinking about functions which have
;;; lists as names. To deal with that there is set-function-name-intern
;;; which takes a list spec for a function name and turns it into a symbol
;;; if need be.
;;;
;;; When given a funcallable instance, set-function-name MUST side-effect
;;; that FIN to give it the name. When given any other kind of function
;;; set-function-name is allowed to return new function which is the 'same'
;;; except that it has the name.
;;;
;;; In all cases, set-function-name must return the new (or same) function.
;;;
(defun set-function-name (function new-name)
(declare (notinline set-function-name-1 intern-function-name))
(set-function-name-1 function
(intern-function-name new-name)
new-name))
(defun set-function-name-1 (function new-name uninterned-name)
(declare (ignore new-name uninterned-name))
function)
(defun intern-function-name (name)
(cond ((symbolp name) name)
((listp name)
(intern (let ((*package* *the-pcl-package*)
(*print-case* :upcase)
(*print-pretty* nil)
(*print-gensym* 't))
(format nil "~S" name))
*the-pcl-package*))))
;;;
;;; COMPILE-LAMBDA
;;;
;;; This is like the Common Lisp function COMPILE. In fact, that is what
;;; it ends up calling. The difference is that it deals with things like
;;; watching out for recursive calls to the compiler or not calling the
;;; compiler in certain cases or allowing the compiler not to be present.
;;;
;;; This starts out with several variables and support functions which
;;; should be conditionalized for any new port of PCL. Note that these
;;; default to reasonable values, many new ports won't need to look at
;;; these values at all.
;;;
;;; *COMPILER-PRESENT-P* NIL means the compiler is not loaded
;;;
;;; *COMPILER-SPEED* one of :FAST :MEDIUM or :SLOW
;;;
;;; *COMPILER-REENTRANT-P* T ==> OK to call compiler recursively
;;; NIL ==> not OK
;;;
;;; function IN-THE-COMPILER-P returns T if in the compiler, NIL otherwise
;;; This is not called if *compiler-reentrant-p*
;;; is T, so it only needs to be implemented for
;;; ports which have non-reentrant compilers.
;;;
;;;
(defvar *compiler-present-p* t)
(defvar *compiler-speed*
#+(or KCL IBCL GCLisp CMU) :slow
#-(or KCL IBCL GCLisp CMU) :fast)
(defvar *compiler-reentrant-p*
#+(and (not XKCL) (or KCL IBCL)) nil
#-(and (not XKCL) (or KCL IBCL)) t)
(defun in-the-compiler-p ()
#+(and (not xkcl) (or KCL IBCL))compiler::*compiler-in-use*
#+gclisp (typep (eval '(function (lambda ()))) 'lexical-closure)
)
(defvar *compile-lambda-break-p* nil)
(defun compile-lambda (lambda &optional (desirability :fast))
(when *compile-lambda-break-p* (break))
(cond ((null *compiler-present-p*)
(compile-lambda-uncompiled lambda))
((and (null *compiler-reentrant-p*)
(in-the-compiler-p))
(compile-lambda-deferred lambda))
((eq desirability :fast)
(compile nil lambda))
((and (eq desirability :medium)
(member *compiler-speed* '(:fast :medium)))
(compile nil lambda))
((and (eq desirability :slow)
(eq *compiler-speed* ':fast))
(compile nil lambda))
(t
(compile-lambda-uncompiled lambda))))
(defun compile-lambda-uncompiled (uncompiled)
#'(lambda (&rest args) (apply (coerce uncompiled 'function) args)))
(defun compile-lambda-deferred (uncompiled)
(let ((function (coerce uncompiled 'function))
(compiled nil))
(declare (type (or function null) compiled))
#'(lambda (&rest args)
(if compiled
(apply compiled args)
(if (in-the-compiler-p)
(apply function args)
(progn (setq compiled (compile nil uncompiled))
(apply compiled args)))))))
(defmacro precompile-random-code-segments (&optional system)
`(progn
(eval-when (compile)
(update-dispatch-dfuns)
(compile-iis-functions nil))
(precompile-function-generators ,system)
(precompile-dfun-constructors ,system)
(precompile-iis-functions ,system)
(eval-when (load)
(compile-iis-functions t))))
(defun record-definition (type spec &rest args)
(declare (ignore type spec args))
())
(defun doctor-dfun-for-the-debugger (gf dfun) (declare (ignore gf)) dfun)
;; From braid.lisp
#-new-kcl-wrapper
(defmacro built-in-or-structure-wrapper (x)
(once-only (x)
(if (structure-functions-exist-p) ; otherwise structurep is too slow for this
`(if (structurep ,x)
(wrapper-for-structure ,x)
(if (symbolp ,x)
(if ,x *the-wrapper-of-symbol* *the-wrapper-of-null*)
(built-in-wrapper-of ,x)))
`(or (and (symbolp ,x)
(if ,x *the-wrapper-of-symbol* *the-wrapper-of-null*))
(built-in-or-structure-wrapper1 ,x)))))
#-cmu17
(defmacro wrapper-of-macro (x)
`(cond ((std-instance-p ,x)
(std-instance-wrapper ,x))
((fsc-instance-p ,x)
(fsc-instance-wrapper ,x))
(t
(#+new-kcl-wrapper built-in-wrapper-of
#-new-kcl-wrapper built-in-or-structure-wrapper
,x))))
#+cmu17
(defmacro wrapper-of-macro (x)
`(kernel:layout-of ,x))
;Low level functions for structures
;Functions on arbitrary objects
(defvar *structure-table* (make-hash-table :test 'eq))
(defun declare-structure (name included-name slot-description-list)
(setf (gethash name *structure-table*)
(cons included-name slot-description-list)))
(unless (fboundp 'structure-functions-exist-p)
(setf (symbol-function 'structure-functions-exist-p)
#'(lambda () nil)))
(defun default-structurep (x)
(structure-type-p (type-of x)))
(defun default-structure-instance-p (x)
(let ((type (type-of x)))
(and (not (eq type 'std-instance))
(structure-type-p type))))
(defun default-structure-type (x)
(type-of x))
(unless (fboundp 'structurep)
(setf (symbol-function 'structurep) #'default-structurep))
; excludes std-instance
(unless (fboundp 'structure-instance-p)
(setf (symbol-function 'structure-instance-p) #'default-structure-instance-p))
; returns a symbol
(unless (fboundp 'structure-type)
(setf (symbol-function 'structure-type) #'default-structure-type))
;Functions on symbols naming structures
; Excludes structures types created with the :type option
(defun structure-type-p (symbol)
(not (null (gethash symbol *structure-table*))))
(defun structure-type-included-type-name (symbol)
(car (gethash symbol *structure-table*)))
; direct slots only
; The results of this function are used only by the functions below.
(defun structure-type-slot-description-list (symbol)
(cdr (gethash symbol *structure-table*)))
;Functions on slot-descriptions (returned by the function above)
;returns a symbol
(defun structure-slotd-name (structure-slot-description)
(first structure-slot-description))
;returns a symbol
(defun structure-slotd-accessor-symbol (structure-slot-description)
(second structure-slot-description))
;returns a symbol or a list or nil
(defun structure-slotd-writer-function (structure-slot-description)
(third structure-slot-description))
(defun structure-slotd-type (structure-slot-description)
(fourth structure-slot-description))
(defun structure-slotd-init-form (structure-slot-description)
(fifth structure-slot-description))
|