* boot-9.scm (struct-layout, %struct-printer-tag, struct-printer,
[bpt/guile.git] / ice-9 / boot-9.scm
1 ;;; installed-scm-file
2
3 ;;;; Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
4 ;;;;
5 ;;;; This program is free software; you can redistribute it and/or modify
6 ;;;; it under the terms of the GNU General Public License as published by
7 ;;;; the Free Software Foundation; either version 2, or (at your option)
8 ;;;; any later version.
9 ;;;;
10 ;;;; This program is distributed in the hope that it will be useful,
11 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ;;;; GNU General Public License for more details.
14 ;;;;
15 ;;;; You should have received a copy of the GNU General Public License
16 ;;;; along with this software; see the file COPYING. If not, write to
17 ;;;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 ;;;; Boston, MA 02111-1307 USA
19 ;;;;
20 \f
21
22 ;;; This file is the first thing loaded into Guile. It adds many mundane
23 ;;; definitions and a few that are interesting.
24 ;;;
25 ;;; The module system (hence the hierarchical namespace) are defined in this
26 ;;; file.
27 ;;;
28
29 \f
30 ;;; {Features}
31 ;;
32
33 (define (provide sym)
34 (if (not (memq sym *features*))
35 (set! *features* (cons sym *features*))))
36
37 \f
38 ;;; {R4RS compliance}
39
40 (primitive-load-path "ice-9/r4rs.scm")
41
42 \f
43 ;;; {Simple Debugging Tools}
44 ;;
45
46
47 ;; peek takes any number of arguments, writes them to the
48 ;; current ouput port, and returns the last argument.
49 ;; It is handy to wrap around an expression to look at
50 ;; a value each time is evaluated, e.g.:
51 ;;
52 ;; (+ 10 (troublesome-fn))
53 ;; => (+ 10 (pk 'troublesome-fn-returned (troublesome-fn)))
54 ;;
55
56 (define (peek . stuff)
57 (newline)
58 (display ";;; ")
59 (write stuff)
60 (newline)
61 (car (last-pair stuff)))
62
63 (define pk peek)
64
65 (define (warn . stuff)
66 (with-output-to-port (current-error-port)
67 (lambda ()
68 (newline)
69 (display ";;; WARNING ")
70 (display stuff)
71 (newline)
72 (car (last-pair stuff)))))
73
74 \f
75 ;;; {Trivial Functions}
76 ;;;
77
78 (define (id x) x)
79 (define (1+ n) (+ n 1))
80 (define (-1+ n) (+ n -1))
81 (define 1- -1+)
82 (define return-it noop)
83 (define (and=> value procedure) (and value (procedure value)))
84 (define (make-hash-table k) (make-vector k '()))
85
86 ;;; apply-to-args is functionally redunant with apply and, worse,
87 ;;; is less general than apply since it only takes two arguments.
88 ;;;
89 ;;; On the other hand, apply-to-args is a syntacticly convenient way to
90 ;;; perform binding in many circumstances when the "let" family of
91 ;;; of forms don't cut it. E.g.:
92 ;;;
93 ;;; (apply-to-args (return-3d-mouse-coords)
94 ;;; (lambda (x y z)
95 ;;; ...))
96 ;;;
97
98 (define (apply-to-args args fn) (apply fn args))
99
100 \f
101 ;;; {Integer Math}
102 ;;;
103
104 (define (ipow-by-squaring x k acc proc)
105 (cond ((zero? k) acc)
106 ((= 1 k) (proc acc x))
107 (else (logical:ipow-by-squaring (proc x x)
108 (quotient k 2)
109 (if (even? k) acc (proc acc x))
110 proc))))
111
112 (define string-character-length string-length)
113
114
115
116 ;; A convenience function for combining flag bits. Like logior, but
117 ;; handles the cases of 0 and 1 arguments.
118 ;;
119 (define (flags . args)
120 (cond
121 ((null? args) 0)
122 ((null? (cdr args)) (car args))
123 (else (apply logior args))))
124
125 \f
126 ;;; {Symbol Properties}
127 ;;;
128
129 (define (symbol-property sym prop)
130 (let ((pair (assoc prop (symbol-pref sym))))
131 (and pair (cdr pair))))
132
133 (define (set-symbol-property! sym prop val)
134 (let ((pair (assoc prop (symbol-pref sym))))
135 (if pair
136 (set-cdr! pair val)
137 (symbol-pset! sym (acons prop val (symbol-pref sym))))))
138
139 (define (symbol-property-remove! sym prop)
140 (let ((pair (assoc prop (symbol-pref sym))))
141 (if pair
142 (symbol-pset! sym (delq! pair (symbol-pref sym))))))
143
144 \f
145
146 ;;; {Line and Delimited I/O}
147
148 ;;; corresponds to SCM_LINE_INCREMENTORS in libguile.
149 (define scm-line-incrementors "\n")
150
151 (define (read-line! string . maybe-port)
152 (let* ((port (if (pair? maybe-port)
153 (car maybe-port)
154 (current-input-port))))
155 (let* ((rv (%read-delimited! scm-line-incrementors
156 string
157 #t
158 port))
159 (terminator (car rv))
160 (nchars (cdr rv)))
161 (cond ((and (= nchars 0)
162 (eof-object? terminator))
163 terminator)
164 ((not terminator) #f)
165 (else nchars)))))
166
167 (define (read-delimited! delims buf . args)
168 (let* ((num-args (length args))
169 (port (if (> num-args 0)
170 (car args)
171 (current-input-port)))
172 (handle-delim (if (> num-args 1)
173 (cadr args)
174 'trim))
175 (start (if (> num-args 2)
176 (caddr args)
177 0))
178 (end (if (> num-args 3)
179 (cadddr args)
180 (string-length buf))))
181 (let* ((rv (%read-delimited! delims
182 buf
183 (not (eq? handle-delim 'peek))
184 port
185 start
186 end))
187 (terminator (car rv))
188 (nchars (cdr rv)))
189 (cond ((or (not terminator) ; buffer filled
190 (eof-object? terminator))
191 (if (zero? nchars)
192 (if (eq? handle-delim 'split)
193 (cons terminator terminator)
194 terminator)
195 (if (eq? handle-delim 'split)
196 (cons nchars terminator)
197 nchars)))
198 (else
199 (case handle-delim
200 ((trim peek) nchars)
201 ((concat) (string-set! buf nchars terminator)
202 (+ nchars 1))
203 ((split) (cons nchars terminator))
204 (else (error "unexpected handle-delim value: "
205 handle-delim))))))))
206
207 (define (read-delimited delims . args)
208 (let* ((port (if (pair? args)
209 (let ((pt (car args)))
210 (set! args (cdr args))
211 pt)
212 (current-input-port)))
213 (handle-delim (if (pair? args)
214 (car args)
215 'trim)))
216 (let loop ((substrings ())
217 (total-chars 0)
218 (buf-size 100)) ; doubled each time through.
219 (let* ((buf (make-string buf-size))
220 (rv (%read-delimited! delims
221 buf
222 (not (eq? handle-delim 'peek))
223 port))
224 (terminator (car rv))
225 (nchars (cdr rv))
226 (join-substrings
227 (lambda ()
228 (apply string-append
229 (reverse
230 (cons (if (and (eq? handle-delim 'concat)
231 (not (eof-object? terminator)))
232 (string terminator)
233 "")
234 (cons (make-shared-substring buf 0 nchars)
235 substrings))))))
236 (new-total (+ total-chars nchars)))
237 (cond ((not terminator)
238 ;; buffer filled.
239 (loop (cons (substring buf 0 nchars) substrings)
240 new-total
241 (* buf-size 2)))
242 ((eof-object? terminator)
243 (if (zero? new-total)
244 (if (eq? handle-delim 'split)
245 (cons terminator terminator)
246 terminator)
247 (if (eq? handle-delim 'split)
248 (cons (join-substrings) terminator)
249 (join-substrings))))
250 (else
251 (case handle-delim
252 ((trim peek concat) (join-substrings))
253 ((split) (cons (join-substrings) terminator))
254 (else (error "unexpected handle-delim value: "
255 handle-delim)))))))))
256
257 (define (read-line . args)
258 (apply read-delimited scm-line-incrementors args))
259
260 \f
261 ;;; {Arrays}
262 ;;;
263
264 (begin
265 (define uniform-vector? array?)
266 (define make-uniform-vector dimensions->uniform-array)
267 ; (define uniform-vector-ref array-ref)
268 (define (uniform-vector-set! u i o)
269 (uniform-array-set1! u o i))
270 (define uniform-vector-fill! array-fill!)
271 (define uniform-vector-read! uniform-array-read!)
272 (define uniform-vector-write uniform-array-write)
273
274 (define (make-array fill . args)
275 (dimensions->uniform-array args () fill))
276 (define (make-uniform-array prot . args)
277 (dimensions->uniform-array args prot))
278 (define (list->array ndim lst)
279 (list->uniform-array ndim '() lst))
280 (define (list->uniform-vector prot lst)
281 (list->uniform-array 1 prot lst))
282 (define (array-shape a)
283 (map (lambda (ind) (if (number? ind) (list 0 (+ -1 ind)) ind))
284 (array-dimensions a))))
285
286 \f
287 ;;; {Keywords}
288 ;;;
289
290 (define (symbol->keyword symbol)
291 (make-keyword-from-dash-symbol (symbol-append '- symbol)))
292
293 (define (keyword->symbol kw)
294 (let ((sym (keyword-dash-symbol kw)))
295 (string->symbol (substring sym 1 (length sym)))))
296
297 (define (kw-arg-ref args kw)
298 (let ((rem (member kw args)))
299 (and rem (pair? (cdr rem)) (cadr rem))))
300
301 \f
302
303 ;;; Printing structs
304
305 ;; The printing of structures can be customized by setting the builtin
306 ;; variable *struct-printer* to a procedure. A second dispatching
307 ;; step is implemented here to allow for struct-type specific printing
308 ;; procedures.
309 ;;
310 ;; A particular type of structures is characterized by its vtable. In
311 ;; addition to some internal fields, such a vtable can contain
312 ;; arbitrary user-defined fields. We use the first of these fields to
313 ;; hold the specific printing procedure. To avoid breaking code that
314 ;; already uses this first extra-field for some other purposes, we use
315 ;; a unique tag to decide whether it really contains a structure
316 ;; printer or not.
317 ;;
318 ;; XXX - Printing structures is probably fundamental enough that we
319 ;; can simply hardcode the vtable slot convention and expect everyone
320 ;; to obey it.
321 ;;
322 ;; A structure-type specific printer follows the same calling
323 ;; convention as the builtin *struct-printer*.
324
325 ;; A shorthand for one already hardcoded vtable convention
326
327 (define (struct-layout s)
328 (struct-ref (struct-vtable s) 0))
329
330 ;; This is our new convention for storing printing procedures
331
332 (define %struct-printer-tag (cons '%struct-printer-tag #f))
333
334 (define (struct-printer s)
335 (and (>= (string-length (struct-layout s))
336 (* 2 struct-vtable-offset))
337 (let ((p (struct-ref (struct-vtable s) struct-vtable-offset)))
338 (and (eq? (car p) %struct-printer-tag)
339 (cdr p)))))
340
341 (define (make-struct-printer printer)
342 (cons %struct-printer-tag printer))
343
344 ;; Note: While the printer is extracted from a structure itself, it
345 ;; has to be set in the vtable of the structure.
346
347 (define (set-struct-printer-in-vtable! vtable printer)
348 (struct-set! vtable struct-vtable-offset (make-struct-printer printer)))
349
350 ;; The dispatcher
351
352 (set! *struct-printer* (lambda (s p)
353 (let ((printer (struct-printer s)))
354 (and printer
355 (printer s p)))))
356
357 \f
358 ;;; {Records}
359 ;;;
360
361 ;; Printing records: by default, records are printed as
362 ;;
363 ;; #<type-name field1: val1 field2: val2 ...>
364 ;;
365 ;; You can change that by giving a custom printing function to
366 ;; MAKE-RECORD-TYPE (after the list of field symbols). This function
367 ;; will be called like
368 ;;
369 ;; (<printer> object port)
370 ;;
371 ;; It should print OBJECT to PORT.
372
373 ;; 0: printer, 1: type-name, 2: fields
374 (define record-type-vtable
375 (make-vtable-vtable "prprpr" 0
376 (make-struct-printer
377 (lambda (s p)
378 (cond ((eq? s record-type-vtable)
379 (display "#<record-type-vtable>" p))
380 (else
381 (display "#<record-type " p)
382 (display (record-type-name s) p)
383 (display ">" p)))))))
384
385 (define (record-type? obj)
386 (and (struct? obj) (eq? record-type-vtable (struct-vtable obj))))
387
388 (define (make-record-type type-name fields . opt)
389 (let ((printer-fn (and (pair? opt) (car opt))))
390 (let ((struct (make-struct record-type-vtable 0
391 (make-struct-layout
392 (apply symbol-append
393 (map (lambda (f) "pw") fields)))
394 (make-struct-printer
395 (or printer-fn
396 (lambda (s p)
397 (display "#<" p)
398 (display type-name p)
399 (let loop ((fields fields)
400 (off 0))
401 (cond
402 ((not (null? fields))
403 (display " " p)
404 (display (car fields) p)
405 (display ": " p)
406 (display (struct-ref s off) p)
407 (loop (cdr fields) (+ 1 off)))))
408 (display ">" p))))
409 type-name
410 (copy-tree fields))))
411 struct)))
412
413 (define (record-type-name obj)
414 (if (record-type? obj)
415 (struct-ref obj (+ 1 struct-vtable-offset))
416 (error 'not-a-record-type obj)))
417
418 (define (record-type-fields obj)
419 (if (record-type? obj)
420 (struct-ref obj (+ 2 struct-vtable-offset))
421 (error 'not-a-record-type obj)))
422
423 (define (record-constructor rtd . opt)
424 (let ((field-names (if (pair? opt) (car opt) (record-type-fields rtd))))
425 (eval `(lambda ,field-names
426 (make-struct ',rtd 0 ,@(map (lambda (f)
427 (if (memq f field-names)
428 f
429 #f))
430 (record-type-fields rtd)))))))
431
432 (define (record-predicate rtd)
433 (lambda (obj) (and (struct? obj) (eq? rtd (struct-vtable obj)))))
434
435 (define (record-accessor rtd field-name)
436 (let* ((pos (list-index (record-type-fields rtd) field-name)))
437 (if (not pos)
438 (error 'no-such-field field-name))
439 (eval `(lambda (obj)
440 (and (eq? ',rtd (record-type-descriptor obj))
441 (struct-ref obj ,pos))))))
442
443 (define (record-modifier rtd field-name)
444 (let* ((pos (list-index (record-type-fields rtd) field-name)))
445 (if (not pos)
446 (error 'no-such-field field-name))
447 (eval `(lambda (obj val)
448 (and (eq? ',rtd (record-type-descriptor obj))
449 (struct-set! obj ,pos val))))))
450
451
452 (define (record? obj)
453 (and (struct? obj) (record-type? (struct-vtable obj))))
454
455 (define (record-type-descriptor obj)
456 (if (struct? obj)
457 (struct-vtable obj)
458 (error 'not-a-record obj)))
459
460 (provide 'record)
461
462 \f
463 ;;; {Booleans}
464 ;;;
465
466 (define (->bool x) (not (not x)))
467
468 \f
469 ;;; {Symbols}
470 ;;;
471
472 (define (symbol-append . args)
473 (string->symbol (apply string-append args)))
474
475 (define (list->symbol . args)
476 (string->symbol (apply list->string args)))
477
478 (define (symbol . args)
479 (string->symbol (apply string args)))
480
481 (define (obarray-symbol-append ob . args)
482 (string->obarray-symbol (apply string-append ob args)))
483
484 (define obarray-gensym
485 (let ((n -1))
486 (lambda (obarray . opt)
487 (if (null? opt)
488 (set! opt '(%%gensym)))
489 (let loop ((proposed-name (apply string-append opt)))
490 (if (string->obarray-symbol obarray proposed-name #t)
491 (loop (apply string-append (append opt (begin (set! n (1+ n)) (list (number->string n))))))
492 (string->obarray-symbol obarray proposed-name))))))
493
494 (define (gensym . args) (apply obarray-gensym #f args))
495
496 \f
497 ;;; {Lists}
498 ;;;
499
500 (define (list-index l k)
501 (let loop ((n 0)
502 (l l))
503 (and (not (null? l))
504 (if (eq? (car l) k)
505 n
506 (loop (+ n 1) (cdr l))))))
507
508 (define (make-list n init)
509 (let loop ((answer '())
510 (n n))
511 (if (<= n 0)
512 answer
513 (loop (cons init answer) (- n 1)))))
514
515
516 \f
517 ;;; {and-map, or-map, and map-in-order}
518 ;;;
519 ;;; (and-map fn lst) is like (and (fn (car lst)) (fn (cadr lst)) (fn...) ...)
520 ;;; (or-map fn lst) is like (or (fn (car lst)) (fn (cadr lst)) (fn...) ...)
521 ;;; (map-in-order fn lst) is like (map fn lst) but definately in order of lst.
522 ;;;
523
524 ;; and-map f l
525 ;;
526 ;; Apply f to successive elements of l until exhaustion or f returns #f.
527 ;; If returning early, return #f. Otherwise, return the last value returned
528 ;; by f. If f has never been called because l is empty, return #t.
529 ;;
530 (define (and-map f lst)
531 (let loop ((result #t)
532 (l lst))
533 (and result
534 (or (and (null? l)
535 result)
536 (loop (f (car l)) (cdr l))))))
537
538 ;; or-map f l
539 ;;
540 ;; Apply f to successive elements of l until exhaustion or while f returns #f.
541 ;; If returning early, return the return value of f.
542 ;;
543 (define (or-map f lst)
544 (let loop ((result #f)
545 (l lst))
546 (or result
547 (and (not (null? l))
548 (loop (f (car l)) (cdr l))))))
549
550 ;; map-in-order
551 ;;
552 ;; Like map, but guaranteed to process the list in order.
553 ;;
554 (define (map-in-order fn l)
555 (if (null? l)
556 '()
557 (cons (fn (car l))
558 (map-in-order fn (cdr l)))))
559
560 \f
561 ;;; {Hooks}
562 (define (run-hooks hook)
563 (for-each (lambda (thunk) (thunk)) hook))
564
565 (define add-hook!
566 (procedure->macro
567 (lambda (exp env)
568 `(let ((thunk ,(caddr exp)))
569 (if (not (memq thunk ,(cadr exp)))
570 (set! ,(cadr exp)
571 (cons thunk ,(cadr exp))))))))
572
573 \f
574 ;;; {Files}
575 ;;; !!!! these should be implemented using Tcl commands, not fports.
576 ;;;
577
578 (define (feature? feature)
579 (and (memq feature *features*) #t))
580
581 ;; Using the vector returned by stat directly is probably not a good
582 ;; idea (it could just as well be a record). Hence some accessors.
583 (define (stat:dev f) (vector-ref f 0))
584 (define (stat:ino f) (vector-ref f 1))
585 (define (stat:mode f) (vector-ref f 2))
586 (define (stat:nlink f) (vector-ref f 3))
587 (define (stat:uid f) (vector-ref f 4))
588 (define (stat:gid f) (vector-ref f 5))
589 (define (stat:rdev f) (vector-ref f 6))
590 (define (stat:size f) (vector-ref f 7))
591 (define (stat:atime f) (vector-ref f 8))
592 (define (stat:mtime f) (vector-ref f 9))
593 (define (stat:ctime f) (vector-ref f 10))
594 (define (stat:blksize f) (vector-ref f 11))
595 (define (stat:blocks f) (vector-ref f 12))
596
597 ;; derived from stat mode.
598 (define (stat:type f) (vector-ref f 13))
599 (define (stat:perms f) (vector-ref f 14))
600
601 (define file-exists?
602 (if (feature? 'posix)
603 (lambda (str)
604 (access? str F_OK))
605 (lambda (str)
606 (let ((port (catch 'system-error (lambda () (open-file str OPEN_READ))
607 (lambda args #f))))
608 (if port (begin (close-port port) #t)
609 #f)))))
610
611 (define file-is-directory?
612 (if (feature? 'i/o-extensions)
613 (lambda (str)
614 (eq? (stat:type (stat str)) 'directory))
615 (lambda (str)
616 (display str)
617 (newline)
618 (let ((port (catch 'system-error
619 (lambda () (open-file (string-append str "/.")
620 OPEN_READ))
621 (lambda args #f))))
622 (if port (begin (close-port port) #t)
623 #f)))))
624
625 (define (has-suffix? str suffix)
626 (let ((sufl (string-length suffix))
627 (sl (string-length str)))
628 (and (> sl sufl)
629 (string=? (substring str (- sl sufl) sl) suffix))))
630
631 \f
632 ;;; {Error Handling}
633 ;;;
634
635 (define (error . args)
636 (save-stack)
637 (if (null? args)
638 (scm-error 'misc-error #f "?" #f #f)
639 (let loop ((msg "%s")
640 (rest (cdr args)))
641 (if (not (null? rest))
642 (loop (string-append msg " %S")
643 (cdr rest))
644 (scm-error 'misc-error #f msg args #f)))))
645
646 ;; bad-throw is the hook that is called upon a throw to a an unhandled
647 ;; key (unless the throw has four arguments, in which case
648 ;; it's usually interpreted as an error throw.)
649 ;; If the key has a default handler (a throw-handler-default property),
650 ;; it is applied to the throw.
651 ;;
652 (define (bad-throw key . args)
653 (let ((default (symbol-property key 'throw-handler-default)))
654 (or (and default (apply default key args))
655 (apply error "unhandled-exception:" key args))))
656
657 \f
658 ;;; {Non-polymorphic versions of POSIX functions}
659
660 (define (getgrnam name) (getgr name))
661 (define (getgrgid id) (getgr id))
662 (define (gethostbyaddr addr) (gethost addr))
663 (define (gethostbyname name) (gethost name))
664 (define (getnetbyaddr addr) (getnet addr))
665 (define (getnetbyname name) (getnet name))
666 (define (getprotobyname name) (getproto name))
667 (define (getprotobynumber addr) (getproto addr))
668 (define (getpwnam name) (getpw name))
669 (define (getpwuid uid) (getpw uid))
670 (define (getservbyname name proto) (getserv name proto))
671 (define (getservbyport port proto) (getserv port proto))
672 (define (endgrent) (setgr))
673 (define (endhostent) (sethost))
674 (define (endnetent) (setnet))
675 (define (endprotoent) (setproto))
676 (define (endpwent) (setpw))
677 (define (endservent) (setserv))
678 (define (getgrent) (getgr))
679 (define (gethostent) (gethost))
680 (define (getnetent) (getnet))
681 (define (getprotoent) (getproto))
682 (define (getpwent) (getpw))
683 (define (getservent) (getserv))
684 (define (reopen-file . args) (apply freopen args))
685 (define (setgrent) (setgr #f))
686 (define (sethostent) (sethost #t))
687 (define (setnetent) (setnet #t))
688 (define (setprotoent) (setproto #t))
689 (define (setpwent) (setpw #t))
690 (define (setservent) (setserv #t))
691
692 (define (passwd:name obj) (vector-ref obj 0))
693 (define (passwd:passwd obj) (vector-ref obj 1))
694 (define (passwd:uid obj) (vector-ref obj 2))
695 (define (passwd:gid obj) (vector-ref obj 3))
696 (define (passwd:gecos obj) (vector-ref obj 4))
697 (define (passwd:dir obj) (vector-ref obj 5))
698 (define (passwd:shell obj) (vector-ref obj 6))
699
700 (define (group:name obj) (vector-ref obj 0))
701 (define (group:passwd obj) (vector-ref obj 1))
702 (define (group:gid obj) (vector-ref obj 2))
703 (define (group:mem obj) (vector-ref obj 3))
704
705 (define (hostent:name obj) (vector-ref obj 0))
706 (define (hostent:aliases obj) (vector-ref obj 1))
707 (define (hostent:addrtype obj) (vector-ref obj 2))
708 (define (hostent:length obj) (vector-ref obj 3))
709 (define (hostent:addr-list obj) (vector-ref obj 4))
710
711 (define (netent:name obj) (vector-ref obj 0))
712 (define (netent:aliases obj) (vector-ref obj 1))
713 (define (netent:addrtype obj) (vector-ref obj 2))
714 (define (netent:net obj) (vector-ref obj 3))
715
716 (define (protoent:name obj) (vector-ref obj 0))
717 (define (protoent:aliases obj) (vector-ref obj 1))
718 (define (protoent:proto obj) (vector-ref obj 2))
719
720 (define (servent:name obj) (vector-ref obj 0))
721 (define (servent:aliases obj) (vector-ref obj 1))
722 (define (servent:port obj) (vector-ref obj 2))
723 (define (servent:proto obj) (vector-ref obj 3))
724
725 (define (sockaddr:fam obj) (vector-ref obj 0))
726 (define (sockaddr:path obj) (vector-ref obj 1))
727 (define (sockaddr:addr obj) (vector-ref obj 1))
728 (define (sockaddr:port obj) (vector-ref obj 2))
729
730 (define (utsname:sysname obj) (vector-ref obj 0))
731 (define (utsname:nodename obj) (vector-ref obj 1))
732 (define (utsname:release obj) (vector-ref obj 2))
733 (define (utsname:version obj) (vector-ref obj 3))
734 (define (utsname:machine obj) (vector-ref obj 4))
735
736 (define (tm:sec obj) (vector-ref obj 0))
737 (define (tm:min obj) (vector-ref obj 1))
738 (define (tm:hour obj) (vector-ref obj 2))
739 (define (tm:mday obj) (vector-ref obj 3))
740 (define (tm:mon obj) (vector-ref obj 4))
741 (define (tm:year obj) (vector-ref obj 5))
742 (define (tm:wday obj) (vector-ref obj 6))
743 (define (tm:yday obj) (vector-ref obj 7))
744 (define (tm:isdst obj) (vector-ref obj 8))
745 (define (tm:gmtoff obj) (vector-ref obj 9))
746 (define (tm:zone obj) (vector-ref obj 10))
747
748 (define (set-tm:sec obj val) (vector-set! obj 0 val))
749 (define (set-tm:min obj val) (vector-set! obj 1 val))
750 (define (set-tm:hour obj val) (vector-set! obj 2 val))
751 (define (set-tm:mday obj val) (vector-set! obj 3 val))
752 (define (set-tm:mon obj val) (vector-set! obj 4 val))
753 (define (set-tm:year obj val) (vector-set! obj 5 val))
754 (define (set-tm:wday obj val) (vector-set! obj 6 val))
755 (define (set-tm:yday obj val) (vector-set! obj 7 val))
756 (define (set-tm:isdst obj val) (vector-set! obj 8 val))
757 (define (set-tm:gmtoff obj val) (vector-set! obj 9 val))
758 (define (set-tm:zone obj val) (vector-set! obj 10 val))
759
760 (define (file-position . args) (apply ftell args))
761 (define (file-set-position . args) (apply fseek args))
762
763 (define (open-input-pipe command) (open-pipe command OPEN_READ))
764 (define (open-output-pipe command) (open-pipe command OPEN_WRITE))
765
766 (define (move->fdes port fd)
767 (primitive-move->fdes port fd)
768 (set-port-revealed! port 1)
769 port)
770
771 (define (release-port-handle port)
772 (let ((revealed (port-revealed port)))
773 (if (> revealed 0)
774 (set-port-revealed! port (- revealed 1)))))
775
776 \f
777 ;;; {Load Paths}
778 ;;;
779
780 ;;; Here for backward compatability
781 ;;
782 (define scheme-file-suffix (lambda () ".scm"))
783
784 (define (in-vicinity vicinity file)
785 (let ((tail (let ((len (string-length vicinity)))
786 (if (zero? len) #f
787 (string-ref vicinity (- len 1))))))
788 (string-append vicinity
789 (if (eq? tail #\/) "" "/")
790 file)))
791
792 \f
793 ;;; {Help for scm_shell}
794 ;;; The argument-processing code used by Guile-based shells generates
795 ;;; Scheme code based on the argument list. This page contains help
796 ;;; functions for the code it generates.
797
798 (define (command-line) (program-arguments))
799
800 ;; This is mostly for the internal use of the code generated by
801 ;; scm_compile_shell_switches.
802 (define (load-user-init)
803 (define (has-init? dir)
804 (let ((path (in-vicinity dir ".guile")))
805 (catch 'system-error
806 (lambda ()
807 (let ((stats (stat path)))
808 (if (not (eq? (stat:type stats) 'directory))
809 path)))
810 (lambda dummy #f))))
811 (let ((path (or (has-init? (getenv "HOME"))
812 (has-init? (passwd:dir (getpw (getuid)))))))
813 (if path (primitive-load path))))
814
815 \f
816 ;;; {Loading by paths}
817
818 ;;; Load a Scheme source file named NAME, searching for it in the
819 ;;; directories listed in %load-path, and applying each of the file
820 ;;; name extensions listed in %load-extensions.
821 (define (load-from-path name)
822 (start-stack 'load-stack
823 (primitive-load-path name)))
824
825
826 \f
827 ;;; {Transcendental Functions}
828 ;;;
829 ;;; Derived from "Transcen.scm", Complex trancendental functions for SCM.
830 ;;; Copyright (C) 1992, 1993 Jerry D. Hedden.
831 ;;; See the file `COPYING' for terms applying to this program.
832 ;;;
833
834 (define (exp z)
835 (if (real? z) ($exp z)
836 (make-polar ($exp (real-part z)) (imag-part z))))
837
838 (define (log z)
839 (if (and (real? z) (>= z 0))
840 ($log z)
841 (make-rectangular ($log (magnitude z)) (angle z))))
842
843 (define (sqrt z)
844 (if (real? z)
845 (if (negative? z) (make-rectangular 0 ($sqrt (- z)))
846 ($sqrt z))
847 (make-polar ($sqrt (magnitude z)) (/ (angle z) 2))))
848
849 (define expt
850 (let ((integer-expt integer-expt))
851 (lambda (z1 z2)
852 (cond ((exact? z2)
853 (integer-expt z1 z2))
854 ((and (real? z2) (real? z1) (>= z1 0))
855 ($expt z1 z2))
856 (else
857 (exp (* z2 (log z1))))))))
858
859 (define (sinh z)
860 (if (real? z) ($sinh z)
861 (let ((x (real-part z)) (y (imag-part z)))
862 (make-rectangular (* ($sinh x) ($cos y))
863 (* ($cosh x) ($sin y))))))
864 (define (cosh z)
865 (if (real? z) ($cosh z)
866 (let ((x (real-part z)) (y (imag-part z)))
867 (make-rectangular (* ($cosh x) ($cos y))
868 (* ($sinh x) ($sin y))))))
869 (define (tanh z)
870 (if (real? z) ($tanh z)
871 (let* ((x (* 2 (real-part z)))
872 (y (* 2 (imag-part z)))
873 (w (+ ($cosh x) ($cos y))))
874 (make-rectangular (/ ($sinh x) w) (/ ($sin y) w)))))
875
876 (define (asinh z)
877 (if (real? z) ($asinh z)
878 (log (+ z (sqrt (+ (* z z) 1))))))
879
880 (define (acosh z)
881 (if (and (real? z) (>= z 1))
882 ($acosh z)
883 (log (+ z (sqrt (- (* z z) 1))))))
884
885 (define (atanh z)
886 (if (and (real? z) (> z -1) (< z 1))
887 ($atanh z)
888 (/ (log (/ (+ 1 z) (- 1 z))) 2)))
889
890 (define (sin z)
891 (if (real? z) ($sin z)
892 (let ((x (real-part z)) (y (imag-part z)))
893 (make-rectangular (* ($sin x) ($cosh y))
894 (* ($cos x) ($sinh y))))))
895 (define (cos z)
896 (if (real? z) ($cos z)
897 (let ((x (real-part z)) (y (imag-part z)))
898 (make-rectangular (* ($cos x) ($cosh y))
899 (- (* ($sin x) ($sinh y)))))))
900 (define (tan z)
901 (if (real? z) ($tan z)
902 (let* ((x (* 2 (real-part z)))
903 (y (* 2 (imag-part z)))
904 (w (+ ($cos x) ($cosh y))))
905 (make-rectangular (/ ($sin x) w) (/ ($sinh y) w)))))
906
907 (define (asin z)
908 (if (and (real? z) (>= z -1) (<= z 1))
909 ($asin z)
910 (* -i (asinh (* +i z)))))
911
912 (define (acos z)
913 (if (and (real? z) (>= z -1) (<= z 1))
914 ($acos z)
915 (+ (/ (angle -1) 2) (* +i (asinh (* +i z))))))
916
917 (define (atan z . y)
918 (if (null? y)
919 (if (real? z) ($atan z)
920 (/ (log (/ (- +i z) (+ +i z))) +2i))
921 ($atan2 z (car y))))
922
923 (set! abs magnitude)
924
925 (define (log10 arg)
926 (/ (log arg) (log 10)))
927
928 \f
929
930 ;;; {Reader Extensions}
931 ;;;
932
933 ;;; Reader code for various "#c" forms.
934 ;;;
935
936 (define (parse-path-symbol s)
937 (define (separate-fields-discarding-char ch str ret)
938 (let loop ((fields '())
939 (str str))
940 (cond
941 ((string-rindex str ch)
942 => (lambda (pos) (loop (cons (make-shared-substring str (+ 1 pos)) fields)
943 (make-shared-substring str 0 pos))))
944 (else (ret (cons str fields))))))
945 (separate-fields-discarding-char #\/
946 s
947 (lambda (fields)
948 (map string->symbol fields))))
949
950
951 (read-hash-extend #\' (lambda (c port)
952 (read port)))
953 (read-hash-extend #\. (lambda (c port)
954 (eval (read port))))
955
956 (if (feature? 'array)
957 (begin
958 (let ((make-array-proc (lambda (template)
959 (lambda (c port)
960 (read:uniform-vector template port)))))
961 (for-each (lambda (char template)
962 (read-hash-extend char
963 (make-array-proc template)))
964 '(#\b #\a #\u #\e #\s #\i #\c)
965 '(#t #\a 1 -1 1.0 1/3 0+i)))
966 (let ((array-proc (lambda (c port)
967 (read:array c port))))
968 (for-each (lambda (char) (read-hash-extend char array-proc))
969 '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)))))
970
971 ;; pushed to the beginning of the alist since it's used more than the
972 ;; others at present.
973 (read-hash-extend #\/
974 (lambda (c port)
975 (let ((look (peek-char port)))
976 (if (or (eof-object? look)
977 (and (char? look)
978 (or (char-whitespace? look)
979 (string-index ")" look))))
980 '()
981 (parse-path-symbol (read port))))))
982
983 (define (read:array digit port)
984 (define chr0 (char->integer #\0))
985 (let ((rank (let readnum ((val (- (char->integer digit) chr0)))
986 (if (char-numeric? (peek-char port))
987 (readnum (+ (* 10 val)
988 (- (char->integer (read-char port)) chr0)))
989 val)))
990 (prot (if (eq? #\( (peek-char port))
991 '()
992 (let ((c (read-char port)))
993 (case c ((#\b) #t)
994 ((#\a) #\a)
995 ((#\u) 1)
996 ((#\e) -1)
997 ((#\s) 1.0)
998 ((#\i) 1/3)
999 ((#\c) 0+i)
1000 (else (error "read:array unknown option " c)))))))
1001 (if (eq? (peek-char port) #\()
1002 (list->uniform-array rank prot (read port))
1003 (error "read:array list not found"))))
1004
1005 (define (read:uniform-vector proto port)
1006 (if (eq? #\( (peek-char port))
1007 (list->uniform-array 1 proto (read port))
1008 (error "read:uniform-vector list not found")))
1009
1010 \f
1011 ;;; {Command Line Options}
1012 ;;;
1013
1014 (define (get-option argv kw-opts kw-args return)
1015 (cond
1016 ((null? argv)
1017 (return #f #f argv))
1018
1019 ((or (not (eq? #\- (string-ref (car argv) 0)))
1020 (eq? (string-length (car argv)) 1))
1021 (return 'normal-arg (car argv) (cdr argv)))
1022
1023 ((eq? #\- (string-ref (car argv) 1))
1024 (let* ((kw-arg-pos (or (string-index (car argv) #\=)
1025 (string-length (car argv))))
1026 (kw (symbol->keyword (substring (car argv) 2 kw-arg-pos)))
1027 (kw-opt? (member kw kw-opts))
1028 (kw-arg? (member kw kw-args))
1029 (arg (or (and (not (eq? kw-arg-pos (string-length (car argv))))
1030 (substring (car argv)
1031 (+ kw-arg-pos 1)
1032 (string-length (car argv))))
1033 (and kw-arg?
1034 (begin (set! argv (cdr argv)) (car argv))))))
1035 (if (or kw-opt? kw-arg?)
1036 (return kw arg (cdr argv))
1037 (return 'usage-error kw (cdr argv)))))
1038
1039 (else
1040 (let* ((char (substring (car argv) 1 2))
1041 (kw (symbol->keyword char)))
1042 (cond
1043
1044 ((member kw kw-opts)
1045 (let* ((rest-car (substring (car argv) 2 (string-length (car argv))))
1046 (new-argv (if (= 0 (string-length rest-car))
1047 (cdr argv)
1048 (cons (string-append "-" rest-car) (cdr argv)))))
1049 (return kw #f new-argv)))
1050
1051 ((member kw kw-args)
1052 (let* ((rest-car (substring (car argv) 2 (string-length (car argv))))
1053 (arg (if (= 0 (string-length rest-car))
1054 (cadr argv)
1055 rest-car))
1056 (new-argv (if (= 0 (string-length rest-car))
1057 (cddr argv)
1058 (cdr argv))))
1059 (return kw arg new-argv)))
1060
1061 (else (return 'usage-error kw argv)))))))
1062
1063 (define (for-next-option proc argv kw-opts kw-args)
1064 (let loop ((argv argv))
1065 (get-option argv kw-opts kw-args
1066 (lambda (opt opt-arg argv)
1067 (and opt (proc opt opt-arg argv loop))))))
1068
1069 (define (display-usage-report kw-desc)
1070 (for-each
1071 (lambda (kw)
1072 (or (eq? (car kw) #t)
1073 (eq? (car kw) 'else)
1074 (let* ((opt-desc kw)
1075 (help (cadr opt-desc))
1076 (opts (car opt-desc))
1077 (opts-proper (if (string? (car opts)) (cdr opts) opts))
1078 (arg-name (if (string? (car opts))
1079 (string-append "<" (car opts) ">")
1080 ""))
1081 (left-part (string-append
1082 (with-output-to-string
1083 (lambda ()
1084 (map (lambda (x) (display (keyword-symbol x)) (display " "))
1085 opts-proper)))
1086 arg-name))
1087 (middle-part (if (and (< (length left-part) 30)
1088 (< (length help) 40))
1089 (make-string (- 30 (length left-part)) #\ )
1090 "\n\t")))
1091 (display left-part)
1092 (display middle-part)
1093 (display help)
1094 (newline))))
1095 kw-desc))
1096
1097
1098
1099 (define (transform-usage-lambda cases)
1100 (let* ((raw-usage (delq! 'else (map car cases)))
1101 (usage-sans-specials (map (lambda (x)
1102 (or (and (not (list? x)) x)
1103 (and (symbol? (car x)) #t)
1104 (and (boolean? (car x)) #t)
1105 x))
1106 raw-usage))
1107 (usage-desc (delq! #t usage-sans-specials))
1108 (kw-desc (map car usage-desc))
1109 (kw-opts (apply append (map (lambda (x) (and (not (string? (car x))) x)) kw-desc)))
1110 (kw-args (apply append (map (lambda (x) (and (string? (car x)) (cdr x))) kw-desc)))
1111 (transmogrified-cases (map (lambda (case)
1112 (cons (let ((opts (car case)))
1113 (if (or (boolean? opts) (eq? 'else opts))
1114 opts
1115 (cond
1116 ((symbol? (car opts)) opts)
1117 ((boolean? (car opts)) opts)
1118 ((string? (caar opts)) (cdar opts))
1119 (else (car opts)))))
1120 (cdr case)))
1121 cases)))
1122 `(let ((%display-usage (lambda () (display-usage-report ',usage-desc))))
1123 (lambda (%argv)
1124 (let %next-arg ((%argv %argv))
1125 (get-option %argv
1126 ',kw-opts
1127 ',kw-args
1128 (lambda (%opt %arg %new-argv)
1129 (case %opt
1130 ,@ transmogrified-cases))))))))
1131
1132
1133 \f
1134
1135 ;;; {Low Level Modules}
1136 ;;;
1137 ;;; These are the low level data structures for modules.
1138 ;;;
1139 ;;; !!! warning: The interface to lazy binder procedures is going
1140 ;;; to be changed in an incompatible way to permit all the basic
1141 ;;; module ops to be virtualized.
1142 ;;;
1143 ;;; (make-module size use-list lazy-binding-proc) => module
1144 ;;; module-{obarray,uses,binder}[|-set!]
1145 ;;; (module? obj) => [#t|#f]
1146 ;;; (module-locally-bound? module symbol) => [#t|#f]
1147 ;;; (module-bound? module symbol) => [#t|#f]
1148 ;;; (module-symbol-locally-interned? module symbol) => [#t|#f]
1149 ;;; (module-symbol-interned? module symbol) => [#t|#f]
1150 ;;; (module-local-variable module symbol) => [#<variable ...> | #f]
1151 ;;; (module-variable module symbol) => [#<variable ...> | #f]
1152 ;;; (module-symbol-binding module symbol opt-value)
1153 ;;; => [ <obj> | opt-value | an error occurs ]
1154 ;;; (module-make-local-var! module symbol) => #<variable...>
1155 ;;; (module-add! module symbol var) => unspecified
1156 ;;; (module-remove! module symbol) => unspecified
1157 ;;; (module-for-each proc module) => unspecified
1158 ;;; (make-scm-module) => module ; a lazy copy of the symhash module
1159 ;;; (set-current-module module) => unspecified
1160 ;;; (current-module) => #<module...>
1161 ;;;
1162 ;;;
1163
1164 \f
1165 ;;; {Printing Modules}
1166 ;; This is how modules are printed. You can re-define it.
1167 ;; (Redefining is actually more complicated than simply redefining
1168 ;; %print-module because that would only change the binding and not
1169 ;; the value stored in the vtable that determines how record are
1170 ;; printed. Sigh.)
1171
1172 (define (%print-module mod port) ; unused args: depth length style table)
1173 (display "#<" port)
1174 (display (or (module-kind mod) "module") port)
1175 (let ((name (module-name mod)))
1176 (if name
1177 (begin
1178 (display " " port)
1179 (display name port))))
1180 (display " " port)
1181 (display (number->string (object-address mod) 16) port)
1182 (display ">" port))
1183
1184 ;; module-type
1185 ;;
1186 ;; A module is characterized by an obarray in which local symbols
1187 ;; are interned, a list of modules, "uses", from which non-local
1188 ;; bindings can be inherited, and an optional lazy-binder which
1189 ;; is a (CLOSURE module symbol) which, as a last resort, can provide
1190 ;; bindings that would otherwise not be found locally in the module.
1191 ;;
1192 (define module-type
1193 (make-record-type 'module '(obarray uses binder eval-closure name kind)
1194 %print-module))
1195
1196 ;; make-module &opt size uses binder
1197 ;;
1198 ;; Create a new module, perhaps with a particular size of obarray,
1199 ;; initial uses list, or binding procedure.
1200 ;;
1201 (define make-module
1202 (lambda args
1203
1204 (define (parse-arg index default)
1205 (if (> (length args) index)
1206 (list-ref args index)
1207 default))
1208
1209 (if (> (length args) 3)
1210 (error "Too many args to make-module." args))
1211
1212 (let ((size (parse-arg 0 1021))
1213 (uses (parse-arg 1 '()))
1214 (binder (parse-arg 2 #f)))
1215
1216 (if (not (integer? size))
1217 (error "Illegal size to make-module." size))
1218 (if (not (and (list? uses)
1219 (and-map module? uses)))
1220 (error "Incorrect use list." uses))
1221 (if (and binder (not (procedure? binder)))
1222 (error
1223 "Lazy-binder expected to be a procedure or #f." binder))
1224
1225 (let ((module (module-constructor (make-vector size '())
1226 uses binder #f #f #f)))
1227
1228 ;; We can't pass this as an argument to module-constructor,
1229 ;; because we need it to close over a pointer to the module
1230 ;; itself.
1231 (set-module-eval-closure! module
1232 (lambda (symbol define?)
1233 (if define?
1234 (module-make-local-var! module symbol)
1235 (module-variable module symbol))))
1236
1237 module))))
1238
1239 (define module-constructor (record-constructor module-type))
1240 (define module-obarray (record-accessor module-type 'obarray))
1241 (define set-module-obarray! (record-modifier module-type 'obarray))
1242 (define module-uses (record-accessor module-type 'uses))
1243 (define set-module-uses! (record-modifier module-type 'uses))
1244 (define module-binder (record-accessor module-type 'binder))
1245 (define set-module-binder! (record-modifier module-type 'binder))
1246 (define module-eval-closure (record-accessor module-type 'eval-closure))
1247 (define set-module-eval-closure! (record-modifier module-type 'eval-closure))
1248 (define module-name (record-accessor module-type 'name))
1249 (define set-module-name! (record-modifier module-type 'name))
1250 (define module-kind (record-accessor module-type 'kind))
1251 (define set-module-kind! (record-modifier module-type 'kind))
1252 (define module? (record-predicate module-type))
1253
1254
1255 (define (eval-in-module exp module)
1256 (eval2 exp (module-eval-closure module)))
1257
1258 \f
1259 ;;; {Module Searching in General}
1260 ;;;
1261 ;;; We sometimes want to look for properties of a symbol
1262 ;;; just within the obarray of one module. If the property
1263 ;;; holds, then it is said to hold ``locally'' as in, ``The symbol
1264 ;;; DISPLAY is locally rebound in the module `safe-guile'.''
1265 ;;;
1266 ;;;
1267 ;;; Other times, we want to test for a symbol property in the obarray
1268 ;;; of M and, if it is not found there, try each of the modules in the
1269 ;;; uses list of M. This is the normal way of testing for some
1270 ;;; property, so we state these properties without qualification as
1271 ;;; in: ``The symbol 'fnord is interned in module M because it is
1272 ;;; interned locally in module M2 which is a member of the uses list
1273 ;;; of M.''
1274 ;;;
1275
1276 ;; module-search fn m
1277 ;;
1278 ;; return the first non-#f result of FN applied to M and then to
1279 ;; the modules in the uses of m, and so on recursively. If all applications
1280 ;; return #f, then so does this function.
1281 ;;
1282 (define (module-search fn m v)
1283 (define (loop pos)
1284 (and (pair? pos)
1285 (or (module-search fn (car pos) v)
1286 (loop (cdr pos)))))
1287 (or (fn m v)
1288 (loop (module-uses m))))
1289
1290
1291 ;;; {Is a symbol bound in a module?}
1292 ;;;
1293 ;;; Symbol S in Module M is bound if S is interned in M and if the binding
1294 ;;; of S in M has been set to some well-defined value.
1295 ;;;
1296
1297 ;; module-locally-bound? module symbol
1298 ;;
1299 ;; Is a symbol bound (interned and defined) locally in a given module?
1300 ;;
1301 (define (module-locally-bound? m v)
1302 (let ((var (module-local-variable m v)))
1303 (and var
1304 (variable-bound? var))))
1305
1306 ;; module-bound? module symbol
1307 ;;
1308 ;; Is a symbol bound (interned and defined) anywhere in a given module
1309 ;; or its uses?
1310 ;;
1311 (define (module-bound? m v)
1312 (module-search module-locally-bound? m v))
1313
1314 ;;; {Is a symbol interned in a module?}
1315 ;;;
1316 ;;; Symbol S in Module M is interned if S occurs in
1317 ;;; of S in M has been set to some well-defined value.
1318 ;;;
1319 ;;; It is possible to intern a symbol in a module without providing
1320 ;;; an initial binding for the corresponding variable. This is done
1321 ;;; with:
1322 ;;; (module-add! module symbol (make-undefined-variable))
1323 ;;;
1324 ;;; In that case, the symbol is interned in the module, but not
1325 ;;; bound there. The unbound symbol shadows any binding for that
1326 ;;; symbol that might otherwise be inherited from a member of the uses list.
1327 ;;;
1328
1329 (define (module-obarray-get-handle ob key)
1330 ((if (symbol? key) hashq-get-handle hash-get-handle) ob key))
1331
1332 (define (module-obarray-ref ob key)
1333 ((if (symbol? key) hashq-ref hash-ref) ob key))
1334
1335 (define (module-obarray-set! ob key val)
1336 ((if (symbol? key) hashq-set! hash-set!) ob key val))
1337
1338 (define (module-obarray-remove! ob key)
1339 ((if (symbol? key) hashq-remove! hash-remove!) ob key))
1340
1341 ;; module-symbol-locally-interned? module symbol
1342 ;;
1343 ;; is a symbol interned (not neccessarily defined) locally in a given module
1344 ;; or its uses? Interned symbols shadow inherited bindings even if
1345 ;; they are not themselves bound to a defined value.
1346 ;;
1347 (define (module-symbol-locally-interned? m v)
1348 (not (not (module-obarray-get-handle (module-obarray m) v))))
1349
1350 ;; module-symbol-interned? module symbol
1351 ;;
1352 ;; is a symbol interned (not neccessarily defined) anywhere in a given module
1353 ;; or its uses? Interned symbols shadow inherited bindings even if
1354 ;; they are not themselves bound to a defined value.
1355 ;;
1356 (define (module-symbol-interned? m v)
1357 (module-search module-symbol-locally-interned? m v))
1358
1359
1360 ;;; {Mapping modules x symbols --> variables}
1361 ;;;
1362
1363 ;; module-local-variable module symbol
1364 ;; return the local variable associated with a MODULE and SYMBOL.
1365 ;;
1366 ;;; This function is very important. It is the only function that can
1367 ;;; return a variable from a module other than the mutators that store
1368 ;;; new variables in modules. Therefore, this function is the location
1369 ;;; of the "lazy binder" hack.
1370 ;;;
1371 ;;; If symbol is defined in MODULE, and if the definition binds symbol
1372 ;;; to a variable, return that variable object.
1373 ;;;
1374 ;;; If the symbols is not found at first, but the module has a lazy binder,
1375 ;;; then try the binder.
1376 ;;;
1377 ;;; If the symbol is not found at all, return #f.
1378 ;;;
1379 (define (module-local-variable m v)
1380 ; (caddr
1381 ; (list m v
1382 (let ((b (module-obarray-ref (module-obarray m) v)))
1383 (or (and (variable? b) b)
1384 (and (module-binder m)
1385 ((module-binder m) m v #f)))))
1386 ;))
1387
1388 ;; module-variable module symbol
1389 ;;
1390 ;; like module-local-variable, except search the uses in the
1391 ;; case V is not found in M.
1392 ;;
1393 (define (module-variable m v)
1394 (module-search module-local-variable m v))
1395
1396
1397 ;;; {Mapping modules x symbols --> bindings}
1398 ;;;
1399 ;;; These are similar to the mapping to variables, except that the
1400 ;;; variable is dereferenced.
1401 ;;;
1402
1403 ;; module-symbol-binding module symbol opt-value
1404 ;;
1405 ;; return the binding of a variable specified by name within
1406 ;; a given module, signalling an error if the variable is unbound.
1407 ;; If the OPT-VALUE is passed, then instead of signalling an error,
1408 ;; return OPT-VALUE.
1409 ;;
1410 (define (module-symbol-local-binding m v . opt-val)
1411 (let ((var (module-local-variable m v)))
1412 (if var
1413 (variable-ref var)
1414 (if (not (null? opt-val))
1415 (car opt-val)
1416 (error "Locally unbound variable." v)))))
1417
1418 ;; module-symbol-binding module symbol opt-value
1419 ;;
1420 ;; return the binding of a variable specified by name within
1421 ;; a given module, signalling an error if the variable is unbound.
1422 ;; If the OPT-VALUE is passed, then instead of signalling an error,
1423 ;; return OPT-VALUE.
1424 ;;
1425 (define (module-symbol-binding m v . opt-val)
1426 (let ((var (module-variable m v)))
1427 (if var
1428 (variable-ref var)
1429 (if (not (null? opt-val))
1430 (car opt-val)
1431 (error "Unbound variable." v)))))
1432
1433
1434 \f
1435 ;;; {Adding Variables to Modules}
1436 ;;;
1437 ;;;
1438
1439
1440 ;; module-make-local-var! module symbol
1441 ;;
1442 ;; ensure a variable for V in the local namespace of M.
1443 ;; If no variable was already there, then create a new and uninitialzied
1444 ;; variable.
1445 ;;
1446 (define (module-make-local-var! m v)
1447 (or (let ((b (module-obarray-ref (module-obarray m) v)))
1448 (and (variable? b) b))
1449 (and (module-binder m)
1450 ((module-binder m) m v #t))
1451 (begin
1452 (let ((answer (make-undefined-variable v)))
1453 (module-obarray-set! (module-obarray m) v answer)
1454 answer))))
1455
1456 ;; module-add! module symbol var
1457 ;;
1458 ;; ensure a particular variable for V in the local namespace of M.
1459 ;;
1460 (define (module-add! m v var)
1461 (if (not (variable? var))
1462 (error "Bad variable to module-add!" var))
1463 (module-obarray-set! (module-obarray m) v var))
1464
1465 ;; module-remove!
1466 ;;
1467 ;; make sure that a symbol is undefined in the local namespace of M.
1468 ;;
1469 (define (module-remove! m v)
1470 (module-obarray-remove! (module-obarray m) v))
1471
1472 (define (module-clear! m)
1473 (vector-fill! (module-obarray m) '()))
1474
1475 ;; MODULE-FOR-EACH -- exported
1476 ;;
1477 ;; Call PROC on each symbol in MODULE, with arguments of (SYMBOL VARIABLE).
1478 ;;
1479 (define (module-for-each proc module)
1480 (let ((obarray (module-obarray module)))
1481 (do ((index 0 (+ index 1))
1482 (end (vector-length obarray)))
1483 ((= index end))
1484 (for-each
1485 (lambda (bucket)
1486 (proc (car bucket) (cdr bucket)))
1487 (vector-ref obarray index)))))
1488
1489
1490 (define (module-map proc module)
1491 (let* ((obarray (module-obarray module))
1492 (end (vector-length obarray)))
1493
1494 (let loop ((i 0)
1495 (answer '()))
1496 (if (= i end)
1497 answer
1498 (loop (+ 1 i)
1499 (append!
1500 (map (lambda (bucket)
1501 (proc (car bucket) (cdr bucket)))
1502 (vector-ref obarray i))
1503 answer))))))
1504 \f
1505
1506 ;;; {Low Level Bootstrapping}
1507 ;;;
1508
1509 ;; make-root-module
1510
1511 ;; A root module uses the symhash table (the system's privileged
1512 ;; obarray). Being inside a root module is like using SCM without
1513 ;; any module system.
1514 ;;
1515
1516
1517 (define (root-module-closure m s define?)
1518 (let ((bi (and (symbol-interned? #f s)
1519 (builtin-variable s))))
1520 (and bi
1521 (or define? (variable-bound? bi))
1522 (begin
1523 (module-add! m s bi)
1524 bi))))
1525
1526 (define (make-root-module)
1527 (make-module 1019 '() root-module-closure))
1528
1529
1530 ;; make-scm-module
1531
1532 ;; An scm module is a module into which the lazy binder copies
1533 ;; variable bindings from the system symhash table. The mapping is
1534 ;; one way only; newly introduced bindings in an scm module are not
1535 ;; copied back into the system symhash table (and can be used to override
1536 ;; bindings from the symhash table).
1537 ;;
1538
1539 (define (make-scm-module)
1540 (make-module 1019 '()
1541 (lambda (m s define?)
1542 (let ((bi (and (symbol-interned? #f s)
1543 (builtin-variable s))))
1544 (and bi
1545 (variable-bound? bi)
1546 (begin
1547 (module-add! m s bi)
1548 bi))))))
1549
1550
1551
1552
1553 ;; the-module
1554 ;;
1555 (define the-module #f)
1556
1557 ;; set-current-module module
1558 ;;
1559 ;; set the current module as viewed by the normalizer.
1560 ;;
1561 (define (set-current-module m)
1562 (set! the-module m)
1563 (if m
1564 (set! *top-level-lookup-closure* (module-eval-closure the-module))
1565 (set! *top-level-lookup-closure* #f)))
1566
1567
1568 ;; current-module
1569 ;;
1570 ;; return the current module as viewed by the normalizer.
1571 ;;
1572 (define (current-module) the-module)
1573 \f
1574 ;;; {Module-based Loading}
1575 ;;;
1576
1577 (define (save-module-excursion thunk)
1578 (let ((inner-module (current-module))
1579 (outer-module #f))
1580 (dynamic-wind (lambda ()
1581 (set! outer-module (current-module))
1582 (set-current-module inner-module)
1583 (set! inner-module #f))
1584 thunk
1585 (lambda ()
1586 (set! inner-module (current-module))
1587 (set-current-module outer-module)
1588 (set! outer-module #f)))))
1589
1590 (define basic-load load)
1591
1592 (define (load-module . args)
1593 (save-module-excursion (lambda () (apply basic-load args))))
1594
1595
1596 \f
1597 ;;; {MODULE-REF -- exported}
1598 ;;
1599 ;; Returns the value of a variable called NAME in MODULE or any of its
1600 ;; used modules. If there is no such variable, then if the optional third
1601 ;; argument DEFAULT is present, it is returned; otherwise an error is signaled.
1602 ;;
1603 (define (module-ref module name . rest)
1604 (let ((variable (module-variable module name)))
1605 (if (and variable (variable-bound? variable))
1606 (variable-ref variable)
1607 (if (null? rest)
1608 (error "No variable named" name 'in module)
1609 (car rest) ; default value
1610 ))))
1611
1612 ;; MODULE-SET! -- exported
1613 ;;
1614 ;; Sets the variable called NAME in MODULE (or in a module that MODULE uses)
1615 ;; to VALUE; if there is no such variable, an error is signaled.
1616 ;;
1617 (define (module-set! module name value)
1618 (let ((variable (module-variable module name)))
1619 (if variable
1620 (variable-set! variable value)
1621 (error "No variable named" name 'in module))))
1622
1623 ;; MODULE-DEFINE! -- exported
1624 ;;
1625 ;; Sets the variable called NAME in MODULE to VALUE; if there is no such
1626 ;; variable, it is added first.
1627 ;;
1628 (define (module-define! module name value)
1629 (let ((variable (module-local-variable module name)))
1630 (if variable
1631 (variable-set! variable value)
1632 (module-add! module name (make-variable value name)))))
1633
1634 ;; MODULE-DEFINED? -- exported
1635 ;;
1636 ;; Return #t iff NAME is defined in MODULE (or in a module that MODULE
1637 ;; uses)
1638 ;;
1639 (define (module-defined? module name)
1640 (let ((variable (module-variable module name)))
1641 (and variable (variable-bound? variable))))
1642
1643 ;; MODULE-USE! module interface
1644 ;;
1645 ;; Add INTERFACE to the list of interfaces used by MODULE.
1646 ;;
1647 (define (module-use! module interface)
1648 (set-module-uses! module
1649 (cons interface (delq! interface (module-uses module)))))
1650
1651 \f
1652 ;;; {Recursive Namespaces}
1653 ;;;
1654 ;;;
1655 ;;; A hierarchical namespace emerges if we consider some module to be
1656 ;;; root, and variables bound to modules as nested namespaces.
1657 ;;;
1658 ;;; The routines in this file manage variable names in hierarchical namespace.
1659 ;;; Each variable name is a list of elements, looked up in successively nested
1660 ;;; modules.
1661 ;;;
1662 ;;; (nested-ref some-root-module '(foo bar baz))
1663 ;;; => <value of a variable named baz in the module bound to bar in
1664 ;;; the module bound to foo in some-root-module>
1665 ;;;
1666 ;;;
1667 ;;; There are:
1668 ;;;
1669 ;;; ;; a-root is a module
1670 ;;; ;; name is a list of symbols
1671 ;;;
1672 ;;; nested-ref a-root name
1673 ;;; nested-set! a-root name val
1674 ;;; nested-define! a-root name val
1675 ;;; nested-remove! a-root name
1676 ;;;
1677 ;;;
1678 ;;; (current-module) is a natural choice for a-root so for convenience there are
1679 ;;; also:
1680 ;;;
1681 ;;; local-ref name == nested-ref (current-module) name
1682 ;;; local-set! name val == nested-set! (current-module) name val
1683 ;;; local-define! name val == nested-define! (current-module) name val
1684 ;;; local-remove! name == nested-remove! (current-module) name
1685 ;;;
1686
1687
1688 (define (nested-ref root names)
1689 (let loop ((cur root)
1690 (elts names))
1691 (cond
1692 ((null? elts) cur)
1693 ((not (module? cur)) #f)
1694 (else (loop (module-ref cur (car elts) #f) (cdr elts))))))
1695
1696 (define (nested-set! root names val)
1697 (let loop ((cur root)
1698 (elts names))
1699 (if (null? (cdr elts))
1700 (module-set! cur (car elts) val)
1701 (loop (module-ref cur (car elts)) (cdr elts)))))
1702
1703 (define (nested-define! root names val)
1704 (let loop ((cur root)
1705 (elts names))
1706 (if (null? (cdr elts))
1707 (module-define! cur (car elts) val)
1708 (loop (module-ref cur (car elts)) (cdr elts)))))
1709
1710 (define (nested-remove! root names)
1711 (let loop ((cur root)
1712 (elts names))
1713 (if (null? (cdr elts))
1714 (module-remove! cur (car elts))
1715 (loop (module-ref cur (car elts)) (cdr elts)))))
1716
1717 (define (local-ref names) (nested-ref (current-module) names))
1718 (define (local-set! names val) (nested-set! (current-module) names val))
1719 (define (local-define names val) (nested-define! (current-module) names val))
1720 (define (local-remove names) (nested-remove! (current-module) names))
1721
1722
1723 \f
1724 ;;; {#/app}
1725 ;;;
1726 ;;; The root of conventionally named objects not directly in the top level.
1727 ;;;
1728 ;;; #/app/modules
1729 ;;; #/app/modules/guile
1730 ;;;
1731 ;;; The directory of all modules and the standard root module.
1732 ;;;
1733
1734 (define (module-public-interface m) (module-ref m '%module-public-interface #f))
1735 (define (set-module-public-interface! m i) (module-define! m '%module-public-interface i))
1736 (define the-root-module (make-root-module))
1737 (define the-scm-module (make-scm-module))
1738 (set-module-public-interface! the-root-module the-scm-module)
1739 (set-module-name! the-root-module 'the-root-module)
1740 (set-module-name! the-scm-module 'the-scm-module)
1741
1742 (set-current-module the-root-module)
1743
1744 (define app (make-module 31))
1745 (local-define '(app modules) (make-module 31))
1746 (local-define '(app modules guile) the-root-module)
1747
1748 ;; (define-special-value '(app modules new-ws) (lambda () (make-scm-module)))
1749
1750 (define (resolve-module name . maybe-autoload)
1751 (let ((full-name (append '(app modules) name)))
1752 (let ((already (local-ref full-name)))
1753 (or already
1754 (begin
1755 (if (or (null? maybe-autoload) (car maybe-autoload))
1756 (or (try-module-autoload name)
1757 (try-module-dynamic-link name)))
1758 (make-modules-in (current-module) full-name))))))
1759
1760 (define (beautify-user-module! module)
1761 (if (not (module-public-interface module))
1762 (let ((interface (make-module 31)))
1763 (set-module-name! interface (module-name module))
1764 (set-module-kind! interface 'interface)
1765 (set-module-public-interface! module interface)))
1766 (if (and (not (memq the-scm-module (module-uses module)))
1767 (not (eq? module the-root-module)))
1768 (set-module-uses! module (append (module-uses module) (list the-scm-module)))))
1769
1770 (define (make-modules-in module name)
1771 (if (null? name)
1772 module
1773 (cond
1774 ((module-ref module (car name) #f) => (lambda (m) (make-modules-in m (cdr name))))
1775 (else (let ((m (make-module 31)))
1776 (set-module-kind! m 'directory)
1777 (set-module-name! m (car name))
1778 (module-define! module (car name) m)
1779 (make-modules-in m (cdr name)))))))
1780
1781 (define (resolve-interface name)
1782 (let ((module (resolve-module name)))
1783 (and module (module-public-interface module))))
1784
1785
1786 (define %autoloader-developer-mode #t)
1787
1788 (define (process-define-module args)
1789 (let* ((module-id (car args))
1790 (module (resolve-module module-id #f))
1791 (kws (cdr args)))
1792 (beautify-user-module! module)
1793 (let loop ((kws kws)
1794 (reversed-interfaces '()))
1795 (if (null? kws)
1796 (for-each (lambda (interface)
1797 (module-use! module interface))
1798 reversed-interfaces)
1799 (case (cond ((keyword? (car kws))
1800 (keyword->symbol (car kws)))
1801 ((and (symbol? (car kws))
1802 (eq? (string-ref (car kws) 0) #\:))
1803 (string->symbol (substring (car kws) 1)))
1804 (else #f))
1805 ((use-module)
1806 (if (not (pair? (cdr kws)))
1807 (error "unrecognized defmodule argument" kws))
1808 (let* ((used-name (cadr kws))
1809 (used-module (resolve-module used-name)))
1810 (if (not (module-ref used-module '%module-public-interface #f))
1811 (begin
1812 ((if %autoloader-developer-mode warn error)
1813 "no code for module" (module-name used-module))
1814 (beautify-user-module! used-module)))
1815 (let ((interface (module-public-interface used-module)))
1816 (if (not interface)
1817 (error "missing interface for use-module" used-module))
1818 (loop (cddr kws) (cons interface reversed-interfaces)))))
1819 (else
1820 (error "unrecognized defmodule argument" kws)))))
1821 module))
1822 \f
1823 ;;; {Autoloading modules}
1824
1825 (define autoloads-in-progress '())
1826
1827 (define (try-module-autoload module-name)
1828
1829 (define (sfx name) (string-append name (scheme-file-suffix)))
1830 (let* ((reverse-name (reverse module-name))
1831 (name (car reverse-name))
1832 (dir-hint-module-name (reverse (cdr reverse-name)))
1833 (dir-hint (apply symbol-append (map (lambda (elt) (symbol-append elt "/")) dir-hint-module-name))))
1834 (resolve-module dir-hint-module-name #f)
1835 (and (not (autoload-done-or-in-progress? dir-hint name))
1836 (let ((didit #f))
1837 (dynamic-wind
1838 (lambda () (autoload-in-progress! dir-hint name))
1839 (lambda ()
1840 (let loop ((dirs %load-path))
1841 (and (not (null? dirs))
1842 (or
1843 (let ((d (car dirs))
1844 (trys (list
1845 dir-hint
1846 (sfx dir-hint)
1847 (in-vicinity dir-hint name)
1848 (in-vicinity dir-hint (sfx name)))))
1849 (and (or-map (lambda (f)
1850 (let ((full (in-vicinity d f)))
1851 full
1852 (and (file-exists? full)
1853 (not (file-is-directory? full))
1854 (begin
1855 (save-module-excursion
1856 (lambda ()
1857 (load (string-append
1858 d "/" f))))
1859 #t))))
1860 trys)
1861 (begin
1862 (set! didit #t)
1863 #t)))
1864 (loop (cdr dirs))))))
1865 (lambda () (set-autoloaded! dir-hint name didit)))
1866 didit))))
1867
1868 ;;; Dynamic linking of modules
1869
1870 ;; Initializing a module that is written in C is a two step process.
1871 ;; First the module's `module init' function is called. This function
1872 ;; is expected to call `scm_register_module_xxx' to register the `real
1873 ;; init' function. Later, when the module is referenced for the first
1874 ;; time, this real init function is called in the right context. See
1875 ;; gtcltk-lib/gtcltk-module.c for an example.
1876 ;;
1877 ;; The code for the module can be in a regular shared library (so that
1878 ;; the `module init' function will be called when libguile is
1879 ;; initialized). Or it can be dynamically linked.
1880 ;;
1881 ;; You can safely call `scm_register_module_xxx' before libguile
1882 ;; itself is initialized. You could call it from an C++ constructor
1883 ;; of a static object, for example.
1884 ;;
1885 ;; To make your Guile extension into a dynamic linkable module, follow
1886 ;; these easy steps:
1887 ;;
1888 ;; - Find a name for your module, like #/ice-9/gtcltk
1889 ;; - Write a function with a name like
1890 ;;
1891 ;; scm_init_ice_9_gtcltk_module
1892 ;;
1893 ;; This is your `module init' function. It should call
1894 ;;
1895 ;; scm_register_module_xxx ("ice-9 gtcltk", scm_init_gtcltk);
1896 ;;
1897 ;; "ice-9 gtcltk" is the C version of the module name. Slashes are
1898 ;; replaced by spaces, the rest is untouched. `scm_init_gtcltk' is
1899 ;; the real init function that executes the usual initializations
1900 ;; like making new smobs, etc.
1901 ;;
1902 ;; - Make a shared library with your code and a name like
1903 ;;
1904 ;; ice-9/libgtcltk.so
1905 ;;
1906 ;; and put it somewhere in %load-path.
1907 ;;
1908 ;; - Then you can simply write `:use-module #/ice-9/gtcltk' and it
1909 ;; will be linked automatically.
1910 ;;
1911 ;; This is all very experimental.
1912
1913 (define (split-c-module-name str)
1914 (let loop ((rev '())
1915 (start 0)
1916 (pos 0)
1917 (end (string-length str)))
1918 (cond
1919 ((= pos end)
1920 (reverse (cons (string->symbol (substring str start pos)) rev)))
1921 ((eq? (string-ref str pos) #\space)
1922 (loop (cons (string->symbol (substring str start pos)) rev)
1923 (+ pos 1)
1924 (+ pos 1)
1925 end))
1926 (else
1927 (loop rev start (+ pos 1) end)))))
1928
1929 (define (convert-c-registered-modules dynobj)
1930 (let ((res (map (lambda (c)
1931 (list (split-c-module-name (car c)) (cdr c) dynobj))
1932 (c-registered-modules))))
1933 (c-clear-registered-modules)
1934 res))
1935
1936 (define registered-modules (convert-c-registered-modules #f))
1937
1938 (define (init-dynamic-module modname)
1939 (or-map (lambda (modinfo)
1940 (if (equal? (car modinfo) modname)
1941 (let ((mod (resolve-module modname #f)))
1942 (save-module-excursion
1943 (lambda ()
1944 (set-current-module mod)
1945 (dynamic-call (cadr modinfo) (caddr modinfo))
1946 (set-module-public-interface! mod mod)))
1947 (set! registered-modules (delq! modinfo registered-modules))
1948 #t)
1949 #f))
1950 registered-modules))
1951
1952 (define (dynamic-maybe-call name dynobj)
1953 (catch #t ; could use false-if-exception here
1954 (lambda ()
1955 (dynamic-call name dynobj))
1956 (lambda args
1957 #f)))
1958
1959 (define (dynamic-maybe-link filename)
1960 (catch #t ; could use false-if-exception here
1961 (lambda ()
1962 (dynamic-link filename))
1963 (lambda args
1964 #f)))
1965
1966 (define (find-and-link-dynamic-module module-name)
1967 (define (make-init-name mod-name)
1968 (string-append 'scm_init
1969 (list->string (map (lambda (c)
1970 (if (or (char-alphabetic? c)
1971 (char-numeric? c))
1972 c
1973 #\_))
1974 (string->list mod-name)))
1975 '_module))
1976 (let ((libname
1977 (let loop ((dirs "")
1978 (syms module-name))
1979 (cond
1980 ((null? (cdr syms))
1981 (string-append dirs "lib" (car syms) ".so"))
1982 (else
1983 (loop (string-append dirs (car syms) "/") (cdr syms))))))
1984 (init (make-init-name (apply string-append
1985 (map (lambda (s)
1986 (string-append "_" s))
1987 module-name)))))
1988 ;; (pk 'libname libname 'init init)
1989 (or-map
1990 (lambda (dir)
1991 (let ((full (in-vicinity dir libname)))
1992 ;; (pk 'trying full)
1993 (if (file-exists? full)
1994 (begin
1995 (link-dynamic-module full init)
1996 #t)
1997 #f)))
1998 %load-path)))
1999
2000 (define (link-dynamic-module filename initname)
2001 (let ((dynobj (dynamic-link filename)))
2002 (dynamic-call initname dynobj)
2003 (set! registered-modules
2004 (append! (convert-c-registered-modules dynobj)
2005 registered-modules))))
2006
2007 (define (try-module-dynamic-link module-name)
2008 (or (init-dynamic-module module-name)
2009 (and (find-and-link-dynamic-module module-name)
2010 (init-dynamic-module module-name))))
2011
2012
2013
2014 (define autoloads-done '((guile . guile)))
2015
2016 (define (autoload-done-or-in-progress? p m)
2017 (let ((n (cons p m)))
2018 (->bool (or (member n autoloads-done)
2019 (member n autoloads-in-progress)))))
2020
2021 (define (autoload-done! p m)
2022 (let ((n (cons p m)))
2023 (set! autoloads-in-progress
2024 (delete! n autoloads-in-progress))
2025 (or (member n autoloads-done)
2026 (set! autoloads-done (cons n autoloads-done)))))
2027
2028 (define (autoload-in-progress! p m)
2029 (let ((n (cons p m)))
2030 (set! autoloads-done
2031 (delete! n autoloads-done))
2032 (set! autoloads-in-progress (cons n autoloads-in-progress))))
2033
2034 (define (set-autoloaded! p m done?)
2035 (if done?
2036 (autoload-done! p m)
2037 (let ((n (cons p m)))
2038 (set! autoloads-done (delete! n autoloads-done))
2039 (set! autoloads-in-progress (delete! n autoloads-in-progress)))))
2040
2041
2042
2043
2044 \f
2045 ;;; {Macros}
2046 ;;;
2047
2048 (define macro-table (make-weak-key-hash-table 523))
2049 (define xformer-table (make-weak-key-hash-table 523))
2050
2051 (define (defmacro? m) (hashq-ref macro-table m))
2052 (define (assert-defmacro?! m) (hashq-set! macro-table m #t))
2053 (define (defmacro-transformer m) (hashq-ref xformer-table m))
2054 (define (set-defmacro-transformer! m t) (hashq-set! xformer-table m t))
2055
2056 (define defmacro:transformer
2057 (lambda (f)
2058 (let* ((xform (lambda (exp env)
2059 (copy-tree (apply f (cdr exp)))))
2060 (a (procedure->memoizing-macro xform)))
2061 (assert-defmacro?! a)
2062 (set-defmacro-transformer! a f)
2063 a)))
2064
2065
2066 (define defmacro
2067 (let ((defmacro-transformer
2068 (lambda (name parms . body)
2069 (let ((transformer `(lambda ,parms ,@body)))
2070 `(define ,name
2071 (,(lambda (transformer)
2072 (defmacro:transformer transformer))
2073 ,transformer))))))
2074 (defmacro:transformer defmacro-transformer)))
2075
2076 (define defmacro:syntax-transformer
2077 (lambda (f)
2078 (procedure->syntax
2079 (lambda (exp env)
2080 (copy-tree (apply f (cdr exp)))))))
2081
2082
2083 ;; XXX - should the definition of the car really be looked up in the
2084 ;; current module?
2085
2086 (define (macroexpand-1 e)
2087 (cond
2088 ((pair? e) (let* ((a (car e))
2089 (val (and (symbol? a) (local-ref (list a)))))
2090 (if (defmacro? val)
2091 (apply (defmacro-transformer val) (cdr e))
2092 e)))
2093 (#t e)))
2094
2095 (define (macroexpand e)
2096 (cond
2097 ((pair? e) (let* ((a (car e))
2098 (val (and (symbol? a) (local-ref (list a)))))
2099 (if (defmacro? val)
2100 (macroexpand (apply (defmacro-transformer val) (cdr e)))
2101 e)))
2102 (#t e)))
2103
2104 (define gentemp
2105 (let ((*gensym-counter* -1))
2106 (lambda ()
2107 (set! *gensym-counter* (+ *gensym-counter* 1))
2108 (string->symbol
2109 (string-append "scm:G" (number->string *gensym-counter*))))))
2110
2111
2112 \f
2113
2114 ;;; {Running Repls}
2115 ;;;
2116
2117 (define (repl read evaler print)
2118 (let loop ((source (read (current-input-port))))
2119 (print (evaler source))
2120 (loop (read (current-input-port)))))
2121
2122 ;; A provisional repl that acts like the SCM repl:
2123 ;;
2124 (define scm-repl-silent #f)
2125 (define (assert-repl-silence v) (set! scm-repl-silent v))
2126
2127 (define *unspecified* (if #f #f))
2128 (define (unspecified? v) (eq? v *unspecified*))
2129
2130 (define scm-repl-print-unspecified #f)
2131 (define (assert-repl-print-unspecified v) (set! scm-repl-print-unspecified v))
2132
2133 (define scm-repl-verbose #f)
2134 (define (assert-repl-verbosity v) (set! scm-repl-verbose v))
2135
2136 (define scm-repl-prompt "guile> ")
2137
2138 (define (set-repl-prompt! v) (set! scm-repl-prompt v))
2139
2140 (define (default-lazy-handler key . args)
2141 (save-stack lazy-handler-dispatch)
2142 (apply throw key args))
2143
2144 (define apply-frame-handler default-lazy-handler)
2145 (define exit-frame-handler default-lazy-handler)
2146
2147 (define (lazy-handler-dispatch key . args)
2148 (case key
2149 ((apply-frame)
2150 (apply apply-frame-handler key args))
2151 ((exit-frame)
2152 (apply exit-frame-handler key args))
2153 (else
2154 (apply default-lazy-handler key args))))
2155
2156 (define abort-hook '())
2157
2158 (define (error-catching-loop thunk)
2159 (let ((status #f))
2160 (define (loop first)
2161 (let ((next
2162 (catch #t
2163
2164 (lambda ()
2165 (lazy-catch #t
2166 (lambda ()
2167 (dynamic-wind
2168 (lambda () (unmask-signals))
2169 (lambda ()
2170 (first)
2171
2172 ;; This line is needed because mark
2173 ;; doesn't do closures quite right.
2174 ;; Unreferenced locals should be
2175 ;; collected.
2176 ;;
2177 (set! first #f)
2178 (let loop ((v (thunk)))
2179 (loop (thunk)))
2180 #f)
2181 (lambda () (mask-signals))))
2182
2183 lazy-handler-dispatch))
2184
2185 (lambda (key . args)
2186 (case key
2187 ((quit)
2188 (force-output)
2189 (set! status args)
2190 #f)
2191
2192 ((switch-repl)
2193 (apply throw 'switch-repl args))
2194
2195 ((abort)
2196 ;; This is one of the closures that require
2197 ;; (set! first #f) above
2198 ;;
2199 (lambda ()
2200 (run-hooks abort-hook)
2201 (force-output)
2202 (display "ABORT: " (current-error-port))
2203 (write args (current-error-port))
2204 (newline (current-error-port))
2205 (if (and (not has-shown-debugger-hint?)
2206 (not (memq 'backtrace
2207 (debug-options-interface)))
2208 (stack? the-last-stack))
2209 (begin
2210 (newline (current-error-port))
2211 (display
2212 "Type \"(backtrace)\" to get more information.\n"
2213 (current-error-port))
2214 (set! has-shown-debugger-hint? #t)))
2215 (set! stack-saved? #f)))
2216
2217 (else
2218 ;; This is the other cons-leak closure...
2219 (lambda ()
2220 (cond ((= (length args) 4)
2221 (apply handle-system-error key args))
2222 (else
2223 (apply bad-throw key args))))))))))
2224 (if next (loop next) status)))
2225 (loop (lambda () #t))))
2226
2227 ;;(define the-last-stack #f) Defined by scm_init_backtrace ()
2228 (define stack-saved? #f)
2229
2230 (define (save-stack . narrowing)
2231 (cond (stack-saved?)
2232 ((not (memq 'debug (debug-options-interface)))
2233 (set! the-last-stack #f)
2234 (set! stack-saved? #t))
2235 (else
2236 (set! the-last-stack
2237 (case (stack-id #t)
2238 ((repl-stack)
2239 (apply make-stack #t save-stack eval narrowing))
2240 ((load-stack)
2241 (apply make-stack #t save-stack gsubr-apply narrowing))
2242 ((tk-stack)
2243 (apply make-stack #t save-stack tk-stack-mark narrowing))
2244 ((#t)
2245 (apply make-stack #t save-stack 0 1 narrowing))
2246 (else (let ((id (stack-id #t)))
2247 (and (procedure? id)
2248 (apply make-stack #t save-stack id narrowing))))))
2249 (set! stack-saved? #t))))
2250
2251 (define before-error-hook '())
2252 (define after-error-hook '())
2253 (define before-backtrace-hook '())
2254 (define after-backtrace-hook '())
2255
2256 (define has-shown-debugger-hint? #f)
2257
2258 (define (handle-system-error key . args)
2259 (let ((cep (current-error-port)))
2260 (cond ((not (stack? the-last-stack)))
2261 ((memq 'backtrace (debug-options-interface))
2262 (run-hooks before-backtrace-hook)
2263 (newline cep)
2264 (display-backtrace the-last-stack cep)
2265 (newline cep)
2266 (run-hooks after-backtrace-hook)))
2267 (run-hooks before-error-hook)
2268 (apply display-error the-last-stack cep args)
2269 (run-hooks after-error-hook)
2270 (force-output cep)
2271 (throw 'abort key)))
2272
2273 (define (quit . args)
2274 (apply throw 'quit args))
2275
2276 (define exit quit)
2277
2278 ;;(define has-shown-backtrace-hint? #f) Defined by scm_init_backtrace ()
2279
2280 ;; Replaced by C code:
2281 ;;(define (backtrace)
2282 ;; (if the-last-stack
2283 ;; (begin
2284 ;; (newline)
2285 ;; (display-backtrace the-last-stack (current-output-port))
2286 ;; (newline)
2287 ;; (if (and (not has-shown-backtrace-hint?)
2288 ;; (not (memq 'backtrace (debug-options-interface))))
2289 ;; (begin
2290 ;; (display
2291 ;;"Type \"(debug-enable 'backtrace)\" if you would like a backtrace
2292 ;;automatically if an error occurs in the future.\n")
2293 ;; (set! has-shown-backtrace-hint? #t))))
2294 ;; (display "No backtrace available.\n")))
2295
2296 (define (error-catching-repl r e p)
2297 (error-catching-loop (lambda () (p (e (r))))))
2298
2299 (define (gc-run-time)
2300 (cdr (assq 'gc-time-taken (gc-stats))))
2301
2302 (define before-read-hook '())
2303 (define after-read-hook '())
2304
2305 (define (scm-style-repl)
2306 (letrec (
2307 (start-gc-rt #f)
2308 (start-rt #f)
2309 (repl-report-reset (lambda () #f))
2310 (repl-report-start-timing (lambda ()
2311 (set! start-gc-rt (gc-run-time))
2312 (set! start-rt (get-internal-run-time))))
2313 (repl-report (lambda ()
2314 (display ";;; ")
2315 (display (inexact->exact
2316 (* 1000 (/ (- (get-internal-run-time) start-rt)
2317 internal-time-units-per-second))))
2318 (display " msec (")
2319 (display (inexact->exact
2320 (* 1000 (/ (- (gc-run-time) start-gc-rt)
2321 internal-time-units-per-second))))
2322 (display " msec in gc)\n")))
2323
2324 (consume-trailing-whitespace
2325 (lambda ()
2326 (let ((ch (peek-char)))
2327 (cond
2328 ((eof-object? ch))
2329 ((or (char=? ch #\space) (char=? ch #\tab))
2330 (read-char)
2331 (consume-trailing-whitespace))
2332 ((char=? ch #\newline)
2333 (read-char))))))
2334 (-read (lambda ()
2335 (if scm-repl-prompt
2336 (begin
2337 (display (cond ((string? scm-repl-prompt)
2338 scm-repl-prompt)
2339 ((thunk? scm-repl-prompt)
2340 (scm-repl-prompt))
2341 (else "> ")))
2342 (force-output)
2343 (repl-report-reset)))
2344 (run-hooks before-read-hook)
2345 (let ((val (read (current-input-port))))
2346 ;; As described in R4RS, the READ procedure updates the
2347 ;; port to point to the first characetr past the end of
2348 ;; the external representation of the object. This
2349 ;; means that it doesn't consume the newline typically
2350 ;; found after an expression. This means that, when
2351 ;; debugging Guile with GDB, GDB gets the newline, which
2352 ;; it often interprets as a "continue" command, making
2353 ;; breakpoints kind of useless. So, consume any
2354 ;; trailing newline here, as well as any whitespace
2355 ;; before it.
2356 (consume-trailing-whitespace)
2357 (run-hooks after-read-hook)
2358 (if (eof-object? val)
2359 (begin
2360 (repl-report-start-timing)
2361 (if scm-repl-verbose
2362 (begin
2363 (newline)
2364 (display ";;; EOF -- quitting")
2365 (newline)))
2366 (quit 0)))
2367 val)))
2368
2369 (-eval (lambda (sourc)
2370 (repl-report-start-timing)
2371 (start-stack 'repl-stack (eval sourc))))
2372
2373 (-print (lambda (result)
2374 (if (not scm-repl-silent)
2375 (begin
2376 (if (or scm-repl-print-unspecified
2377 (not (unspecified? result)))
2378 (begin
2379 (write result)
2380 (newline)))
2381 (if scm-repl-verbose
2382 (repl-report))
2383 (force-output)))))
2384
2385 (-quit (lambda (args)
2386 (if scm-repl-verbose
2387 (begin
2388 (display ";;; QUIT executed, repl exitting")
2389 (newline)
2390 (repl-report)))
2391 args))
2392
2393 (-abort (lambda ()
2394 (if scm-repl-verbose
2395 (begin
2396 (display ";;; ABORT executed.")
2397 (newline)
2398 (repl-report)))
2399 (repl -read -eval -print))))
2400
2401 (let ((status (error-catching-repl -read
2402 -eval
2403 -print)))
2404 (-quit status))))
2405
2406
2407 \f
2408 ;;; {IOTA functions: generating lists of numbers}
2409
2410 (define (reverse-iota n) (if (> n 0) (cons (1- n) (reverse-iota (1- n))) '()))
2411 (define (iota n) (list-reverse! (reverse-iota n)))
2412
2413 \f
2414 ;;; {While}
2415 ;;;
2416 ;;; with `continue' and `break'.
2417 ;;;
2418
2419 (defmacro while (cond . body)
2420 `(letrec ((continue (lambda () (or (not ,cond) (begin (begin ,@ body) (continue)))))
2421 (break (lambda val (apply throw 'break val))))
2422 (catch 'break
2423 (lambda () (continue))
2424 (lambda v (cadr v)))))
2425
2426
2427 \f
2428
2429 ;;; {Macros}
2430 ;;;
2431
2432 ;; actually....hobbit might be able to hack these with a little
2433 ;; coaxing
2434 ;;
2435
2436 (defmacro define-macro (first . rest)
2437 (let ((name (if (symbol? first) first (car first)))
2438 (transformer
2439 (if (symbol? first)
2440 (car rest)
2441 `(lambda ,(cdr first) ,@rest))))
2442 `(define ,name (defmacro:transformer ,transformer))))
2443
2444
2445 (defmacro define-syntax-macro (first . rest)
2446 (let ((name (if (symbol? first) first (car first)))
2447 (transformer
2448 (if (symbol? first)
2449 (car rest)
2450 `(lambda ,(cdr first) ,@rest))))
2451 `(define ,name (defmacro:syntax-transformer ,transformer))))
2452 \f
2453 ;;; {Module System Macros}
2454 ;;;
2455
2456 (defmacro define-module args
2457 `(let* ((process-define-module process-define-module)
2458 (set-current-module set-current-module)
2459 (module (process-define-module ',args)))
2460 (set-current-module module)
2461 module))
2462
2463 ;; the guts of the use-modules macro. add the interfaces of the named
2464 ;; modules to the use-list of the current module, in order
2465 (define (process-use-modules module-names)
2466 (for-each (lambda (module-name)
2467 (let ((mod-iface (resolve-interface module-name)))
2468 (or mod-iface
2469 (error "no such module" module-name))
2470 (module-use! (current-module) mod-iface)))
2471 (reverse module-names)))
2472
2473 (defmacro use-modules modules
2474 `(process-use-modules ',modules))
2475
2476 (define define-private define)
2477
2478 (defmacro define-public args
2479 (define (syntax)
2480 (error "bad syntax" (list 'define-public args)))
2481 (define (defined-name n)
2482 (cond
2483 ((symbol? n) n)
2484 ((pair? n) (defined-name (car n)))
2485 (else (syntax))))
2486 (cond
2487 ((null? args) (syntax))
2488
2489 (#t (let ((name (defined-name (car args))))
2490 `(begin
2491 (let ((public-i (module-public-interface (current-module))))
2492 ;; Make sure there is a local variable:
2493 ;;
2494 (module-define! (current-module)
2495 ',name
2496 (module-ref (current-module) ',name #f))
2497
2498 ;; Make sure that local is exported:
2499 ;;
2500 (module-add! public-i ',name (module-variable (current-module) ',name)))
2501
2502 ;; Now (re)define the var normally.
2503 ;;
2504 (define-private ,@ args))))))
2505
2506
2507
2508 (defmacro defmacro-public args
2509 (define (syntax)
2510 (error "bad syntax" (list 'defmacro-public args)))
2511 (define (defined-name n)
2512 (cond
2513 ((symbol? n) n)
2514 (else (syntax))))
2515 (cond
2516 ((null? args) (syntax))
2517
2518 (#t (let ((name (defined-name (car args))))
2519 `(begin
2520 (let ((public-i (module-public-interface (current-module))))
2521 ;; Make sure there is a local variable:
2522 ;;
2523 (module-define! (current-module)
2524 ',name
2525 (module-ref (current-module) ',name #f))
2526
2527 ;; Make sure that local is exported:
2528 ;;
2529 (module-add! public-i ',name (module-variable (current-module) ',name)))
2530
2531 ;; Now (re)define the var normally.
2532 ;;
2533 (defmacro ,@ args))))))
2534
2535
2536
2537
2538 (define load load-module)
2539 ;(define (load . args)
2540 ; (start-stack 'load-stack (apply load-module args)))
2541
2542
2543 \f
2544 ;;; {I/O functions for Tcl channels (disabled)}
2545
2546 ;; (define in-ch (get-standard-channel TCL_STDIN))
2547 ;; (define out-ch (get-standard-channel TCL_STDOUT))
2548 ;; (define err-ch (get-standard-channel TCL_STDERR))
2549 ;;
2550 ;; (define inp (%make-channel-port in-ch "r"))
2551 ;; (define outp (%make-channel-port out-ch "w"))
2552 ;; (define errp (%make-channel-port err-ch "w"))
2553 ;;
2554 ;; (define %system-char-ready? char-ready?)
2555 ;;
2556 ;; (define (char-ready? p)
2557 ;; (if (not (channel-port? p))
2558 ;; (%system-char-ready? p)
2559 ;; (let* ((channel (%channel-port-channel p))
2560 ;; (old-blocking (channel-option-ref channel :blocking)))
2561 ;; (dynamic-wind
2562 ;; (lambda () (set-channel-option the-root-tcl-interpreter channel :blocking "0"))
2563 ;; (lambda () (not (eof-object? (peek-char p))))
2564 ;; (lambda () (set-channel-option the-root-tcl-interpreter channel :blocking old-blocking))))))
2565 ;;
2566 ;; (define (top-repl)
2567 ;; (with-input-from-port inp
2568 ;; (lambda ()
2569 ;; (with-output-to-port outp
2570 ;; (lambda ()
2571 ;; (with-error-to-port errp
2572 ;; (lambda ()
2573 ;; (scm-style-repl))))))))
2574 ;;
2575 ;; (set-current-input-port inp)
2576 ;; (set-current-output-port outp)
2577 ;; (set-current-error-port errp)
2578
2579 ;; this is just (scm-style-repl) with a wrapper to install and remove
2580 ;; signal handlers.
2581 (define (top-repl)
2582 (let ((old-handlers #f)
2583 (signals `((,SIGINT . "User interrupt")
2584 (,SIGFPE . "Arithmetic error")
2585 (,SIGBUS . "Bad memory access (bus error)")
2586 (,SIGSEGV . "Bad memory access (Segmentation violation)"))))
2587
2588 (dynamic-wind
2589
2590 ;; call at entry
2591 (lambda ()
2592 (let ((make-handler (lambda (msg)
2593 (lambda (sig)
2594 (scm-error 'signal
2595 #f
2596 msg
2597 #f
2598 (list sig))))))
2599 (set! old-handlers
2600 (map (lambda (sig-msg)
2601 (sigaction (car sig-msg)
2602 (make-handler (cdr sig-msg))))
2603 signals))))
2604
2605 ;; the protected thunk.
2606 (lambda ()
2607 (scm-style-repl))
2608
2609 ;; call at exit.
2610 (lambda ()
2611 (map (lambda (sig-msg old-handler)
2612 (if (not (car old-handler))
2613 ;; restore original C handler.
2614 (sigaction (car sig-msg) #f)
2615 ;; restore Scheme handler, SIG_IGN or SIG_DFL.
2616 (sigaction (car sig-msg)
2617 (car old-handler)
2618 (cdr old-handler))))
2619 signals old-handlers)))))
2620
2621 (defmacro false-if-exception (expr)
2622 `(catch #t (lambda () ,expr)
2623 (lambda args #f)))
2624
2625 \f
2626 ;;; {Calling Conventions}
2627 (define-module (ice-9 calling))
2628
2629 ;;;;
2630 ;;;
2631 ;;; This file contains a number of macros that support
2632 ;;; common calling conventions.
2633
2634 ;;;
2635 ;;; with-excursion-function <vars> proc
2636 ;;; <vars> is an unevaluated list of names that are bound in the caller.
2637 ;;; proc is a procedure, called:
2638 ;;; (proc excursion)
2639 ;;;
2640 ;;; excursion is a procedure isolates all changes to <vars>
2641 ;;; in the dynamic scope of the call to proc. In other words,
2642 ;;; the values of <vars> are saved when proc is entered, and when
2643 ;;; proc returns, those values are restored. Values are also restored
2644 ;;; entering and leaving the call to proc non-locally, such as using
2645 ;;; call-with-current-continuation, error, or throw.
2646 ;;;
2647 (defmacro-public with-excursion-function (vars proc)
2648 `(,proc ,(excursion-function-syntax vars)))
2649
2650
2651
2652 ;;; with-getter-and-setter <vars> proc
2653 ;;; <vars> is an unevaluated list of names that are bound in the caller.
2654 ;;; proc is a procedure, called:
2655 ;;; (proc getter setter)
2656 ;;;
2657 ;;; getter and setter are procedures used to access
2658 ;;; or modify <vars>.
2659 ;;;
2660 ;;; setter, called with keywords arguments, modifies the named
2661 ;;; values. If "foo" and "bar" are among <vars>, then:
2662 ;;;
2663 ;;; (setter :foo 1 :bar 2)
2664 ;;; == (set! foo 1 bar 2)
2665 ;;;
2666 ;;; getter, called with just keywords, returns
2667 ;;; a list of the corresponding values. For example,
2668 ;;; if "foo" and "bar" are among the <vars>, then
2669 ;;;
2670 ;;; (getter :foo :bar)
2671 ;;; => (<value-of-foo> <value-of-bar>)
2672 ;;;
2673 ;;; getter, called with no arguments, returns a list of all accepted
2674 ;;; keywords and the corresponding values. If "foo" and "bar" are
2675 ;;; the *only* <vars>, then:
2676 ;;;
2677 ;;; (getter)
2678 ;;; => (:foo <value-of-bar> :bar <value-of-foo>)
2679 ;;;
2680 ;;; The unusual calling sequence of a getter supports too handy
2681 ;;; idioms:
2682 ;;;
2683 ;;; (apply setter (getter)) ;; save and restore
2684 ;;;
2685 ;;; (apply-to-args (getter :foo :bar) ;; fetch and bind
2686 ;;; (lambda (foo bar) ....))
2687 ;;;
2688 ;;; ;; [ "apply-to-args" is just like two-argument "apply" except that it
2689 ;;; ;; takes its arguments in a different order.
2690 ;;;
2691 ;;;
2692 (defmacro-public with-getter-and-setter (vars proc)
2693 `(,proc ,@ (getter-and-setter-syntax vars)))
2694
2695 ;;; with-getter vars proc
2696 ;;; A short-hand for a call to with-getter-and-setter.
2697 ;;; The procedure is called:
2698 ;;; (proc getter)
2699 ;;;
2700 (defmacro-public with-getter (vars proc)
2701 `(,proc ,(car (getter-and-setter-syntax vars))))
2702
2703
2704 ;;; with-delegating-getter-and-setter <vars> get-delegate set-delegate proc
2705 ;;; Compose getters and setters.
2706 ;;;
2707 ;;; <vars> is an unevaluated list of names that are bound in the caller.
2708 ;;;
2709 ;;; get-delegate is called by the new getter to extend the set of
2710 ;;; gettable variables beyond just <vars>
2711 ;;; set-delegate is called by the new setter to extend the set of
2712 ;;; gettable variables beyond just <vars>
2713 ;;;
2714 ;;; proc is a procedure that is called
2715 ;;; (proc getter setter)
2716 ;;;
2717 (defmacro-public with-delegating-getter-and-setter (vars get-delegate set-delegate proc)
2718 `(,proc ,@ (delegating-getter-and-setter-syntax vars get-delegate set-delegate)))
2719
2720
2721 ;;; with-delegating-getter-and-setter <vars> get-delegate set-delegate proc
2722 ;;; <vars> is an unevaluated list of names that are bound in the caller.
2723 ;;; proc is called:
2724 ;;;
2725 ;;; (proc excursion getter setter)
2726 ;;;
2727 ;;; See also:
2728 ;;; with-getter-and-setter
2729 ;;; with-excursion-function
2730 ;;;
2731 (defmacro-public with-excursion-getter-and-setter (vars proc)
2732 `(,proc ,(excursion-function-syntax vars)
2733 ,@ (getter-and-setter-syntax vars)))
2734
2735
2736 (define (excursion-function-syntax vars)
2737 (let ((saved-value-names (map gensym vars))
2738 (tmp-var-name (gensym 'temp))
2739 (swap-fn-name (gensym 'swap))
2740 (thunk-name (gensym 'thunk)))
2741 `(lambda (,thunk-name)
2742 (letrec ((,tmp-var-name #f)
2743 (,swap-fn-name
2744 (lambda () ,@ (map (lambda (n sn) `(set! ,tmp-var-name ,n ,n ,sn ,sn ,tmp-var-name))
2745 vars saved-value-names)))
2746 ,@ (map (lambda (sn n) `(,sn ,n)) saved-value-names vars))
2747 (dynamic-wind
2748 ,swap-fn-name
2749 ,thunk-name
2750 ,swap-fn-name)))))
2751
2752
2753 (define (getter-and-setter-syntax vars)
2754 (let ((args-name (gensym 'args))
2755 (an-arg-name (gensym 'an-arg))
2756 (new-val-name (gensym 'new-value))
2757 (loop-name (gensym 'loop))
2758 (kws (map symbol->keyword vars)))
2759 (list `(lambda ,args-name
2760 (let ,loop-name ((,args-name ,args-name))
2761 (if (null? ,args-name)
2762 ,(if (null? kws)
2763 ''()
2764 `(let ((all-vals (,loop-name ',kws)))
2765 (let ,loop-name ((vals all-vals)
2766 (kws ',kws))
2767 (if (null? vals)
2768 '()
2769 `(,(car kws) ,(car vals) ,@(,loop-name (cdr vals) (cdr kws)))))))
2770 (map (lambda (,an-arg-name)
2771 (case ,an-arg-name
2772 ,@ (append
2773 (map (lambda (kw v) `((,kw) ,v)) kws vars)
2774 `((else (throw 'bad-get-option ,an-arg-name))))))
2775 ,args-name))))
2776
2777 `(lambda ,args-name
2778 (let ,loop-name ((,args-name ,args-name))
2779 (or (null? ,args-name)
2780 (null? (cdr ,args-name))
2781 (let ((,an-arg-name (car ,args-name))
2782 (,new-val-name (cadr ,args-name)))
2783 (case ,an-arg-name
2784 ,@ (append
2785 (map (lambda (kw v) `((,kw) (set! ,v ,new-val-name))) kws vars)
2786 `((else (throw 'bad-set-option ,an-arg-name)))))
2787 (,loop-name (cddr ,args-name)))))))))
2788
2789 (define (delegating-getter-and-setter-syntax vars get-delegate set-delegate)
2790 (let ((args-name (gensym 'args))
2791 (an-arg-name (gensym 'an-arg))
2792 (new-val-name (gensym 'new-value))
2793 (loop-name (gensym 'loop))
2794 (kws (map symbol->keyword vars)))
2795 (list `(lambda ,args-name
2796 (let ,loop-name ((,args-name ,args-name))
2797 (if (null? ,args-name)
2798 (append!
2799 ,(if (null? kws)
2800 ''()
2801 `(let ((all-vals (,loop-name ',kws)))
2802 (let ,loop-name ((vals all-vals)
2803 (kws ',kws))
2804 (if (null? vals)
2805 '()
2806 `(,(car kws) ,(car vals) ,@(,loop-name (cdr vals) (cdr kws)))))))
2807 (,get-delegate))
2808 (map (lambda (,an-arg-name)
2809 (case ,an-arg-name
2810 ,@ (append
2811 (map (lambda (kw v) `((,kw) ,v)) kws vars)
2812 `((else (car (,get-delegate ,an-arg-name)))))))
2813 ,args-name))))
2814
2815 `(lambda ,args-name
2816 (let ,loop-name ((,args-name ,args-name))
2817 (or (null? ,args-name)
2818 (null? (cdr ,args-name))
2819 (let ((,an-arg-name (car ,args-name))
2820 (,new-val-name (cadr ,args-name)))
2821 (case ,an-arg-name
2822 ,@ (append
2823 (map (lambda (kw v) `((,kw) (set! ,v ,new-val-name))) kws vars)
2824 `((else (,set-delegate ,an-arg-name ,new-val-name)))))
2825 (,loop-name (cddr ,args-name)))))))))
2826
2827
2828
2829
2830 ;;; with-configuration-getter-and-setter <vars-etc> proc
2831 ;;;
2832 ;;; Create a getter and setter that can trigger arbitrary computation.
2833 ;;;
2834 ;;; <vars-etc> is a list of variable specifiers, explained below.
2835 ;;; proc is called:
2836 ;;;
2837 ;;; (proc getter setter)
2838 ;;;
2839 ;;; Each element of the <vars-etc> list is of the form:
2840 ;;;
2841 ;;; (<var> getter-hook setter-hook)
2842 ;;;
2843 ;;; Both hook elements are evaluated; the variable name is not.
2844 ;;; Either hook may be #f or procedure.
2845 ;;;
2846 ;;; A getter hook is a thunk that returns a value for the corresponding
2847 ;;; variable. If omitted (#f is passed), the binding of <var> is
2848 ;;; returned.
2849 ;;;
2850 ;;; A setter hook is a procedure of one argument that accepts a new value
2851 ;;; for the corresponding variable. If omitted, the binding of <var>
2852 ;;; is simply set using set!.
2853 ;;;
2854 (defmacro-public with-configuration-getter-and-setter (vars-etc proc)
2855 `((lambda (simpler-get simpler-set body-proc)
2856 (with-delegating-getter-and-setter ()
2857 simpler-get simpler-set body-proc))
2858
2859 (lambda (kw)
2860 (case kw
2861 ,@(map (lambda (v) `((,(symbol->keyword (car v)))
2862 ,(cond
2863 ((cadr v) => list)
2864 (else `(list ,(car v))))))
2865 vars-etc)))
2866
2867 (lambda (kw new-val)
2868 (case kw
2869 ,@(map (lambda (v) `((,(symbol->keyword (car v)))
2870 ,(cond
2871 ((caddr v) => (lambda (proc) `(,proc new-val)))
2872 (else `(set! ,(car v) new-val)))))
2873 vars-etc)))
2874
2875 ,proc))
2876
2877 (defmacro-public with-delegating-configuration-getter-and-setter (vars-etc delegate-get delegate-set proc)
2878 `((lambda (simpler-get simpler-set body-proc)
2879 (with-delegating-getter-and-setter ()
2880 simpler-get simpler-set body-proc))
2881
2882 (lambda (kw)
2883 (case kw
2884 ,@(append! (map (lambda (v) `((,(symbol->keyword (car v)))
2885 ,(cond
2886 ((cadr v) => list)
2887 (else `(list ,(car v))))))
2888 vars-etc)
2889 `((else (,delegate-get kw))))))
2890
2891 (lambda (kw new-val)
2892 (case kw
2893 ,@(append! (map (lambda (v) `((,(symbol->keyword (car v)))
2894 ,(cond
2895 ((caddr v) => (lambda (proc) `(,proc new-val)))
2896 (else `(set! ,(car v) new-val)))))
2897 vars-etc)
2898 `((else (,delegate-set kw new-val))))))
2899
2900 ,proc))
2901
2902
2903 ;;; let-configuration-getter-and-setter <vars-etc> proc
2904 ;;;
2905 ;;; This procedure is like with-configuration-getter-and-setter (q.v.)
2906 ;;; except that each element of <vars-etc> is:
2907 ;;;
2908 ;;; (<var> initial-value getter-hook setter-hook)
2909 ;;;
2910 ;;; Unlike with-configuration-getter-and-setter, let-configuration-getter-and-setter
2911 ;;; introduces bindings for the variables named in <vars-etc>.
2912 ;;; It is short-hand for:
2913 ;;;
2914 ;;; (let ((<var1> initial-value-1)
2915 ;;; (<var2> initial-value-2)
2916 ;;; ...)
2917 ;;; (with-configuration-getter-and-setter ((<var1> v1-get v1-set) ...) proc))
2918 ;;;
2919 (defmacro-public let-with-configuration-getter-and-setter (vars-etc proc)
2920 `(let ,(map (lambda (v) `(,(car v) ,(cadr v))) vars-etc)
2921 (with-configuration-getter-and-setter ,(map (lambda (v) `(,(car v) ,(caddr v) ,(cadddr v))) vars-etc)
2922 ,proc)))
2923
2924
2925
2926 \f
2927 ;;; {Implementation of COMMON LISP list functions for Scheme}
2928
2929 (define-module (ice-9 common-list))
2930
2931 ;;"comlist.scm" Implementation of COMMON LISP list functions for Scheme
2932 ; Copyright (C) 1991, 1993, 1995 Aubrey Jaffer.
2933 ;
2934 ;Permission to copy this software, to redistribute it, and to use it
2935 ;for any purpose is granted, subject to the following restrictions and
2936 ;understandings.
2937 ;
2938 ;1. Any copy made of this software must include this copyright notice
2939 ;in full.
2940 ;
2941 ;2. I have made no warrantee or representation that the operation of
2942 ;this software will be error-free, and I am under no obligation to
2943 ;provide any services, by way of maintenance, update, or otherwise.
2944 ;
2945 ;3. In conjunction with products arising from the use of this
2946 ;material, there shall be no use of my name in any advertising,
2947 ;promotional, or sales literature without prior written consent in
2948 ;each case.
2949
2950 ;;;From: hugh@ear.mit.edu (Hugh Secker-Walker)
2951 (define-public (make-list k . init)
2952 (set! init (if (pair? init) (car init)))
2953 (do ((k k (+ -1 k))
2954 (result '() (cons init result)))
2955 ((<= k 0) result)))
2956
2957 (define-public (adjoin e l) (if (memq e l) l (cons e l)))
2958
2959 (define-public (union l1 l2)
2960 (cond ((null? l1) l2)
2961 ((null? l2) l1)
2962 (else (union (cdr l1) (adjoin (car l1) l2)))))
2963
2964 (define-public (intersection l1 l2)
2965 (cond ((null? l1) l1)
2966 ((null? l2) l2)
2967 ((memv (car l1) l2) (cons (car l1) (intersection (cdr l1) l2)))
2968 (else (intersection (cdr l1) l2))))
2969
2970 (define-public (set-difference l1 l2)
2971 (cond ((null? l1) l1)
2972 ((memv (car l1) l2) (set-difference (cdr l1) l2))
2973 (else (cons (car l1) (set-difference (cdr l1) l2)))))
2974
2975 (define-public (reduce-init p init l)
2976 (if (null? l)
2977 init
2978 (reduce-init p (p init (car l)) (cdr l))))
2979
2980 (define-public (reduce p l)
2981 (cond ((null? l) l)
2982 ((null? (cdr l)) (car l))
2983 (else (reduce-init p (car l) (cdr l)))))
2984
2985 (define-public (some pred l . rest)
2986 (cond ((null? rest)
2987 (let mapf ((l l))
2988 (and (not (null? l))
2989 (or (pred (car l)) (mapf (cdr l))))))
2990 (else (let mapf ((l l) (rest rest))
2991 (and (not (null? l))
2992 (or (apply pred (car l) (map car rest))
2993 (mapf (cdr l) (map cdr rest))))))))
2994
2995 (define-public (every pred l . rest)
2996 (cond ((null? rest)
2997 (let mapf ((l l))
2998 (or (null? l)
2999 (and (pred (car l)) (mapf (cdr l))))))
3000 (else (let mapf ((l l) (rest rest))
3001 (or (null? l)
3002 (and (apply pred (car l) (map car rest))
3003 (mapf (cdr l) (map cdr rest))))))))
3004
3005 (define-public (notany pred . ls) (not (apply some pred ls)))
3006
3007 (define-public (notevery pred . ls) (not (apply every pred ls)))
3008
3009 (define-public (find-if t l)
3010 (cond ((null? l) #f)
3011 ((t (car l)) (car l))
3012 (else (find-if t (cdr l)))))
3013
3014 (define-public (member-if t l)
3015 (cond ((null? l) #f)
3016 ((t (car l)) l)
3017 (else (member-if t (cdr l)))))
3018
3019 (define-public (remove-if p l)
3020 (cond ((null? l) '())
3021 ((p (car l)) (remove-if p (cdr l)))
3022 (else (cons (car l) (remove-if p (cdr l))))))
3023
3024 (define-public (delete-if! pred list)
3025 (let delete-if ((list list))
3026 (cond ((null? list) '())
3027 ((pred (car list)) (delete-if (cdr list)))
3028 (else
3029 (set-cdr! list (delete-if (cdr list)))
3030 list))))
3031
3032 (define-public (delete-if-not! pred list)
3033 (let delete-if ((list list))
3034 (cond ((null? list) '())
3035 ((not (pred (car list))) (delete-if (cdr list)))
3036 (else
3037 (set-cdr! list (delete-if (cdr list)))
3038 list))))
3039
3040 (define-public (butlast lst n)
3041 (letrec ((l (- (length lst) n))
3042 (bl (lambda (lst n)
3043 (cond ((null? lst) lst)
3044 ((positive? n)
3045 (cons (car lst) (bl (cdr lst) (+ -1 n))))
3046 (else '())))))
3047 (bl lst (if (negative? n)
3048 (slib:error "negative argument to butlast" n)
3049 l))))
3050
3051 (define-public (and? . args)
3052 (cond ((null? args) #t)
3053 ((car args) (apply and? (cdr args)))
3054 (else #f)))
3055
3056 (define-public (or? . args)
3057 (cond ((null? args) #f)
3058 ((car args) #t)
3059 (else (apply or? (cdr args)))))
3060
3061 (define-public (has-duplicates? lst)
3062 (cond ((null? lst) #f)
3063 ((member (car lst) (cdr lst)) #t)
3064 (else (has-duplicates? (cdr lst)))))
3065
3066 (define-public (list* x . y)
3067 (define (list*1 x)
3068 (if (null? (cdr x))
3069 (car x)
3070 (cons (car x) (list*1 (cdr x)))))
3071 (if (null? y)
3072 x
3073 (cons x (list*1 y))))
3074
3075 ;; pick p l
3076 ;; Apply P to each element of L, returning a list of elts
3077 ;; for which P returns a non-#f value.
3078 ;;
3079 (define-public (pick p l)
3080 (let loop ((s '())
3081 (l l))
3082 (cond
3083 ((null? l) s)
3084 ((p (car l)) (loop (cons (car l) s) (cdr l)))
3085 (else (loop s (cdr l))))))
3086
3087 ;; pick p l
3088 ;; Apply P to each element of L, returning a list of the
3089 ;; non-#f return values of P.
3090 ;;
3091 (define-public (pick-mappings p l)
3092 (let loop ((s '())
3093 (l l))
3094 (cond
3095 ((null? l) s)
3096 ((p (car l)) => (lambda (mapping) (loop (cons mapping s) (cdr l))))
3097 (else (loop s (cdr l))))))
3098
3099 (define-public (uniq l)
3100 (if (null? l)
3101 '()
3102 (let ((u (uniq (cdr l))))
3103 (if (memq (car l) u)
3104 u
3105 (cons (car l) u)))))
3106
3107 \f
3108 ;;; {Functions for browsing modules}
3109
3110 (define-module (ice-9 ls)
3111 :use-module (ice-9 common-list))
3112
3113 ;;;;
3114 ;;; local-definitions-in root name
3115 ;;; Returns a list of names defined locally in the named
3116 ;;; subdirectory of root.
3117 ;;; definitions-in root name
3118 ;;; Returns a list of all names defined in the named
3119 ;;; subdirectory of root. The list includes alll locally
3120 ;;; defined names as well as all names inherited from a
3121 ;;; member of a use-list.
3122 ;;;
3123 ;;; A convenient interface for examining the nature of things:
3124 ;;;
3125 ;;; ls . various-names
3126 ;;;
3127 ;;; With just one argument, interpret that argument as the
3128 ;;; name of a subdirectory of the current module and
3129 ;;; return a list of names defined there.
3130 ;;;
3131 ;;; With more than one argument, still compute
3132 ;;; subdirectory lists, but return a list:
3133 ;;; ((<subdir-name> . <names-defined-there>)
3134 ;;; (<subdir-name> . <names-defined-there>)
3135 ;;; ...)
3136 ;;;
3137
3138 (define-public (local-definitions-in root names)
3139 (let ((m (nested-ref root names))
3140 (answer '()))
3141 (if (not (module? m))
3142 (set! answer m)
3143 (module-for-each (lambda (k v) (set! answer (cons k answer))) m))
3144 answer))
3145
3146 (define-public (definitions-in root names)
3147 (let ((m (nested-ref root names)))
3148 (if (not (module? m))
3149 m
3150 (reduce union
3151 (cons (local-definitions-in m '())
3152 (map (lambda (m2) (definitions-in m2 '()))
3153 (module-uses m)))))))
3154
3155 (define-public (ls . various-refs)
3156 (and various-refs
3157 (if (cdr various-refs)
3158 (map (lambda (ref)
3159 (cons ref (definitions-in (current-module) ref)))
3160 various-refs)
3161 (definitions-in (current-module) (car various-refs)))))
3162
3163 (define-public (lls . various-refs)
3164 (and various-refs
3165 (if (cdr various-refs)
3166 (map (lambda (ref)
3167 (cons ref (local-definitions-in (current-module) ref)))
3168 various-refs)
3169 (local-definitions-in (current-module) (car various-refs)))))
3170
3171 (define-public (recursive-local-define name value)
3172 (let ((parent (reverse! (cdr (reverse name)))))
3173 (and parent (make-modules-in (current-module) parent))
3174 (local-define name value)))
3175 \f
3176 ;;; {Queues}
3177
3178 (define-module (ice-9 q))
3179
3180 ;;;; Copyright (C) 1995 Free Software Foundation, Inc.
3181 ;;;;
3182 ;;;; This program is free software; you can redistribute it and/or modify
3183 ;;;; it under the terms of the GNU General Public License as published by
3184 ;;;; the Free Software Foundation; either version 2, or (at your option)
3185 ;;;; any later version.
3186 ;;;;
3187 ;;;; This program is distributed in the hope that it will be useful,
3188 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
3189 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3190 ;;;; GNU General Public License for more details.
3191 ;;;;
3192 ;;;; You should have received a copy of the GNU General Public License
3193 ;;;; along with this software; see the file COPYING. If not, write to
3194 ;;;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
3195 ;;;; Boston, MA 02111-1307 USA
3196 ;;;;
3197
3198 ;;;;
3199 ;;; Q: Based on the interface to
3200 ;;;
3201 ;;; "queue.scm" Queues/Stacks for Scheme
3202 ;;; Written by Andrew Wilcox (awilcox@astro.psu.edu) on April 1, 1992.
3203 ;;;
3204
3205 ;;;;
3206 ;;; {Q}
3207 ;;;
3208 ;;; A list is just a bunch of cons pairs that follows some constrains, right?
3209 ;;; Association lists are the same. Hash tables are just vectors and association
3210 ;;; lists. You can print them, read them, write them as constants, pun them off as other data
3211 ;;; structures etc. This is good. This is lisp. These structures are fast and compact
3212 ;;; and easy to manipulate arbitrarily because of their simple, regular structure and
3213 ;;; non-disjointedness (associations being lists and so forth).
3214 ;;;
3215 ;;; So I figured, queues should be the same -- just a "subtype" of cons-pair
3216 ;;; structures in general.
3217 ;;;
3218 ;;; A queue is a cons pair:
3219 ;;; ( <the-q> . <last-pair> )
3220 ;;;
3221 ;;; <the-q> is a list of things in the q. New elements go at the end of that list.
3222 ;;;
3223 ;;; <last-pair> is #f if the q is empty, and otherwise is the last pair of <the-q>.
3224 ;;;
3225 ;;; q's print nicely, but alas, they do not read well because the eq?-ness of
3226 ;;; <last-pair> and (last-pair <the-q>) is lost by read. The procedure
3227 ;;;
3228 ;;; (sync-q! q)
3229 ;;;
3230 ;;; recomputes and resets the <last-pair> component of a queue.
3231 ;;;
3232
3233 (define-public (sync-q! obj) (set-cdr! obj (and (car obj) (last-pair (car obj)))))
3234
3235 ;;; make-q
3236 ;;; return a new q.
3237 ;;;
3238 (define-public (make-q) (cons '() '()))
3239
3240 ;;; q? obj
3241 ;;; Return true if obj is a Q.
3242 ;;; An object is a queue if it is equal? to '(#f . #f) or
3243 ;;; if it is a pair P with (list? (car P)) and (eq? (cdr P) (last-pair P)).
3244 ;;;
3245 (define-public (q? obj) (and (pair? obj)
3246 (or (and (null? (car obj))
3247 (null? (cdr obj)))
3248 (and
3249 (list? (car obj))
3250 (eq? (cdr obj) (last-pair (car obj)))))))
3251
3252 ;;; q-empty? obj
3253 ;;;
3254 (define-public (q-empty? obj) (null? (car obj)))
3255
3256 ;;; q-empty-check q
3257 ;;; Throw a q-empty exception if Q is empty.
3258 (define-public (q-empty-check q) (if (q-empty? q) (throw 'q-empty q)))
3259
3260
3261 ;;; q-front q
3262 ;;; Return the first element of Q.
3263 (define-public (q-front q) (q-empty-check q) (caar q))
3264
3265 ;;; q-front q
3266 ;;; Return the last element of Q.
3267 (define-public (q-rear q) (q-empty-check q) (cadr q))
3268
3269 ;;; q-remove! q obj
3270 ;;; Remove all occurences of obj from Q.
3271 (define-public (q-remove! q obj)
3272 (while (memq obj (car q))
3273 (set-car! q (delq! obj (car q))))
3274 (set-cdr! q (last-pair (car q))))
3275
3276 ;;; q-push! q obj
3277 ;;; Add obj to the front of Q
3278 (define-public (q-push! q d)
3279 (let ((h (cons d (car q))))
3280 (set-car! q h)
3281 (if (null? (cdr q))
3282 (set-cdr! q h))))
3283
3284 ;;; enq! q obj
3285 ;;; Add obj to the rear of Q
3286 (define-public (enq! q d)
3287 (let ((h (cons d '())))
3288 (if (not (null? (cdr q)))
3289 (set-cdr! (cdr q) h)
3290 (set-car! q h))
3291 (set-cdr! q h)))
3292
3293 ;;; q-pop! q
3294 ;;; Take the front of Q and return it.
3295 (define-public (q-pop! q)
3296 (q-empty-check q)
3297 (let ((it (caar q))
3298 (next (cdar q)))
3299 (if (not next)
3300 (set-cdr! q #f))
3301 (set-car! q next)
3302 it))
3303
3304 ;;; deq! q
3305 ;;; Take the front of Q and return it.
3306 (define-public deq! q-pop!)
3307
3308 ;;; q-length q
3309 ;;; Return the number of enqueued elements.
3310 ;;;
3311 (define-public (q-length q) (length (car q)))
3312
3313
3314
3315 \f
3316 ;;; {The runq data structure}
3317
3318 (define-module (ice-9 runq)
3319 :use-module (ice-9 q))
3320
3321 ;;;; Copyright (C) 1996 Free Software Foundation, Inc.
3322 ;;;;
3323 ;;;; This program is free software; you can redistribute it and/or modify
3324 ;;;; it under the terms of the GNU General Public License as published by
3325 ;;;; the Free Software Foundation; either version 2, or (at your option)
3326 ;;;; any later version.
3327 ;;;;
3328 ;;;; This program is distributed in the hope that it will be useful,
3329 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
3330 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3331 ;;;; GNU General Public License for more details.
3332 ;;;;
3333 ;;;; You should have received a copy of the GNU General Public License
3334 ;;;; along with this software; see the file COPYING. If not, write to
3335 ;;;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
3336 ;;;; Boston, MA 02111-1307 USA
3337 ;;;;
3338
3339 ;;;;
3340 ;;;
3341 ;;; One way to schedule parallel computations in a serial environment is
3342 ;;; to explicitly divide each task up into small, finite execution time,
3343 ;;; strips. Then you interleave the execution of strips from various
3344 ;;; tasks to achieve a kind of parallelism. Runqs are a handy data
3345 ;;; structure for this style of programming.
3346 ;;;
3347 ;;; We use thunks (nullary procedures) and lists of thunks to represent
3348 ;;; strips. By convention, the return value of a strip-thunk must either
3349 ;;; be another strip or the value #f.
3350 ;;;
3351 ;;; A runq is a procedure that manages a queue of strips. Called with no
3352 ;;; arguments, it processes one strip from the queue. Called with
3353 ;;; arguments, the arguments form a control message for the queue. The
3354 ;;; first argument is a symbol which is the message selector.
3355 ;;;
3356 ;;; A strip is processed this way: If the strip is a thunk, the thunk is
3357 ;;; called -- if it returns a strip, that strip is added back to the
3358 ;;; queue. To process a strip which is a list of thunks, the CAR of that
3359 ;;; list is called. After a call to that CAR, there are 0, 1, or 2 strips
3360 ;;; -- perhaps one returned by the thunk, and perhaps the CDR of the
3361 ;;; original strip if that CDR is not nil. The runq puts whichever of
3362 ;;; these strips exist back on the queue. (The exact order in which
3363 ;;; strips are put back on the queue determines the scheduling behavior of
3364 ;;; a particular queue -- it's a parameter.)
3365 ;;;
3366 ;;;
3367
3368
3369
3370 ;;;;
3371 ;;; (runq-control q msg . args)
3372 ;;;
3373 ;;; processes in the default way the control messages that
3374 ;;; can be sent to a runq. Q should be an ordinary
3375 ;;; Q (see utils/q.scm).
3376 ;;;
3377 ;;; The standard runq messages are:
3378 ;;;
3379 ;;; 'add! strip0 strip1... ;; to enqueue one or more strips
3380 ;;; 'enqueue! strip0 strip1... ;; to enqueue one or more strips
3381 ;;; 'push! strip0 ... ;; add strips to the front of the queue
3382 ;;; 'empty? ;; true if it is
3383 ;;; 'length ;; how many strips in the queue?
3384 ;;; 'kill! ;; empty the queue
3385 ;;; else ;; throw 'not-understood
3386 ;;;
3387 (define-public (runq-control q msg . args)
3388 (case msg
3389 ((add!) (for-each (lambda (t) (enq! q t)) args) '*unspecified*)
3390 ((enque!) (for-each (lambda (t) (enq! q t)) args) '*unspecified*)
3391 ((push!) (for-each (lambda (t) (q-push! q t)) args) '*unspecified*)
3392 ((empty?) (q-empty? q))
3393 ((length) (q-length q))
3394 ((kill!) (set! q (make-q)))
3395 (else (throw 'not-understood msg args))))
3396
3397 (define (run-strip thunk) (catch #t thunk (lambda ign (warn 'runq-strip thunk ign) #f)))
3398
3399 ;;;;
3400 ;;; make-void-runq
3401 ;;;
3402 ;;; Make a runq that discards all messages except "length", for which
3403 ;;; it returns 0.
3404 ;;;
3405 (define-public (make-void-runq)
3406 (lambda opts
3407 (and opts
3408 (apply-to-args opts
3409 (lambda (msg . args)
3410 (case msg
3411 ((length) 0)
3412 (else #f)))))))
3413
3414 ;;;;
3415 ;;; (make-fair-runq)
3416 ;;;
3417 ;;; Returns a runq procedure.
3418 ;;; Called with no arguments, the procedure processes one strip from the queue.
3419 ;;; Called with arguments, it uses runq-control.
3420 ;;;
3421 ;;; In a fair runq, if a strip returns a new strip X, X is added
3422 ;;; to the end of the queue, meaning it will be the last to execute
3423 ;;; of all the remaining procedures.
3424 ;;;
3425 (define-public (make-fair-runq)
3426 (letrec ((q (make-q))
3427 (self
3428 (lambda ctl
3429 (if ctl
3430 (apply runq-control q ctl)
3431 (and (not (q-empty? q))
3432 (let ((next-strip (deq! q)))
3433 (cond
3434 ((procedure? next-strip) (let ((k (run-strip next-strip)))
3435 (and k (enq! q k))))
3436 ((pair? next-strip) (let ((k (run-strip (car next-strip))))
3437 (and k (enq! q k)))
3438 (if (not (null? (cdr next-strip)))
3439 (enq! q (cdr next-strip)))))
3440 self))))))
3441 self))
3442
3443
3444 ;;;;
3445 ;;; (make-exclusive-runq)
3446 ;;;
3447 ;;; Returns a runq procedure.
3448 ;;; Called with no arguments, the procedure processes one strip from the queue.
3449 ;;; Called with arguments, it uses runq-control.
3450 ;;;
3451 ;;; In an exclusive runq, if a strip W returns a new strip X, X is added
3452 ;;; to the front of the queue, meaning it will be the next to execute
3453 ;;; of all the remaining procedures.
3454 ;;;
3455 ;;; An exception to this occurs if W was the CAR of a list of strips.
3456 ;;; In that case, after the return value of W is pushed onto the front
3457 ;;; of the queue, the CDR of the list of strips is pushed in front
3458 ;;; of that (if the CDR is not nil). This way, the rest of the thunks
3459 ;;; in the list that contained W have priority over the return value of W.
3460 ;;;
3461 (define-public (make-exclusive-runq)
3462 (letrec ((q (make-q))
3463 (self
3464 (lambda ctl
3465 (if ctl
3466 (apply runq-control q ctl)
3467 (and (not (q-empty? q))
3468 (let ((next-strip (deq! q)))
3469 (cond
3470 ((procedure? next-strip) (let ((k (run-strip next-strip)))
3471 (and k (q-push! q k))))
3472 ((pair? next-strip) (let ((k (run-strip (car next-strip))))
3473 (and k (q-push! q k)))
3474 (if (not (null? (cdr next-strip)))
3475 (q-push! q (cdr next-strip)))))
3476 self))))))
3477 self))
3478
3479
3480 ;;;;
3481 ;;; (make-subordinate-runq-to superior basic-inferior)
3482 ;;;
3483 ;;; Returns a runq proxy for the runq basic-inferior.
3484 ;;;
3485 ;;; The proxy watches for operations on the basic-inferior that cause
3486 ;;; a transition from a queue length of 0 to a non-zero length and
3487 ;;; vice versa. While the basic-inferior queue is not empty,
3488 ;;; the proxy installs a task on the superior runq. Each strip
3489 ;;; of that task processes N strips from the basic-inferior where
3490 ;;; N is the length of the basic-inferior queue when the proxy
3491 ;;; strip is entered. [Countless scheduling variations are possible.]
3492 ;;;
3493 (define-public (make-subordinate-runq-to superior-runq basic-runq)
3494 (let ((runq-task (cons #f #f)))
3495 (set-car! runq-task
3496 (lambda ()
3497 (if (basic-runq 'empty?)
3498 (set-cdr! runq-task #f)
3499 (do ((n (basic-runq 'length) (1- n)))
3500 ((<= n 0) #f)
3501 (basic-runq)))))
3502 (letrec ((self
3503 (lambda ctl
3504 (if (not ctl)
3505 (let ((answer (basic-runq)))
3506 (self 'empty?)
3507 answer)
3508 (begin
3509 (case (car ctl)
3510 ((suspend) (set-cdr! runq-task #f))
3511 (else (let ((answer (apply basic-runq ctl)))
3512 (if (and (not (cdr runq-task)) (not (basic-runq 'empty?)))
3513 (begin
3514 (set-cdr! runq-task runq-task)
3515 (superior-runq 'add! runq-task)))
3516 answer))))))))
3517 self)))
3518
3519 ;;;;
3520 ;;; (define fork-strips (lambda args args))
3521 ;;; Return a strip that starts several strips in
3522 ;;; parallel. If this strip is enqueued on a fair
3523 ;;; runq, strips of the parallel subtasks will run
3524 ;;; round-robin style.
3525 ;;;
3526 (define fork-strips (lambda args args))
3527
3528
3529 ;;;;
3530 ;;; (strip-sequence . strips)
3531 ;;;
3532 ;;; Returns a new strip which is the concatenation of the argument strips.
3533 ;;;
3534 (define-public ((strip-sequence . strips))
3535 (let loop ((st (let ((a strips)) (set! strips #f) a)))
3536 (and (not (null? st))
3537 (let ((then ((car st))))
3538 (if then
3539 (lambda () (loop (cons then (cdr st))))
3540 (lambda () (loop (cdr st))))))))
3541
3542
3543 ;;;;
3544 ;;; (fair-strip-subtask . initial-strips)
3545 ;;;
3546 ;;; Returns a new strip which is the synchronos, fair,
3547 ;;; parallel execution of the argument strips.
3548 ;;;
3549 ;;;
3550 ;;;
3551 (define-public (fair-strip-subtask . initial-strips)
3552 (let ((st (make-fair-runq)))
3553 (apply st 'add! initial-strips)
3554 st))
3555
3556 \f
3557 ;;; {String Fun}
3558
3559 (define-module (ice-9 string-fun))
3560
3561 ;;;;
3562 ;;;
3563 ;;; Various string funcitons, particularly those that take
3564 ;;; advantage of the "shared substring" capability.
3565 ;;;
3566 \f
3567 ;;; {String Fun: Dividing Strings Into Fields}
3568 ;;;
3569 ;;; The names of these functions are very regular.
3570 ;;; Here is a grammar of a call to one of these:
3571 ;;;
3572 ;;; <string-function-invocation>
3573 ;;; := (<action>-<seperator-disposition>-<seperator-determination> <seperator-param> <str> <ret>)
3574 ;;;
3575 ;;; <str> = the string
3576 ;;;
3577 ;;; <ret> = The continuation. String functions generally return
3578 ;;; multiple values by passing them to this procedure.
3579 ;;;
3580 ;;; <action> = split
3581 ;;; | separate-fields
3582 ;;;
3583 ;;; "split" means to divide a string into two parts.
3584 ;;; <ret> will be called with two arguments.
3585 ;;;
3586 ;;; "separate-fields" means to divide a string into as many
3587 ;;; parts as possible. <ret> will be called with
3588 ;;; however many fields are found.
3589 ;;;
3590 ;;; <seperator-disposition> = before
3591 ;;; | after
3592 ;;; | discarding
3593 ;;;
3594 ;;; "before" means to leave the seperator attached to
3595 ;;; the beginning of the field to its right.
3596 ;;; "after" means to leave the seperator attached to
3597 ;;; the end of the field to its left.
3598 ;;; "discarding" means to discard seperators.
3599 ;;;
3600 ;;; Other dispositions might be handy. For example, "isolate"
3601 ;;; could mean to treat the separator as a field unto itself.
3602 ;;;
3603 ;;; <seperator-determination> = char
3604 ;;; | predicate
3605 ;;;
3606 ;;; "char" means to use a particular character as field seperator.
3607 ;;; "predicate" means to check each character using a particular predicate.
3608 ;;;
3609 ;;; Other determinations might be handy. For example, "character-set-member".
3610 ;;;
3611 ;;; <seperator-param> = A parameter that completes the meaning of the determinations.
3612 ;;; For example, if the determination is "char", then this parameter
3613 ;;; says which character. If it is "predicate", the parameter is the
3614 ;;; predicate.
3615 ;;;
3616 ;;;
3617 ;;; For example:
3618 ;;;
3619 ;;; (separate-fields-discarding-char #\, "foo, bar, baz, , bat" list)
3620 ;;; => ("foo" " bar" " baz" " " " bat")
3621 ;;;
3622 ;;; (split-after-char #\- 'an-example-of-split list)
3623 ;;; => ("an-" "example-of-split")
3624 ;;;
3625 ;;; As an alternative to using a determination "predicate", or to trying to do anything
3626 ;;; complicated with these functions, consider using regular expressions.
3627 ;;;
3628
3629 (define-public (split-after-char char str ret)
3630 (let ((end (cond
3631 ((string-index str char) => 1+)
3632 (else (string-length str)))))
3633 (ret (make-shared-substring str 0 end)
3634 (make-shared-substring str end))))
3635
3636 (define-public (split-before-char char str ret)
3637 (let ((end (or (string-index str char)
3638 (string-length str))))
3639 (ret (make-shared-substring str 0 end)
3640 (make-shared-substring str end))))
3641
3642 (define-public (split-discarding-char char str ret)
3643 (let ((end (string-index str char)))
3644 (if (not end)
3645 (ret str "")
3646 (ret (make-shared-substring str 0 end)
3647 (make-shared-substring str (1+ end))))))
3648
3649 (define-public (split-after-char-last char str ret)
3650 (let ((end (cond
3651 ((string-rindex str char) => 1+)
3652 (else 0))))
3653 (ret (make-shared-substring str 0 end)
3654 (make-shared-substring str end))))
3655
3656 (define-public (split-before-char-last char str ret)
3657 (let ((end (or (string-rindex str char) 0)))
3658 (ret (make-shared-substring str 0 end)
3659 (make-shared-substring str end))))
3660
3661 (define-public (split-discarding-char-last char str ret)
3662 (let ((end (string-rindex str char)))
3663 (if (not end)
3664 (ret str "")
3665 (ret (make-shared-substring str 0 end)
3666 (make-shared-substring str (1+ end))))))
3667
3668 (define (split-before-predicate pred str ret)
3669 (let loop ((n 0))
3670 (cond
3671 ((= n (length str)) (ret str ""))
3672 ((not (pred (string-ref str n))) (loop (1+ n)))
3673 (else (ret (make-shared-substring str 0 n)
3674 (make-shared-substring str n))))))
3675 (define (split-after-predicate pred str ret)
3676 (let loop ((n 0))
3677 (cond
3678 ((= n (length str)) (ret str ""))
3679 ((not (pred (string-ref str n))) (loop (1+ n)))
3680 (else (ret (make-shared-substring str 0 (1+ n))
3681 (make-shared-substring str (1+ n)))))))
3682
3683 (define (split-discarding-predicate pred str ret)
3684 (let loop ((n 0))
3685 (cond
3686 ((= n (length str)) (ret str ""))
3687 ((not (pred (string-ref str n))) (loop (1+ n)))
3688 (else (ret (make-shared-substring str 0 n)
3689 (make-shared-substring str (1+ n)))))))
3690
3691 (define-public (separate-fields-discarding-char ch str ret)
3692 (let loop ((fields '())
3693 (str str))
3694 (cond
3695 ((string-rindex str ch)
3696 => (lambda (pos) (loop (cons (make-shared-substring str (+ 1 w)) fields)
3697 (make-shared-substring str 0 w))))
3698 (else (ret (cons str fields))))))
3699
3700 (define-public (separate-fields-after-char ch str ret)
3701 (let loop ((fields '())
3702 (str str))
3703 (cond
3704 ((string-rindex str ch)
3705 => (lambda (pos) (loop (cons (make-shared-substring str (+ 1 w)) fields)
3706 (make-shared-substring str 0 (+ 1 w)))))
3707 (else (ret (cons str fields))))))
3708
3709 (define-public (separate-fields-before-char ch str ret)
3710 (let loop ((fields '())
3711 (str str))
3712 (cond
3713 ((string-rindex str ch)
3714 => (lambda (pos) (loop (cons (make-shared-substring str w) fields)
3715 (make-shared-substring str 0 w))))
3716 (else (ret (cons str fields))))))
3717
3718 \f
3719 ;;; {String Fun: String Prefix Predicates}
3720 ;;;
3721 ;;; Very simple:
3722 ;;;
3723 ;;; (define-public ((string-prefix-predicate pred?) prefix str)
3724 ;;; (and (<= (length prefix) (length str))
3725 ;;; (pred? prefix (make-shared-substring str 0 (length prefix)))))
3726 ;;;
3727 ;;; (define-public string-prefix=? (string-prefix-predicate string=?))
3728 ;;;
3729
3730 (define-public ((string-prefix-predicate pred?) prefix str)
3731 (and (<= (length prefix) (length str))
3732 (pred? prefix (make-shared-substring str 0 (length prefix)))))
3733
3734 (define-public string-prefix=? (string-prefix-predicate string=?))
3735
3736 \f
3737 ;;; {String Fun: Strippers}
3738 ;;;
3739 ;;; <stripper> = sans-<removable-part>
3740 ;;;
3741 ;;; <removable-part> = surrounding-whitespace
3742 ;;; | trailing-whitespace
3743 ;;; | leading-whitespace
3744 ;;; | final-newline
3745 ;;;
3746
3747 (define-public (sans-surrounding-whitespace s)
3748 (let ((st 0)
3749 (end (string-length s)))
3750 (while (and (< st (string-length s))
3751 (char-whitespace? (string-ref s st)))
3752 (set! st (1+ st)))
3753 (while (and (< 0 end)
3754 (char-whitespace? (string-ref s (1- end))))
3755 (set! end (1- end)))
3756 (if (< end st)
3757 ""
3758 (make-shared-substring s st end))))
3759
3760 (define-public (sans-trailing-whitespace s)
3761 (let ((st 0)
3762 (end (string-length s)))
3763 (while (and (< 0 end)
3764 (char-whitespace? (string-ref s (1- end))))
3765 (set! end (1- end)))
3766 (if (< end st)
3767 ""
3768 (make-shared-substring s st end))))
3769
3770 (define-public (sans-leading-whitespace s)
3771 (let ((st 0)
3772 (end (string-length s)))
3773 (while (and (< st (string-length s))
3774 (char-whitespace? (string-ref s st)))
3775 (set! st (1+ st)))
3776 (if (< end st)
3777 ""
3778 (make-shared-substring s st end))))
3779
3780 (define-public (sans-final-newline str)
3781 (cond
3782 ((= 0 (string-length str))
3783 str)
3784
3785 ((char=? #\nl (string-ref str (1- (string-length str))))
3786 (make-shared-substring str 0 (1- (string-length str))))
3787
3788 (else str)))
3789 \f
3790 ;;; {String Fun: has-trailing-newline?}
3791 ;;;
3792
3793 (define-public (has-trailing-newline? str)
3794 (and (< 0 (string-length str))
3795 (char=? #\nl (string-ref str (1- (string-length str))))))
3796
3797
3798 \f
3799 ;;; {String Fun: with-regexp-parts}
3800
3801 (define-public (with-regexp-parts regexp fields str return fail)
3802 (let ((parts (regexec regexp str fields)))
3803 (if (number? parts)
3804 (fail parts)
3805 (apply return parts))))
3806
3807 \f
3808 ;;; {Load debug extension code if debug extensions present.}
3809 ;;;
3810 ;;; *fixme* This is a temporary solution.
3811 ;;;
3812
3813 (if (memq 'debug-extensions *features*)
3814 (define-module (guile) :use-module (ice-9 debug)))
3815
3816 \f
3817 ;;; {Load session support if present.}
3818 ;;;
3819 ;;; *fixme* This is a temporary solution.
3820 ;;;
3821
3822 (if (%search-load-path "ice-9/session.scm")
3823 (define-module (guile) :use-module (ice-9 session)))
3824
3825 \f
3826 ;;; {Load thread code if threads are present.}
3827 ;;;
3828 ;;; *fixme* This is a temporary solution.
3829 ;;;
3830
3831 (if (memq 'threads *features*)
3832 (define-module (guile) :use-module (ice-9 threads)))
3833
3834 \f
3835 ;;; {Load emacs interface support if emacs option is given.}
3836 ;;;
3837 ;;; *fixme* This is a temporary solution.
3838 ;;;
3839
3840 (if (and (module-defined? the-root-module 'use-emacs-interface)
3841 use-emacs-interface)
3842 (define-module (guile) :use-module (ice-9 emacs)))
3843
3844 \f
3845 ;;; {Load regexp code if regexp primitives are available.}
3846
3847 (if (memq 'regex *features*)
3848 (define-module (guile) :use-module (ice-9 regex)))
3849
3850 \f
3851
3852 (define-module (guile))
3853
3854 (append! %load-path (cons "." ()))