File: notes.text

package info (click to toggle)
gcl 2.6.14-21
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 60,864 kB
  • sloc: ansic: 177,407; lisp: 151,509; asm: 128,169; sh: 22,510; cpp: 11,923; tcl: 3,181; perl: 2,930; makefile: 2,360; sed: 334; yacc: 226; lex: 95; awk: 30; fortran: 24; csh: 23
file content (366 lines) | stat: -rw-r--r-- 16,919 bytes parent folder | download | duplicates (15)
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
Summary of changes from the PCL in cmucl 17f:
  Add a few read-time conditionalizations on cmu17, so that PCL can again
    work in Lisps other than CMU.  (*sgf-wrapper*)
  Add a read-time conditionalization on cmu for the defstruct 
    pcl-funcallable-instance.
  Make MAKE-INSTANCE faster.
    The initial slot values objects are now vectors rather than lists.
    The new macro copy-slots is the fast way to use the initial slot values vectors.
    Improve the functions generated by make-instance-function-simple.
  Hide all uses of kernel:instance-lambda (CMU) inside the new macro fin-lambda-fn,
    and the new function make-dispatch-lambda.  (see line 1082 of cache.lisp)
  Improve dispatch-dfun-cost.  (Otherwise, DEFMETHOD can take much too long).
  Add a #-lucid before the use of *print-readably* in printing-random-thing.
  Move wrapper-of-macro to low.lisp.
Summary of changes from cmucl 17e to cmucl 17f:
  Fix a problem with :after methods on accessors in PCL.  Also, fixed some problems
    with the result of get-secondary-dispatch-function1 when there are no
    methods.
  Fix make-defmethod-form (boot.lisp), to avoid calling standard-char-p on
    non-characters.
  Add compiler-macro for pcl:find-class which does lookup at load-time
    when the name is a constant.  (Needs load-time-value and define-compiler-macro)
  Fix to update-instance-for-different-class.
  Improved handling of invalid structure instances.
  New parameterized version of use-dispatch-dfun-p which avoids pessimizing
    GFs with many methods.
  Fix change-class-internal.
  When signalling an incompatible superclass error, added a hint to the
    message to check out VALIDATE-SUPERCLASSES.
  CMU: Structure-object is now no longer shadowed in PCL.  Code that was using
    PCL::STRUCTURE-OBJECT will now work better.
  CMU: BUILT-IN-CLASS, CLASS-NAME, CLASS-OF and FIND-CLASS are once again exported
    from PCL.  This will cause a name conflict if anyone use-package's PCL, but
    this will at least warn about the distinction.  Probably you shouldn't
    USE-PACKAGE PCL for this reason, but you can now say PCL:FIND-CLASS instead
    of PCL::FIND-CLASS.  It is also possible to use SHADOW or SHADOWING-IMPORT
    to resolve the conflict.
  When updating arg-info slots, check to see if the value is already there.
    This can reduce non-shared pages.
  CMU: Fix a problem with PCL clobbering byte functions when setting their names.
  Definitive tweak for handling function-p in
    compute-secondary-dispatch-function1 which avoids an infinite recursion. 







These notes correspond to the "August 5 92 PCL" version of PCL.

  This version of PCL is much closer than previous versions of PCL
to the metaobject protocol specified in "The Art of the Metaobject Protocol", 
chapters 5 and 6, by Gregor Kiczales, Jim des Riveres, and Daniel G. Bobrow.


[Please read the file may-day-notes.text also.  Most of that file still applies.]

Support for structures
  You can use structure-class as a metaclass to create new classes.
  Classes created this way create and evaluate defstruct forms which
  have generated symbols for the structure accessors and constructor.
  The generated symbols are used by the primary slot-value-using-class
  methods and by the primary allocate-instance method for structures.
  Defmethod optimizes usages of slot-value (when no user-defined 
  slot-value-using-class methods exist) into direct calls of the
  generated symbol accessor, which the compiler can then optimize further.
  Even when there are user-defined methods on slot-value-using-class,
  PCL does a variety of optimizations.
  
  If your implementation's version of the *-low.lisp file
  contains definitions of certain structure functions (see the end of
  low.lisp, cmu-low.lisp, lucid-low.lisp, and kcl-low.lisp), then
  structure classes are supported for all defstructs.  In this case,
  structure classes are created automatically, when necessary.

New Classes:
structure-class
structure-object
slot-class
slot-object
structure-direct-slot-definition
structure-effective-slot-definition

Improvements to slot-access
  Optimization for slot-value outsize of defmethod
  Optimization for slot-value inside of defmethod, but not of a specialized parameter.
  Optimizations that work even when there are :around methods
  on slot-value-using-class.

New types: 
   `(class ,class-object)
   `(class-eq ,class-object)

New specializer class: class-eq-specializer
  Every class has a class-eq specializer which represents all
  the direct instances of that class.
  This is useful in *subtypep.  For example, here is the way 
  generic-function initialization checks that the method-class is valid:
   (and (classp method-class)
	(*subtypep (class-eq-specializer method-class)
		   (find-class 'standard-method)))
  If you want to define methods having class-eq specializers,
  see "Initialization of method metaobjects".  The default behavior of PCL
  is to disallow this.

compute-applicable-methods-using-types

caching improvements

no magic-generic-functions list
  This simplifies some things, but complicates some other things.
  I wanted to support user-defined classes which are their own metaclass.
  You can now do:
(defclass y (standard-class) ())
(defmethod validate-superclass ((c y) (sc standard-class)) t)
(defclass y (standard-class) () (:metaclass y))

method-function changes (see the comments for make-method-lambda, below)

final dfuns

-------------------------

gfs which obey AMOP ch 6
  accessor-method-slot-definition
  add-dependent
  add-direct-method
  add-direct-subclass
  add-method
  allocate-instance
  compute-class-precedence-list
  compute-default-initargs
  compute-discriminating-function  
  compute-effective-slot-definition
[Note: compute-effective-slot-definition relys on 
 compute-effective-slot-definition-initargs and effective-slot-definition-class.
 compute-effective-slot-definition-initargs is quite useful, but is not in
 AMOP ch 6.]
  compute-slots
  direct-slot-definition-class
  effective-slot-definition-class
  ensure-class
  ensure-class-using-class
  ensure-generic-function
  ensure-generic-function-using-class
  eql-specializer-object
  extract-lambda-list
  extract-specializer-names
  finalize-inheritance
  find-method-combination
  funcallable-standard-instance-access
  {generic-function-method-class, generic-function-method-combination,
   generic-function-lambda-list, generic-function-methods, generic-function-name}
  intern-eql-specializer
  make-instance
  make-method-lambda
  map-dependents
  {method-function, method-generic-function, method-lambda-list,
   method-specializers, method-qualifiers}
  {class-default-initargs, class-direct-default-initargs, class-direct-slots,
   class-direct-subclasses, class-direct-superclasses, class-finalized-p,
   class-name, class-precedence-list, class-prototype, class-slots}
  {slot-definition-allocation, slot-definition-initargs, slot-definition-initform,
   slot-definition-initfunction, slot-definition-name, slot-definition-type}
  {slot-definition-readers, slot-definition-writers}
  {slot-definition-location}
  remove-dependent
  remove-direct-method
  remove-direct-subclass
  remove-method
  set-funcallable-instance-function
  (setf slot-value-using-class)
  slot-boundp-using-class
  slot-makunbound-using-class
  specializer-direct-generic-functions
  specializer-direct-methods
  standard-instance-access
  update-dependent

gfs which DO NOT obey AMOP ch 6

compute-applicable-methods
compute-applicable-methods-using-classes
  Handles class-eq specializers without signalling an error.  
  But see "Initialization of method metaobjects", below.

compute-effective-method
  Returns only one value. 

generic-function-argument-precedence-order
  Not yet defined.  Can get this information from the arg-info structure.

generic-function-declarations
  Not yet defined.

reader-method-class
  Not yet defined.  Some bootstrapping considerations are involved, 
  but adding this will not be very hard.

(setf class-name)
  Currently just a writer method.  Does not call reinitialize-instance or
  (setf find-class).

(setf generic-function-name)
  Currently just a writer method.  Does not call reinitialize-instance.

writer-method-class
  Not yet defined.  Some bootstrapping considerations are involved, 
  but adding this will not be very hard.

---------------------------

Initialization of method metaobjects
  The following methods are defined:
    legal-qualifiers-p (method standard-method) qualifiers
    legal-lambda-list-p (method standard-method) lambda-list
    legal-specializers-p (method standard-method) specializers
    legal-method-function-p (method standard-method) function
    legal-documentation-p (method standard-method) documentation

    legal-specializer-p (method standard-method) specializer

  You can override them if you want.
  The method for legal-specializers-p calls legal-specializer-p
  on each specializer.
  The method for legal-specializer-p allows any kind of specializer
  when the variable *allow-experimental-specializers-p* is t
  (this variable is initially nil).

---------------------------
Optimizations on slot-value
  Outside of a defmethod when define-compiler-macro is not implemented
  or the slot-name is not constant, or
  Inside a defmethod when the slot-name is not a constant:
(1)   no optimization of slot-value, slot-value-using-class is called.
      slot-value-using-class has a special dfun, though, which calls
      the slot's slot-definition-reader-function.  This function is
      a result of get-accessor-method-function.
  Outside of a defmethod when define-compiler-macro is implemented and
  the slot-name is a constant, or
  Inside a defmethod when the slot-name is a constant but the object is 
  not either (the value of a parameter specialized to a subclass of structure-object
  for which no user-defined slot-value-using-class methods apply at defmethod time), 
  or (the value of a parameter specialized to a subclass of standard-object).
(2)   PCL arranges to call an automatically created generic function
      which has one method: a reader method defined on class slot-object.
  Inside a defmethod when the slot-name is a constant and the object 
  is (the value of a parameter specialized to a subclass of structure-object
  for which no user-defined slot-value-using-class methods apply).
(3)   The slot-value form is converted to a call of the structure slot's 
      accessor function, which the compiler can then optimize further.
  Inside a defmethod when the slot-name is a constant and the object 
  is (the value of a parameter specialized to a subclass of standard-object).
(4)   The access requires two arefs, a call to (typep x 'fixnum), and a call to eq,
      in the best case.  If user defined slot-value-using-class methods apply
      at slot-value execution time, or the slot is unbound, the unoptimized 
      slot-value function (1) is called.  This was in May Day PCL; what is new here
      is that the PV (permutation vector) is looked up at defmethod load time
      rather than at run time, if the effective method is cached.

Generic functions containing only accessor methods for which no user-defined
methods on slot-value-using-class apply and which involve only standard-classes:
      A special dfun is called: one-class, two-class, one-index, or n-n.
      These were all in May Day PCL.
Generic functions excluded by the above, which contain accessor methods:
      In place of each accessor method's method-function, a function returned by
      get-accessor-method-function is used.

get-accessor-method-function (gf type class slotd) ; type is reader, writer, or boundp.
  If there is only one applicable method,
      (This method will be the system supplied one)
      the function that is returned is optimized for the current state of the
      class.  When the class changes, it must be recomputed.
  otherwise,
      a secondary dispatch function for slot-value-using-class is computed
      (using what is known about the types of the arguments) and converted 
      into an accessor function.

get-secondary-dispatch-function (gf methods types &optional method-alist wrappers)
  The types argument describes what is known about the types of the arguments.
  Method-alist is used (when supplied) to do things like replace the
  standard slot-value-using-class method function with a function optimized
  for what is known about the arguments.
  Wrappers (when supplied) means that the resulting function is guaranteed to
  be called only whith those wrappers.  Make-effective-method-function calls
  the generic-function method-function-for-caching with method-alist and
  wrappers to get a optimized method function.  (PV lookup is done at the time
  method-function-for-caching is called).

compute-applicable-methods:  Here I tried to stick with the MOP.
  The function cache-miss-values looks at the second value of the result of 
  compute-applicable-methods-using-classes.  If this value is null, we aren't 
  supposed to cache the result of camuc.  So we don't.  Instead we cache a 
  result of (default-secondary-dispatch-function gf), which in turn calls 
  compute-applicable-methods each time it is called.
---------------------------

To do:

Problem: sometimes there is no need to call a gf's dfun: the emf that is invoked
         can be cached in the caller's method closure.
1.  In expand-defmethod-internal, optimize calls to generic-functions.
  Add the support for this optimization.

2.   [When CMUCL improves its setf handling, remove the comment in
   the file macros.lisp beginning the line ";#+cmu (pushnew :setf *features*)"]



--------------
1) Generalize expand-defmethod-internal so that it can be used for non-defmethod
code.  Maybe by (a) having a parameter that says whether it is being called by 
defmethod, and (b) using the techniques used by the series package (shadowing 
defun and some others, making the shadowed definitions call e-d-i, making it 
easy for people to do the relevant package modifications)

2) Extending generic-functions by allowing the user at defgeneric time to supply
the name of a function which will be supplied (by the system) with a definition
which will return equivalent results to those returned by the generic function,
but which will (in some cases) have less checking than the generic function.
One-class, two-class, and one-index gf dfuns will map to a result of 
get-optimized-std-accessor-method-function, checking gf dfuns will map to their
function, and any other dfun will remain the same.

3) Extending expand-defmethod-internal to optimize calls to generic-functions.
There are a variety of possibilities that need to be considered; one of them
will be to arrange to call the optimized functions produced by (2) when it
is known to be safe.  

----------------------------------------------------------------------
----------------------------------------------------------------------

Here is how PCL uses the compiler at run time:

  The only function that uses COMPILE is COMPILE-LAMBDA, defined in
low.lisp.  See the code for some comments on how it works.

There are basically three uses of COMPILE-LAMBDA: 
  for creating discriminator functions (March 92 PCL creates discriminator 
    functions via lap code, September 16 PCL creates lisp code directly -
    it is easier to read the Sept PCL code.  Both versions invoke 
    COMPILE-LAMBDA in a similar manner.)  Precompiling of discriminator
    functions is done via the macro precompile-dfun-constructors.
 for creating constructor functions (This is in Sept PCL only; 
    see fast-init.lisp for more information).  Precompiling of 
    constructor functions is done via the macro precompile-iis-functions.
 for creating the internal functions used by GET-FUNCTION (defined in 
    fngen.lisp.  Refer to the September 16 92 PCL version because it has 
    better documentation on GET-FUNCTION.)  Precompiling of these functions
    is done by precompile-function-generators.

Precompiling of all three kinds of functions is done by
PRECOMPILILE-RANDOM-CODE-SEGMENTS (defined in low.lisp).

There are two uses of GET-FUNCTION (actually GET-FUNCTION1):
  to create effective-method-functions, which are the functions which
     actually call methods.  Every method referred to by an 
     effective-method-function is an applicable method as determined by
     COMPUTE-APPLICABLE-METHODS (or maybe -USING-CLASSES or 
     -USING-TYPES).  See the file combin.lisp.
  to create secondary dispatch functions.  These functions are called by
     discriminator functions when the dfun couldn't determine the set of
     applicable methods (when EQL specializers are present), and are
     actually discriminator functions in themselves sometimes (these 
     are called dispatch dfuns).  See the file methods.lisp.