1 ! :folding=none:collapseFolds=1:
5 ! Copyright (C) 2004 Slava Pestov.
7 ! Redistribution and use in source and binary forms, with or without
8 ! modification, are permitted provided that the following conditions are met:
10 ! 1. Redistributions of source code must retain the above copyright notice,
11 ! this list of conditions and the following disclaimer.
13 ! 2. Redistributions in binary form must reproduce the above copyright notice,
14 ! this list of conditions and the following disclaimer in the documentation
15 ! and/or other materials provided with the distribution.
17 ! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 ! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
19 ! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 ! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 ! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 ! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 ! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 ! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 ! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 : emit ( cell -- ) image vector-push ;
52 : emit64 ( bignum -- )
53 #! Little endian byte order
54 dup HEX: ffffffff bitand emit
55 32 shift> HEX: ffffffff bitand emit ;
57 : fixup ( value offset -- ) image set-vector-nth ;
61 : image-magic HEX: 0f0e0d0c ;
64 : cell ( we're compiling for a 32-bit system ) 4 ;
69 : untag ( cell tag -- ) tag-mask bitnot bitand ;
70 : tag ( cell -- tag ) tag-mask bitand ;
72 : fixnum-tag BIN: 000 ;
75 : object-tag BIN: 011 ;
76 : rational-tag BIN: 100 ;
77 : complex-tag BIN: 101 ;
78 : header-tag BIN: 110 ;
79 : gc-fwd-ptr BIN: 111 ; ( we don't output these )
92 : immediate ( x tag -- tagged ) swap tag-bits shift< bitor ;
93 : >header ( id -- tagged ) header-tag immediate ;
100 ( relocation base at end of header ) 0 emit
101 ( bootstrap quotation set later ) 0 emit
102 ( global namespace set later ) 0 emit
103 ( size of heap set later ) 0 emit ;
105 : boot-quot-offset 3 ;
107 : heap-size-offset 5 ;
110 ( Top of heap pointer )
112 : here ( -- size ) image vector-length header-size - cell * ;
113 : here-as ( tag -- pointer ) here swap bitor ;
114 : pad ( -- ) here 8 mod 4 = [ 0 emit ] when ;
116 ( Remember what objects we've compiled )
118 : pooled-object ( object -- pointer )
121 : pool-object ( object pointer -- )
122 swap "objects" get set-hash ;
126 : 'fixnum ( n -- tagged ) fixnum-tag immediate ;
130 : 'float ( f -- tagged )
132 float-type >header emit
133 0 emit ( alignment -- FIXME 64-bit arch )
138 : 'bignum ( bignum -- tagged )
142 bignum-type >header emit
143 0 emit ( alignment -- FIXME 64-bit arch )
144 ( bignum -- ) emit64 ;
148 ! Padded with fixnums for 8-byte alignment
150 : f, object-tag here-as "f" set f-type >header emit 0 'fixnum emit ;
151 : t, object-tag here-as "t" set t-type >header emit 0 'fixnum emit ;
152 : empty, empty-type >header emit 0 'fixnum emit ;
154 ( Beginning of the image )
155 ! The image proper begins with the header, then EMPTY, F, T
157 : begin ( -- ) header empty, f, t, ;
161 : word, ( -- pointer )
162 word-tag here-as word-tag >header emit 0 emit ;
164 ! This is to handle mutually recursive words
165 ! It is a hack. A recursive word in the cdr of a
166 ! cons doesn't work! This never happends though.
168 ! Eg : foo [ 5 | foo ] ;
170 : fixup-word-later ( word -- )
171 image vector-length cons "word-fixups" get vector-push ;
173 : fixup-word ( where word -- )
174 dup pooled-object dup [
177 drop "Not in image: " swap word-name cat2 throw
181 "word-fixups" get [ unswons fixup-word ] vector-each ;
183 : 'word ( word -- pointer )
184 dup pooled-object dup [
188 ! Remember where we are, and add the reference later
196 : cons, ( -- pointer ) cons-tag here-as ;
197 : 'cons ( c -- tagged ) uncons ' swap ' cons, -rot emit emit ;
202 "big-endian" get [ swap ] when 16 shift< bitor emit ;
204 : pack-at ( n str -- )
205 2dup str-nth rot succ rot str-nth pack ;
207 : (pack-string) ( n str -- )
211 2dup str-length pred = [
215 ] ifte >r 2 + r> (pack-string)
218 : pack-string ( str -- ) 0 swap (pack-string) ;
220 : string, ( string -- )
221 object-tag here-as swap
222 string-type >header emit
228 : 'string ( string -- pointer )
229 #! We pool strings so that each string is only written once
231 dup pooled-object dup [
234 drop dup string, dup >r pool-object r>
241 : namespace-buckets 23 ;
245 : (vocabulary) ( name -- vocab )
246 #! Vocabulary for target image.
247 dup "vocabularies" get hash dup [
250 drop >r namespace-buckets <hashtable> dup r>
251 "vocabularies" get set-hash
254 : (word+) ( word -- )
255 #! Add the word to a vocabulary in the target image.
256 dup word-name over word-vocabulary
257 (vocabulary) set-hash ;
259 : 'plist ( word -- plist )
262 dup word-name "name" swons ,
263 dup word-vocabulary "vocabulary" swons ,
264 "parsing" swap word-property >boolean "parsing" swons ,
268 : (worddef,) ( word primitive parameter -- )
269 ' >r >r dup (word+) dup 'plist >r
272 r> ( primitive -- ) emit
273 r> ( parameter -- ) emit
277 : primitive, ( word primitive -- ) f (worddef,) ;
278 : compound, ( word definition -- ) 1 swap (worddef,) ;
280 ( Arrays and vectors )
282 : 'array ( list -- untagged )
285 array-type >header emit
287 ( elements -- ) [ emit ] each
290 : 'vector ( vector -- pointer )
291 dup vector>list 'array swap vector-length
292 object-tag here-as >r
293 vector-type >header emit
298 ( Cross-compile a reference to an object )
300 : ' ( obj -- pointer )
302 [ fixnum? ] [ 'fixnum ]
303 [ bignum? ] [ 'bignum ]
304 [ float? ] [ 'float ]
307 [ char? ] [ 'fixnum ]
308 [ string? ] [ 'string ]
309 [ vector? ] [ 'vector ]
310 [ t = ] [ drop "t" get ]
311 [ f = ] [ drop "f" get ]
312 [ drop t ] [ "Cannot cross-compile: " swap cat2 throw ]
317 : (set-boot) ( quot -- ) ' boot-quot-offset fixup ;
318 : (set-global) ( namespace -- ) ' global-offset fixup ;
321 "vocabularies" get "vocabularies"
322 namespace-buckets <hashtable>
323 dup >r set-hash r> (set-global) ;
325 : end ( -- ) global, fixup-words here heap-size-offset fixup ;
329 : byte0 ( num -- byte ) 24 shift> HEX: ff bitand ;
330 : byte1 ( num -- byte ) 16 shift> HEX: ff bitand ;
331 : byte2 ( num -- byte ) 8 shift> HEX: ff bitand ;
332 : byte3 ( num -- byte ) HEX: ff bitand ;
334 : write-little-endian ( word -- )
335 dup byte3 >char write
336 dup byte2 >char write
337 dup byte1 >char write
340 : write-big-endian ( word -- )
341 dup byte0 >char write
342 dup byte1 >char write
343 dup byte2 >char write
346 : write-word ( word -- )
353 : write-image ( image file -- )
354 <filebw> [ [ write-word ] vector-each ] with-stream ;
356 : with-image ( quot -- image )
358 300000 <vector> "image" set
359 521 <hashtable> "objects" set
360 namespace-buckets <hashtable> "vocabularies" set
361 ! Note that this is a vector that we can side-effect,
362 ! since ; ends up using this variable from nested
364 1000 <vector> "word-fixups" set
369 : test-image ( quot -- ) with-image vector>list . ;