0.8.2.15:
[sbcl.git] / doc / FOR-CMUCL-DEVELOPERS
1 This document was motivated by a request from Paolo Amoroso for notes
2 or other documentation on my work on SBCL. It's intended for
3 developers who are familiar with the guts of CMU CL, as an overview of
4 the changes made to CMU CL in order to produce SBCL. It was written
5 for the initial release (sbcl-0.5.0) and has not been updated since
6 then.
7
8 There are two sections in this report: 
9   I. non-fundamental changes
10   II. fundamental changes
11 In this context, fundamental changes are changes which were
12 directly driven by the goal of making the system bootstrap itself.
13
14
15 Section I: non-fundamental changes
16
17 Before I describe the fundamental changes I had to make in order to
18 get the system to bootstrap itself, let me emphasize that there are
19 many non-fundamental changes as well. I won't try to summarize them
20 all, but I'll mention some to give some idea. (Some more information
21 about why I made some of these changes is in the PRINCIPLES file in
22 the distribution.)
23
24 Many, many extensions have been removed.
25
26 Packages have all been renamed; in the final system,
27 the system packages have names which begin with "SB-".
28 Mostly these correspond closely to CMU CL packages, 
29 e.g. the "C" package of CMU CL has become the "SB-C" package,
30 and the "EXTENSIONS" package of CMU CL has become the "SB-EXT" 
31 package.
32
33 Some other definitions and declarations have been centralized, too.
34 E.g. the build order is defined in one place, and all the COMMON-LISP
35 special variables are declared in one place.
36
37 I've made various reformatting changes in the comments, and
38 added a number of comments.
39
40 INFO is now implemented as a function instead of a macro,
41 using keywords as its first and second arguments, and is
42 no longer in the extensions package, but is considered a
43 private implementation detail.
44
45 The expected Lisp function arguments and command line arguments
46 for SAVE-LISP (now called SAVE-LISP-AND-DIE) and loading
47 the core back into a new Lisp have changed completely.
48
49 The SB-UNIX package no longer attempts to be a complete user interface
50 to Unix. Instead, it's considered a private part of the implementation
51 of SBCL, and tries to implement only what's needed by the current
52 implementation of SBCL.
53
54 Lots of stale conditional code was deleted, e.g. code to support
55 portability to archaic systems in the LOOP and PCL packages. (The
56 SB-PCL and SB-LOOP packages no longer aspire to portability.)
57
58 Various internal symbols, and even some externally-visible extensions,
59 have been given less-ambiguous or more-modern names, with more to
60 follow. (E.g. SAVE-LISP becoming SAVE-LISP-AND-DIE, both to avoid
61 surprising the user and to reserve the name SAVE-LISP in case we ever
62 manage to implement a SAVE-LISP which doesn't cause the system to die
63 afterwards. And GIVE-UP and ABORT-TRANSFORM have been renamed
64 to GIVE-UP-IR1-TRANSFORM and ABORT-IR1-TRANSFORM. And so on.)
65
66 Various internal names "NEW-FOO" have been changed to FOO, generally
67 after deleting the obsolete old version of FOO. This has happened both
68 with names at the Lisp level (e.g. "NEW-ASSEM") and at the Unix
69 filesystem level (e.g. "new-hash.lisp" and "new-assem.lisp").
70
71 A cultural change, rather than a technical one: The system no longer
72 tries to be binary compatible between releases.
73
74 Per-file credits for programs should move into a single
75 centralized CREDITS file Real Soon Now.
76
77 A lot of spelling errors have been corrected.:-)
78
79
80 Section II. fundamental changes
81
82 There were a number of things which I changed in order to get the
83 system to boot itself.
84
85 The source files have been extensively reordered to fix broken forward
86 references. In many cases, this required breaking one CMU CL source
87 file into more than one SBCL source file, and scattering the multiple
88 SBCL source files into multiple places in the build order. (Some of
89 the breakups were motivated by reasons which no longer exist, and
90 could be undone now, e.g. "class.lisp" could probably go back into
91 "classes.lisp". But I think most of the reasons still apply.)
92
93 The assembler and genesis were rewritten for portability, using
94 vectors for scratch space instead of using SAPs.
95
96 We define new readmacro syntax #!+ and #!- which acts like
97 the standard #+ and #- syntax, except that it switches on the 
98 target feature list instead of the host feature list. We also 
99 introduce temporary new features like :XC-HOST ("in the cross-compilation
100 host") and :XC ("in the cross-compiler") which will be used
101 to control some of the behavior below.
102
103 A new package SB-XC ("cross-compiler") was introduced to hold
104 affecting-the-target versions of various things like DEFMACRO,
105 DEFTYPE, FIND-CLASS, CONSTANTP, CLASS, etc. So e.g. when you're
106 building the cross-compiler in the cross-compilation host Lisp,
107 SB-XC:DEFMACRO defines a macro in the target Lisp; SB-XC:CONSTANTP
108 tells you whether something is known to be constant in the target
109 Lisp; and SB-XC:CLASS is the class of an object which represents a
110 class in the target Lisp. In order to make everything work out later
111 when running the cross-compiler to produce code for the target Lisp,
112 SB-XC turns into a sort of nickname for the COMMON-LISP package.
113 Except it's a little more complicated than that..
114
115 It doesn't quite work to make SB-XC into a nickname for COMMON-LISP
116 while building code for the target, because then much of the code in
117 EVAL-WHEN (:COMPILE-TOPLEVEL :EXECUTE) forms would break. Instead, we
118 read in code using the ordinary SB-XC package, and then when we
119 process code in any situation other than :COMPILE-TOPLEVEL, we run it
120 through the function UNCROSS to translate any SB-XC symbols into the
121 corresponding CL symbols. (This doesn't seem like a very elegant
122 solution, but it does seem to work.:-)
123
124 Even after we've implemented the UNCROSS hack, a lot of the code inside
125 EVAL-WHEN forms is still broken, because it does things like CL:DEFMACRO
126 to define macros which are intended to show up in the target, and
127 under the new system we really need it to do SB-XC:DEFMACRO instead
128 in order to achieve the desired effect. So we have to go through
129 all the EVAL-WHEN forms and convert various CL:FOO operations
130 to the corresponding SB-XC:FOO operations. Or sometimes instead we
131 convert code a la
132         (EVAL-WHEN (COMPILE EVAL)
133           (DEFMACRO FOO ..))
134         (code-using-foo)
135 into code a la
136         (MACROLET ((FOO ..))
137           (code-using-foo))
138 Or sometimes we even give up and write 
139         (DEFMACRO FOO ..)
140         (code-using-foo)
141 instead, figuring it's not *that* important to try to save a few bytes
142 in the target Lisp by keeping FOO from being defined. And in a few
143 shameful instances we even did things like
144         #+XC (DEFMACRO FOO ..)
145         #-XC (DEFMACRO FOO ..
146 or
147         #+XC (code-using-foo)
148         #-XC (other-code-using-foo)
149 even though we know that we will burn in hell for it. (The really
150 horribly unmaintainable stuff along those lines is three compiler-building
151 macros which I hope to fix before anyone else notices them.:-)
152
153 In order to avoid trashing the host Common Lisp when cross-compiling
154 under another instance of ourself (and in order to avoid coming to
155 depend on its internals in various weird ways, like some systems we
156 could mention but won't:-) we make the system use different package
157 names at cold init time than afterwards. The internal packages are
158 named "SB!FOO" while we're building the system, and "SB-FOO"
159 afterwards.
160
161 In order to make the system work even when we're renaming its packages
162 out from underneath it, we need to seek out and destroy any nasty
163 hacks which refer to particular package names, like the one in
164 %PRIMITIVE which wants to reintern the symbols in its arguments into
165 the "C"/"SB-C"/"SB!C" package.
166
167 Incidentally, because of the #! readmacros and the "SB!FOO" package
168 names, the system sources are unreadable to the running system. (The
169 undefined readmacros and package names cause READ-ERRORs.) I'd like
170 to make a little hack to fix this for use when experimenting with 
171 and maintaining the system, but I haven't gotten around to it,
172 despite several false starts. Real Soon Now..
173
174 In order to keep track of layouts and other type and structure
175 information set up under the cross-compiler, we use a system built
176 around the DEF!STRUCT macro. (The #\! character is used to name a lot
177 of cold-boot-related stuff.) When building the cross-compiler, the
178 DEF!STRUCT macro is a wrapper around portable DEFSTRUCT which builds
179 its own portable information about the structures being created, and
180 arranges for host Lisp instances of the structures to be dumpable as
181 target Lisp instances as necessary. (This system uses MAKE-LOAD-FORM
182 heavily and is the reason that I say that bootstrapping under CLISP is
183 not likely to happen until CLISP supports MAKE-LOAD-FORM.) When
184 running the cross-compiler, DEF!STRUCT basically reduces to the
185 DEFSTRUCT macro.
186
187 In order to be able to make this system handle target Lisp code,
188 we need to be able to test whether a host Lisp value matches a 
189 target Lisp type specifier. With the information available from 
190 DEF!STRUCT, and various hackery, we can do that, implementing things
191 like SB-XC:TYPEP.
192
193 Now that we know how to represent target Lisp objects in the
194 cross-compiler running under vanilla ANSI Common Lisp, we need to make
195 the dump code portable. This is not too hard given that the cases
196 which would be hard tend not to be used in the implementation of SBCL
197 itself, so the cross-compiler doesn't need to be able to handle them
198 anyway. Specialized arrays are an exception, and currently we dodge
199 the issue by making the compiler use not-as-specialized-as-possible
200 array values. Probably this is fixable by bootstrapping in two passes,
201 one pass under vanilla ANSI Common Lisp and then another under the
202 SBCL created by the first pass. That way, the problem goes away in the
203 second pass pass, since we know that all types represented by the
204 target SBCL can be represented in the cross-compilation host SBCL.