File: gcl_pcl_low.lisp

package info (click to toggle)
gcl 2.6.7%2Bdfsga-1
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 84,796 kB
  • sloc: ansic: 452,686; lisp: 156,133; asm: 111,405; sh: 29,299; cpp: 18,599; perl: 5,602; makefile: 5,201; tcl: 3,181; sed: 469; yacc: 378; lex: 174; fortran: 48; awk: 30; csh: 23
file content (459 lines) | stat: -rw-r--r-- 15,788 bytes parent folder | download | duplicates (13)
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))