Add note about "#&".
[bpt/guile.git] / ice-9 / boot-9.scm
CommitLineData
0f2d19dd
JB
1;;; installed-scm-file
2
6906bd0d 3;;;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
0f2d19dd
JB
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
15328041
JB
17;;;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18;;;; Boston, MA 02111-1307 USA
0f2d19dd
JB
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
21ed9efe
MD
30;;; {Features}
31;;
32
33(define (provide sym)
34 (if (not (memq sym *features*))
35 (set! *features* (cons sym *features*))))
36
50706e94
JB
37;;; Return #t iff FEATURE is available to this Guile interpreter.
38;;; In SLIB, provided? also checks to see if the module is available.
39;;; We should do that too, but don't.
40(define (provided? feature)
41 (and (memq feature *features*) #t))
42
52cfc69b
GH
43;;; presumably deprecated.
44(define feature? provided?)
45
8641dd9e
GB
46;;; let format alias simple-format until the more complete version is loaded
47(define format simple-format)
48
21ed9efe 49\f
79451588
JB
50;;; {R4RS compliance}
51
52(primitive-load-path "ice-9/r4rs.scm")
53
54\f
44cf1f0f 55;;; {Simple Debugging Tools}
0f2d19dd
JB
56;;
57
58
59;; peek takes any number of arguments, writes them to the
60;; current ouput port, and returns the last argument.
61;; It is handy to wrap around an expression to look at
62;; a value each time is evaluated, e.g.:
63;;
64;; (+ 10 (troublesome-fn))
65;; => (+ 10 (pk 'troublesome-fn-returned (troublesome-fn)))
66;;
67
68(define (peek . stuff)
69 (newline)
70 (display ";;; ")
71 (write stuff)
72 (newline)
73 (car (last-pair stuff)))
74
75(define pk peek)
76
77(define (warn . stuff)
78 (with-output-to-port (current-error-port)
79 (lambda ()
80 (newline)
81 (display ";;; WARNING ")
6355358a 82 (display stuff)
0f2d19dd
JB
83 (newline)
84 (car (last-pair stuff)))))
85
86\f
79451588 87;;; {Trivial Functions}
0f2d19dd 88;;;
79451588
JB
89
90(define (id x) x)
91(define (1+ n) (+ n 1))
92(define (-1+ n) (+ n -1))
93(define 1- -1+)
94(define return-it noop)
132e5fac 95(define (and=> value procedure) (and value (procedure value)))
79451588
JB
96(define (make-hash-table k) (make-vector k '()))
97
0f2d19dd
JB
98;;; apply-to-args is functionally redunant with apply and, worse,
99;;; is less general than apply since it only takes two arguments.
100;;;
101;;; On the other hand, apply-to-args is a syntacticly convenient way to
102;;; perform binding in many circumstances when the "let" family of
103;;; of forms don't cut it. E.g.:
104;;;
105;;; (apply-to-args (return-3d-mouse-coords)
106;;; (lambda (x y z)
107;;; ...))
108;;;
109
110(define (apply-to-args args fn) (apply fn args))
111
112\f
0f2d19dd
JB
113;;; {Integer Math}
114;;;
115
0f2d19dd
JB
116(define (ipow-by-squaring x k acc proc)
117 (cond ((zero? k) acc)
118 ((= 1 k) (proc acc x))
52c5a23a
JB
119 (else (ipow-by-squaring (proc x x)
120 (quotient k 2)
121 (if (even? k) acc (proc acc x))
122 proc))))
0f2d19dd
JB
123
124(define string-character-length string-length)
125
126
127
128;; A convenience function for combining flag bits. Like logior, but
129;; handles the cases of 0 and 1 arguments.
130;;
131(define (flags . args)
132 (cond
133 ((null? args) 0)
134 ((null? (cdr args)) (car args))
135 (else (apply logior args))))
136
137\f
0f2d19dd
JB
138;;; {Symbol Properties}
139;;;
140
141(define (symbol-property sym prop)
142 (let ((pair (assoc prop (symbol-pref sym))))
143 (and pair (cdr pair))))
144
145(define (set-symbol-property! sym prop val)
146 (let ((pair (assoc prop (symbol-pref sym))))
147 (if pair
148 (set-cdr! pair val)
149 (symbol-pset! sym (acons prop val (symbol-pref sym))))))
150
151(define (symbol-property-remove! sym prop)
152 (let ((pair (assoc prop (symbol-pref sym))))
153 (if pair
154 (symbol-pset! sym (delq! pair (symbol-pref sym))))))
155
156\f
1e531c3a
GH
157
158;;; {Line and Delimited I/O}
159
160;;; corresponds to SCM_LINE_INCREMENTORS in libguile.
161(define scm-line-incrementors "\n")
162
163(define (read-line! string . maybe-port)
164 (let* ((port (if (pair? maybe-port)
165 (car maybe-port)
166 (current-input-port))))
167 (let* ((rv (%read-delimited! scm-line-incrementors
168 string
169 #t
170 port))
171 (terminator (car rv))
172 (nchars (cdr rv)))
173 (cond ((and (= nchars 0)
174 (eof-object? terminator))
175 terminator)
176 ((not terminator) #f)
177 (else nchars)))))
178
179(define (read-delimited! delims buf . args)
180 (let* ((num-args (length args))
181 (port (if (> num-args 0)
182 (car args)
183 (current-input-port)))
184 (handle-delim (if (> num-args 1)
185 (cadr args)
186 'trim))
187 (start (if (> num-args 2)
188 (caddr args)
189 0))
190 (end (if (> num-args 3)
191 (cadddr args)
192 (string-length buf))))
193 (let* ((rv (%read-delimited! delims
194 buf
195 (not (eq? handle-delim 'peek))
196 port
197 start
198 end))
199 (terminator (car rv))
200 (nchars (cdr rv)))
201 (cond ((or (not terminator) ; buffer filled
202 (eof-object? terminator))
203 (if (zero? nchars)
204 (if (eq? handle-delim 'split)
205 (cons terminator terminator)
206 terminator)
207 (if (eq? handle-delim 'split)
208 (cons nchars terminator)
209 nchars)))
210 (else
211 (case handle-delim
212 ((trim peek) nchars)
e3306d80 213 ((concat) (string-set! buf (+ nchars start) terminator)
1e531c3a
GH
214 (+ nchars 1))
215 ((split) (cons nchars terminator))
216 (else (error "unexpected handle-delim value: "
217 handle-delim))))))))
218
219(define (read-delimited delims . args)
220 (let* ((port (if (pair? args)
221 (let ((pt (car args)))
222 (set! args (cdr args))
223 pt)
224 (current-input-port)))
225 (handle-delim (if (pair? args)
226 (car args)
227 'trim)))
228 (let loop ((substrings ())
229 (total-chars 0)
230 (buf-size 100)) ; doubled each time through.
231 (let* ((buf (make-string buf-size))
232 (rv (%read-delimited! delims
233 buf
234 (not (eq? handle-delim 'peek))
235 port))
236 (terminator (car rv))
237 (nchars (cdr rv))
238 (join-substrings
239 (lambda ()
240 (apply string-append
241 (reverse
242 (cons (if (and (eq? handle-delim 'concat)
243 (not (eof-object? terminator)))
244 (string terminator)
245 "")
246 (cons (make-shared-substring buf 0 nchars)
247 substrings))))))
248 (new-total (+ total-chars nchars)))
249 (cond ((not terminator)
250 ;; buffer filled.
251 (loop (cons (substring buf 0 nchars) substrings)
252 new-total
253 (* buf-size 2)))
254 ((eof-object? terminator)
255 (if (zero? new-total)
256 (if (eq? handle-delim 'split)
257 (cons terminator terminator)
258 terminator)
259 (if (eq? handle-delim 'split)
260 (cons (join-substrings) terminator)
261 (join-substrings))))
262 (else
263 (case handle-delim
264 ((trim peek concat) (join-substrings))
265 ((split) (cons (join-substrings) terminator))
848f2a01
TP
266
267
1e531c3a
GH
268 (else (error "unexpected handle-delim value: "
269 handle-delim)))))))))
848f2a01
TP
270
271;;; read-line [PORT [HANDLE-DELIM]] reads a newline-terminated string
272;;; from PORT. The return value depends on the value of HANDLE-DELIM,
273;;; which may be one of the symbols `trim', `concat', `peek' and
274;;; `split'. If it is `trim' (the default), the trailing newline is
275;;; removed and the string is returned. If `concat', the string is
276;;; returned with the trailing newline intact. If `peek', the newline
277;;; is left in the input port buffer and the string is returned. If
278;;; `split', the newline is split from the string and read-line
279;;; returns a pair consisting of the truncated string and the newline.
280
1e531c3a 281(define (read-line . args)
848f2a01
TP
282 (let* ((port (if (null? args)
283 (current-input-port)
284 (car args)))
285 (handle-delim (if (> (length args) 1)
286 (cadr args)
287 'trim))
288 (line/delim (%read-line port))
289 (line (car line/delim))
290 (delim (cdr line/delim)))
291 (case handle-delim
292 ((trim) line)
293 ((split) line/delim)
294 ((concat) (if (and (string? line) (char? delim))
295 (string-append line (string delim))
296 line))
297 ((peek) (if (char? delim)
298 (unread-char delim port))
299 line)
300 (else
301 (error "unexpected handle-delim value: " handle-delim)))))
1e531c3a
GH
302
303\f
0f2d19dd
JB
304;;; {Arrays}
305;;;
306
afe5177e
GH
307(if (provided? 'array)
308 (primitive-load-path "ice-9/arrays.scm"))
0f2d19dd
JB
309
310\f
311;;; {Keywords}
312;;;
313
314(define (symbol->keyword symbol)
315 (make-keyword-from-dash-symbol (symbol-append '- symbol)))
316
317(define (keyword->symbol kw)
06f0414c 318 (let ((sym (symbol->string (keyword-dash-symbol kw))))
11b05261 319 (string->symbol (substring sym 1 (string-length sym)))))
0f2d19dd
JB
320
321(define (kw-arg-ref args kw)
322 (let ((rem (member kw args)))
323 (and rem (pair? (cdr rem)) (cadr rem))))
324
325\f
fa7e9274 326
9f9aa47b 327;;; {Structs}
fa7e9274
MV
328
329(define (struct-layout s)
9f9aa47b 330 (struct-ref (struct-vtable s) vtable-index-layout))
fa7e9274
MV
331
332\f
d7faeb2e
MD
333
334;;; Environments
335
336(define the-environment
337 (procedure->syntax
338 (lambda (x e)
339 e)))
340
341(define the-root-environment (the-environment))
342
343(define (environment-module env)
344 (let ((closure (and (pair? env) (car (last-pair env)))))
345 (and closure (procedure-property closure 'module))))
346
347\f
0f2d19dd
JB
348;;; {Records}
349;;;
350
fa7e9274
MV
351;; Printing records: by default, records are printed as
352;;
353;; #<type-name field1: val1 field2: val2 ...>
354;;
355;; You can change that by giving a custom printing function to
356;; MAKE-RECORD-TYPE (after the list of field symbols). This function
357;; will be called like
358;;
359;; (<printer> object port)
360;;
361;; It should print OBJECT to PORT.
362
cf8f1a90 363(define (inherit-print-state old-port new-port)
8a30733e
MD
364 (if (get-print-state old-port)
365 (port-with-print-state new-port (get-print-state old-port))
cf8f1a90
MV
366 new-port))
367
9f9aa47b 368;; 0: type-name, 1: fields
fa7e9274 369(define record-type-vtable
9f9aa47b
MD
370 (make-vtable-vtable "prpr" 0
371 (lambda (s p)
372 (cond ((eq? s record-type-vtable)
373 (display "#<record-type-vtable>" p))
374 (else
375 (display "#<record-type " p)
376 (display (record-type-name s) p)
377 (display ">" p))))))
0f2d19dd
JB
378
379(define (record-type? obj)
380 (and (struct? obj) (eq? record-type-vtable (struct-vtable obj))))
381
382(define (make-record-type type-name fields . opt)
8e693424 383 (let ((printer-fn (and (pair? opt) (car opt))))
0f2d19dd 384 (let ((struct (make-struct record-type-vtable 0
c7c03b9f 385 (make-struct-layout
06f0414c 386 (apply string-append
c7c03b9f 387 (map (lambda (f) "pw") fields)))
9f9aa47b
MD
388 (or printer-fn
389 (lambda (s p)
390 (display "#<" p)
391 (display type-name p)
392 (let loop ((fields fields)
393 (off 0))
394 (cond
395 ((not (null? fields))
396 (display " " p)
397 (display (car fields) p)
398 (display ": " p)
399 (display (struct-ref s off) p)
400 (loop (cdr fields) (+ 1 off)))))
401 (display ">" p)))
0f2d19dd
JB
402 type-name
403 (copy-tree fields))))
c8eed875
MD
404 ;; Temporary solution: Associate a name to the record type descriptor
405 ;; so that the object system can create a wrapper class for it.
406 (set-struct-vtable-name! struct (if (symbol? type-name)
407 type-name
408 (string->symbol type-name)))
0f2d19dd
JB
409 struct)))
410
411(define (record-type-name obj)
412 (if (record-type? obj)
9f9aa47b 413 (struct-ref obj vtable-offset-user)
0f2d19dd
JB
414 (error 'not-a-record-type obj)))
415
416(define (record-type-fields obj)
417 (if (record-type? obj)
9f9aa47b 418 (struct-ref obj (+ 1 vtable-offset-user))
0f2d19dd
JB
419 (error 'not-a-record-type obj)))
420
421(define (record-constructor rtd . opt)
8e693424 422 (let ((field-names (if (pair? opt) (car opt) (record-type-fields rtd))))
d7faeb2e
MD
423 (local-eval `(lambda ,field-names
424 (make-struct ',rtd 0 ,@(map (lambda (f)
425 (if (memq f field-names)
426 f
427 #f))
428 (record-type-fields rtd))))
429 the-root-environment)))
0f2d19dd
JB
430
431(define (record-predicate rtd)
432 (lambda (obj) (and (struct? obj) (eq? rtd (struct-vtable obj)))))
433
434(define (record-accessor rtd field-name)
435 (let* ((pos (list-index (record-type-fields rtd) field-name)))
436 (if (not pos)
437 (error 'no-such-field field-name))
d7faeb2e
MD
438 (local-eval `(lambda (obj)
439 (and (eq? ',rtd (record-type-descriptor obj))
440 (struct-ref obj ,pos)))
441 the-root-environment)))
0f2d19dd
JB
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))
d7faeb2e
MD
447 (local-eval `(lambda (obj val)
448 (and (eq? ',rtd (record-type-descriptor obj))
449 (struct-set! obj ,pos val)))
450 the-root-environment)))
0f2d19dd
JB
451
452
453(define (record? obj)
454 (and (struct? obj) (record-type? (struct-vtable obj))))
455
456(define (record-type-descriptor obj)
457 (if (struct? obj)
458 (struct-vtable obj)
459 (error 'not-a-record obj)))
460
21ed9efe
MD
461(provide 'record)
462
0f2d19dd
JB
463\f
464;;; {Booleans}
465;;;
466
467(define (->bool x) (not (not x)))
468
469\f
470;;; {Symbols}
471;;;
472
473(define (symbol-append . args)
06f0414c 474 (string->symbol (apply string-append (map symbol->string args))))
0f2d19dd
JB
475
476(define (list->symbol . args)
477 (string->symbol (apply list->string args)))
478
479(define (symbol . args)
480 (string->symbol (apply string args)))
481
0f2d19dd
JB
482\f
483;;; {Lists}
484;;;
485
486(define (list-index l k)
487 (let loop ((n 0)
488 (l l))
489 (and (not (null? l))
490 (if (eq? (car l) k)
491 n
492 (loop (+ n 1) (cdr l))))))
493
75fd4fb6
JB
494(define (make-list n . init)
495 (if (pair? init) (set! init (car init)))
0f2d19dd
JB
496 (let loop ((answer '())
497 (n n))
498 (if (<= n 0)
499 answer
500 (loop (cons init answer) (- n 1)))))
501
502
503\f
1729d8ff
MD
504;;; {Multiple return values}
505
506(define *values-rtd*
507 (make-record-type "values"
508 '(values)))
509
44484f52
MD
510;;; These two are needed internally in boot-9.scm.
511;;; They shouldn't be visible outside this module.
512(define values? (record-predicate *values-rtd*))
513(define get-values (record-accessor *values-rtd* 'values))
514
1729d8ff
MD
515(define values
516 (let ((make-values (record-constructor *values-rtd*)))
517 (lambda x
518 (if (and (not (null? x))
519 (null? (cdr x)))
520 (car x)
521 (make-values x)))))
522
523(define call-with-values
44484f52
MD
524 (lambda (producer consumer)
525 (let ((result (producer)))
526 (if (values? result)
527 (apply consumer (get-values result))
528 (consumer result)))))
1729d8ff 529
87cfc5da 530(provide 'values)
1729d8ff
MD
531
532\f
3e3cec45 533;;; {and-map and or-map}
0f2d19dd
JB
534;;;
535;;; (and-map fn lst) is like (and (fn (car lst)) (fn (cadr lst)) (fn...) ...)
536;;; (or-map fn lst) is like (or (fn (car lst)) (fn (cadr lst)) (fn...) ...)
537;;; (map-in-order fn lst) is like (map fn lst) but definately in order of lst.
538;;;
539
540;; and-map f l
541;;
542;; Apply f to successive elements of l until exhaustion or f returns #f.
543;; If returning early, return #f. Otherwise, return the last value returned
544;; by f. If f has never been called because l is empty, return #t.
545;;
546(define (and-map f lst)
547 (let loop ((result #t)
548 (l lst))
549 (and result
550 (or (and (null? l)
551 result)
552 (loop (f (car l)) (cdr l))))))
553
554;; or-map f l
555;;
556;; Apply f to successive elements of l until exhaustion or while f returns #f.
557;; If returning early, return the return value of f.
558;;
559(define (or-map f lst)
560 (let loop ((result #f)
561 (l lst))
562 (or result
563 (and (not (null? l))
564 (loop (f (car l)) (cdr l))))))
565
59e1116d 566\f
0f2d19dd 567
52cfc69b
GH
568(if (provided? 'posix)
569 (primitive-load-path "ice-9/posix.scm"))
6fa8995c 570
52cfc69b
GH
571(if (provided? 'socket)
572 (primitive-load-path "ice-9/networking.scm"))
3afb28ce 573
6fa8995c 574(define file-exists?
52cfc69b 575 (if (provided? 'posix)
6fa8995c
GH
576 (lambda (str)
577 (access? str F_OK))
578 (lambda (str)
579 (let ((port (catch 'system-error (lambda () (open-file str OPEN_READ))
580 (lambda args #f))))
581 (if port (begin (close-port port) #t)
582 #f)))))
583
584(define file-is-directory?
52cfc69b 585 (if (provided? 'posix)
6fa8995c 586 (lambda (str)
3afb28ce 587 (eq? (stat:type (stat str)) 'directory))
6fa8995c 588 (lambda (str)
6fa8995c
GH
589 (let ((port (catch 'system-error
590 (lambda () (open-file (string-append str "/.")
591 OPEN_READ))
592 (lambda args #f))))
593 (if port (begin (close-port port) #t)
594 #f)))))
0f2d19dd
JB
595
596(define (has-suffix? str suffix)
597 (let ((sufl (string-length suffix))
598 (sl (string-length str)))
599 (and (> sl sufl)
600 (string=? (substring str (- sl sufl) sl) suffix))))
601
0f2d19dd
JB
602\f
603;;; {Error Handling}
604;;;
605
0f2d19dd 606(define (error . args)
21ed9efe 607 (save-stack)
2194b6f0 608 (if (null? args)
5552355a 609 (scm-error 'misc-error #f "?" #f #f)
8641dd9e 610 (let loop ((msg "~A")
2194b6f0
GH
611 (rest (cdr args)))
612 (if (not (null? rest))
8641dd9e 613 (loop (string-append msg " ~S")
2194b6f0 614 (cdr rest))
5552355a 615 (scm-error 'misc-error #f msg args #f)))))
be2d2c70 616
1349bd53 617;; bad-throw is the hook that is called upon a throw to a an unhandled
9a0d70e2
GH
618;; key (unless the throw has four arguments, in which case
619;; it's usually interpreted as an error throw.)
620;; If the key has a default handler (a throw-handler-default property),
0f2d19dd
JB
621;; it is applied to the throw.
622;;
1349bd53 623(define (bad-throw key . args)
0f2d19dd
JB
624 (let ((default (symbol-property key 'throw-handler-default)))
625 (or (and default (apply default key args))
2194b6f0 626 (apply error "unhandled-exception:" key args))))
0f2d19dd 627
0f2d19dd 628\f
bce074ee 629
708bf0f3
GH
630(define (tm:sec obj) (vector-ref obj 0))
631(define (tm:min obj) (vector-ref obj 1))
632(define (tm:hour obj) (vector-ref obj 2))
633(define (tm:mday obj) (vector-ref obj 3))
634(define (tm:mon obj) (vector-ref obj 4))
635(define (tm:year obj) (vector-ref obj 5))
636(define (tm:wday obj) (vector-ref obj 6))
637(define (tm:yday obj) (vector-ref obj 7))
638(define (tm:isdst obj) (vector-ref obj 8))
639(define (tm:gmtoff obj) (vector-ref obj 9))
640(define (tm:zone obj) (vector-ref obj 10))
641
642(define (set-tm:sec obj val) (vector-set! obj 0 val))
643(define (set-tm:min obj val) (vector-set! obj 1 val))
644(define (set-tm:hour obj val) (vector-set! obj 2 val))
645(define (set-tm:mday obj val) (vector-set! obj 3 val))
646(define (set-tm:mon obj val) (vector-set! obj 4 val))
647(define (set-tm:year obj val) (vector-set! obj 5 val))
648(define (set-tm:wday obj val) (vector-set! obj 6 val))
649(define (set-tm:yday obj val) (vector-set! obj 7 val))
650(define (set-tm:isdst obj val) (vector-set! obj 8 val))
651(define (set-tm:gmtoff obj val) (vector-set! obj 9 val))
652(define (set-tm:zone obj val) (vector-set! obj 10 val))
653
6afcd3b2
GH
654(define (tms:clock obj) (vector-ref obj 0))
655(define (tms:utime obj) (vector-ref obj 1))
656(define (tms:stime obj) (vector-ref obj 2))
657(define (tms:cutime obj) (vector-ref obj 3))
658(define (tms:cstime obj) (vector-ref obj 4))
659
bce074ee
GH
660(define (file-position . args) (apply ftell args))
661(define (file-set-position . args) (apply fseek args))
8b13c6b3 662
e38303a2
GH
663(define (move->fdes fd/port fd)
664 (cond ((integer? fd/port)
7a6f1ffa 665 (dup->fdes fd/port fd)
e38303a2
GH
666 (close fd/port)
667 fd)
668 (else
669 (primitive-move->fdes fd/port fd)
670 (set-port-revealed! fd/port 1)
671 fd/port)))
8b13c6b3
GH
672
673(define (release-port-handle port)
674 (let ((revealed (port-revealed port)))
675 (if (> revealed 0)
676 (set-port-revealed! port (- revealed 1)))))
0f2d19dd 677
e38303a2 678(define (dup->port port/fd mode . maybe-fd)
7a6f1ffa 679 (let ((port (fdopen (apply dup->fdes port/fd maybe-fd)
e38303a2
GH
680 mode)))
681 (if (pair? maybe-fd)
682 (set-port-revealed! port 1))
683 port))
684
685(define (dup->inport port/fd . maybe-fd)
686 (apply dup->port port/fd "r" maybe-fd))
687
688(define (dup->outport port/fd . maybe-fd)
689 (apply dup->port port/fd "w" maybe-fd))
690
e38303a2
GH
691(define (dup port/fd . maybe-fd)
692 (if (integer? port/fd)
693 (apply dup->fdes port/fd maybe-fd)
694 (apply dup->port port/fd (port-mode port/fd) maybe-fd)))
695
696(define (duplicate-port port modes)
697 (dup->port port modes))
698
699(define (fdes->inport fdes)
700 (let loop ((rest-ports (fdes->ports fdes)))
701 (cond ((null? rest-ports)
702 (let ((result (fdopen fdes "r")))
703 (set-port-revealed! result 1)
704 result))
705 ((input-port? (car rest-ports))
706 (set-port-revealed! (car rest-ports)
707 (+ (port-revealed (car rest-ports)) 1))
708 (car rest-ports))
709 (else
710 (loop (cdr rest-ports))))))
711
712(define (fdes->outport fdes)
713 (let loop ((rest-ports (fdes->ports fdes)))
714 (cond ((null? rest-ports)
715 (let ((result (fdopen fdes "w")))
716 (set-port-revealed! result 1)
717 result))
718 ((output-port? (car rest-ports))
719 (set-port-revealed! (car rest-ports)
720 (+ (port-revealed (car rest-ports)) 1))
721 (car rest-ports))
722 (else
723 (loop (cdr rest-ports))))))
724
725(define (port->fdes port)
726 (set-port-revealed! port (+ (port-revealed port) 1))
727 (fileno port))
728
956055a9
GH
729(define (setenv name value)
730 (if value
731 (putenv (string-append name "=" value))
732 (putenv name)))
733
0f2d19dd
JB
734\f
735;;; {Load Paths}
736;;;
737
0f2d19dd
JB
738;;; Here for backward compatability
739;;
740(define scheme-file-suffix (lambda () ".scm"))
741
3cab8392
JB
742(define (in-vicinity vicinity file)
743 (let ((tail (let ((len (string-length vicinity)))
534a0099
MD
744 (if (zero? len)
745 #f
3cab8392
JB
746 (string-ref vicinity (- len 1))))))
747 (string-append vicinity
534a0099
MD
748 (if (or (not tail)
749 (eq? tail #\/))
750 ""
751 "/")
3cab8392 752 file)))
02ceadb8 753
0f2d19dd 754\f
ef00e7f4
JB
755;;; {Help for scm_shell}
756;;; The argument-processing code used by Guile-based shells generates
757;;; Scheme code based on the argument list. This page contains help
758;;; functions for the code it generates.
759
ef00e7f4
JB
760(define (command-line) (program-arguments))
761
5aa7fe69
JB
762;; This is mostly for the internal use of the code generated by
763;; scm_compile_shell_switches.
ef00e7f4 764(define (load-user-init)
1f08acd9
GH
765 (let* ((home (or (getenv "HOME")
766 (false-if-exception (passwd:dir (getpwuid (getuid))))
767 "/")) ;; fallback for cygwin etc.
768 (init-file (in-vicinity home ".guile")))
769 (if (file-exists? init-file)
770 (primitive-load init-file))))
ef00e7f4
JB
771
772\f
a06181a2
JB
773;;; {Loading by paths}
774
775;;; Load a Scheme source file named NAME, searching for it in the
776;;; directories listed in %load-path, and applying each of the file
777;;; name extensions listed in %load-extensions.
778(define (load-from-path name)
779 (start-stack 'load-stack
75a97b92 780 (primitive-load-path name)))
0f2d19dd 781
5552355a 782
0f2d19dd 783\f
0f2d19dd
JB
784;;; {Transcendental Functions}
785;;;
786;;; Derived from "Transcen.scm", Complex trancendental functions for SCM.
0543c9b7 787;;; Written by Jerry D. Hedden, (C) FSF.
0f2d19dd
JB
788;;; See the file `COPYING' for terms applying to this program.
789;;;
790
791(define (exp z)
792 (if (real? z) ($exp z)
793 (make-polar ($exp (real-part z)) (imag-part z))))
794
795(define (log z)
796 (if (and (real? z) (>= z 0))
797 ($log z)
798 (make-rectangular ($log (magnitude z)) (angle z))))
799
800(define (sqrt z)
801 (if (real? z)
802 (if (negative? z) (make-rectangular 0 ($sqrt (- z)))
803 ($sqrt z))
804 (make-polar ($sqrt (magnitude z)) (/ (angle z) 2))))
805
806(define expt
807 (let ((integer-expt integer-expt))
808 (lambda (z1 z2)
22381005
DH
809 (cond ((integer? z2)
810 (if (>= z2 0)
811 (integer-expt z1 z2)
812 (/ 1 (integer-expt z1 (- z2)))))
0f2d19dd
JB
813 ((and (real? z2) (real? z1) (>= z1 0))
814 ($expt z1 z2))
815 (else
816 (exp (* z2 (log z1))))))))
817
818(define (sinh z)
819 (if (real? z) ($sinh z)
820 (let ((x (real-part z)) (y (imag-part z)))
821 (make-rectangular (* ($sinh x) ($cos y))
822 (* ($cosh x) ($sin y))))))
823(define (cosh z)
824 (if (real? z) ($cosh z)
825 (let ((x (real-part z)) (y (imag-part z)))
826 (make-rectangular (* ($cosh x) ($cos y))
827 (* ($sinh x) ($sin y))))))
828(define (tanh z)
829 (if (real? z) ($tanh z)
830 (let* ((x (* 2 (real-part z)))
831 (y (* 2 (imag-part z)))
832 (w (+ ($cosh x) ($cos y))))
833 (make-rectangular (/ ($sinh x) w) (/ ($sin y) w)))))
834
835(define (asinh z)
836 (if (real? z) ($asinh z)
837 (log (+ z (sqrt (+ (* z z) 1))))))
838
839(define (acosh z)
840 (if (and (real? z) (>= z 1))
841 ($acosh z)
842 (log (+ z (sqrt (- (* z z) 1))))))
843
844(define (atanh z)
845 (if (and (real? z) (> z -1) (< z 1))
846 ($atanh z)
847 (/ (log (/ (+ 1 z) (- 1 z))) 2)))
848
849(define (sin z)
850 (if (real? z) ($sin z)
851 (let ((x (real-part z)) (y (imag-part z)))
852 (make-rectangular (* ($sin x) ($cosh y))
853 (* ($cos x) ($sinh y))))))
854(define (cos z)
855 (if (real? z) ($cos z)
856 (let ((x (real-part z)) (y (imag-part z)))
857 (make-rectangular (* ($cos x) ($cosh y))
858 (- (* ($sin x) ($sinh y)))))))
859(define (tan z)
860 (if (real? z) ($tan z)
861 (let* ((x (* 2 (real-part z)))
862 (y (* 2 (imag-part z)))
863 (w (+ ($cos x) ($cosh y))))
864 (make-rectangular (/ ($sin x) w) (/ ($sinh y) w)))))
865
866(define (asin z)
867 (if (and (real? z) (>= z -1) (<= z 1))
868 ($asin z)
869 (* -i (asinh (* +i z)))))
870
871(define (acos z)
872 (if (and (real? z) (>= z -1) (<= z 1))
873 ($acos z)
874 (+ (/ (angle -1) 2) (* +i (asinh (* +i z))))))
875
876(define (atan z . y)
877 (if (null? y)
878 (if (real? z) ($atan z)
879 (/ (log (/ (- +i z) (+ +i z))) +2i))
880 ($atan2 z (car y))))
881
65495221
GH
882(define (log10 arg)
883 (/ (log arg) (log 10)))
884
0f2d19dd 885\f
0f2d19dd
JB
886
887;;; {Reader Extensions}
888;;;
889
890;;; Reader code for various "#c" forms.
891;;;
892
75a97b92
GH
893(read-hash-extend #\' (lambda (c port)
894 (read port)))
895(read-hash-extend #\. (lambda (c port)
d7faeb2e 896 (eval (read port) (interaction-environment))))
75a97b92 897
0f2d19dd
JB
898\f
899;;; {Command Line Options}
900;;;
901
902(define (get-option argv kw-opts kw-args return)
903 (cond
904 ((null? argv)
905 (return #f #f argv))
906
907 ((or (not (eq? #\- (string-ref (car argv) 0)))
908 (eq? (string-length (car argv)) 1))
909 (return 'normal-arg (car argv) (cdr argv)))
910
911 ((eq? #\- (string-ref (car argv) 1))
912 (let* ((kw-arg-pos (or (string-index (car argv) #\=)
913 (string-length (car argv))))
914 (kw (symbol->keyword (substring (car argv) 2 kw-arg-pos)))
915 (kw-opt? (member kw kw-opts))
916 (kw-arg? (member kw kw-args))
917 (arg (or (and (not (eq? kw-arg-pos (string-length (car argv))))
918 (substring (car argv)
919 (+ kw-arg-pos 1)
920 (string-length (car argv))))
921 (and kw-arg?
922 (begin (set! argv (cdr argv)) (car argv))))))
923 (if (or kw-opt? kw-arg?)
924 (return kw arg (cdr argv))
925 (return 'usage-error kw (cdr argv)))))
926
927 (else
928 (let* ((char (substring (car argv) 1 2))
929 (kw (symbol->keyword char)))
930 (cond
931
932 ((member kw kw-opts)
933 (let* ((rest-car (substring (car argv) 2 (string-length (car argv))))
934 (new-argv (if (= 0 (string-length rest-car))
935 (cdr argv)
936 (cons (string-append "-" rest-car) (cdr argv)))))
937 (return kw #f new-argv)))
938
939 ((member kw kw-args)
940 (let* ((rest-car (substring (car argv) 2 (string-length (car argv))))
941 (arg (if (= 0 (string-length rest-car))
942 (cadr argv)
943 rest-car))
944 (new-argv (if (= 0 (string-length rest-car))
945 (cddr argv)
946 (cdr argv))))
947 (return kw arg new-argv)))
948
949 (else (return 'usage-error kw argv)))))))
950
951(define (for-next-option proc argv kw-opts kw-args)
952 (let loop ((argv argv))
953 (get-option argv kw-opts kw-args
954 (lambda (opt opt-arg argv)
955 (and opt (proc opt opt-arg argv loop))))))
956
957(define (display-usage-report kw-desc)
958 (for-each
959 (lambda (kw)
960 (or (eq? (car kw) #t)
961 (eq? (car kw) 'else)
962 (let* ((opt-desc kw)
963 (help (cadr opt-desc))
964 (opts (car opt-desc))
965 (opts-proper (if (string? (car opts)) (cdr opts) opts))
966 (arg-name (if (string? (car opts))
967 (string-append "<" (car opts) ">")
968 ""))
969 (left-part (string-append
970 (with-output-to-string
971 (lambda ()
972 (map (lambda (x) (display (keyword-symbol x)) (display " "))
973 opts-proper)))
974 arg-name))
11b05261
MD
975 (middle-part (if (and (< (string-length left-part) 30)
976 (< (string-length help) 40))
977 (make-string (- 30 (string-length left-part)) #\ )
0f2d19dd
JB
978 "\n\t")))
979 (display left-part)
980 (display middle-part)
981 (display help)
982 (newline))))
983 kw-desc))
984
985
986
0f2d19dd
JB
987(define (transform-usage-lambda cases)
988 (let* ((raw-usage (delq! 'else (map car cases)))
989 (usage-sans-specials (map (lambda (x)
990 (or (and (not (list? x)) x)
991 (and (symbol? (car x)) #t)
992 (and (boolean? (car x)) #t)
993 x))
994 raw-usage))
ed440df5 995 (usage-desc (delq! #t usage-sans-specials))
0f2d19dd
JB
996 (kw-desc (map car usage-desc))
997 (kw-opts (apply append (map (lambda (x) (and (not (string? (car x))) x)) kw-desc)))
998 (kw-args (apply append (map (lambda (x) (and (string? (car x)) (cdr x))) kw-desc)))
999 (transmogrified-cases (map (lambda (case)
1000 (cons (let ((opts (car case)))
1001 (if (or (boolean? opts) (eq? 'else opts))
1002 opts
1003 (cond
1004 ((symbol? (car opts)) opts)
1005 ((boolean? (car opts)) opts)
1006 ((string? (caar opts)) (cdar opts))
1007 (else (car opts)))))
1008 (cdr case)))
1009 cases)))
1010 `(let ((%display-usage (lambda () (display-usage-report ',usage-desc))))
1011 (lambda (%argv)
1012 (let %next-arg ((%argv %argv))
1013 (get-option %argv
1014 ',kw-opts
1015 ',kw-args
1016 (lambda (%opt %arg %new-argv)
1017 (case %opt
1018 ,@ transmogrified-cases))))))))
1019
1020
1021\f
1022
1023;;; {Low Level Modules}
1024;;;
1025;;; These are the low level data structures for modules.
1026;;;
1027;;; !!! warning: The interface to lazy binder procedures is going
1028;;; to be changed in an incompatible way to permit all the basic
1029;;; module ops to be virtualized.
1030;;;
1031;;; (make-module size use-list lazy-binding-proc) => module
1032;;; module-{obarray,uses,binder}[|-set!]
1033;;; (module? obj) => [#t|#f]
1034;;; (module-locally-bound? module symbol) => [#t|#f]
1035;;; (module-bound? module symbol) => [#t|#f]
1036;;; (module-symbol-locally-interned? module symbol) => [#t|#f]
1037;;; (module-symbol-interned? module symbol) => [#t|#f]
1038;;; (module-local-variable module symbol) => [#<variable ...> | #f]
1039;;; (module-variable module symbol) => [#<variable ...> | #f]
1040;;; (module-symbol-binding module symbol opt-value)
1041;;; => [ <obj> | opt-value | an error occurs ]
1042;;; (module-make-local-var! module symbol) => #<variable...>
1043;;; (module-add! module symbol var) => unspecified
1044;;; (module-remove! module symbol) => unspecified
1045;;; (module-for-each proc module) => unspecified
1046;;; (make-scm-module) => module ; a lazy copy of the symhash module
1047;;; (set-current-module module) => unspecified
1048;;; (current-module) => #<module...>
1049;;;
1050;;;
1051
1052\f
44cf1f0f
JB
1053;;; {Printing Modules}
1054;; This is how modules are printed. You can re-define it.
fa7e9274
MV
1055;; (Redefining is actually more complicated than simply redefining
1056;; %print-module because that would only change the binding and not
1057;; the value stored in the vtable that determines how record are
1058;; printed. Sigh.)
1059
1060(define (%print-module mod port) ; unused args: depth length style table)
0f2d19dd
JB
1061 (display "#<" port)
1062 (display (or (module-kind mod) "module") port)
1063 (let ((name (module-name mod)))
1064 (if name
1065 (begin
1066 (display " " port)
1067 (display name port))))
1068 (display " " port)
1069 (display (number->string (object-address mod) 16) port)
1070 (display ">" port))
1071
1072;; module-type
1073;;
1074;; A module is characterized by an obarray in which local symbols
1075;; are interned, a list of modules, "uses", from which non-local
1076;; bindings can be inherited, and an optional lazy-binder which
31d50456 1077;; is a (CLOSURE module symbol) which, as a last resort, can provide
0f2d19dd
JB
1078;; bindings that would otherwise not be found locally in the module.
1079;;
d7faeb2e
MD
1080;; NOTE: If you change here, you also need to change libguile/modules.h.
1081;;
0f2d19dd 1082(define module-type
7a0ff2f8 1083 (make-record-type 'module
1777c18b
MD
1084 '(obarray uses binder eval-closure transformer name kind
1085 observers weak-observers observer-id)
8b718458 1086 %print-module))
0f2d19dd 1087
8b718458 1088;; make-module &opt size uses binder
0f2d19dd 1089;;
8b718458
JB
1090;; Create a new module, perhaps with a particular size of obarray,
1091;; initial uses list, or binding procedure.
0f2d19dd 1092;;
0f2d19dd
JB
1093(define make-module
1094 (lambda args
0f2d19dd 1095
8b718458
JB
1096 (define (parse-arg index default)
1097 (if (> (length args) index)
1098 (list-ref args index)
1099 default))
1100
1101 (if (> (length args) 3)
1102 (error "Too many args to make-module." args))
0f2d19dd 1103
8b718458
JB
1104 (let ((size (parse-arg 0 1021))
1105 (uses (parse-arg 1 '()))
1106 (binder (parse-arg 2 #f)))
0f2d19dd 1107
8b718458
JB
1108 (if (not (integer? size))
1109 (error "Illegal size to make-module." size))
1110 (if (not (and (list? uses)
1111 (and-map module? uses)))
1112 (error "Incorrect use list." uses))
0f2d19dd
JB
1113 (if (and binder (not (procedure? binder)))
1114 (error
1115 "Lazy-binder expected to be a procedure or #f." binder))
1116
8b718458 1117 (let ((module (module-constructor (make-vector size '())
1777c18b
MD
1118 uses binder #f #f #f #f
1119 '()
1120 (make-weak-value-hash-table 31)
1121 0)))
8b718458
JB
1122
1123 ;; We can't pass this as an argument to module-constructor,
1124 ;; because we need it to close over a pointer to the module
1125 ;; itself.
6906bd0d 1126 (set-module-eval-closure! module (standard-eval-closure module))
8b718458
JB
1127
1128 module))))
0f2d19dd 1129
8b718458 1130(define module-constructor (record-constructor module-type))
0f2d19dd
JB
1131(define module-obarray (record-accessor module-type 'obarray))
1132(define set-module-obarray! (record-modifier module-type 'obarray))
1133(define module-uses (record-accessor module-type 'uses))
1134(define set-module-uses! (record-modifier module-type 'uses))
1135(define module-binder (record-accessor module-type 'binder))
1136(define set-module-binder! (record-modifier module-type 'binder))
631c1902
MD
1137
1138;; NOTE: This binding is used in libguile/modules.c.
31d50456 1139(define module-eval-closure (record-accessor module-type 'eval-closure))
631c1902 1140
7a0ff2f8
MD
1141(define module-transformer (record-accessor module-type 'transformer))
1142(define set-module-transformer! (record-modifier module-type 'transformer))
0f2d19dd
JB
1143(define module-name (record-accessor module-type 'name))
1144(define set-module-name! (record-modifier module-type 'name))
1145(define module-kind (record-accessor module-type 'kind))
1146(define set-module-kind! (record-modifier module-type 'kind))
1777c18b
MD
1147(define module-observers (record-accessor module-type 'observers))
1148(define set-module-observers! (record-modifier module-type 'observers))
1149(define module-weak-observers (record-accessor module-type 'weak-observers))
1150(define module-observer-id (record-accessor module-type 'observer-id))
1151(define set-module-observer-id! (record-modifier module-type 'observer-id))
0f2d19dd
JB
1152(define module? (record-predicate module-type))
1153
edc185c7
MD
1154(define set-module-eval-closure!
1155 (let ((setter (record-modifier module-type 'eval-closure)))
1156 (lambda (module closure)
1157 (setter module closure)
1158 ;; Make it possible to lookup the module from the environment.
1159 ;; This implementation is correct since an eval closure can belong
1160 ;; to maximally one module.
1161 (set-procedure-property! closure 'module module))))
8b718458 1162
d7faeb2e
MD
1163;;; This procedure is depreated
1164;;;
1165(define eval-in-module eval)
0f2d19dd
JB
1166
1167\f
1777c18b
MD
1168;;; {Observer protocol}
1169;;;
1170
1171(define (module-observe module proc)
1172 (set-module-observers! module (cons proc (module-observers module)))
1173 (cons module proc))
1174
1175(define (module-observe-weak module proc)
1176 (let ((id (module-observer-id module)))
1177 (hash-set! (module-weak-observers module) id proc)
1178 (set-module-observer-id! module (+ 1 id))
1179 (cons module id)))
1180
1181(define (module-unobserve token)
1182 (let ((module (car token))
1183 (id (cdr token)))
1184 (if (integer? id)
1185 (hash-remove! (module-weak-observers module) id)
1186 (set-module-observers! module (delq1! id (module-observers module)))))
1187 *unspecified*)
1188
1a961d7e 1189(define (module-modified m)
1777c18b
MD
1190 (for-each (lambda (proc) (proc m)) (module-observers m))
1191 (hash-fold (lambda (id proc res) (proc m)) #f (module-weak-observers m)))
1192
1193\f
0f2d19dd
JB
1194;;; {Module Searching in General}
1195;;;
1196;;; We sometimes want to look for properties of a symbol
1197;;; just within the obarray of one module. If the property
1198;;; holds, then it is said to hold ``locally'' as in, ``The symbol
1199;;; DISPLAY is locally rebound in the module `safe-guile'.''
1200;;;
1201;;;
1202;;; Other times, we want to test for a symbol property in the obarray
1203;;; of M and, if it is not found there, try each of the modules in the
1204;;; uses list of M. This is the normal way of testing for some
1205;;; property, so we state these properties without qualification as
1206;;; in: ``The symbol 'fnord is interned in module M because it is
1207;;; interned locally in module M2 which is a member of the uses list
1208;;; of M.''
1209;;;
1210
1211;; module-search fn m
1212;;
1213;; return the first non-#f result of FN applied to M and then to
1214;; the modules in the uses of m, and so on recursively. If all applications
1215;; return #f, then so does this function.
1216;;
1217(define (module-search fn m v)
1218 (define (loop pos)
1219 (and (pair? pos)
1220 (or (module-search fn (car pos) v)
1221 (loop (cdr pos)))))
1222 (or (fn m v)
1223 (loop (module-uses m))))
1224
1225
1226;;; {Is a symbol bound in a module?}
1227;;;
1228;;; Symbol S in Module M is bound if S is interned in M and if the binding
1229;;; of S in M has been set to some well-defined value.
1230;;;
1231
1232;; module-locally-bound? module symbol
1233;;
1234;; Is a symbol bound (interned and defined) locally in a given module?
1235;;
1236(define (module-locally-bound? m v)
1237 (let ((var (module-local-variable m v)))
1238 (and var
1239 (variable-bound? var))))
1240
1241;; module-bound? module symbol
1242;;
1243;; Is a symbol bound (interned and defined) anywhere in a given module
1244;; or its uses?
1245;;
1246(define (module-bound? m v)
1247 (module-search module-locally-bound? m v))
1248
1249;;; {Is a symbol interned in a module?}
1250;;;
1251;;; Symbol S in Module M is interned if S occurs in
1252;;; of S in M has been set to some well-defined value.
1253;;;
1254;;; It is possible to intern a symbol in a module without providing
1255;;; an initial binding for the corresponding variable. This is done
1256;;; with:
1257;;; (module-add! module symbol (make-undefined-variable))
1258;;;
1259;;; In that case, the symbol is interned in the module, but not
1260;;; bound there. The unbound symbol shadows any binding for that
1261;;; symbol that might otherwise be inherited from a member of the uses list.
1262;;;
1263
1264(define (module-obarray-get-handle ob key)
1265 ((if (symbol? key) hashq-get-handle hash-get-handle) ob key))
1266
1267(define (module-obarray-ref ob key)
1268 ((if (symbol? key) hashq-ref hash-ref) ob key))
1269
1270(define (module-obarray-set! ob key val)
1271 ((if (symbol? key) hashq-set! hash-set!) ob key val))
1272
1273(define (module-obarray-remove! ob key)
1274 ((if (symbol? key) hashq-remove! hash-remove!) ob key))
1275
1276;; module-symbol-locally-interned? module symbol
1277;;
1278;; is a symbol interned (not neccessarily defined) locally in a given module
1279;; or its uses? Interned symbols shadow inherited bindings even if
1280;; they are not themselves bound to a defined value.
1281;;
1282(define (module-symbol-locally-interned? m v)
1283 (not (not (module-obarray-get-handle (module-obarray m) v))))
1284
1285;; module-symbol-interned? module symbol
1286;;
1287;; is a symbol interned (not neccessarily defined) anywhere in a given module
1288;; or its uses? Interned symbols shadow inherited bindings even if
1289;; they are not themselves bound to a defined value.
1290;;
1291(define (module-symbol-interned? m v)
1292 (module-search module-symbol-locally-interned? m v))
1293
1294
1295;;; {Mapping modules x symbols --> variables}
1296;;;
1297
1298;; module-local-variable module symbol
1299;; return the local variable associated with a MODULE and SYMBOL.
1300;;
1301;;; This function is very important. It is the only function that can
1302;;; return a variable from a module other than the mutators that store
1303;;; new variables in modules. Therefore, this function is the location
1304;;; of the "lazy binder" hack.
1305;;;
1306;;; If symbol is defined in MODULE, and if the definition binds symbol
1307;;; to a variable, return that variable object.
1308;;;
1309;;; If the symbols is not found at first, but the module has a lazy binder,
1310;;; then try the binder.
1311;;;
1312;;; If the symbol is not found at all, return #f.
1313;;;
1314(define (module-local-variable m v)
6fa8995c
GH
1315; (caddr
1316; (list m v
0f2d19dd
JB
1317 (let ((b (module-obarray-ref (module-obarray m) v)))
1318 (or (and (variable? b) b)
1319 (and (module-binder m)
6fa8995c
GH
1320 ((module-binder m) m v #f)))))
1321;))
0f2d19dd
JB
1322
1323;; module-variable module symbol
1324;;
1325;; like module-local-variable, except search the uses in the
1326;; case V is not found in M.
1327;;
6906bd0d
MD
1328;; NOTE: This function is superseded with C code (see modules.c)
1329;;; when using the standard eval closure.
1330;;
0f2d19dd
JB
1331(define (module-variable m v)
1332 (module-search module-local-variable m v))
1333
1334
1335;;; {Mapping modules x symbols --> bindings}
1336;;;
1337;;; These are similar to the mapping to variables, except that the
1338;;; variable is dereferenced.
1339;;;
1340
1341;; module-symbol-binding module symbol opt-value
1342;;
1343;; return the binding of a variable specified by name within
1344;; a given module, signalling an error if the variable is unbound.
1345;; If the OPT-VALUE is passed, then instead of signalling an error,
1346;; return OPT-VALUE.
1347;;
1348(define (module-symbol-local-binding m v . opt-val)
1349 (let ((var (module-local-variable m v)))
1350 (if var
1351 (variable-ref var)
1352 (if (not (null? opt-val))
1353 (car opt-val)
1354 (error "Locally unbound variable." v)))))
1355
1356;; module-symbol-binding module symbol opt-value
1357;;
1358;; return the binding of a variable specified by name within
1359;; a given module, signalling an error if the variable is unbound.
1360;; If the OPT-VALUE is passed, then instead of signalling an error,
1361;; return OPT-VALUE.
1362;;
1363(define (module-symbol-binding m v . opt-val)
1364 (let ((var (module-variable m v)))
1365 (if var
1366 (variable-ref var)
1367 (if (not (null? opt-val))
1368 (car opt-val)
1369 (error "Unbound variable." v)))))
1370
1371
1372\f
1373;;; {Adding Variables to Modules}
1374;;;
1375;;;
1376
1377
1378;; module-make-local-var! module symbol
1379;;
1380;; ensure a variable for V in the local namespace of M.
1381;; If no variable was already there, then create a new and uninitialzied
1382;; variable.
1383;;
1384(define (module-make-local-var! m v)
1385 (or (let ((b (module-obarray-ref (module-obarray m) v)))
1777c18b
MD
1386 (and (variable? b)
1387 (begin
1a961d7e 1388 (module-modified m)
1777c18b 1389 b)))
0f2d19dd
JB
1390 (and (module-binder m)
1391 ((module-binder m) m v #t))
1392 (begin
1393 (let ((answer (make-undefined-variable v)))
1394 (module-obarray-set! (module-obarray m) v answer)
1a961d7e 1395 (module-modified m)
0f2d19dd
JB
1396 answer))))
1397
1398;; module-add! module symbol var
1399;;
1400;; ensure a particular variable for V in the local namespace of M.
1401;;
1402(define (module-add! m v var)
1403 (if (not (variable? var))
1404 (error "Bad variable to module-add!" var))
1777c18b 1405 (module-obarray-set! (module-obarray m) v var)
1a961d7e 1406 (module-modified m))
0f2d19dd
JB
1407
1408;; module-remove!
1409;;
1410;; make sure that a symbol is undefined in the local namespace of M.
1411;;
1412(define (module-remove! m v)
1777c18b 1413 (module-obarray-remove! (module-obarray m) v)
1a961d7e 1414 (module-modified m))
0f2d19dd
JB
1415
1416(define (module-clear! m)
1777c18b 1417 (vector-fill! (module-obarray m) '())
1a961d7e 1418 (module-modified m))
0f2d19dd
JB
1419
1420;; MODULE-FOR-EACH -- exported
1421;;
1422;; Call PROC on each symbol in MODULE, with arguments of (SYMBOL VARIABLE).
1423;;
1424(define (module-for-each proc module)
1425 (let ((obarray (module-obarray module)))
1426 (do ((index 0 (+ index 1))
1427 (end (vector-length obarray)))
1428 ((= index end))
1429 (for-each
1430 (lambda (bucket)
1431 (proc (car bucket) (cdr bucket)))
1432 (vector-ref obarray index)))))
1433
1434
1435(define (module-map proc module)
1436 (let* ((obarray (module-obarray module))
1437 (end (vector-length obarray)))
1438
1439 (let loop ((i 0)
1440 (answer '()))
1441 (if (= i end)
1442 answer
1443 (loop (+ 1 i)
1444 (append!
1445 (map (lambda (bucket)
1446 (proc (car bucket) (cdr bucket)))
1447 (vector-ref obarray i))
1448 answer))))))
1449\f
1450
1451;;; {Low Level Bootstrapping}
1452;;;
1453
1454;; make-root-module
1455
21ed9efe 1456;; A root module uses the symhash table (the system's privileged
0f2d19dd
JB
1457;; obarray). Being inside a root module is like using SCM without
1458;; any module system.
1459;;
1460
1461
31d50456 1462(define (root-module-closure m s define?)
0f2d19dd
JB
1463 (let ((bi (and (symbol-interned? #f s)
1464 (builtin-variable s))))
1465 (and bi
1466 (or define? (variable-bound? bi))
1467 (begin
1468 (module-add! m s bi)
1469 bi))))
1470
1471(define (make-root-module)
31d50456 1472 (make-module 1019 '() root-module-closure))
0f2d19dd
JB
1473
1474
1475;; make-scm-module
1476
1477;; An scm module is a module into which the lazy binder copies
1478;; variable bindings from the system symhash table. The mapping is
1479;; one way only; newly introduced bindings in an scm module are not
1480;; copied back into the system symhash table (and can be used to override
1481;; bindings from the symhash table).
1482;;
1483
6906bd0d
MD
1484(define (scm-module-closure m s define?)
1485 (let ((bi (and (symbol-interned? #f s)
1486 (builtin-variable s))))
1487 (and bi
1488 (variable-bound? bi)
1489 (begin
1490 (module-add! m s bi)
1491 bi))))
0f2d19dd 1492
6906bd0d
MD
1493(define (make-scm-module)
1494 (make-module 1019 '() scm-module-closure))
0f2d19dd
JB
1495
1496
1497
1498;; the-module
631c1902
MD
1499;;
1500;; NOTE: This binding is used in libguile/modules.c.
1501;;
bd0fb3cf 1502(define the-module (make-fluid))
0f2d19dd 1503
7a0ff2f8 1504;; scm:eval-transformer
d43f8c97 1505;;
bd0fb3cf 1506;;(define scm:eval-transformer (make-fluid)) ; initialized in eval.c.
d43f8c97 1507
0f2d19dd
JB
1508;; set-current-module module
1509;;
1510;; set the current module as viewed by the normalizer.
1511;;
631c1902
MD
1512;; NOTE: This binding is used in libguile/modules.c.
1513;;
0f2d19dd 1514(define (set-current-module m)
bd0fb3cf 1515 (fluid-set! the-module m)
7a0ff2f8
MD
1516 (if m
1517 (begin
d7faeb2e 1518 ;; *top-level-lookup-closure* is now deprecated
bd0fb3cf
MD
1519 (fluid-set! *top-level-lookup-closure*
1520 (module-eval-closure (fluid-ref the-module)))
1521 (fluid-set! scm:eval-transformer (module-transformer (fluid-ref the-module))))
1522 (fluid-set! *top-level-lookup-closure* #f)))
0f2d19dd
JB
1523
1524
1525;; current-module
1526;;
1527;; return the current module as viewed by the normalizer.
1528;;
bd0fb3cf 1529(define (current-module) (fluid-ref the-module))
0f2d19dd
JB
1530\f
1531;;; {Module-based Loading}
1532;;;
1533
1534(define (save-module-excursion thunk)
1535 (let ((inner-module (current-module))
1536 (outer-module #f))
1537 (dynamic-wind (lambda ()
1538 (set! outer-module (current-module))
1539 (set-current-module inner-module)
1540 (set! inner-module #f))
1541 thunk
1542 (lambda ()
1543 (set! inner-module (current-module))
1544 (set-current-module outer-module)
1545 (set! outer-module #f)))))
1546
0f2d19dd
JB
1547(define basic-load load)
1548
c6775c40
MD
1549(define (load-module filename)
1550 (save-module-excursion
1551 (lambda ()
1552 (let ((oldname (and (current-load-port)
1553 (port-filename (current-load-port)))))
1554 (basic-load (if (and oldname
1555 (> (string-length filename) 0)
1556 (not (char=? (string-ref filename 0) #\/))
1557 (not (string=? (dirname oldname) ".")))
1558 (string-append (dirname oldname) "/" filename)
1559 filename))))))
0f2d19dd
JB
1560
1561
1562\f
44cf1f0f 1563;;; {MODULE-REF -- exported}
0f2d19dd
JB
1564;;
1565;; Returns the value of a variable called NAME in MODULE or any of its
1566;; used modules. If there is no such variable, then if the optional third
1567;; argument DEFAULT is present, it is returned; otherwise an error is signaled.
1568;;
1569(define (module-ref module name . rest)
1570 (let ((variable (module-variable module name)))
1571 (if (and variable (variable-bound? variable))
1572 (variable-ref variable)
1573 (if (null? rest)
1574 (error "No variable named" name 'in module)
1575 (car rest) ; default value
1576 ))))
1577
1578;; MODULE-SET! -- exported
1579;;
1580;; Sets the variable called NAME in MODULE (or in a module that MODULE uses)
1581;; to VALUE; if there is no such variable, an error is signaled.
1582;;
1583(define (module-set! module name value)
1584 (let ((variable (module-variable module name)))
1585 (if variable
1586 (variable-set! variable value)
1587 (error "No variable named" name 'in module))))
1588
1589;; MODULE-DEFINE! -- exported
1590;;
1591;; Sets the variable called NAME in MODULE to VALUE; if there is no such
1592;; variable, it is added first.
1593;;
1594(define (module-define! module name value)
1595 (let ((variable (module-local-variable module name)))
1596 (if variable
1777c18b
MD
1597 (begin
1598 (variable-set! variable value)
1a961d7e 1599 (module-modified module))
0f2d19dd
JB
1600 (module-add! module name (make-variable value name)))))
1601
ed218d98
MV
1602;; MODULE-DEFINED? -- exported
1603;;
1604;; Return #t iff NAME is defined in MODULE (or in a module that MODULE
1605;; uses)
1606;;
1607(define (module-defined? module name)
1608 (let ((variable (module-variable module name)))
1609 (and variable (variable-bound? variable))))
1610
0f2d19dd
JB
1611;; MODULE-USE! module interface
1612;;
1613;; Add INTERFACE to the list of interfaces used by MODULE.
1614;;
1615(define (module-use! module interface)
1616 (set-module-uses! module
1777c18b 1617 (cons interface (delq! interface (module-uses module))))
1a961d7e 1618 (module-modified module))
0f2d19dd
JB
1619
1620\f
0f2d19dd
JB
1621;;; {Recursive Namespaces}
1622;;;
1623;;;
1624;;; A hierarchical namespace emerges if we consider some module to be
1625;;; root, and variables bound to modules as nested namespaces.
1626;;;
1627;;; The routines in this file manage variable names in hierarchical namespace.
1628;;; Each variable name is a list of elements, looked up in successively nested
1629;;; modules.
1630;;;
0dd5491c 1631;;; (nested-ref some-root-module '(foo bar baz))
0f2d19dd
JB
1632;;; => <value of a variable named baz in the module bound to bar in
1633;;; the module bound to foo in some-root-module>
1634;;;
1635;;;
1636;;; There are:
1637;;;
1638;;; ;; a-root is a module
1639;;; ;; name is a list of symbols
1640;;;
0dd5491c
MD
1641;;; nested-ref a-root name
1642;;; nested-set! a-root name val
1643;;; nested-define! a-root name val
1644;;; nested-remove! a-root name
0f2d19dd
JB
1645;;;
1646;;;
1647;;; (current-module) is a natural choice for a-root so for convenience there are
1648;;; also:
1649;;;
0dd5491c
MD
1650;;; local-ref name == nested-ref (current-module) name
1651;;; local-set! name val == nested-set! (current-module) name val
1652;;; local-define! name val == nested-define! (current-module) name val
1653;;; local-remove! name == nested-remove! (current-module) name
0f2d19dd
JB
1654;;;
1655
1656
0dd5491c 1657(define (nested-ref root names)
0f2d19dd
JB
1658 (let loop ((cur root)
1659 (elts names))
1660 (cond
1661 ((null? elts) cur)
1662 ((not (module? cur)) #f)
1663 (else (loop (module-ref cur (car elts) #f) (cdr elts))))))
1664
0dd5491c 1665(define (nested-set! root names val)
0f2d19dd
JB
1666 (let loop ((cur root)
1667 (elts names))
1668 (if (null? (cdr elts))
1669 (module-set! cur (car elts) val)
1670 (loop (module-ref cur (car elts)) (cdr elts)))))
1671
0dd5491c 1672(define (nested-define! root names val)
0f2d19dd
JB
1673 (let loop ((cur root)
1674 (elts names))
1675 (if (null? (cdr elts))
1676 (module-define! cur (car elts) val)
1677 (loop (module-ref cur (car elts)) (cdr elts)))))
1678
0dd5491c 1679(define (nested-remove! root names)
0f2d19dd
JB
1680 (let loop ((cur root)
1681 (elts names))
1682 (if (null? (cdr elts))
1683 (module-remove! cur (car elts))
1684 (loop (module-ref cur (car elts)) (cdr elts)))))
1685
0dd5491c
MD
1686(define (local-ref names) (nested-ref (current-module) names))
1687(define (local-set! names val) (nested-set! (current-module) names val))
1688(define (local-define names val) (nested-define! (current-module) names val))
1689(define (local-remove names) (nested-remove! (current-module) names))
0f2d19dd
JB
1690
1691
1692\f
8bb7330c 1693;;; {The (app) module}
0f2d19dd
JB
1694;;;
1695;;; The root of conventionally named objects not directly in the top level.
1696;;;
8bb7330c
JB
1697;;; (app modules)
1698;;; (app modules guile)
0f2d19dd
JB
1699;;;
1700;;; The directory of all modules and the standard root module.
1701;;;
1702
edc185c7
MD
1703(define (module-public-interface m)
1704 (module-ref m '%module-public-interface #f))
1705(define (set-module-public-interface! m i)
1706 (module-define! m '%module-public-interface i))
1707(define (set-system-module! m s)
1708 (set-procedure-property! (module-eval-closure m) 'system-module s))
0f2d19dd
JB
1709(define the-root-module (make-root-module))
1710(define the-scm-module (make-scm-module))
1711(set-module-public-interface! the-root-module the-scm-module)
d5504515
MD
1712(set-module-name! the-root-module '(guile))
1713(set-module-name! the-scm-module '(guile))
1714(set-module-kind! the-scm-module 'interface)
edc185c7 1715(for-each set-system-module! (list the-root-module the-scm-module) '(#t #t))
0f2d19dd
JB
1716
1717(set-current-module the-root-module)
1718
1719(define app (make-module 31))
0dd5491c
MD
1720(local-define '(app modules) (make-module 31))
1721(local-define '(app modules guile) the-root-module)
0f2d19dd
JB
1722
1723;; (define-special-value '(app modules new-ws) (lambda () (make-scm-module)))
1724
432558b9
MD
1725(define (try-load-module name)
1726 (or (try-module-linked name)
1727 (try-module-autoload name)
1728 (try-module-dynamic-link name)))
1729
1f60d9d2
MD
1730;; NOTE: This binding is used in libguile/modules.c.
1731;;
0209ca9a 1732(define (resolve-module name . maybe-autoload)
0f2d19dd 1733 (let ((full-name (append '(app modules) name)))
0dd5491c 1734 (let ((already (local-ref full-name)))
432558b9
MD
1735 (if already
1736 ;; The module already exists...
1737 (if (and (or (null? maybe-autoload) (car maybe-autoload))
1738 (not (module-ref already '%module-public-interface #f)))
1739 ;; ...but we are told to load and it doesn't contain source, so
1740 (begin
1741 (try-load-module name)
1742 already)
1743 ;; simply return it.
1744 already)
3e3cec45 1745 (begin
432558b9 1746 ;; Try to autoload it if we are told so
3e3cec45 1747 (if (or (null? maybe-autoload) (car maybe-autoload))
432558b9
MD
1748 (try-load-module name))
1749 ;; Get/create it.
3e3cec45 1750 (make-modules-in (current-module) full-name))))))
0f2d19dd
JB
1751
1752(define (beautify-user-module! module)
3e3cec45
MD
1753 (let ((interface (module-public-interface module)))
1754 (if (or (not interface)
1755 (eq? interface module))
1756 (let ((interface (make-module 31)))
1757 (set-module-name! interface (module-name module))
1758 (set-module-kind! interface 'interface)
1759 (set-module-public-interface! module interface))))
cc7f066c
MD
1760 (if (and (not (memq the-scm-module (module-uses module)))
1761 (not (eq? module the-root-module)))
0f2d19dd
JB
1762 (set-module-uses! module (append (module-uses module) (list the-scm-module)))))
1763
90847923
MD
1764(define (purify-module! module)
1765 "Removes bindings in MODULE which are inherited from the (guile) module."
1766 (let ((use-list (module-uses module)))
1767 (if (and (pair? use-list)
1768 (eq? (car (last-pair use-list)) the-scm-module))
1769 (set-module-uses! module (reverse (cdr (reverse use-list)))))))
1770
631c1902
MD
1771;; NOTE: This binding is used in libguile/modules.c.
1772;;
0f2d19dd
JB
1773(define (make-modules-in module name)
1774 (if (null? name)
1775 module
1776 (cond
3e3cec45
MD
1777 ((module-ref module (car name) #f)
1778 => (lambda (m) (make-modules-in m (cdr name))))
0f2d19dd
JB
1779 (else (let ((m (make-module 31)))
1780 (set-module-kind! m 'directory)
d5504515
MD
1781 (set-module-name! m (append (or (module-name module)
1782 '())
1783 (list (car name))))
0f2d19dd
JB
1784 (module-define! module (car name) m)
1785 (make-modules-in m (cdr name)))))))
1786
1787(define (resolve-interface name)
1788 (let ((module (resolve-module name)))
1789 (and module (module-public-interface module))))
1790
1791
1792(define %autoloader-developer-mode #t)
1793
1794(define (process-define-module args)
1795 (let* ((module-id (car args))
0209ca9a 1796 (module (resolve-module module-id #f))
0f2d19dd
JB
1797 (kws (cdr args)))
1798 (beautify-user-module! module)
0209ca9a 1799 (let loop ((kws kws)
44484f52
MD
1800 (reversed-interfaces '())
1801 (exports '()))
0209ca9a 1802 (if (null? kws)
44484f52
MD
1803 (begin
1804 (for-each (lambda (interface)
1805 (module-use! module interface))
1806 reversed-interfaces)
1807 (module-export! module exports))
06f0414c
MD
1808 (let ((keyword (if (keyword? (car kws))
1809 (keyword->symbol (car kws))
1810 (and (symbol? (car kws))
1811 (let ((s (symbol->string (car kws))))
1812 (and (eq? (string-ref s 0) #\:)
1813 (string->symbol (substring s 1))))))))
f714ca8e
MD
1814 (case keyword
1815 ((use-module use-syntax)
1816 (if (not (pair? (cdr kws)))
1817 (error "unrecognized defmodule argument" kws))
1818 (let* ((used-name (cadr kws))
1819 (used-module (resolve-module used-name)))
45a02a29
MD
1820 (if (not (module-ref used-module
1821 '%module-public-interface
1822 #f))
3e3cec45 1823 (begin
45a02a29
MD
1824 ((if %autoloader-developer-mode warn error)
1825 "no code for module" (module-name used-module))
1826 (beautify-user-module! used-module)))
1827 (let ((interface (module-public-interface used-module)))
1828 (if (not interface)
1829 (error "missing interface for use-module"
1830 used-module))
1831 (if (eq? keyword 'use-syntax)
7cbaee0c
MD
1832 (set-module-transformer!
1833 module
45a02a29
MD
1834 (module-ref interface (car (last-pair used-name))
1835 #f)))
1836 (loop (cddr kws)
44484f52
MD
1837 (cons interface reversed-interfaces)
1838 exports))))
71225060
MD
1839 ((autoload)
1840 (if (not (and (pair? (cdr kws)) (pair? (cddr kws))))
1841 (error "unrecognized defmodule argument" kws))
1842 (loop (cdddr kws)
1843 (cons (make-autoload-interface module
1844 (cadr kws)
1845 (caddr kws))
44484f52
MD
1846 reversed-interfaces)
1847 exports))
edc185c7
MD
1848 ((no-backtrace)
1849 (set-system-module! module #t)
44484f52 1850 (loop (cdr kws) reversed-interfaces exports))
90847923
MD
1851 ((pure)
1852 (purify-module! module)
44484f52 1853 (loop (cdr kws) reversed-interfaces exports))
90847923 1854 ((export)
a473fead 1855 (if (not (pair? (cdr kws)))
90847923 1856 (error "unrecognized defmodule argument" kws))
44484f52
MD
1857 (loop (cddr kws)
1858 reversed-interfaces
1859 (append (cadr kws) exports)))
f714ca8e
MD
1860 (else
1861 (error "unrecognized defmodule argument" kws))))))
0f2d19dd 1862 module))
71225060
MD
1863
1864;;; {Autoload}
1865
1866(define (make-autoload-interface module name bindings)
1867 (let ((b (lambda (a sym definep)
1868 (and (memq sym bindings)
1869 (let ((i (module-public-interface (resolve-module name))))
1870 (if (not i)
1871 (error "missing interface for module" name))
1872 ;; Replace autoload-interface with interface
1873 (set-car! (memq a (module-uses module)) i)
1874 (module-local-variable i sym))))))
d5504515 1875 (module-constructor #() '() b #f #f name 'autoload
6b64c19b 1876 '() (make-weak-value-hash-table 31) 0)))
71225060 1877
0f2d19dd 1878\f
44cf1f0f 1879;;; {Autoloading modules}
0f2d19dd
JB
1880
1881(define autoloads-in-progress '())
1882
1883(define (try-module-autoload module-name)
0f2d19dd 1884 (let* ((reverse-name (reverse module-name))
06f0414c 1885 (name (symbol->string (car reverse-name)))
0f2d19dd 1886 (dir-hint-module-name (reverse (cdr reverse-name)))
06f0414c
MD
1887 (dir-hint (apply string-append
1888 (map (lambda (elt)
1889 (string-append (symbol->string elt) "/"))
1890 dir-hint-module-name))))
0209ca9a 1891 (resolve-module dir-hint-module-name #f)
0f2d19dd
JB
1892 (and (not (autoload-done-or-in-progress? dir-hint name))
1893 (let ((didit #f))
1894 (dynamic-wind
1895 (lambda () (autoload-in-progress! dir-hint name))
defed517
MD
1896 (lambda ()
1897 (let ((full (%search-load-path (in-vicinity dir-hint name))))
1898 (if full
1899 (begin
1900 (save-module-excursion (lambda () (primitive-load full)))
1901 (set! didit #t)))))
0f2d19dd
JB
1902 (lambda () (set-autoloaded! dir-hint name didit)))
1903 didit))))
1904
71225060 1905\f
d0cbd20c
MV
1906;;; Dynamic linking of modules
1907
1908;; Initializing a module that is written in C is a two step process.
1909;; First the module's `module init' function is called. This function
1910;; is expected to call `scm_register_module_xxx' to register the `real
1911;; init' function. Later, when the module is referenced for the first
1912;; time, this real init function is called in the right context. See
1913;; gtcltk-lib/gtcltk-module.c for an example.
1914;;
1915;; The code for the module can be in a regular shared library (so that
1916;; the `module init' function will be called when libguile is
1917;; initialized). Or it can be dynamically linked.
1918;;
1919;; You can safely call `scm_register_module_xxx' before libguile
1920;; itself is initialized. You could call it from an C++ constructor
1921;; of a static object, for example.
1922;;
1923;; To make your Guile extension into a dynamic linkable module, follow
1924;; these easy steps:
1925;;
8bb7330c 1926;; - Find a name for your module, like (ice-9 gtcltk)
d0cbd20c
MV
1927;; - Write a function with a name like
1928;;
1929;; scm_init_ice_9_gtcltk_module
1930;;
1931;; This is your `module init' function. It should call
1932;;
1933;; scm_register_module_xxx ("ice-9 gtcltk", scm_init_gtcltk);
1934;;
1935;; "ice-9 gtcltk" is the C version of the module name. Slashes are
1936;; replaced by spaces, the rest is untouched. `scm_init_gtcltk' is
ed218d98 1937;; the real init function that executes the usual initializations
d0cbd20c
MV
1938;; like making new smobs, etc.
1939;;
1940;; - Make a shared library with your code and a name like
1941;;
1942;; ice-9/libgtcltk.so
1943;;
1944;; and put it somewhere in %load-path.
1945;;
8bb7330c 1946;; - Then you can simply write `:use-module (ice-9 gtcltk)' and it
d0cbd20c
MV
1947;; will be linked automatically.
1948;;
1949;; This is all very experimental.
1950
1951(define (split-c-module-name str)
1952 (let loop ((rev '())
1953 (start 0)
1954 (pos 0)
1955 (end (string-length str)))
1956 (cond
1957 ((= pos end)
1958 (reverse (cons (string->symbol (substring str start pos)) rev)))
1959 ((eq? (string-ref str pos) #\space)
1960 (loop (cons (string->symbol (substring str start pos)) rev)
1961 (+ pos 1)
1962 (+ pos 1)
1963 end))
1964 (else
1965 (loop rev start (+ pos 1) end)))))
1966
1967(define (convert-c-registered-modules dynobj)
1968 (let ((res (map (lambda (c)
1969 (list (split-c-module-name (car c)) (cdr c) dynobj))
1970 (c-registered-modules))))
1971 (c-clear-registered-modules)
1972 res))
1973
3e3cec45
MD
1974(define registered-modules '())
1975
1976(define (register-modules dynobj)
1977 (set! registered-modules
1978 (append! (convert-c-registered-modules dynobj)
1979 registered-modules)))
1980
d0cbd20c 1981(define (init-dynamic-module modname)
3e3cec45
MD
1982 ;; Register any linked modules which has been registered on the C level
1983 (register-modules #f)
d0cbd20c
MV
1984 (or-map (lambda (modinfo)
1985 (if (equal? (car modinfo) modname)
c04e89c7
MD
1986 (begin
1987 (set! registered-modules (delq! modinfo registered-modules))
1988 (let ((mod (resolve-module modname #f)))
1989 (save-module-excursion
1990 (lambda ()
1991 (set-current-module mod)
1992 (set-module-public-interface! mod mod)
1993 (dynamic-call (cadr modinfo) (caddr modinfo))
1994 ))
1995 #t))
d0cbd20c
MV
1996 #f))
1997 registered-modules))
1998
1999(define (dynamic-maybe-call name dynobj)
2000 (catch #t ; could use false-if-exception here
2001 (lambda ()
2002 (dynamic-call name dynobj))
2003 (lambda args
2004 #f)))
2005
ed218d98
MV
2006(define (dynamic-maybe-link filename)
2007 (catch #t ; could use false-if-exception here
2008 (lambda ()
2009 (dynamic-link filename))
2010 (lambda args
2011 #f)))
2012
d0cbd20c
MV
2013(define (find-and-link-dynamic-module module-name)
2014 (define (make-init-name mod-name)
bd9e24b3 2015 (string-append "scm_init"
d0cbd20c
MV
2016 (list->string (map (lambda (c)
2017 (if (or (char-alphabetic? c)
2018 (char-numeric? c))
2019 c
2020 #\_))
2021 (string->list mod-name)))
bd9e24b3 2022 "_module"))
ebd79f62
TP
2023
2024 ;; Put the subdirectory for this module in the car of SUBDIR-AND-LIBNAME,
2025 ;; and the `libname' (the name of the module prepended by `lib') in the cdr
2026 ;; field. For example, if MODULE-NAME is the list (inet tcp-ip udp), then
2027 ;; SUBDIR-AND-LIBNAME will be the pair ("inet/tcp-ip" . "libudp").
2028 (let ((subdir-and-libname
d0cbd20c
MV
2029 (let loop ((dirs "")
2030 (syms module-name))
ebd79f62 2031 (if (null? (cdr syms))
06f0414c
MD
2032 (cons dirs (string-append "lib" (symbol->string (car syms))))
2033 (loop (string-append dirs (symbol->string (car syms)) "/")
2034 (cdr syms)))))
d0cbd20c
MV
2035 (init (make-init-name (apply string-append
2036 (map (lambda (s)
06f0414c
MD
2037 (string-append "_"
2038 (symbol->string s)))
d0cbd20c 2039 module-name)))))
ebd79f62
TP
2040 (let ((subdir (car subdir-and-libname))
2041 (libname (cdr subdir-and-libname)))
2042
2043 ;; Now look in each dir in %LOAD-PATH for `subdir/libfoo.la'. If that
2044 ;; file exists, fetch the dlname from that file and attempt to link
2045 ;; against it. If `subdir/libfoo.la' does not exist, or does not seem
2046 ;; to name any shared library, look for `subdir/libfoo.so' instead and
2047 ;; link against that.
2048 (let check-dirs ((dir-list %load-path))
2049 (if (null? dir-list)
2050 #f
2051 (let* ((dir (in-vicinity (car dir-list) subdir))
2052 (sharlib-full
2053 (or (try-using-libtool-name dir libname)
2054 (try-using-sharlib-name dir libname))))
2055 (if (and sharlib-full (file-exists? sharlib-full))
2056 (link-dynamic-module sharlib-full init)
2057 (check-dirs (cdr dir-list)))))))))
2058
2059(define (try-using-libtool-name libdir libname)
ebd79f62
TP
2060 (let ((libtool-filename (in-vicinity libdir
2061 (string-append libname ".la"))))
2062 (and (file-exists? libtool-filename)
352d134c 2063 libtool-filename)))
ebd79f62
TP
2064
2065(define (try-using-sharlib-name libdir libname)
2066 (in-vicinity libdir (string-append libname ".so")))
d0cbd20c
MV
2067
2068(define (link-dynamic-module filename initname)
3e3cec45
MD
2069 ;; Register any linked modules which has been registered on the C level
2070 (register-modules #f)
6b856182
MV
2071 (let ((dynobj (dynamic-link filename)))
2072 (dynamic-call initname dynobj)
3e3cec45 2073 (register-modules dynobj)))
a4f9b1f6
MD
2074
2075(define (try-module-linked module-name)
2076 (init-dynamic-module module-name))
2077
d0cbd20c 2078(define (try-module-dynamic-link module-name)
a4f9b1f6
MD
2079 (and (find-and-link-dynamic-module module-name)
2080 (init-dynamic-module module-name)))
d0cbd20c 2081
ed218d98
MV
2082
2083
0f2d19dd
JB
2084(define autoloads-done '((guile . guile)))
2085
2086(define (autoload-done-or-in-progress? p m)
2087 (let ((n (cons p m)))
2088 (->bool (or (member n autoloads-done)
2089 (member n autoloads-in-progress)))))
2090
2091(define (autoload-done! p m)
2092 (let ((n (cons p m)))
2093 (set! autoloads-in-progress
2094 (delete! n autoloads-in-progress))
2095 (or (member n autoloads-done)
2096 (set! autoloads-done (cons n autoloads-done)))))
2097
2098(define (autoload-in-progress! p m)
2099 (let ((n (cons p m)))
2100 (set! autoloads-done
2101 (delete! n autoloads-done))
2102 (set! autoloads-in-progress (cons n autoloads-in-progress))))
2103
2104(define (set-autoloaded! p m done?)
2105 (if done?
2106 (autoload-done! p m)
2107 (let ((n (cons p m)))
2108 (set! autoloads-done (delete! n autoloads-done))
2109 (set! autoloads-in-progress (delete! n autoloads-in-progress)))))
2110
2111
2112
2113
2114\f
2115;;; {Macros}
2116;;;
2117
7a0ff2f8
MD
2118(define (primitive-macro? m)
2119 (and (macro? m)
2120 (not (macro-transformer m))))
2121
2122;;; {Defmacros}
2123;;;
9591db87
MD
2124(define macro-table (make-weak-key-hash-table 523))
2125(define xformer-table (make-weak-key-hash-table 523))
0f2d19dd
JB
2126
2127(define (defmacro? m) (hashq-ref macro-table m))
2128(define (assert-defmacro?! m) (hashq-set! macro-table m #t))
2129(define (defmacro-transformer m) (hashq-ref xformer-table m))
2130(define (set-defmacro-transformer! m t) (hashq-set! xformer-table m t))
2131
2132(define defmacro:transformer
2133 (lambda (f)
2134 (let* ((xform (lambda (exp env)
2135 (copy-tree (apply f (cdr exp)))))
2136 (a (procedure->memoizing-macro xform)))
2137 (assert-defmacro?! a)
2138 (set-defmacro-transformer! a f)
2139 a)))
2140
2141
2142(define defmacro
2143 (let ((defmacro-transformer
2144 (lambda (name parms . body)
2145 (let ((transformer `(lambda ,parms ,@body)))
2146 `(define ,name
2147 (,(lambda (transformer)
2148 (defmacro:transformer transformer))
2149 ,transformer))))))
2150 (defmacro:transformer defmacro-transformer)))
2151
2152(define defmacro:syntax-transformer
2153 (lambda (f)
2154 (procedure->syntax
2155 (lambda (exp env)
2156 (copy-tree (apply f (cdr exp)))))))
2157
ed218d98
MV
2158
2159;; XXX - should the definition of the car really be looked up in the
2160;; current module?
2161
0f2d19dd
JB
2162(define (macroexpand-1 e)
2163 (cond
2164 ((pair? e) (let* ((a (car e))
ed218d98 2165 (val (and (symbol? a) (local-ref (list a)))))
0f2d19dd
JB
2166 (if (defmacro? val)
2167 (apply (defmacro-transformer val) (cdr e))
2168 e)))
2169 (#t e)))
2170
2171(define (macroexpand e)
2172 (cond
2173 ((pair? e) (let* ((a (car e))
ed218d98 2174 (val (and (symbol? a) (local-ref (list a)))))
0f2d19dd
JB
2175 (if (defmacro? val)
2176 (macroexpand (apply (defmacro-transformer val) (cdr e)))
2177 e)))
2178 (#t e)))
2179
e672f1b5
MD
2180(define (gentemp)
2181 (gensym "scm:G"))
0f2d19dd 2182
534a0099 2183(provide 'defmacro)
0f2d19dd
JB
2184
2185\f
2186
83b38198
MD
2187;;; {Run-time options}
2188
16b8ebbe
MD
2189((let* ((names '((eval-options-interface
2190 (eval-options eval-enable eval-disable)
2191 (eval-set!))
2192
2193 (debug-options-interface
83b38198
MD
2194 (debug-options debug-enable debug-disable)
2195 (debug-set!))
2196
2197 (evaluator-traps-interface
2198 (traps trap-enable trap-disable)
2199 (trap-set!))
2200
2201 (read-options-interface
2202 (read-options read-enable read-disable)
2203 (read-set!))
2204
2205 (print-options-interface
2206 (print-options print-enable print-disable)
2207 (print-set!))
e586be78
MD
2208
2209 (readline-options-interface
2210 (readline-options readline-enable readline-disable)
2211 (readline-set!))
83b38198
MD
2212 ))
2213 (option-name car)
2214 (option-value cadr)
2215 (option-documentation caddr)
2216
2217 (print-option (lambda (option)
2218 (display (option-name option))
2219 (if (< (string-length
2220 (symbol->string (option-name option)))
2221 8)
2222 (display #\tab))
2223 (display #\tab)
2224 (display (option-value option))
2225 (display #\tab)
2226 (display (option-documentation option))
2227 (newline)))
2228
2229 ;; Below follows the macros defining the run-time option interfaces.
2230
2231 (make-options (lambda (interface)
2232 `(lambda args
2233 (cond ((null? args) (,interface))
45456413 2234 ((list? (car args))
83b38198 2235 (,interface (car args)) (,interface))
2f110c3c 2236 (else (for-each ,print-option
83b38198
MD
2237 (,interface #t)))))))
2238
2239 (make-enable (lambda (interface)
2240 `(lambda flags
2241 (,interface (append flags (,interface)))
2242 (,interface))))
2243
2244 (make-disable (lambda (interface)
2245 `(lambda flags
2246 (let ((options (,interface)))
2247 (for-each (lambda (flag)
2248 (set! options (delq! flag options)))
2249 flags)
2250 (,interface options)
2251 (,interface)))))
2252
2253 (make-set! (lambda (interface)
2254 `((name exp)
2255 (,'quasiquote
2256 (begin (,interface (append (,interface)
2257 (list '(,'unquote name)
2258 (,'unquote exp))))
2259 (,interface))))))
2260 )
2261 (procedure->macro
2262 (lambda (exp env)
2263 (cons 'begin
2264 (apply append
2265 (map (lambda (group)
2266 (let ((interface (car group)))
2267 (append (map (lambda (name constructor)
2268 `(define ,name
2269 ,(constructor interface)))
2270 (cadr group)
2271 (list make-options
2272 make-enable
2273 make-disable))
2274 (map (lambda (name constructor)
2275 `(defmacro ,name
2276 ,@(constructor interface)))
2277 (caddr group)
2278 (list make-set!)))))
2279 names)))))))
2280
2281\f
2282
0f2d19dd
JB
2283;;; {Running Repls}
2284;;;
2285
2286(define (repl read evaler print)
75a97b92 2287 (let loop ((source (read (current-input-port))))
0f2d19dd 2288 (print (evaler source))
75a97b92 2289 (loop (read (current-input-port)))))
0f2d19dd
JB
2290
2291;; A provisional repl that acts like the SCM repl:
2292;;
2293(define scm-repl-silent #f)
2294(define (assert-repl-silence v) (set! scm-repl-silent v))
2295
21ed9efe
MD
2296(define *unspecified* (if #f #f))
2297(define (unspecified? v) (eq? v *unspecified*))
2298
2299(define scm-repl-print-unspecified #f)
2300(define (assert-repl-print-unspecified v) (set! scm-repl-print-unspecified v))
2301
79451588 2302(define scm-repl-verbose #f)
0f2d19dd
JB
2303(define (assert-repl-verbosity v) (set! scm-repl-verbose v))
2304
e6875011 2305(define scm-repl-prompt "guile> ")
0f2d19dd 2306
e6875011
MD
2307(define (set-repl-prompt! v) (set! scm-repl-prompt v))
2308
d5d34fa1
MD
2309(define (default-lazy-handler key . args)
2310 (save-stack lazy-handler-dispatch)
2311 (apply throw key args))
2312
45456413 2313(define enter-frame-handler default-lazy-handler)
d5d34fa1
MD
2314(define apply-frame-handler default-lazy-handler)
2315(define exit-frame-handler default-lazy-handler)
2316
2317(define (lazy-handler-dispatch key . args)
2318 (case key
2319 ((apply-frame)
2320 (apply apply-frame-handler key args))
2321 ((exit-frame)
2322 (apply exit-frame-handler key args))
45456413
MD
2323 ((enter-frame)
2324 (apply enter-frame-handler key args))
d5d34fa1
MD
2325 (else
2326 (apply default-lazy-handler key args))))
0f2d19dd 2327
3e3cec45 2328(define abort-hook (make-hook))
59e1116d 2329
28d8ab3c
GH
2330;; these definitions are used if running a script.
2331;; otherwise redefined in error-catching-loop.
2332(define (set-batch-mode?! arg) #t)
2333(define (batch-mode?) #t)
4bbbcd5c 2334
0f2d19dd 2335(define (error-catching-loop thunk)
4bbbcd5c
GH
2336 (let ((status #f)
2337 (interactive #t))
8e44e7a0
GH
2338 (define (loop first)
2339 (let ((next
2340 (catch #t
9a0d70e2 2341
8e44e7a0
GH
2342 (lambda ()
2343 (lazy-catch #t
2344 (lambda ()
2345 (dynamic-wind
2346 (lambda () (unmask-signals))
2347 (lambda ()
45456413
MD
2348 (with-traps
2349 (lambda ()
2350 (first)
8e44e7a0 2351
45456413
MD
2352 ;; This line is needed because mark
2353 ;; doesn't do closures quite right.
2354 ;; Unreferenced locals should be
2355 ;; collected.
2356 ;;
2357 (set! first #f)
2358 (let loop ((v (thunk)))
2359 (loop (thunk)))
2360 #f)))
8e44e7a0
GH
2361 (lambda () (mask-signals))))
2362
2363 lazy-handler-dispatch))
2364
2365 (lambda (key . args)
2366 (case key
2367 ((quit)
8e44e7a0
GH
2368 (set! status args)
2369 #f)
2370
2371 ((switch-repl)
2372 (apply throw 'switch-repl args))
2373
2374 ((abort)
2375 ;; This is one of the closures that require
2376 ;; (set! first #f) above
2377 ;;
2378 (lambda ()
04efd24d 2379 (run-hook abort-hook)
e13c54c4 2380 (force-output (current-output-port))
8e44e7a0
GH
2381 (display "ABORT: " (current-error-port))
2382 (write args (current-error-port))
2383 (newline (current-error-port))
4bbbcd5c 2384 (if interactive
e13c54c4
JB
2385 (begin
2386 (if (and
2387 (not has-shown-debugger-hint?)
2388 (not (memq 'backtrace
2389 (debug-options-interface)))
2390 (stack? (fluid-ref the-last-stack)))
2391 (begin
2392 (newline (current-error-port))
2393 (display
cb546c61 2394 "Type \"(backtrace)\" to get more information or \"(debug)\" to enter the debugger.\n"
e13c54c4
JB
2395 (current-error-port))
2396 (set! has-shown-debugger-hint? #t)))
2397 (force-output (current-error-port)))
2398 (begin
2399 (primitive-exit 1)))
8e44e7a0
GH
2400 (set! stack-saved? #f)))
2401
2402 (else
2403 ;; This is the other cons-leak closure...
2404 (lambda ()
2405 (cond ((= (length args) 4)
2406 (apply handle-system-error key args))
2407 (else
2408 (apply bad-throw key args))))))))))
2409 (if next (loop next) status)))
5f5f2642
MD
2410 (set! set-batch-mode?! (lambda (arg)
2411 (cond (arg
2412 (set! interactive #f)
2413 (restore-signals))
2414 (#t
2415 (error "sorry, not implemented")))))
2416 (set! batch-mode? (lambda () (not interactive)))
8e44e7a0 2417 (loop (lambda () #t))))
0f2d19dd 2418
8bb7f646 2419;;(define the-last-stack (make-fluid)) Defined by scm_init_backtrace ()
8087b6be 2420(define before-signal-stack (make-fluid))
21ed9efe
MD
2421(define stack-saved? #f)
2422
2423(define (save-stack . narrowing)
edc185c7
MD
2424 (or stack-saved?
2425 (cond ((not (memq 'debug (debug-options-interface)))
2426 (fluid-set! the-last-stack #f)
2427 (set! stack-saved? #t))
2428 (else
2429 (fluid-set!
2430 the-last-stack
2431 (case (stack-id #t)
2432 ((repl-stack)
2433 (apply make-stack #t save-stack eval #t 0 narrowing))
2434 ((load-stack)
2435 (apply make-stack #t save-stack 0 #t 0 narrowing))
2436 ((tk-stack)
2437 (apply make-stack #t save-stack tk-stack-mark #t 0 narrowing))
2438 ((#t)
2439 (apply make-stack #t save-stack 0 1 narrowing))
2440 (else
2441 (let ((id (stack-id #t)))
2442 (and (procedure? id)
2443 (apply make-stack #t save-stack id #t 0 narrowing))))))
2444 (set! stack-saved? #t)))))
1c6cd8e8 2445
3e3cec45
MD
2446(define before-error-hook (make-hook))
2447(define after-error-hook (make-hook))
2448(define before-backtrace-hook (make-hook))
2449(define after-backtrace-hook (make-hook))
1c6cd8e8 2450
21ed9efe
MD
2451(define has-shown-debugger-hint? #f)
2452
35c5db87
GH
2453(define (handle-system-error key . args)
2454 (let ((cep (current-error-port)))
8bb7f646 2455 (cond ((not (stack? (fluid-ref the-last-stack))))
21ed9efe 2456 ((memq 'backtrace (debug-options-interface))
04efd24d 2457 (run-hook before-backtrace-hook)
21ed9efe 2458 (newline cep)
755457ec 2459 (display "Backtrace:\n")
8bb7f646 2460 (display-backtrace (fluid-ref the-last-stack) cep)
21ed9efe 2461 (newline cep)
04efd24d
MD
2462 (run-hook after-backtrace-hook)))
2463 (run-hook before-error-hook)
8bb7f646 2464 (apply display-error (fluid-ref the-last-stack) cep args)
04efd24d 2465 (run-hook after-error-hook)
35c5db87
GH
2466 (force-output cep)
2467 (throw 'abort key)))
21ed9efe 2468
0f2d19dd
JB
2469(define (quit . args)
2470 (apply throw 'quit args))
2471
7950df7c
GH
2472(define exit quit)
2473
d590bbf6
MD
2474;;(define has-shown-backtrace-hint? #f) Defined by scm_init_backtrace ()
2475
2476;; Replaced by C code:
2477;;(define (backtrace)
8bb7f646 2478;; (if (fluid-ref the-last-stack)
d590bbf6
MD
2479;; (begin
2480;; (newline)
8bb7f646 2481;; (display-backtrace (fluid-ref the-last-stack) (current-output-port))
d590bbf6
MD
2482;; (newline)
2483;; (if (and (not has-shown-backtrace-hint?)
2484;; (not (memq 'backtrace (debug-options-interface))))
2485;; (begin
2486;; (display
2487;;"Type \"(debug-enable 'backtrace)\" if you would like a backtrace
2488;;automatically if an error occurs in the future.\n")
2489;; (set! has-shown-backtrace-hint? #t))))
2490;; (display "No backtrace available.\n")))
21ed9efe 2491
0f2d19dd
JB
2492(define (error-catching-repl r e p)
2493 (error-catching-loop (lambda () (p (e (r))))))
2494
2495(define (gc-run-time)
2496 (cdr (assq 'gc-time-taken (gc-stats))))
2497
3e3cec45
MD
2498(define before-read-hook (make-hook))
2499(define after-read-hook (make-hook))
1c6cd8e8 2500
dc5c2038
MD
2501;;; The default repl-reader function. We may override this if we've
2502;;; the readline library.
2503(define repl-reader
2504 (lambda (prompt)
2505 (display prompt)
2506 (force-output)
04efd24d 2507 (run-hook before-read-hook)
dc5c2038
MD
2508 (read (current-input-port))))
2509
0f2d19dd
JB
2510(define (scm-style-repl)
2511 (letrec (
2512 (start-gc-rt #f)
2513 (start-rt #f)
0f2d19dd
JB
2514 (repl-report-start-timing (lambda ()
2515 (set! start-gc-rt (gc-run-time))
2516 (set! start-rt (get-internal-run-time))))
2517 (repl-report (lambda ()
2518 (display ";;; ")
2519 (display (inexact->exact
2520 (* 1000 (/ (- (get-internal-run-time) start-rt)
2521 internal-time-units-per-second))))
2522 (display " msec (")
2523 (display (inexact->exact
2524 (* 1000 (/ (- (gc-run-time) start-gc-rt)
2525 internal-time-units-per-second))))
2526 (display " msec in gc)\n")))
480977d0
JB
2527
2528 (consume-trailing-whitespace
2529 (lambda ()
2530 (let ((ch (peek-char)))
2531 (cond
2532 ((eof-object? ch))
2533 ((or (char=? ch #\space) (char=? ch #\tab))
2534 (read-char)
2535 (consume-trailing-whitespace))
2536 ((char=? ch #\newline)
2537 (read-char))))))
0f2d19dd 2538 (-read (lambda ()
dc5c2038
MD
2539 (let ((val
2540 (let ((prompt (cond ((string? scm-repl-prompt)
2541 scm-repl-prompt)
2542 ((thunk? scm-repl-prompt)
2543 (scm-repl-prompt))
2544 (scm-repl-prompt "> ")
2545 (else ""))))
2546 (repl-reader prompt))))
2547
480977d0 2548 ;; As described in R4RS, the READ procedure updates the
e13c54c4 2549 ;; port to point to the first character past the end of
480977d0
JB
2550 ;; the external representation of the object. This
2551 ;; means that it doesn't consume the newline typically
2552 ;; found after an expression. This means that, when
2553 ;; debugging Guile with GDB, GDB gets the newline, which
2554 ;; it often interprets as a "continue" command, making
2555 ;; breakpoints kind of useless. So, consume any
2556 ;; trailing newline here, as well as any whitespace
2557 ;; before it.
e13c54c4
JB
2558 ;; But not if EOF, for control-D.
2559 (if (not (eof-object? val))
2560 (consume-trailing-whitespace))
04efd24d 2561 (run-hook after-read-hook)
0f2d19dd
JB
2562 (if (eof-object? val)
2563 (begin
7950df7c 2564 (repl-report-start-timing)
0f2d19dd
JB
2565 (if scm-repl-verbose
2566 (begin
2567 (newline)
2568 (display ";;; EOF -- quitting")
2569 (newline)))
2570 (quit 0)))
2571 val)))
2572
2573 (-eval (lambda (sourc)
2574 (repl-report-start-timing)
d7faeb2e
MD
2575 (start-stack 'repl-stack
2576 (eval sourc (interaction-environment)))))
0f2d19dd 2577
44484f52
MD
2578 (-print (let ((maybe-print (lambda (result)
2579 (if (or scm-repl-print-unspecified
2580 (not (unspecified? result)))
2581 (begin
2582 (write result)
2583 (newline))))))
2584 (lambda (result)
2585 (if (not scm-repl-silent)
2586 (begin
2587 (if (values? result)
2588 (for-each maybe-print (get-values result))
2589 (maybe-print result))
2590 (if scm-repl-verbose
2591 (repl-report))
2592 (force-output))))))
0f2d19dd 2593
8e44e7a0 2594 (-quit (lambda (args)
0f2d19dd
JB
2595 (if scm-repl-verbose
2596 (begin
2597 (display ";;; QUIT executed, repl exitting")
2598 (newline)
2599 (repl-report)))
8e44e7a0 2600 args))
0f2d19dd
JB
2601
2602 (-abort (lambda ()
2603 (if scm-repl-verbose
2604 (begin
2605 (display ";;; ABORT executed.")
2606 (newline)
2607 (repl-report)))
2608 (repl -read -eval -print))))
2609
8e44e7a0
GH
2610 (let ((status (error-catching-repl -read
2611 -eval
2612 -print)))
2613 (-quit status))))
2614
0f2d19dd 2615
0f2d19dd 2616\f
44cf1f0f 2617;;; {IOTA functions: generating lists of numbers}
0f2d19dd 2618
e69cd299
MD
2619(define (iota n)
2620 (let loop ((count (1- n)) (result '()))
2621 (if (< count 0) result
2622 (loop (1- count) (cons count result)))))
0f2d19dd
JB
2623
2624\f
2625;;; {While}
2626;;;
2627;;; with `continue' and `break'.
2628;;;
2629
2630(defmacro while (cond . body)
2631 `(letrec ((continue (lambda () (or (not ,cond) (begin (begin ,@ body) (continue)))))
2632 (break (lambda val (apply throw 'break val))))
2633 (catch 'break
2634 (lambda () (continue))
2635 (lambda v (cadr v)))))
2636
7398c2c2
MD
2637;;; {collect}
2638;;;
2639;;; Similar to `begin' but returns a list of the results of all constituent
2640;;; forms instead of the result of the last form.
2641;;; (The definition relies on the current left-to-right
2642;;; order of evaluation of operands in applications.)
2643
2644(defmacro collect forms
2645 (cons 'list forms))
0f2d19dd 2646
8a6a8671
MV
2647;;; {with-fluids}
2648
2649;; with-fluids is a convenience wrapper for the builtin procedure
2650;; `with-fluids*'. The syntax is just like `let':
2651;;
2652;; (with-fluids ((fluid val)
2653;; ...)
2654;; body)
2655
2656(defmacro with-fluids (bindings . body)
2657 `(with-fluids* (list ,@(map car bindings)) (list ,@(map cadr bindings))
2658 (lambda () ,@body)))
2659
0f2d19dd
JB
2660\f
2661
2662;;; {Macros}
2663;;;
2664
2665;; actually....hobbit might be able to hack these with a little
2666;; coaxing
2667;;
2668
2669(defmacro define-macro (first . rest)
2670 (let ((name (if (symbol? first) first (car first)))
2671 (transformer
2672 (if (symbol? first)
2673 (car rest)
2674 `(lambda ,(cdr first) ,@rest))))
2675 `(define ,name (defmacro:transformer ,transformer))))
2676
2677
2678(defmacro define-syntax-macro (first . rest)
2679 (let ((name (if (symbol? first) first (car first)))
2680 (transformer
2681 (if (symbol? first)
2682 (car rest)
2683 `(lambda ,(cdr first) ,@rest))))
2684 `(define ,name (defmacro:syntax-transformer ,transformer))))
2685\f
2686;;; {Module System Macros}
2687;;;
2688
2689(defmacro define-module args
2690 `(let* ((process-define-module process-define-module)
2691 (set-current-module set-current-module)
2692 (module (process-define-module ',args)))
2693 (set-current-module module)
2694 module))
2695
89da9036
MV
2696;; the guts of the use-modules macro. add the interfaces of the named
2697;; modules to the use-list of the current module, in order
2698(define (process-use-modules module-names)
2699 (for-each (lambda (module-name)
2700 (let ((mod-iface (resolve-interface module-name)))
2701 (or mod-iface
2702 (error "no such module" module-name))
2703 (module-use! (current-module) mod-iface)))
2704 (reverse module-names)))
2705
33cf699f 2706(defmacro use-modules modules
89da9036 2707 `(process-use-modules ',modules))
33cf699f 2708
cf266109 2709(defmacro use-syntax (spec)
7cbaee0c
MD
2710 `(begin
2711 ,@(if (pair? spec)
2712 `((process-use-modules ',(list spec))
2713 (set-module-transformer! (current-module)
2714 ,(car (last-pair spec))))
2715 `((set-module-transformer! (current-module) ,spec)))
bd0fb3cf 2716 (fluid-set! scm:eval-transformer (module-transformer (current-module)))))
7a0ff2f8 2717
0f2d19dd
JB
2718(define define-private define)
2719
2720(defmacro define-public args
2721 (define (syntax)
2722 (error "bad syntax" (list 'define-public args)))
2723 (define (defined-name n)
2724 (cond
3c5af9ef
JB
2725 ((symbol? n) n)
2726 ((pair? n) (defined-name (car n)))
2727 (else (syntax))))
0f2d19dd 2728 (cond
3c5af9ef
JB
2729 ((null? args) (syntax))
2730
2731 (#t (let ((name (defined-name (car args))))
2732 `(begin
2733 (let ((public-i (module-public-interface (current-module))))
2734 ;; Make sure there is a local variable:
2735 ;;
2736 (module-define! (current-module)
2737 ',name
2738 (module-ref (current-module) ',name #f))
0f2d19dd 2739
3c5af9ef
JB
2740 ;; Make sure that local is exported:
2741 ;;
2742 (module-add! public-i ',name
2743 (module-variable (current-module) ',name)))
0f2d19dd 2744
3c5af9ef
JB
2745 ;; Now (re)define the var normally. Bernard URBAN
2746 ;; suggests we use eval here to accomodate Hobbit; it lets
2747 ;; the interpreter handle the define-private form, which
2748 ;; Hobbit can't digest.
d7faeb2e 2749 (eval '(define-private ,@ args) (interaction-environment)))))))
0f2d19dd
JB
2750
2751
2752
2753(defmacro defmacro-public args
2754 (define (syntax)
2755 (error "bad syntax" (list 'defmacro-public args)))
2756 (define (defined-name n)
2757 (cond
2758 ((symbol? n) n)
2759 (else (syntax))))
2760 (cond
2761 ((null? args) (syntax))
2762
2763 (#t (let ((name (defined-name (car args))))
2764 `(begin
2765 (let ((public-i (module-public-interface (current-module))))
2766 ;; Make sure there is a local variable:
2767 ;;
2768 (module-define! (current-module)
2769 ',name
2770 (module-ref (current-module) ',name #f))
2771
2772 ;; Make sure that local is exported:
2773 ;;
2774 (module-add! public-i ',name (module-variable (current-module) ',name)))
2775
2776 ;; Now (re)define the var normally.
2777 ;;
2778 (defmacro ,@ args))))))
2779
2780
90847923
MD
2781(define (module-export! m names)
2782 (let ((public-i (module-public-interface m)))
2783 (for-each (lambda (name)
2784 ;; Make sure there is a local variable:
2785 (module-define! m name (module-ref m name #f))
2786 ;; Make sure that local is exported:
2787 (module-add! public-i name (module-variable m name)))
2788 names)))
2789
a0cc0a01 2790(defmacro export names
90847923 2791 `(module-export! (current-module) ',names))
a0cc0a01
MD
2792
2793(define export-syntax export)
2794
2795
0f2d19dd
JB
2796(define load load-module)
2797
2798
2799\f
9aca88c3
JB
2800;;; {Load emacs interface support if emacs option is given.}
2801
2802(define (load-emacs-interface)
2803 (if (memq 'debug-extensions *features*)
2804 (debug-enable 'backtrace))
2805 (define-module (guile-user) :use-module (ice-9 emacs)))
2806
2807\f
0f2d19dd 2808
755457ec
MD
2809(define using-readline?
2810 (let ((using-readline? (make-fluid)))
2811 (make-procedure-with-setter
2812 (lambda () (fluid-ref using-readline?))
2813 (lambda (v) (fluid-set! using-readline? v)))))
2814
e1a191a8
GH
2815;; this is just (scm-style-repl) with a wrapper to install and remove
2816;; signal handlers.
8e44e7a0 2817(define (top-repl)
9aca88c3
JB
2818
2819 ;; Load emacs interface support if emacs option is given.
2820 (if (and (module-defined? the-root-module 'use-emacs-interface)
2821 use-emacs-interface)
2822 (load-emacs-interface))
2823
4fdf8b2c 2824 ;; Place the user in the guile-user module.
00b33968 2825 (define-module (guile-user)
6b64c19b 2826 :use-module (guile) ;so that bindings will be checked here first
00b33968
MD
2827 :use-module (ice-9 session)
2828 :use-module (ice-9 debug)
6b64c19b 2829 :autoload (ice-9 debugger) (debug)) ;load debugger on demand
00b33968
MD
2830 (if (memq 'threads *features*)
2831 (define-module (guile-user) :use-module (ice-9 threads)))
2832 (if (memq 'regex *features*)
2833 (define-module (guile-user) :use-module (ice-9 regex)))
4fdf8b2c 2834
e1a191a8 2835 (let ((old-handlers #f)
52cfc69b
GH
2836 (signals (if (provided? 'posix)
2837 `((,SIGINT . "User interrupt")
2838 (,SIGFPE . "Arithmetic error")
2839 (,SIGBUS . "Bad memory access (bus error)")
2840 (,SIGSEGV .
2841 "Bad memory access (Segmentation violation)"))
2842 '())))
e1a191a8
GH
2843
2844 (dynamic-wind
2845
2846 ;; call at entry
2847 (lambda ()
2848 (let ((make-handler (lambda (msg)
2849 (lambda (sig)
8087b6be
MD
2850 ;; Make a backup copy of the stack
2851 (fluid-set! before-signal-stack
2852 (fluid-ref the-last-stack))
096d5f90 2853 (save-stack %deliver-signals)
e1a191a8
GH
2854 (scm-error 'signal
2855 #f
2856 msg
2857 #f
2858 (list sig))))))
2859 (set! old-handlers
2860 (map (lambda (sig-msg)
2861 (sigaction (car sig-msg)
2862 (make-handler (cdr sig-msg))))
2863 signals))))
2864
2865 ;; the protected thunk.
2866 (lambda ()
2055a1bc 2867 (let ((status (scm-style-repl)))
04efd24d 2868 (run-hook exit-hook)
2055a1bc 2869 status))
e1a191a8
GH
2870
2871 ;; call at exit.
2872 (lambda ()
2873 (map (lambda (sig-msg old-handler)
2874 (if (not (car old-handler))
2875 ;; restore original C handler.
2876 (sigaction (car sig-msg) #f)
2877 ;; restore Scheme handler, SIG_IGN or SIG_DFL.
2878 (sigaction (car sig-msg)
2879 (car old-handler)
2880 (cdr old-handler))))
bd9e24b3 2881 signals old-handlers)))))
0f2d19dd 2882
02b754d3
GH
2883(defmacro false-if-exception (expr)
2884 `(catch #t (lambda () ,expr)
2885 (lambda args #f)))
2886
2055a1bc
MD
2887;;; This hook is run at the very end of an interactive session.
2888;;;
3e3cec45 2889(define exit-hook (make-hook))
2055a1bc 2890
4d31f0da
JB
2891\f
2892(define-module (guile))
9946dd45 2893
13e341bb 2894(append! %load-path (cons "." ()))