Commit | Line | Data |
---|---|---|
dea4d055 MW |
1 | ;;; -*-lisp-*- |
2 | ;;; | |
3 | ;;; Class finalization protocol | |
4 | ;;; | |
5 | ;;; (c) 2009 Straylight/Edgeware | |
6 | ;;; | |
7 | ||
8 | ;;;----- Licensing notice --------------------------------------------------- | |
9 | ;;; | |
e0808c47 | 10 | ;;; This file is part of the Sensible Object Design, an object system for C. |
dea4d055 MW |
11 | ;;; |
12 | ;;; SOD is free software; you can redistribute it and/or modify | |
13 | ;;; it under the terms of the GNU General Public License as published by | |
14 | ;;; the Free Software Foundation; either version 2 of the License, or | |
15 | ;;; (at your option) any later version. | |
16 | ;;; | |
17 | ;;; SOD is distributed in the hope that it will be useful, | |
18 | ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | ;;; GNU General Public License for more details. | |
21 | ;;; | |
22 | ;;; You should have received a copy of the GNU General Public License | |
23 | ;;; along with SOD; if not, write to the Free Software Foundation, | |
24 | ;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
25 | ||
26 | (cl:in-package #:sod) | |
27 | ||
28 | ;;;-------------------------------------------------------------------------- | |
e45a106d MW |
29 | ;;; Finalization error handling. |
30 | ||
31 | ;; These variables are internal to the implementation. | |
32 | (defvar-unbound *finalization-errors* | |
33 | "A list of tokens for errors reported about the class being finalized. | |
34 | ||
35 | During finalization, this is bound to a list of tokens corresponding to | |
36 | the problems which have been reported so far via `finalization-error'.") | |
37 | (defvar-unbound *finalization-error-token* | |
38 | "The token to store in `*finalization-errors*' in the event of an error.") | |
39 | ||
40 | (export 'finalization-error) | |
41 | (defmacro finalization-error ((token &rest args) &body body) | |
42 | "Check for a kind of finalization error denoted by TOKEN and the ARGS. | |
43 | ||
44 | The TOKEN and ARGS are convered into an error token as follows. If no | |
45 | ARGS are given, then the TOKEN itself is evaluated and used directly; | |
46 | otherwise, the token is a list whose first element is the result of | |
47 | evaluating TOKEN, and the remaining elements are the results of evaluating | |
48 | the ARGS. Error tokens are compared with `equal'. | |
49 | ||
50 | If a finalization error denoted by this token has already been reported, | |
51 | then do nothing: the BODY is not evaluated, and the result is nil. | |
52 | Special exception: a nil token denotes a `generic' error which can be | |
53 | repeated indefintely. | |
54 | ||
55 | If the BODY signals an error (and doesn't handle it), then the error token | |
56 | is added to a list of reported errors. That way, future calls to | |
57 | `finalization-error' with an equal error token won't cause the user to be | |
58 | inundated with duplicate reports." | |
59 | `(let ((*finalization-error-token* ,(if (null args) token | |
60 | `(list ,token ,@args)))) | |
61 | ,@body)) | |
62 | ||
63 | (export 'finalization-failed) | |
64 | (defun finalization-failed () | |
65 | "Give up on finalizing the current class." | |
66 | (throw '%finalization-failed nil)) | |
67 | ||
68 | ;;;-------------------------------------------------------------------------- | |
dea4d055 MW |
69 | ;;; Protocol definition. |
70 | ||
11e41ddf | 71 | (export 'compute-cpl) |
dea4d055 MW |
72 | (defgeneric compute-cpl (class) |
73 | (:documentation | |
74 | "Returns the class precedence list for CLASS.")) | |
75 | ||
11e41ddf | 76 | (export 'compute-chains) |
dea4d055 MW |
77 | (defgeneric compute-chains (class) |
78 | (:documentation | |
79 | "Compute the layout chains for CLASS. | |
80 | ||
81 | Returns the following three values. | |
82 | ||
83 | * the head of the class's primary chain; | |
84 | ||
85 | * the class's primary chain as a list, most- to least-specific; and | |
86 | ||
87 | * the complete collection of chains, as a list of lists, each most- to | |
88 | least-specific, with the primary chain first. | |
89 | ||
90 | These values will be stored in the CHAIN-HEAD, CHAIN and CHAINS slots. | |
91 | ||
92 | If the chains are ill-formed (i.e., not distinct) then an error is | |
93 | signalled.")) | |
94 | ||
2c0aab07 MW |
95 | (export 'check-class-initializer) |
96 | (defgeneric check-class-initializer (slot class) | |
97 | (:documentation | |
98 | "Check that SLOT has an appropriate initializer. | |
99 | ||
100 | Signal an appropriate continuable error, possibly protected by | |
101 | `finalization-error'. | |
102 | ||
103 | The initializer might come either from the SLOT's defining class (which it | |
104 | already knows), or from the prospective instance CLASS, of which the | |
105 | defining class will be (a superclass of) the metaclass. Or, if the slot | |
106 | is magical, then the initial value might come from somewhere else and it | |
107 | might be forbidden for a programmer to set it explicitly.")) | |
108 | ||
11e41ddf | 109 | (export 'check-sod-class) |
dea4d055 MW |
110 | (defgeneric check-sod-class (class) |
111 | (:documentation | |
112 | "Check the CLASS for validity. | |
113 | ||
114 | This is done as part of class finalization. The checks performed are as | |
115 | follows. | |
116 | ||
117 | * The class name and nickname, and the names of messages, obey the | |
118 | rules (see VALID-NAME-P). | |
119 | ||
120 | * The messages and slots have distinct names. | |
121 | ||
122 | * The classes in the class-precedence-list have distinct nicknames. | |
123 | ||
124 | * The chain-link is actually a proper (though not necessarily direct) | |
125 | superclass. | |
126 | ||
127 | * The chosen metaclass is actually a subclass of all of the | |
128 | superclasses' metaclasses. | |
129 | ||
8b06ce6e MW |
130 | If no attempt has previously been made to finalize the class, then errors |
131 | are signalled for the problems found. If finalizing it has been tried | |
132 | before and failed (or this is a recursive attempt to finalize the class) | |
133 | then nil is returned immediately. Otherwise a non-nil value is | |
134 | returned.")) | |
dea4d055 | 135 | |
11e41ddf | 136 | (export 'finalize-sod-class) |
dea4d055 MW |
137 | (defgeneric finalize-sod-class (class) |
138 | (:documentation | |
139 | "Computes all of the gory details about a class. | |
140 | ||
141 | Once one has stopped inserting methods and slots and so on into a class, | |
142 | one needs to finalize it to determine the layout structure and the class | |
143 | precedence list and so on. More precisely that gets done is this: | |
144 | ||
145 | * Related classes (i.e., direct superclasses and the metaclass) are | |
146 | finalized if they haven't been already. | |
147 | ||
148 | * If you've been naughty and failed to store a list of slots or | |
149 | whatever, then an empty list is inserted. | |
150 | ||
151 | * The class precedence list is computed and stored. | |
152 | ||
153 | * The class is checked for compiance with the well-formedness rules. | |
154 | ||
32bb097f MW |
155 | * The layout chains are computed. |
156 | ||
e45a106d MW |
157 | Returns a generalized boolean: non-nil if the class has been successfully |
158 | finalized -- either just now, or if it was finalized already and nothing | |
159 | needed to be done -- or nil if finalization failed -- either just now, or | |
160 | because the class had previously been marked as broken following a failed | |
161 | finalization attempt. | |
162 | ||
32bb097f | 163 | User methods can assume that the class in question has not yet been |
e45a106d MW |
164 | finalized. Errors during finalization can be reported in the usual way. |
165 | See also `finalization-error' and `finalization-failed' above.")) | |
dea4d055 MW |
166 | |
167 | ;;;----- That's all, folks -------------------------------------------------- |