add current-filename, add-to-path, add-to-load-path
[bpt/guile.git] / module / ice-9 / boot-9.scm
CommitLineData
87e00370 1;;; -*- mode: scheme; coding: utf-8; -*-
0f2d19dd 2
b3da54d1
LC
3;;;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
4;;;; 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
5;;;; Free Software Foundation, Inc.
20edfbbd 6;;;;
73be1d9e
MV
7;;;; This library is free software; you can redistribute it and/or
8;;;; modify it under the terms of the GNU Lesser General Public
9;;;; License as published by the Free Software Foundation; either
53befeb7 10;;;; version 3 of the License, or (at your option) any later version.
73be1d9e
MV
11;;;;
12;;;; This library is distributed in the hope that it will be useful,
0f2d19dd 13;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
14;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15;;;; Lesser General Public License for more details.
16;;;;
17;;;; You should have received a copy of the GNU Lesser General Public
18;;;; License along with this library; if not, write to the Free Software
92205699 19;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
a482f2cc 20;;;;
3d2ada2f 21
0f2d19dd
JB
22\f
23
20edfbbd
TTN
24;;; Commentary:
25
0f2d19dd
JB
26;;; This file is the first thing loaded into Guile. It adds many mundane
27;;; definitions and a few that are interesting.
28;;;
20edfbbd 29;;; The module system (hence the hierarchical namespace) are defined in this
0f2d19dd
JB
30;;; file.
31;;;
32
20edfbbd
TTN
33;;; Code:
34
0f2d19dd 35\f
9fb41cea 36
9c35c579
AW
37;; Before compiling, make sure any symbols are resolved in the (guile)
38;; module, the primary location of those symbols, rather than in
39;; (guile-user), the default module that we compile in.
40
41(eval-when (compile)
42 (set-current-module (resolve-module '(guile))))
43
416f26c7
AW
44\f
45
46;;; {Error handling}
47;;;
48
49;; Define delimited continuation operators, and implement catch and throw in
50;; terms of them.
51
d648f569
AW
52(define make-prompt-tag
53 (lambda* (#:optional (stem "prompt"))
54 (gensym stem)))
55
c6a32a2c
AW
56(define default-prompt-tag
57 ;; not sure if we should expose this to the user as a fluid
58 (let ((%default-prompt-tag (make-prompt-tag)))
59 (lambda ()
60 %default-prompt-tag)))
8fc43b12
AW
61
62(define (call-with-prompt tag thunk handler)
416f26c7 63 (@prompt tag (thunk) handler))
8fc43b12 64(define (abort-to-prompt tag . args)
416f26c7
AW
65 (@abort tag args))
66
67
416f26c7
AW
68;; Define catch and with-throw-handler, using some common helper routines and a
69;; shared fluid. Hide the helpers in a lexical contour.
70
37620f3f 71(define with-throw-handler #f)
416f26c7 72(let ()
416f26c7
AW
73 (define (default-exception-handler k . args)
74 (cond
75 ((eq? k 'quit)
76 (primitive-exit (cond
77 ((not (pair? args)) 0)
78 ((integer? (car args)) (car args))
79 ((not (car args)) 1)
80 (else 0))))
81 (else
82 (format (current-error-port) "guile: uncaught throw to ~a: ~a\n" k args)
83 (primitive-exit 1))))
84
9447207f
AW
85 (define %running-exception-handlers (make-fluid '()))
86 (define %exception-handler (make-fluid default-exception-handler))
87
416f26c7 88 (define (default-throw-handler prompt-tag catch-k)
9447207f 89 (let ((prev (fluid-ref %exception-handler)))
416f26c7
AW
90 (lambda (thrown-k . args)
91 (if (or (eq? thrown-k catch-k) (eqv? catch-k #t))
8fc43b12 92 (apply abort-to-prompt prompt-tag thrown-k args)
416f26c7
AW
93 (apply prev thrown-k args)))))
94
95 (define (custom-throw-handler prompt-tag catch-k pre)
9447207f 96 (let ((prev (fluid-ref %exception-handler)))
416f26c7
AW
97 (lambda (thrown-k . args)
98 (if (or (eq? thrown-k catch-k) (eqv? catch-k #t))
9447207f 99 (let ((running (fluid-ref %running-exception-handlers)))
416f26c7
AW
100 (with-fluids ((%running-exception-handlers (cons pre running)))
101 (if (not (memq pre running))
102 (apply pre thrown-k args))
103 ;; fall through
104 (if prompt-tag
8fc43b12 105 (apply abort-to-prompt prompt-tag thrown-k args)
416f26c7
AW
106 (apply prev thrown-k args))))
107 (apply prev thrown-k args)))))
108
37620f3f
AW
109 (set! catch
110 (lambda* (k thunk handler #:optional pre-unwind-handler)
111 "Invoke @var{thunk} in the dynamic context of @var{handler} for
416f26c7
AW
112exceptions matching @var{key}. If thunk throws to the symbol
113@var{key}, then @var{handler} is invoked this way:
114@lisp
115 (handler key args ...)
116@end lisp
117
118@var{key} is a symbol or @code{#t}.
119
120@var{thunk} takes no arguments. If @var{thunk} returns
121normally, that is the return value of @code{catch}.
122
123Handler is invoked outside the scope of its own @code{catch}.
124If @var{handler} again throws to the same key, a new handler
125from further up the call chain is invoked.
126
127If the key is @code{#t}, then a throw to @emph{any} symbol will
128match this call to @code{catch}.
129
130If a @var{pre-unwind-handler} is given and @var{thunk} throws
131an exception that matches @var{key}, Guile calls the
132@var{pre-unwind-handler} before unwinding the dynamic state and
133invoking the main @var{handler}. @var{pre-unwind-handler} should
134be a procedure with the same signature as @var{handler}, that
135is @code{(lambda (key . args))}. It is typically used to save
136the stack at the point where the exception occurred, but can also
137query other parts of the dynamic state at that point, such as
138fluid values.
139
140A @var{pre-unwind-handler} can exit either normally or non-locally.
141If it exits normally, Guile unwinds the stack and dynamic context
142and then calls the normal (third argument) handler. If it exits
143non-locally, that exit determines the continuation."
37620f3f 144 (if (not (or (symbol? k) (eqv? k #t)))
222056dc 145 (scm-error 'wrong-type-arg "catch"
37620f3f
AW
146 "Wrong type argument in position ~a: ~a"
147 (list 1 k) (list k)))
148 (let ((tag (make-prompt-tag "catch")))
149 (call-with-prompt
150 tag
151 (lambda ()
152 (with-fluids
153 ((%exception-handler
154 (if pre-unwind-handler
155 (custom-throw-handler tag k pre-unwind-handler)
156 (default-throw-handler tag k))))
157 (thunk)))
158 (lambda (cont k . args)
159 (apply handler k args))))))
160
161 (set! with-throw-handler
162 (lambda (k thunk pre-unwind-handler)
163 "Add @var{handler} to the dynamic context as a throw handler
416f26c7 164for key @var{key}, then invoke @var{thunk}."
37620f3f 165 (if (not (or (symbol? k) (eqv? k #t)))
222056dc 166 (scm-error 'wrong-type-arg "with-throw-handler"
37620f3f
AW
167 "Wrong type argument in position ~a: ~a"
168 (list 1 k) (list k)))
169 (with-fluids ((%exception-handler
170 (custom-throw-handler #f k pre-unwind-handler)))
171 (thunk))))
172
173 (set! throw
174 (lambda (key . args)
175 "Invoke the catch form matching @var{key}, passing @var{args} to the
416f26c7
AW
176@var{handler}.
177
178@var{key} is a symbol. It will match catches of the same symbol or of @code{#t}.
179
180If there is no handler at all, Guile prints an error and then exits."
37620f3f 181 (if (not (symbol? key))
9447207f 182 ((fluid-ref %exception-handler) 'wrong-type-arg "throw"
37620f3f 183 "Wrong type argument in position ~a: ~a" (list 1 key) (list key))
9447207f 184 (apply (fluid-ref %exception-handler) key args)))))
416f26c7
AW
185
186
187\f
188
928258fb
AW
189;;; {R4RS compliance}
190;;;
191
192(primitive-load-path "ice-9/r4rs")
193
194\f
195
eb5d1f88
AW
196;;; {Simple Debugging Tools}
197;;;
198
199;; peek takes any number of arguments, writes them to the
200;; current ouput port, and returns the last argument.
201;; It is handy to wrap around an expression to look at
202;; a value each time is evaluated, e.g.:
203;;
9b5a0d84
AW
204;; (+ 10 (troublesome-fn))
205;; => (+ 10 (pk 'troublesome-fn-returned (troublesome-fn)))
eb5d1f88
AW
206;;
207
208(define (peek . stuff)
209 (newline)
210 (display ";;; ")
211 (write stuff)
212 (newline)
213 (car (last-pair stuff)))
214
215(define pk peek)
216
3972de76
AW
217;; Temporary definition; replaced later.
218(define current-warning-port current-error-port)
b7742c6b 219
eb5d1f88 220(define (warn . stuff)
2c27dd57 221 (with-output-to-port (current-warning-port)
eb5d1f88
AW
222 (lambda ()
223 (newline)
224 (display ";;; WARNING ")
225 (display stuff)
226 (newline)
227 (car (last-pair stuff)))))
228
229\f
230
21ed9efe 231;;; {Features}
3d2ada2f 232;;;
21ed9efe
MD
233
234(define (provide sym)
235 (if (not (memq sym *features*))
236 (set! *features* (cons sym *features*))))
237
3d2ada2f
DH
238;; Return #t iff FEATURE is available to this Guile interpreter. In SLIB,
239;; provided? also checks to see if the module is available. We should do that
240;; too, but don't.
241
50706e94
JB
242(define (provided? feature)
243 (and (memq feature *features*) #t))
244
4d248541
AW
245\f
246
9b3cc659
AW
247;;; {Structs}
248;;;
249
250(define (make-struct/no-tail vtable . args)
251 (apply make-struct vtable 0 args))
252
253\f
254
a2230b65
AW
255;;; Boot versions of `map' and `for-each', enough to get the expander
256;;; running.
257;;;
258(define map
259 (case-lambda
260 ((f l)
261 (let map1 ((l l))
262 (if (null? l)
263 '()
264 (cons (f (car l)) (map1 (cdr l))))))
265 ((f l1 l2)
266 (let map2 ((l1 l1) (l2 l2))
267 (if (null? l1)
268 '()
269 (cons (f (car l1) (car l2))
270 (map2 (cdr l1) (cdr l2))))))
271 ((f l1 . rest)
272 (let lp ((l1 l1) (rest rest))
273 (if (null? l1)
274 '()
275 (cons (apply f (car l1) (map car rest))
276 (lp (cdr l1) (map cdr rest))))))))
277
278(define for-each
279 (case-lambda
280 ((f l)
281 (let for-each1 ((l l))
282 (if (pair? l)
283 (begin
284 (f (car l))
285 (for-each1 (cdr l))))))
286 ((f l1 l2)
287 (let for-each2 ((l1 l1) (l2 l2))
288 (if (pair? l1)
289 (begin
290 (f (car l1) (car l2))
291 (for-each2 (cdr l1) (cdr l2))))))
292 ((f l1 . rest)
293 (let lp ((l1 l1) (rest rest))
294 (if (pair? l1)
295 (begin
296 (apply f (car l1) (map car rest))
297 (lp (cdr l1) (map cdr rest))))))))
298
4d248541
AW
299;;; {and-map and or-map}
300;;;
301;;; (and-map fn lst) is like (and (fn (car lst)) (fn (cadr lst)) (fn...) ...)
302;;; (or-map fn lst) is like (or (fn (car lst)) (fn (cadr lst)) (fn...) ...)
303;;;
304
305;; and-map f l
306;;
307;; Apply f to successive elements of l until exhaustion or f returns #f.
308;; If returning early, return #f. Otherwise, return the last value returned
309;; by f. If f has never been called because l is empty, return #t.
310;;
311(define (and-map f lst)
312 (let loop ((result #t)
9b5a0d84 313 (l lst))
4d248541 314 (and result
9b5a0d84
AW
315 (or (and (null? l)
316 result)
317 (loop (f (car l)) (cdr l))))))
4d248541
AW
318
319;; or-map f l
320;;
321;; Apply f to successive elements of l until exhaustion or while f returns #f.
322;; If returning early, return the return value of f.
323;;
324(define (or-map f lst)
325 (let loop ((result #f)
9b5a0d84 326 (l lst))
4d248541 327 (or result
9b5a0d84
AW
328 (and (not (null? l))
329 (loop (f (car l)) (cdr l))))))
4d248541
AW
330
331\f
332
3d2ada2f 333;; let format alias simple-format until the more complete version is loaded
52cfc69b 334
8641dd9e
GB
335(define format simple-format)
336
fdc6aebf
KR
337;; this is scheme wrapping the C code so the final pred call is a tail call,
338;; per SRFI-13 spec
a4c8a02e
AW
339(define string-any
340 (lambda* (char_pred s #:optional (start 0) (end (string-length s)))
fdc6aebf 341 (if (and (procedure? char_pred)
9b5a0d84
AW
342 (> end start)
343 (<= end (string-length s))) ;; let c-code handle range error
344 (or (string-any-c-code char_pred s start (1- end))
345 (char_pred (string-ref s (1- end))))
346 (string-any-c-code char_pred s start end))))
fdc6aebf
KR
347
348;; this is scheme wrapping the C code so the final pred call is a tail call,
349;; per SRFI-13 spec
a4c8a02e
AW
350(define string-every
351 (lambda* (char_pred s #:optional (start 0) (end (string-length s)))
fdc6aebf 352 (if (and (procedure? char_pred)
9b5a0d84
AW
353 (> end start)
354 (<= end (string-length s))) ;; let c-code handle range error
355 (and (string-every-c-code char_pred s start (1- end))
356 (char_pred (string-ref s (1- end))))
357 (string-every-c-code char_pred s start end))))
fdc6aebf 358
1b05b324
MV
359;; A variant of string-fill! that we keep for compatability
360;;
361(define (substring-fill! str start end fill)
362 (string-fill! str fill start end))
363
21ed9efe 364\f
79451588 365
12eae603
AW
366;; Define a minimal stub of the module API for psyntax, before modules
367;; have booted.
efa6f9d9 368(define (module-name x)
a26934a8 369 '(guile))
05a5e5d6
AW
370(define (module-add! module sym var)
371 (hashq-set! (%get-pre-modules-obarray) sym var))
3d5f3091
AW
372(define (module-define! module sym val)
373 (let ((v (hashq-ref (%get-pre-modules-obarray) sym)))
374 (if v
375 (variable-set! v val)
05a5e5d6 376 (module-add! (current-module) sym (make-variable val)))))
3d5f3091
AW
377(define (module-ref module sym)
378 (let ((v (module-variable module sym)))
379 (if v (variable-ref v) (error "badness!" (pk module) (pk sym)))))
12eae603
AW
380(define (resolve-module . args)
381 #f)
3d5f3091 382
6a952e0e 383;; API provided by psyntax
e4721dde 384(define syntax-violation #f)
22225fc1
AW
385(define datum->syntax #f)
386(define syntax->datum #f)
750ae8b7 387(define syntax-source #f)
22225fc1
AW
388(define identifier? #f)
389(define generate-temporaries #f)
13182603 390(define bound-identifier=? #f)
13182603 391(define free-identifier=? #f)
9b0975f1 392(define syntax-local-binding #f)
5a0132b3 393
8a73a6d2 394;; $sc-dispatch is an implementation detail of psyntax. It is used by
6a952e0e 395;; expanded macros, to dispatch an input against a set of patterns.
5a0132b3
AW
396(define $sc-dispatch #f)
397
6a952e0e 398;; Load it up!
13182603 399(primitive-load-path "ice-9/psyntax-pp")
4f692ace
AW
400;; The binding for `macroexpand' has now been overridden, making psyntax the
401;; expander now.
79451588 402
a1a482e0
AW
403(define-syntax and
404 (syntax-rules ()
405 ((_) #t)
406 ((_ x) x)
407 ((_ x y ...) (if x (and y ...) #f))))
408
409(define-syntax or
410 (syntax-rules ()
411 ((_) #f)
412 ((_ x) x)
413 ((_ x y ...) (let ((t x)) (if t t (or y ...))))))
414
9accf3d9
AW
415(define-syntax-rule (when test stmt stmt* ...)
416 (if test (begin stmt stmt* ...)))
417
418(define-syntax-rule (unless test stmt stmt* ...)
419 (if (not test) (begin stmt stmt* ...)))
420
dc1eed52
AW
421;; The "maybe-more" bits are something of a hack, so that we can support
422;; SRFI-61. Rewrites into a standalone syntax-case macro would be
423;; appreciated.
a1a482e0 424(define-syntax cond
dc1eed52
AW
425 (syntax-rules (=> else)
426 ((_ "maybe-more" test consequent)
427 (if test consequent))
428
429 ((_ "maybe-more" test consequent clause ...)
430 (if test consequent (cond clause ...)))
431
432 ((_ (else else1 else2 ...))
433 (begin else1 else2 ...))
434
435 ((_ (test => receiver) more-clause ...)
436 (let ((t test))
437 (cond "maybe-more" t (receiver t) more-clause ...)))
438
439 ((_ (generator guard => receiver) more-clause ...)
440 (call-with-values (lambda () generator)
441 (lambda t
442 (cond "maybe-more"
443 (apply guard t) (apply receiver t) more-clause ...))))
444
445 ((_ (test => receiver ...) more-clause ...)
446 (syntax-violation 'cond "wrong number of receiver expressions"
447 '(test => receiver ...)))
448 ((_ (generator guard => receiver ...) more-clause ...)
449 (syntax-violation 'cond "wrong number of receiver expressions"
450 '(generator guard => receiver ...)))
451
452 ((_ (test) more-clause ...)
453 (let ((t test))
454 (cond "maybe-more" t t more-clause ...)))
455
456 ((_ (test body1 body2 ...) more-clause ...)
457 (cond "maybe-more"
458 test (begin body1 body2 ...) more-clause ...))))
a1a482e0
AW
459
460(define-syntax case
461 (syntax-rules (else)
462 ((case (key ...)
463 clauses ...)
464 (let ((atom-key (key ...)))
465 (case atom-key clauses ...)))
466 ((case key
467 (else result1 result2 ...))
468 (begin result1 result2 ...))
469 ((case key
470 ((atoms ...) result1 result2 ...))
471 (if (memv key '(atoms ...))
472 (begin result1 result2 ...)))
473 ((case key
474 ((atoms ...) result1 result2 ...)
475 clause clauses ...)
476 (if (memv key '(atoms ...))
477 (begin result1 result2 ...)
478 (case key clause clauses ...)))))
479
480(define-syntax do
481 (syntax-rules ()
482 ((do ((var init step ...) ...)
483 (test expr ...)
484 command ...)
485 (letrec
486 ((loop
487 (lambda (var ...)
488 (if test
489 (begin
490 (if #f #f)
491 expr ...)
492 (begin
493 command
494 ...
495 (loop (do "step" var step ...)
496 ...))))))
497 (loop init ...)))
498 ((do "step" x)
499 x)
500 ((do "step" x y)
501 y)))
502
0c65f52c
AW
503(define-syntax-rule (delay exp)
504 (make-promise (lambda () exp)))
79451588 505
cb65f76c
AR
506(include-from-path "ice-9/quasisyntax")
507
41147ee7
AW
508(define-syntax current-source-location
509 (lambda (x)
510 (syntax-case x ()
511 ((_)
512 (with-syntax ((s (datum->syntax x (syntax-source x))))
513 #''s)))))
514
925172cf
AW
515;; We provide this accessor out of convenience. current-line and
516;; current-column aren't so interesting, because they distort what they
517;; are measuring; better to use syntax-source from a macro.
518;;
519(define-syntax current-filename
520 (lambda (x)
521 "A macro that expands to the current filename: the filename that
522the (current-filename) form appears in. Expands to #f if this
523information is unavailable."
524 (and=> (syntax-source x)
525 (lambda (s) (assq-ref s 'filename)))))
526
0c65f52c
AW
527(define-syntax-rule (define-once sym val)
528 (define sym
529 (if (module-locally-bound? (current-module) 'sym) sym val)))
41147ee7 530
a2230b65
AW
531;;; The real versions of `map' and `for-each', with cycle detection, and
532;;; that use reverse! instead of recursion in the case of `map'.
533;;;
534(define map
535 (case-lambda
536 ((f l)
537 (let map1 ((hare l) (tortoise l) (move? #f) (out '()))
538 (if (pair? hare)
539 (if move?
540 (if (eq? tortoise hare)
541 (scm-error 'wrong-type-arg "map" "Circular list: ~S"
542 (list l) #f)
543 (map1 (cdr hare) (cdr tortoise) #f
544 (cons (f (car hare)) out)))
545 (map1 (cdr hare) tortoise #t
546 (cons (f (car hare)) out)))
547 (if (null? hare)
548 (reverse! out)
549 (scm-error 'wrong-type-arg "map" "Not a list: ~S"
550 (list l) #f)))))
551
552 ((f l1 l2)
553 (let map2 ((h1 l1) (h2 l2) (t1 l1) (t2 l2) (move? #f) (out '()))
554 (cond
555 ((pair? h1)
556 (cond
557 ((not (pair? h2))
558 (scm-error 'wrong-type-arg "map"
559 (if (list? h2)
560 "List of wrong length: ~S"
561 "Not a list: ~S")
562 (list l2) #f))
563 ((not move?)
564 (map2 (cdr h1) (cdr h2) t1 t2 #t
565 (cons (f (car h1) (car h2)) out)))
566 ((eq? t1 h1)
567 (scm-error 'wrong-type-arg "map" "Circular list: ~S"
568 (list l1) #f))
569 ((eq? t2 h2)
570 (scm-error 'wrong-type-arg "map" "Circular list: ~S"
571 (list l2) #f))
572 (else
573 (map2 (cdr h1) (cdr h2) (cdr t1) (cdr t2) #f
574 (cons (f (car h1) (car h2)) out)))))
575
576 ((and (null? h1) (null? h2))
577 (reverse! out))
578
579 ((null? h1)
580 (scm-error 'wrong-type-arg "map"
581 (if (list? h2)
582 "List of wrong length: ~S"
583 "Not a list: ~S")
584 (list l2) #f))
585 (else
586 (scm-error 'wrong-type-arg "map"
587 "Not a list: ~S"
588 (list l1) #f)))))
589
590 ((f l1 . rest)
591 (let ((len (length l1)))
592 (let mapn ((rest rest))
593 (or (null? rest)
594 (if (= (length (car rest)) len)
595 (mapn (cdr rest))
596 (scm-error 'wrong-type-arg "map" "List of wrong length: ~S"
597 (list (car rest)) #f)))))
598 (let mapn ((l1 l1) (rest rest) (out '()))
599 (if (null? l1)
600 (reverse! out)
601 (mapn (cdr l1) (map cdr rest)
602 (cons (apply f (car l1) (map car rest)) out)))))))
603
604(define map-in-order map)
605
606(define for-each
607 (case-lambda
608 ((f l)
609 (let for-each1 ((hare l) (tortoise l) (move? #f))
610 (if (pair? hare)
611 (if move?
612 (if (eq? tortoise hare)
613 (scm-error 'wrong-type-arg "for-each" "Circular list: ~S"
614 (list l) #f)
615 (begin
616 (f (car hare))
617 (for-each1 (cdr hare) (cdr tortoise) #f)))
618 (begin
619 (f (car hare))
620 (for-each1 (cdr hare) tortoise #t)))
621
622 (if (not (null? hare))
623 (scm-error 'wrong-type-arg "for-each" "Not a list: ~S"
624 (list l) #f)))))
625
626 ((f l1 l2)
627 (let for-each2 ((h1 l1) (h2 l2) (t1 l1) (t2 l2) (move? #f))
628 (cond
629 ((and (pair? h1) (pair? h2))
630 (cond
631 ((not move?)
632 (f (car h1) (car h2))
633 (for-each2 (cdr h1) (cdr h2) t1 t2 #t))
634 ((eq? t1 h1)
635 (scm-error 'wrong-type-arg "for-each" "Circular list: ~S"
636 (list l1) #f))
637 ((eq? t2 h2)
638 (scm-error 'wrong-type-arg "for-each" "Circular list: ~S"
639 (list l2) #f))
640 (else
641 (f (car h1) (car h2))
642 (for-each2 (cdr h1) (cdr h2) (cdr t1) (cdr t2) #f))))
643
644 ((if (null? h1)
645 (or (null? h2) (pair? h2))
646 (and (pair? h1) (null? h2)))
647 (if #f #f))
648
649 ((list? h1)
650 (scm-error 'wrong-type-arg "for-each" "Unexpected tail: ~S"
651 (list h2) #f))
652 (else
653 (scm-error 'wrong-type-arg "for-each" "Unexpected tail: ~S"
654 (list h1) #f)))))
655
656 ((f l1 . rest)
657 (let ((len (length l1)))
658 (let for-eachn ((rest rest))
659 (or (null? rest)
660 (if (= (length (car rest)) len)
661 (for-eachn (cdr rest))
662 (scm-error 'wrong-type-arg "for-each" "List of wrong length: ~S"
663 (list (car rest)) #f)))))
664
665 (let for-eachn ((l1 l1) (rest rest))
666 (if (pair? l1)
667 (begin
668 (apply f (car l1) (map car rest))
669 (for-eachn (cdr l1) (map cdr rest))))))))
670
671
79451588 672\f
48fdec21 673
40b91dc8
AW
674;;;
675;;; Extensible exception printing.
676;;;
677
678(define set-exception-printer! #f)
e8df456a
AW
679;; There is already a definition of print-exception from backtrace.c
680;; that we will override.
40b91dc8
AW
681
682(let ((exception-printers '()))
683 (define (print-location frame port)
684 (let ((source (and=> frame frame-source)))
685 ;; source := (addr . (filename . (line . column)))
686 (if source
687 (let ((filename (or (cadr source) "<unnamed port>"))
688 (line (caddr source))
689 (col (cdddr source)))
153c4a4a 690 (format port "~a:~a:~a: " filename (1+ line) col))
40b91dc8
AW
691 (format port "ERROR: "))))
692
693 (set! set-exception-printer!
694 (lambda (key proc)
695 (set! exception-printers (acons key proc exception-printers))))
696
697 (set! print-exception
698 (lambda (port frame key args)
699 (define (default-printer)
700 (format port "Throw to key `~a' with args `~s'." key args))
701
702 (if frame
703 (let ((proc (frame-procedure frame)))
704 (print-location frame port)
705 (format port "In procedure ~a:\n"
706 (or (procedure-name proc) proc))))
707
708 (print-location frame port)
709 (catch #t
710 (lambda ()
711 (let ((printer (assq-ref exception-printers key)))
712 (if printer
713 (printer port key args default-printer)
714 (default-printer))))
715 (lambda (k . args)
716 (format port "Error while printing exception.")))
717 (newline port)
718 (force-output port))))
719
720;;;
721;;; Printers for those keys thrown by Guile.
722;;;
723(let ()
724 (define (scm-error-printer port key args default-printer)
725 ;; Abuse case-lambda as a pattern matcher, given that we don't have
726 ;; ice-9 match at this point.
727 (apply (case-lambda
728 ((subr msg args . rest)
729 (if subr
730 (format port "In procedure ~a: " subr))
4e33a132 731 (apply format port msg (or args '())))
40b91dc8
AW
732 (_ (default-printer)))
733 args))
734
735 (define (syntax-error-printer port key args default-printer)
736 (apply (case-lambda
dc20f5a8 737 ((who what where form subform . extra)
40b91dc8
AW
738 (format port "Syntax error:\n")
739 (if where
740 (let ((file (or (assq-ref where 'filename) "unknown file"))
741 (line (and=> (assq-ref where 'line) 1+))
742 (col (assq-ref where 'column)))
743 (format port "~a:~a:~a: " file line col))
744 (format port "unknown location: "))
745 (if who
746 (format port "~a: " who))
747 (format port "~a" what)
748 (if subform
749 (format port " in subform ~s of ~s" subform form)
750 (if form
751 (format port " in form ~s" form))))
752 (_ (default-printer)))
753 args))
754
e7b2efd5
LC
755 (define (getaddrinfo-error-printer port key args default-printer)
756 (format port "In procedure getaddrinfo: ~a" (gai-strerror (car args))))
757
40b91dc8
AW
758 (set-exception-printer! 'goops-error scm-error-printer)
759 (set-exception-printer! 'host-not-found scm-error-printer)
760 (set-exception-printer! 'keyword-argument-error scm-error-printer)
761 (set-exception-printer! 'misc-error scm-error-printer)
762 (set-exception-printer! 'no-data scm-error-printer)
763 (set-exception-printer! 'no-recovery scm-error-printer)
764 (set-exception-printer! 'null-pointer-error scm-error-printer)
765 (set-exception-printer! 'out-of-range scm-error-printer)
766 (set-exception-printer! 'program-error scm-error-printer)
767 (set-exception-printer! 'read-error scm-error-printer)
768 (set-exception-printer! 'regular-expression-syntax scm-error-printer)
769 (set-exception-printer! 'signal scm-error-printer)
770 (set-exception-printer! 'stack-overflow scm-error-printer)
771 (set-exception-printer! 'system-error scm-error-printer)
772 (set-exception-printer! 'try-again scm-error-printer)
773 (set-exception-printer! 'unbound-variable scm-error-printer)
774 (set-exception-printer! 'wrong-number-of-args scm-error-printer)
775 (set-exception-printer! 'wrong-type-arg scm-error-printer)
776
e7b2efd5
LC
777 (set-exception-printer! 'syntax-error syntax-error-printer)
778
779 (set-exception-printer! 'getaddrinfo-error getaddrinfo-error-printer))
40b91dc8
AW
780
781
782\f
783
3d2ada2f
DH
784;;; {Defmacros}
785;;;
3d2ada2f 786
13182603
AW
787(define-syntax define-macro
788 (lambda (x)
97ce9dbf 789 "Define a defmacro."
13182603 790 (syntax-case x ()
97ce9dbf 791 ((_ (macro . args) doc body1 body ...)
a927454d
AW
792 (string? (syntax->datum #'doc))
793 #'(define-macro macro doc (lambda args body1 body ...)))
97ce9dbf 794 ((_ (macro . args) body ...)
a927454d 795 #'(define-macro macro #f (lambda args body ...)))
97ce9dbf 796 ((_ macro doc transformer)
a927454d
AW
797 (or (string? (syntax->datum #'doc))
798 (not (syntax->datum #'doc)))
799 #'(define-syntax macro
800 (lambda (y)
801 doc
a5e95abe
AW
802 #((macro-type . defmacro)
803 (defmacro-args args))
a927454d
AW
804 (syntax-case y ()
805 ((_ . args)
806 (let ((v (syntax->datum #'args)))
807 (datum->syntax y (apply transformer v)))))))))))
13182603
AW
808
809(define-syntax defmacro
810 (lambda (x)
97ce9dbf 811 "Define a defmacro, with the old lispy defun syntax."
13182603 812 (syntax-case x ()
97ce9dbf 813 ((_ macro args doc body1 body ...)
a927454d
AW
814 (string? (syntax->datum #'doc))
815 #'(define-macro macro doc (lambda args body1 body ...)))
97ce9dbf 816 ((_ macro args body ...)
a927454d 817 #'(define-macro macro #f (lambda args body ...))))))
3d2ada2f
DH
818
819(provide 'defmacro)
48fdec21
MV
820
821\f
822
3d2ada2f
DH
823;;; {Deprecation}
824;;;
3d2ada2f 825
ec0f307e
AW
826(define-syntax begin-deprecated
827 (lambda (x)
828 (syntax-case x ()
829 ((_ form form* ...)
830 (if (include-deprecated-features)
831 #'(begin form form* ...)
832 #'(begin))))))
0f2d19dd
JB
833
834\f
3d2ada2f 835
79451588 836;;; {Trivial Functions}
0f2d19dd 837;;;
79451588 838
6b08d75b 839(define (identity x) x)
18f06db9
LC
840
841(define (compose proc . rest)
842 "Compose PROC with the procedures in REST, such that the last one in
843REST is applied first and PROC last, and return the resulting procedure.
844The given procedures must have compatible arity."
845 (if (null? rest)
846 proc
847 (let ((g (apply compose rest)))
848 (lambda args
849 (call-with-values (lambda () (apply g args)) proc)))))
850
851(define (negate proc)
852 "Return a procedure with the same arity as PROC that returns the `not'
853of PROC's result."
854 (lambda args
855 (not (apply proc args))))
856
857(define (const value)
858 "Return a procedure that accepts any number of arguments and returns
859VALUE."
860 (lambda _
861 value))
862
132e5fac 863(define (and=> value procedure) (and value (procedure value)))
e8ed460e 864(define call/cc call-with-current-continuation)
79451588 865
0c65f52c
AW
866(define-syntax-rule (false-if-exception expr)
867 (catch #t
868 (lambda () expr)
869 (lambda (k . args) #f)))
3d2ada2f
DH
870
871\f
872
873;;; {General Properties}
874;;;
875
02b582ce
AW
876;; Properties are a lispy way to associate random info with random objects.
877;; Traditionally properties are implemented as an alist or a plist actually
878;; pertaining to the object in question.
879;;
880;; These "object properties" have the advantage that they can be associated with
881;; any object, even if the object has no plist. Object properties are good when
882;; you are extending pre-existing objects in unexpected ways. They also present
883;; a pleasing, uniform procedure-with-setter interface. But if you have a data
884;; type that always has properties, it's often still best to store those
885;; properties within the object itself.
3d2ada2f
DH
886
887(define (make-object-property)
0c65f52c
AW
888 (define-syntax-rule (with-mutex lock exp)
889 (dynamic-wind (lambda () (lock-mutex lock))
890 (lambda () exp)
891 (lambda () (unlock-mutex lock))))
79488112
AW
892 (let ((prop (make-weak-key-hash-table))
893 (lock (make-mutex)))
3d2ada2f 894 (make-procedure-with-setter
79488112
AW
895 (lambda (obj) (with-mutex lock (hashq-ref prop obj)))
896 (lambda (obj val) (with-mutex lock (hashq-set! prop obj val))))))
897
3d2ada2f 898
0f2d19dd 899\f
6b08d75b 900
0f2d19dd
JB
901;;; {Symbol Properties}
902;;;
903
02b582ce
AW
904;;; Symbol properties are something you see in old Lisp code. In most current
905;;; Guile code, symbols are not used as a data structure -- they are used as
906;;; keys into other data structures.
907
0f2d19dd
JB
908(define (symbol-property sym prop)
909 (let ((pair (assoc prop (symbol-pref sym))))
910 (and pair (cdr pair))))
911
912(define (set-symbol-property! sym prop val)
913 (let ((pair (assoc prop (symbol-pref sym))))
914 (if pair
9b5a0d84
AW
915 (set-cdr! pair val)
916 (symbol-pset! sym (acons prop val (symbol-pref sym))))))
0f2d19dd
JB
917
918(define (symbol-property-remove! sym prop)
919 (let ((pair (assoc prop (symbol-pref sym))))
920 (if pair
9b5a0d84 921 (symbol-pset! sym (delq! pair (symbol-pref sym))))))
0f2d19dd
JB
922
923\f
1e531c3a 924
0f2d19dd
JB
925;;; {Arrays}
926;;;
927
2042e178
MV
928(define (array-shape a)
929 (map (lambda (ind) (if (number? ind) (list 0 (+ -1 ind)) ind))
930 (array-dimensions a)))
0f2d19dd
JB
931
932\f
3d2ada2f 933
0f2d19dd
JB
934;;; {Keywords}
935;;;
936
010b159f
AW
937;;; It's much better if you can use lambda* / define*, of course.
938
0f2d19dd
JB
939(define (kw-arg-ref args kw)
940 (let ((rem (member kw args)))
941 (and rem (pair? (cdr rem)) (cadr rem))))
942
943\f
fa7e9274 944
9f9aa47b 945;;; {Structs}
3d2ada2f 946;;;
fa7e9274
MV
947
948(define (struct-layout s)
9f9aa47b 949 (struct-ref (struct-vtable s) vtable-index-layout))
fa7e9274
MV
950
951\f
d7faeb2e 952
0f2d19dd
JB
953;;; {Records}
954;;;
955
fa7e9274
MV
956;; Printing records: by default, records are printed as
957;;
958;; #<type-name field1: val1 field2: val2 ...>
959;;
960;; You can change that by giving a custom printing function to
961;; MAKE-RECORD-TYPE (after the list of field symbols). This function
962;; will be called like
963;;
964;; (<printer> object port)
965;;
966;; It should print OBJECT to PORT.
967
cf8f1a90 968(define (inherit-print-state old-port new-port)
8a30733e
MD
969 (if (get-print-state old-port)
970 (port-with-print-state new-port (get-print-state old-port))
cf8f1a90
MV
971 new-port))
972
e31f22eb 973;; 0: type-name, 1: fields, 2: constructor
20edfbbd 974(define record-type-vtable
e31f22eb
AW
975 ;; FIXME: This should just call make-vtable, not make-vtable-vtable; but for
976 ;; that we need to expose the bare vtable-vtable to Scheme.
977 (make-vtable-vtable "prprpw" 0
9b5a0d84
AW
978 (lambda (s p)
979 (cond ((eq? s record-type-vtable)
980 (display "#<record-type-vtable>" p))
981 (else
982 (display "#<record-type " p)
983 (display (record-type-name s) p)
984 (display ">" p))))))
0f2d19dd
JB
985
986(define (record-type? obj)
987 (and (struct? obj) (eq? record-type-vtable (struct-vtable obj))))
988
b2669c41 989(define* (make-record-type type-name fields #:optional printer)
31ac29b6 990 ;; Pre-generate constructors for nfields < 20.
e31f22eb
AW
991 (define-syntax make-constructor
992 (lambda (x)
993 (define *max-static-argument-count* 20)
994 (define (make-formals n)
995 (let lp ((i 0))
996 (if (< i n)
997 (cons (datum->syntax
998 x
999 (string->symbol
1000 (string (integer->char (+ (char->integer #\a) i)))))
1001 (lp (1+ i)))
1002 '())))
1003 (syntax-case x ()
1004 ((_ rtd exp) (not (identifier? #'exp))
1005 #'(let ((n exp))
1006 (make-constructor rtd n)))
1007 ((_ rtd nfields)
1008 #`(case nfields
1009 #,@(let lp ((n 0))
1010 (if (< n *max-static-argument-count*)
1011 (cons (with-syntax (((formal ...) (make-formals n))
1012 (n n))
1013 #'((n)
1014 (lambda (formal ...)
1015 (make-struct rtd 0 formal ...))))
1016 (lp (1+ n)))
1017 '()))
1018 (else
1019 (lambda args
1020 (if (= (length args) nfields)
1021 (apply make-struct rtd 0 args)
1022 (scm-error 'wrong-number-of-args
1023 (format #f "make-~a" type-name)
1024 "Wrong number of arguments" '() #f)))))))))
1025
51797cec
AW
1026 (define (default-record-printer s p)
1027 (display "#<" p)
1028 (display (record-type-name (record-type-descriptor s)) p)
1029 (let loop ((fields (record-type-fields (record-type-descriptor s)))
1030 (off 0))
1031 (cond
1032 ((not (null? fields))
1033 (display " " p)
1034 (display (car fields) p)
1035 (display ": " p)
1036 (display (struct-ref s off) p)
1037 (loop (cdr fields) (+ 1 off)))))
1038 (display ">" p))
1039
e31f22eb
AW
1040 (let ((rtd (make-struct record-type-vtable 0
1041 (make-struct-layout
1042 (apply string-append
1043 (map (lambda (f) "pw") fields)))
b2669c41 1044 (or printer default-record-printer)
e31f22eb
AW
1045 type-name
1046 (copy-tree fields))))
1047 (struct-set! rtd (+ vtable-offset-user 2)
1048 (make-constructor rtd (length fields)))
51797cec
AW
1049 ;; Temporary solution: Associate a name to the record type descriptor
1050 ;; so that the object system can create a wrapper class for it.
e31f22eb
AW
1051 (set-struct-vtable-name! rtd (if (symbol? type-name)
1052 type-name
1053 (string->symbol type-name)))
1054 rtd))
0f2d19dd
JB
1055
1056(define (record-type-name obj)
1057 (if (record-type? obj)
9f9aa47b 1058 (struct-ref obj vtable-offset-user)
0f2d19dd
JB
1059 (error 'not-a-record-type obj)))
1060
1061(define (record-type-fields obj)
1062 (if (record-type? obj)
9f9aa47b 1063 (struct-ref obj (+ 1 vtable-offset-user))
0f2d19dd
JB
1064 (error 'not-a-record-type obj)))
1065
d44a0d12
AW
1066(define* (record-constructor rtd #:optional field-names)
1067 (if (not field-names)
e31f22eb 1068 (struct-ref rtd (+ 2 vtable-offset-user))
d44a0d12
AW
1069 (primitive-eval
1070 `(lambda ,field-names
1071 (make-struct ',rtd 0 ,@(map (lambda (f)
1072 (if (memq f field-names)
1073 f
1074 #f))
1075 (record-type-fields rtd)))))))
3bf27608 1076
0f2d19dd
JB
1077(define (record-predicate rtd)
1078 (lambda (obj) (and (struct? obj) (eq? rtd (struct-vtable obj)))))
1079
3ba9acb1 1080(define (%record-type-error rtd obj) ;; private helper
afc4ccd4
KR
1081 (or (eq? rtd (record-type-descriptor obj))
1082 (scm-error 'wrong-type-arg "%record-type-check"
9b5a0d84
AW
1083 "Wrong type record (want `~S'): ~S"
1084 (list (record-type-name rtd) obj)
1085 #f)))
afc4ccd4 1086
0f2d19dd 1087(define (record-accessor rtd field-name)
3bf27608 1088 (let ((pos (list-index (record-type-fields rtd) field-name)))
0f2d19dd 1089 (if (not pos)
9b5a0d84 1090 (error 'no-such-field field-name))
3bf27608
AW
1091 (lambda (obj)
1092 (if (eq? (struct-vtable obj) rtd)
1093 (struct-ref obj pos)
1094 (%record-type-error rtd obj)))))
0f2d19dd
JB
1095
1096(define (record-modifier rtd field-name)
3bf27608 1097 (let ((pos (list-index (record-type-fields rtd) field-name)))
0f2d19dd 1098 (if (not pos)
9b5a0d84 1099 (error 'no-such-field field-name))
3bf27608
AW
1100 (lambda (obj val)
1101 (if (eq? (struct-vtable obj) rtd)
1102 (struct-set! obj pos val)
1103 (%record-type-error rtd obj)))))
0f2d19dd
JB
1104
1105(define (record? obj)
1106 (and (struct? obj) (record-type? (struct-vtable obj))))
1107
1108(define (record-type-descriptor obj)
1109 (if (struct? obj)
1110 (struct-vtable obj)
1111 (error 'not-a-record obj)))
1112
21ed9efe
MD
1113(provide 'record)
1114
0f2d19dd 1115\f
3d2ada2f 1116
0f2d19dd
JB
1117;;; {Booleans}
1118;;;
1119
1120(define (->bool x) (not (not x)))
1121
1122\f
3d2ada2f 1123
0f2d19dd
JB
1124;;; {Symbols}
1125;;;
1126
1127(define (symbol-append . args)
06f0414c 1128 (string->symbol (apply string-append (map symbol->string args))))
0f2d19dd
JB
1129
1130(define (list->symbol . args)
1131 (string->symbol (apply list->string args)))
1132
1133(define (symbol . args)
1134 (string->symbol (apply string args)))
1135
0f2d19dd 1136\f
3d2ada2f 1137
0f2d19dd
JB
1138;;; {Lists}
1139;;;
1140
1141(define (list-index l k)
1142 (let loop ((n 0)
9b5a0d84 1143 (l l))
0f2d19dd 1144 (and (not (null? l))
9b5a0d84
AW
1145 (if (eq? (car l) k)
1146 n
1147 (loop (+ n 1) (cdr l))))))
0f2d19dd 1148
1729d8ff 1149\f
3d2ada2f 1150
073167ef
LC
1151;; Load `posix.scm' even when not (provided? 'posix) so that we get the
1152;; `stat' accessors.
1153(primitive-load-path "ice-9/posix")
6fa8995c 1154
52cfc69b 1155(if (provided? 'socket)
1e6ebf54 1156 (primitive-load-path "ice-9/networking"))
3afb28ce 1157
f3197274 1158;; For reference, Emacs file-exists-p uses stat in this same way.
6fa8995c 1159(define file-exists?
52cfc69b 1160 (if (provided? 'posix)
6fa8995c 1161 (lambda (str)
9b5a0d84 1162 (->bool (stat str #f)))
6fa8995c 1163 (lambda (str)
9b5a0d84
AW
1164 (let ((port (catch 'system-error (lambda () (open-file str OPEN_READ))
1165 (lambda args #f))))
1166 (if port (begin (close-port port) #t)
1167 #f)))))
6fa8995c
GH
1168
1169(define file-is-directory?
52cfc69b 1170 (if (provided? 'posix)
6fa8995c 1171 (lambda (str)
9b5a0d84 1172 (eq? (stat:type (stat str)) 'directory))
6fa8995c 1173 (lambda (str)
9b5a0d84
AW
1174 (let ((port (catch 'system-error
1175 (lambda () (open-file (string-append str "/.")
1176 OPEN_READ))
1177 (lambda args #f))))
1178 (if port (begin (close-port port) #t)
1179 #f)))))
0f2d19dd 1180
019ac1c9
MV
1181(define (system-error-errno args)
1182 (if (eq? (car args) 'system-error)
1183 (car (list-ref args 4))
1184 #f))
1185
0f2d19dd 1186\f
3d2ada2f 1187
0f2d19dd
JB
1188;;; {Error Handling}
1189;;;
1190
4eeaf67c
AW
1191(define error
1192 (case-lambda
1193 (()
4eeaf67c
AW
1194 (scm-error 'misc-error #f "?" #f #f))
1195 ((message . args)
4eeaf67c
AW
1196 (let ((msg (string-join (cons "~A" (make-list (length args) "~S")))))
1197 (scm-error 'misc-error #f msg (cons message args) #f)))))
be2d2c70 1198
0f2d19dd 1199\f
bce074ee 1200
b38507c1
AW
1201;;; {Time Structures}
1202;;;
1203
708bf0f3
GH
1204(define (tm:sec obj) (vector-ref obj 0))
1205(define (tm:min obj) (vector-ref obj 1))
1206(define (tm:hour obj) (vector-ref obj 2))
1207(define (tm:mday obj) (vector-ref obj 3))
1208(define (tm:mon obj) (vector-ref obj 4))
1209(define (tm:year obj) (vector-ref obj 5))
1210(define (tm:wday obj) (vector-ref obj 6))
1211(define (tm:yday obj) (vector-ref obj 7))
1212(define (tm:isdst obj) (vector-ref obj 8))
1213(define (tm:gmtoff obj) (vector-ref obj 9))
1214(define (tm:zone obj) (vector-ref obj 10))
1215
1216(define (set-tm:sec obj val) (vector-set! obj 0 val))
1217(define (set-tm:min obj val) (vector-set! obj 1 val))
1218(define (set-tm:hour obj val) (vector-set! obj 2 val))
1219(define (set-tm:mday obj val) (vector-set! obj 3 val))
1220(define (set-tm:mon obj val) (vector-set! obj 4 val))
1221(define (set-tm:year obj val) (vector-set! obj 5 val))
1222(define (set-tm:wday obj val) (vector-set! obj 6 val))
1223(define (set-tm:yday obj val) (vector-set! obj 7 val))
1224(define (set-tm:isdst obj val) (vector-set! obj 8 val))
1225(define (set-tm:gmtoff obj val) (vector-set! obj 9 val))
1226(define (set-tm:zone obj val) (vector-set! obj 10 val))
1227
6afcd3b2
GH
1228(define (tms:clock obj) (vector-ref obj 0))
1229(define (tms:utime obj) (vector-ref obj 1))
1230(define (tms:stime obj) (vector-ref obj 2))
1231(define (tms:cutime obj) (vector-ref obj 3))
1232(define (tms:cstime obj) (vector-ref obj 4))
1233
b38507c1
AW
1234\f
1235
1236;;; {File Descriptors and Ports}
1237;;;
1238
1334c61a 1239(define file-position ftell)
52c9a338
AW
1240(define* (file-set-position port offset #:optional (whence SEEK_SET))
1241 (seek port offset whence))
8b13c6b3 1242
e38303a2
GH
1243(define (move->fdes fd/port fd)
1244 (cond ((integer? fd/port)
9b5a0d84
AW
1245 (dup->fdes fd/port fd)
1246 (close fd/port)
1247 fd)
1248 (else
1249 (primitive-move->fdes fd/port fd)
1250 (set-port-revealed! fd/port 1)
1251 fd/port)))
8b13c6b3
GH
1252
1253(define (release-port-handle port)
1254 (let ((revealed (port-revealed port)))
1255 (if (> revealed 0)
9b5a0d84 1256 (set-port-revealed! port (- revealed 1)))))
0f2d19dd 1257
02851b26
AW
1258(define dup->port
1259 (case-lambda
1260 ((port/fd mode)
1261 (fdopen (dup->fdes port/fd) mode))
1262 ((port/fd mode new-fd)
1263 (let ((port (fdopen (dup->fdes port/fd new-fd) mode)))
1264 (set-port-revealed! port 1)
1265 port))))
1266
1267(define dup->inport
1268 (case-lambda
1269 ((port/fd)
1270 (dup->port port/fd "r"))
1271 ((port/fd new-fd)
1272 (dup->port port/fd "r" new-fd))))
1273
1274(define dup->outport
1275 (case-lambda
1276 ((port/fd)
1277 (dup->port port/fd "w"))
1278 ((port/fd new-fd)
1279 (dup->port port/fd "w" new-fd))))
1280
1281(define dup
1282 (case-lambda
1283 ((port/fd)
1284 (if (integer? port/fd)
1285 (dup->fdes port/fd)
1286 (dup->port port/fd (port-mode port/fd))))
1287 ((port/fd new-fd)
1288 (if (integer? port/fd)
1289 (dup->fdes port/fd new-fd)
1290 (dup->port port/fd (port-mode port/fd) new-fd)))))
e38303a2
GH
1291
1292(define (duplicate-port port modes)
1293 (dup->port port modes))
1294
1295(define (fdes->inport fdes)
1296 (let loop ((rest-ports (fdes->ports fdes)))
1297 (cond ((null? rest-ports)
9b5a0d84
AW
1298 (let ((result (fdopen fdes "r")))
1299 (set-port-revealed! result 1)
1300 result))
1301 ((input-port? (car rest-ports))
1302 (set-port-revealed! (car rest-ports)
1303 (+ (port-revealed (car rest-ports)) 1))
1304 (car rest-ports))
1305 (else
1306 (loop (cdr rest-ports))))))
e38303a2
GH
1307
1308(define (fdes->outport fdes)
1309 (let loop ((rest-ports (fdes->ports fdes)))
1310 (cond ((null? rest-ports)
9b5a0d84
AW
1311 (let ((result (fdopen fdes "w")))
1312 (set-port-revealed! result 1)
1313 result))
1314 ((output-port? (car rest-ports))
1315 (set-port-revealed! (car rest-ports)
1316 (+ (port-revealed (car rest-ports)) 1))
1317 (car rest-ports))
1318 (else
1319 (loop (cdr rest-ports))))))
e38303a2
GH
1320
1321(define (port->fdes port)
1322 (set-port-revealed! port (+ (port-revealed port) 1))
1323 (fileno port))
1324
956055a9
GH
1325(define (setenv name value)
1326 (if value
1327 (putenv (string-append name "=" value))
1328 (putenv name)))
1329
5c1254da
MV
1330(define (unsetenv name)
1331 "Remove the entry for NAME from the environment."
1332 (putenv name))
1333
0f2d19dd 1334\f
3d2ada2f 1335
0f2d19dd
JB
1336;;; {Load Paths}
1337;;;
1338
3cab8392
JB
1339(define (in-vicinity vicinity file)
1340 (let ((tail (let ((len (string-length vicinity)))
9b5a0d84
AW
1341 (if (zero? len)
1342 #f
1343 (string-ref vicinity (- len 1))))))
3cab8392 1344 (string-append vicinity
9b5a0d84
AW
1345 (if (or (not tail)
1346 (eq? tail #\/))
1347 ""
1348 "/")
1349 file)))
02ceadb8 1350
0f2d19dd 1351\f
3d2ada2f 1352
ef00e7f4 1353;;; {Help for scm_shell}
3d2ada2f 1354;;;
ef00e7f4
JB
1355;;; The argument-processing code used by Guile-based shells generates
1356;;; Scheme code based on the argument list. This page contains help
1357;;; functions for the code it generates.
3d2ada2f 1358;;;
ef00e7f4 1359
ef00e7f4
JB
1360(define (command-line) (program-arguments))
1361
5aa7fe69
JB
1362;; This is mostly for the internal use of the code generated by
1363;; scm_compile_shell_switches.
eef6519b 1364
ef00e7f4 1365(define (load-user-init)
1f08acd9 1366 (let* ((home (or (getenv "HOME")
9b5a0d84
AW
1367 (false-if-exception (passwd:dir (getpwuid (getuid))))
1368 "/")) ;; fallback for cygwin etc.
1369 (init-file (in-vicinity home ".guile")))
1f08acd9 1370 (if (file-exists? init-file)
9b5a0d84 1371 (primitive-load init-file))))
ef00e7f4
JB
1372
1373\f
3d2ada2f 1374
107139ea
AW
1375;;; {The interpreter stack}
1376;;;
1377
06dcb9df 1378;; %stacks defined in stacks.c
a6cd3555 1379(define (%start-stack tag thunk)
8fc43b12
AW
1380 (let ((prompt-tag (make-prompt-tag "start-stack")))
1381 (call-with-prompt
1382 prompt-tag
1383 (lambda ()
1384 (with-fluids ((%stacks (acons tag prompt-tag
1385 (or (fluid-ref %stacks) '()))))
1386 (thunk)))
1387 (lambda (k . args)
52738540 1388 (%start-stack tag (lambda () (apply k args)))))))
0c65f52c
AW
1389
1390(define-syntax-rule (start-stack tag exp)
1391 (%start-stack tag (lambda () exp)))
107139ea
AW
1392
1393\f
1394
a06181a2 1395;;; {Loading by paths}
3d2ada2f 1396;;;
a06181a2
JB
1397
1398;;; Load a Scheme source file named NAME, searching for it in the
1399;;; directories listed in %load-path, and applying each of the file
1400;;; name extensions listed in %load-extensions.
1401(define (load-from-path name)
1402 (start-stack 'load-stack
9b5a0d84 1403 (primitive-load-path name)))
0f2d19dd 1404
925172cf
AW
1405(define-syntax-rule (add-to-path path elt)
1406 "Add ELT to PATH, at compile-time and at run-time."
1407 (eval-when (compile load eval)
1408 (set! path (cons elt path))))
1409
1410(define-syntax-rule (add-to-load-path elt)
1411 "Add ELT to Guile's load path, at compile-time and at run-time."
1412 (add-to-path %load-path elt))
1413
85e95b47
AW
1414(define %load-verbosely #f)
1415(define (assert-load-verbosity v) (set! %load-verbosely v))
1416
1417(define (%load-announce file)
1418 (if %load-verbosely
2c27dd57 1419 (with-output-to-port (current-warning-port)
9b5a0d84
AW
1420 (lambda ()
1421 (display ";;; ")
1422 (display "loading ")
1423 (display file)
1424 (newline)
1425 (force-output)))))
85e95b47
AW
1426
1427(set! %load-hook %load-announce)
1428
0f2d19dd 1429\f
3d2ada2f 1430
0f2d19dd
JB
1431;;; {Reader Extensions}
1432;;;
0f2d19dd
JB
1433;;; Reader code for various "#c" forms.
1434;;;
1435
9447207f 1436(define read-eval? (make-fluid #f))
600c9584
RB
1437(read-hash-extend #\.
1438 (lambda (c port)
1439 (if (fluid-ref read-eval?)
1440 (eval (read port) (interaction-environment))
1441 (error
71335c0d 1442 "#. read expansion found and read-eval? is #f."))))
75a97b92 1443
0f2d19dd 1444\f
3d2ada2f 1445
0f2d19dd
JB
1446;;; {Low Level Modules}
1447;;;
1448;;; These are the low level data structures for modules.
1449;;;
37f5dfe5
DH
1450;;; Every module object is of the type 'module-type', which is a record
1451;;; consisting of the following members:
1452;;;
1453;;; - eval-closure: the function that defines for its module the strategy that
1454;;; shall be followed when looking up symbols in the module.
1455;;;
1456;;; An eval-closure is a function taking two arguments: the symbol to be
1457;;; looked up and a boolean value telling whether a binding for the symbol
1458;;; should be created if it does not exist yet. If the symbol lookup
1459;;; succeeded (either because an existing binding was found or because a new
1460;;; binding was created), a variable object representing the binding is
1461;;; returned. Otherwise, the value #f is returned. Note that the eval
1462;;; closure does not take the module to be searched as an argument: During
1463;;; construction of the eval-closure, the eval-closure has to store the
1464;;; module it belongs to in its environment. This means, that any
1465;;; eval-closure can belong to only one module.
1466;;;
1467;;; The eval-closure of a module can be defined arbitrarily. However, three
1468;;; special cases of eval-closures are to be distinguished: During startup
1469;;; the module system is not yet activated. In this phase, no modules are
1470;;; defined and all bindings are automatically stored by the system in the
1471;;; pre-modules-obarray. Since no eval-closures exist at this time, the
1472;;; functions which require an eval-closure as their argument need to be
1473;;; passed the value #f.
1474;;;
1475;;; The other two special cases of eval-closures are the
1476;;; standard-eval-closure and the standard-interface-eval-closure. Both
1477;;; behave equally for the case that no new binding is to be created. The
1478;;; difference between the two comes in, when the boolean argument to the
1479;;; eval-closure indicates that a new binding shall be created if it is not
1480;;; found.
1481;;;
1482;;; Given that no new binding shall be created, both standard eval-closures
1483;;; define the following standard strategy of searching bindings in the
1484;;; module: First, the module's obarray is searched for the symbol. Second,
1485;;; if no binding for the symbol was found in the module's obarray, the
1486;;; module's binder procedure is exececuted. If this procedure did not
1487;;; return a binding for the symbol, the modules referenced in the module's
1488;;; uses list are recursively searched for a binding of the symbol. If the
1489;;; binding can not be found in these modules also, the symbol lookup has
1490;;; failed.
1491;;;
1492;;; If a new binding shall be created, the standard-interface-eval-closure
1493;;; immediately returns indicating failure. That is, it does not even try
1494;;; to look up the symbol. In contrast, the standard-eval-closure would
1495;;; first search the obarray, and if no binding was found there, would
1496;;; create a new binding in the obarray, therefore not calling the binder
1497;;; procedure or searching the modules in the uses list.
1498;;;
1499;;; The explanation of the following members obarray, binder and uses
1500;;; assumes that the symbol lookup follows the strategy that is defined in
1501;;; the standard-eval-closure and the standard-interface-eval-closure.
1502;;;
1503;;; - obarray: a hash table that maps symbols to variable objects. In this
1504;;; hash table, the definitions are found that are local to the module (that
1505;;; is, not imported from other modules). When looking up bindings in the
1506;;; module, this hash table is searched first.
1507;;;
1508;;; - binder: either #f or a function taking a module and a symbol argument.
1509;;; If it is a function it is called after the obarray has been
1510;;; unsuccessfully searched for a binding. It then can provide bindings
1511;;; that would otherwise not be found locally in the module.
1512;;;
1513;;; - uses: a list of modules from which non-local bindings can be inherited.
1514;;; These modules are the third place queried for bindings after the obarray
1515;;; has been unsuccessfully searched and the binder function did not deliver
1516;;; a result either.
1517;;;
1518;;; - transformer: either #f or a function taking a scheme expression as
1519;;; delivered by read. If it is a function, it will be called to perform
1520;;; syntax transformations (e. g. makro expansion) on the given scheme
1521;;; expression. The output of the transformer function will then be passed
1522;;; to Guile's internal memoizer. This means that the output must be valid
1523;;; scheme code. The only exception is, that the output may make use of the
1524;;; syntax extensions provided to identify the modules that a binding
1525;;; belongs to.
1526;;;
1527;;; - name: the name of the module. This is used for all kinds of printing
1528;;; outputs. In certain places the module name also serves as a way of
1529;;; identification. When adding a module to the uses list of another
1530;;; module, it is made sure that the new uses list will not contain two
1531;;; modules of the same name.
1532;;;
1533;;; - kind: classification of the kind of module. The value is (currently?)
1534;;; only used for printing. It has no influence on how a module is treated.
1535;;; Currently the following values are used when setting the module kind:
1536;;; 'module, 'directory, 'interface, 'custom-interface. If no explicit kind
1537;;; is set, it defaults to 'module.
1538;;;
608860a5
LC
1539;;; - duplicates-handlers: a list of procedures that get called to make a
1540;;; choice between two duplicate bindings when name clashes occur. See the
1541;;; `duplicate-handlers' global variable below.
37f5dfe5 1542;;;
608860a5
LC
1543;;; - observers: a list of procedures that get called when the module is
1544;;; modified.
37f5dfe5 1545;;;
608860a5
LC
1546;;; - weak-observers: a weak-key hash table of procedures that get called
1547;;; when the module is modified. See `module-observe-weak' for details.
37f5dfe5
DH
1548;;;
1549;;; In addition, the module may (must?) contain a binding for
608860a5
LC
1550;;; `%module-public-interface'. This variable should be bound to a module
1551;;; representing the exported interface of a module. See the
1552;;; `module-public-interface' and `module-export!' procedures.
37f5dfe5 1553;;;
0f2d19dd
JB
1554;;; !!! warning: The interface to lazy binder procedures is going
1555;;; to be changed in an incompatible way to permit all the basic
1556;;; module ops to be virtualized.
1557;;;
1558;;; (make-module size use-list lazy-binding-proc) => module
1559;;; module-{obarray,uses,binder}[|-set!]
1560;;; (module? obj) => [#t|#f]
1561;;; (module-locally-bound? module symbol) => [#t|#f]
1562;;; (module-bound? module symbol) => [#t|#f]
1563;;; (module-symbol-locally-interned? module symbol) => [#t|#f]
1564;;; (module-symbol-interned? module symbol) => [#t|#f]
1565;;; (module-local-variable module symbol) => [#<variable ...> | #f]
1566;;; (module-variable module symbol) => [#<variable ...> | #f]
1567;;; (module-symbol-binding module symbol opt-value)
9b5a0d84 1568;;; => [ <obj> | opt-value | an error occurs ]
0f2d19dd
JB
1569;;; (module-make-local-var! module symbol) => #<variable...>
1570;;; (module-add! module symbol var) => unspecified
1571;;; (module-remove! module symbol) => unspecified
1572;;; (module-for-each proc module) => unspecified
1573;;; (make-scm-module) => module ; a lazy copy of the symhash module
1574;;; (set-current-module module) => unspecified
1575;;; (current-module) => #<module...>
1576;;;
1577;;;
1578
1579\f
3d2ada2f 1580
44cf1f0f 1581;;; {Printing Modules}
3d2ada2f
DH
1582;;;
1583
44cf1f0f 1584;; This is how modules are printed. You can re-define it.
31ac29b6 1585(define (%print-module mod port)
0f2d19dd
JB
1586 (display "#<" port)
1587 (display (or (module-kind mod) "module") port)
dc1eed52
AW
1588 (display " " port)
1589 (display (module-name mod) port)
0f2d19dd
JB
1590 (display " " port)
1591 (display (number->string (object-address mod) 16) port)
1592 (display ">" port))
1593
31ac29b6
AW
1594(letrec-syntax
1595 ;; Locally extend the syntax to allow record accessors to be defined at
1596 ;; compile-time. Cache the rtd locally to the constructor, the getters and
1597 ;; the setters, in order to allow for redefinition of the record type; not
1598 ;; relevant in the case of modules, but perhaps if we make this public, it
1599 ;; could matter.
1600
1601 ((define-record-type
1602 (lambda (x)
1603 (define (make-id scope . fragments)
1604 (datum->syntax #'scope
1605 (apply symbol-append
1606 (map (lambda (x)
1607 (if (symbol? x) x (syntax->datum x)))
1608 fragments))))
1609
1610 (define (getter rtd type-name field slot)
1611 #`(define #,(make-id rtd type-name '- field)
1612 (let ((rtd #,rtd))
1613 (lambda (#,type-name)
1614 (if (eq? (struct-vtable #,type-name) rtd)
1615 (struct-ref #,type-name #,slot)
1616 (%record-type-error rtd #,type-name))))))
1617
1618 (define (setter rtd type-name field slot)
1619 #`(define #,(make-id rtd 'set- type-name '- field '!)
1620 (let ((rtd #,rtd))
1621 (lambda (#,type-name val)
1622 (if (eq? (struct-vtable #,type-name) rtd)
1623 (struct-set! #,type-name #,slot val)
1624 (%record-type-error rtd #,type-name))))))
1625
1626 (define (accessors rtd type-name fields n exp)
1627 (syntax-case fields ()
1628 (() exp)
1629 (((field #:no-accessors) field* ...) (identifier? #'field)
1630 (accessors rtd type-name #'(field* ...) (1+ n)
1631 exp))
1632 (((field #:no-setter) field* ...) (identifier? #'field)
1633 (accessors rtd type-name #'(field* ...) (1+ n)
1634 #`(begin #,exp
1635 #,(getter rtd type-name #'field n))))
1636 (((field #:no-getter) field* ...) (identifier? #'field)
1637 (accessors rtd type-name #'(field* ...) (1+ n)
1638 #`(begin #,exp
1639 #,(setter rtd type-name #'field n))))
1640 ((field field* ...) (identifier? #'field)
1641 (accessors rtd type-name #'(field* ...) (1+ n)
1642 #`(begin #,exp
1643 #,(getter rtd type-name #'field n)
1644 #,(setter rtd type-name #'field n))))))
1645
1646 (define (predicate rtd type-name fields exp)
1647 (accessors
1648 rtd type-name fields 0
1649 #`(begin
1650 #,exp
1651 (define (#,(make-id rtd type-name '?) obj)
1652 (and (struct? obj) (eq? (struct-vtable obj) #,rtd))))))
1653
1654 (define (field-list fields)
1655 (syntax-case fields ()
1656 (() '())
1657 (((f . opts) . rest) (identifier? #'f)
1658 (cons #'f (field-list #'rest)))
1659 ((f . rest) (identifier? #'f)
1660 (cons #'f (field-list #'rest)))))
1661
1662 (define (constructor rtd type-name fields exp)
1663 (let ((ctor (make-id rtd type-name '-constructor))
1664 (args (field-list fields)))
1665 (predicate rtd type-name fields
1666 #`(begin #,exp
1667 (define #,ctor
1668 (let ((rtd #,rtd))
1669 (lambda #,args
1670 (make-struct rtd 0 #,@args))))
1671 (struct-set! #,rtd (+ vtable-offset-user 2)
1672 #,ctor)))))
1673
1674 (define (type type-name printer fields)
1675 (define (make-layout)
1676 (let lp ((fields fields) (slots '()))
1677 (syntax-case fields ()
1678 (() (datum->syntax #'here
1679 (make-struct-layout
1680 (apply string-append slots))))
1681 ((_ . rest) (lp #'rest (cons "pw" slots))))))
1682
1683 (let ((rtd (make-id type-name type-name '-type)))
1684 (constructor rtd type-name fields
1685 #`(begin
1686 (define #,rtd
1687 (make-struct record-type-vtable 0
1688 '#,(make-layout)
1689 #,printer
1690 '#,type-name
1691 '#,(field-list fields)))
1692 (set-struct-vtable-name! #,rtd '#,type-name)))))
1693
1694 (syntax-case x ()
1695 ((_ type-name printer (field ...))
1696 (type #'type-name #'printer #'(field ...)))))))
1697
1698 ;; module-type
1699 ;;
1700 ;; A module is characterized by an obarray in which local symbols
1701 ;; are interned, a list of modules, "uses", from which non-local
1702 ;; bindings can be inherited, and an optional lazy-binder which
1703 ;; is a (CLOSURE module symbol) which, as a last resort, can provide
1704 ;; bindings that would otherwise not be found locally in the module.
1705 ;;
1706 ;; NOTE: If you change the set of fields or their order, you also need to
1707 ;; change the constants in libguile/modules.h.
1708 ;;
1709 ;; NOTE: The getter `module-eval-closure' is used in libguile/modules.c.
1710 ;; NOTE: The getter `module-transfomer' is defined libguile/modules.c.
1711 ;; NOTE: The getter `module-name' is defined later, due to boot reasons.
4e48b495 1712 ;; NOTE: The getter `module-public-interface' is used in libguile/modules.c.
31ac29b6
AW
1713 ;;
1714 (define-record-type module
1715 (lambda (obj port) (%print-module obj port))
1716 (obarray
1717 uses
1718 binder
1719 eval-closure
1720 (transformer #:no-getter)
1721 (name #:no-getter)
1722 kind
1723 duplicates-handlers
1724 (import-obarray #:no-setter)
1725 observers
1726 (weak-observers #:no-setter)
f905381d 1727 version
81fc66cf 1728 submodules
4e48b495 1729 submodule-binder
78f79f18
AW
1730 public-interface
1731 filename)))
31ac29b6 1732
0f2d19dd 1733
8b718458 1734;; make-module &opt size uses binder
0f2d19dd 1735;;
8b718458
JB
1736;; Create a new module, perhaps with a particular size of obarray,
1737;; initial uses list, or binding procedure.
0f2d19dd 1738;;
e9729cbb
AW
1739(define* (make-module #:optional (size 31) (uses '()) (binder #f))
1740 (define %default-import-size
1741 ;; Typical number of imported bindings actually used by a module.
1742 600)
1743
1744 (if (not (integer? size))
1745 (error "Illegal size to make-module." size))
1746 (if (not (and (list? uses)
1747 (and-map module? uses)))
1748 (error "Incorrect use list." uses))
1749 (if (and binder (not (procedure? binder)))
1750 (error
1751 "Lazy-binder expected to be a procedure or #f." binder))
1752
1753 (let ((module (module-constructor (make-hash-table size)
1754 uses binder #f macroexpand
1755 #f #f #f
1756 (make-hash-table %default-import-size)
1757 '()
1758 (make-weak-key-hash-table 31) #f
1759 (make-hash-table 7) #f #f #f)))
1760
1761 ;; We can't pass this as an argument to module-constructor,
1762 ;; because we need it to close over a pointer to the module
1763 ;; itself.
1764 (set-module-eval-closure! module (standard-eval-closure module))
1765
1766 module))
0f2d19dd 1767
8b718458 1768
0f2d19dd 1769\f
3d2ada2f 1770
1777c18b
MD
1771;;; {Observer protocol}
1772;;;
1773
1774(define (module-observe module proc)
1775 (set-module-observers! module (cons proc (module-observers module)))
1776 (cons module proc))
1777
723ae5b3 1778(define* (module-observe-weak module observer-id #:optional (proc observer-id))
608860a5
LC
1779 ;; Register PROC as an observer of MODULE under name OBSERVER-ID (which can
1780 ;; be any Scheme object). PROC is invoked and passed MODULE any time
1781 ;; MODULE is modified. PROC gets unregistered when OBSERVER-ID gets GC'd
1782 ;; (thus, it is never unregistered if OBSERVER-ID is an immediate value,
1783 ;; for instance).
1784
1785 ;; The two-argument version is kept for backward compatibility: when called
1786 ;; with two arguments, the observer gets unregistered when closure PROC
1787 ;; gets GC'd (making it impossible to use an anonymous lambda for PROC).
723ae5b3 1788 (hashq-set! (module-weak-observers module) observer-id proc))
1777c18b
MD
1789
1790(define (module-unobserve token)
1791 (let ((module (car token))
9b5a0d84 1792 (id (cdr token)))
1777c18b 1793 (if (integer? id)
9b5a0d84
AW
1794 (hash-remove! (module-weak-observers module) id)
1795 (set-module-observers! module (delq1! id (module-observers module)))))
1777c18b
MD
1796 *unspecified*)
1797
d57da08b 1798(define module-defer-observers #f)
03d6cddc 1799(define module-defer-observers-mutex (make-mutex 'recursive))
d57da08b
MD
1800(define module-defer-observers-table (make-hash-table))
1801
1a961d7e 1802(define (module-modified m)
d57da08b
MD
1803 (if module-defer-observers
1804 (hash-set! module-defer-observers-table m #t)
1805 (module-call-observers m)))
1806
1807;;; This function can be used to delay calls to observers so that they
1808;;; can be called once only in the face of massive updating of modules.
1809;;;
1810(define (call-with-deferred-observers thunk)
1811 (dynamic-wind
1812 (lambda ()
9b5a0d84
AW
1813 (lock-mutex module-defer-observers-mutex)
1814 (set! module-defer-observers #t))
d57da08b
MD
1815 thunk
1816 (lambda ()
9b5a0d84
AW
1817 (set! module-defer-observers #f)
1818 (hash-for-each (lambda (m dummy)
1819 (module-call-observers m))
1820 module-defer-observers-table)
1821 (hash-clear! module-defer-observers-table)
1822 (unlock-mutex module-defer-observers-mutex))))
d57da08b
MD
1823
1824(define (module-call-observers m)
1777c18b 1825 (for-each (lambda (proc) (proc m)) (module-observers m))
608860a5
LC
1826
1827 ;; We assume that weak observers don't (un)register themselves as they are
1828 ;; called since this would preclude proper iteration over the hash table
1829 ;; elements.
1830 (hash-for-each (lambda (id proc) (proc m)) (module-weak-observers m)))
1777c18b
MD
1831
1832\f
3d2ada2f 1833
0f2d19dd
JB
1834;;; {Module Searching in General}
1835;;;
1836;;; We sometimes want to look for properties of a symbol
1837;;; just within the obarray of one module. If the property
1838;;; holds, then it is said to hold ``locally'' as in, ``The symbol
1839;;; DISPLAY is locally rebound in the module `safe-guile'.''
1840;;;
1841;;;
1842;;; Other times, we want to test for a symbol property in the obarray
1843;;; of M and, if it is not found there, try each of the modules in the
1844;;; uses list of M. This is the normal way of testing for some
1845;;; property, so we state these properties without qualification as
1846;;; in: ``The symbol 'fnord is interned in module M because it is
1847;;; interned locally in module M2 which is a member of the uses list
1848;;; of M.''
1849;;;
1850
1851;; module-search fn m
20edfbbd 1852;;
0f2d19dd
JB
1853;; return the first non-#f result of FN applied to M and then to
1854;; the modules in the uses of m, and so on recursively. If all applications
1855;; return #f, then so does this function.
1856;;
1857(define (module-search fn m v)
1858 (define (loop pos)
1859 (and (pair? pos)
9b5a0d84
AW
1860 (or (module-search fn (car pos) v)
1861 (loop (cdr pos)))))
0f2d19dd
JB
1862 (or (fn m v)
1863 (loop (module-uses m))))
1864
1865
1866;;; {Is a symbol bound in a module?}
1867;;;
1868;;; Symbol S in Module M is bound if S is interned in M and if the binding
1869;;; of S in M has been set to some well-defined value.
1870;;;
1871
1872;; module-locally-bound? module symbol
1873;;
1874;; Is a symbol bound (interned and defined) locally in a given module?
1875;;
1876(define (module-locally-bound? m v)
1877 (let ((var (module-local-variable m v)))
1878 (and var
9b5a0d84 1879 (variable-bound? var))))
0f2d19dd
JB
1880
1881;; module-bound? module symbol
1882;;
1883;; Is a symbol bound (interned and defined) anywhere in a given module
1884;; or its uses?
1885;;
1886(define (module-bound? m v)
f176c584
AW
1887 (let ((var (module-variable m v)))
1888 (and var
9b5a0d84 1889 (variable-bound? var))))
0f2d19dd
JB
1890
1891;;; {Is a symbol interned in a module?}
1892;;;
20edfbbd 1893;;; Symbol S in Module M is interned if S occurs in
0f2d19dd
JB
1894;;; of S in M has been set to some well-defined value.
1895;;;
1896;;; It is possible to intern a symbol in a module without providing
1897;;; an initial binding for the corresponding variable. This is done
1898;;; with:
1899;;; (module-add! module symbol (make-undefined-variable))
1900;;;
1901;;; In that case, the symbol is interned in the module, but not
1902;;; bound there. The unbound symbol shadows any binding for that
1903;;; symbol that might otherwise be inherited from a member of the uses list.
1904;;;
1905
1906(define (module-obarray-get-handle ob key)
1907 ((if (symbol? key) hashq-get-handle hash-get-handle) ob key))
1908
1909(define (module-obarray-ref ob key)
1910 ((if (symbol? key) hashq-ref hash-ref) ob key))
1911
1912(define (module-obarray-set! ob key val)
1913 ((if (symbol? key) hashq-set! hash-set!) ob key val))
1914
1915(define (module-obarray-remove! ob key)
1916 ((if (symbol? key) hashq-remove! hash-remove!) ob key))
1917
1918;; module-symbol-locally-interned? module symbol
20edfbbd 1919;;
0f2d19dd
JB
1920;; is a symbol interned (not neccessarily defined) locally in a given module
1921;; or its uses? Interned symbols shadow inherited bindings even if
1922;; they are not themselves bound to a defined value.
1923;;
1924(define (module-symbol-locally-interned? m v)
1925 (not (not (module-obarray-get-handle (module-obarray m) v))))
1926
1927;; module-symbol-interned? module symbol
20edfbbd 1928;;
0f2d19dd
JB
1929;; is a symbol interned (not neccessarily defined) anywhere in a given module
1930;; or its uses? Interned symbols shadow inherited bindings even if
1931;; they are not themselves bound to a defined value.
1932;;
1933(define (module-symbol-interned? m v)
1934 (module-search module-symbol-locally-interned? m v))
1935
1936
1937;;; {Mapping modules x symbols --> variables}
1938;;;
1939
1940;; module-local-variable module symbol
1941;; return the local variable associated with a MODULE and SYMBOL.
1942;;
1943;;; This function is very important. It is the only function that can
1944;;; return a variable from a module other than the mutators that store
1945;;; new variables in modules. Therefore, this function is the location
1946;;; of the "lazy binder" hack.
1947;;;
1948;;; If symbol is defined in MODULE, and if the definition binds symbol
1949;;; to a variable, return that variable object.
1950;;;
1951;;; If the symbols is not found at first, but the module has a lazy binder,
1952;;; then try the binder.
1953;;;
1954;;; If the symbol is not found at all, return #f.
1955;;;
608860a5
LC
1956;;; (This is now written in C, see `modules.c'.)
1957;;;
0f2d19dd
JB
1958
1959;;; {Mapping modules x symbols --> bindings}
1960;;;
1961;;; These are similar to the mapping to variables, except that the
1962;;; variable is dereferenced.
1963;;;
1964
1965;; module-symbol-binding module symbol opt-value
20edfbbd 1966;;
0f2d19dd
JB
1967;; return the binding of a variable specified by name within
1968;; a given module, signalling an error if the variable is unbound.
1969;; If the OPT-VALUE is passed, then instead of signalling an error,
1970;; return OPT-VALUE.
1971;;
1972(define (module-symbol-local-binding m v . opt-val)
1973 (let ((var (module-local-variable m v)))
7b07e5ef 1974 (if (and var (variable-bound? var))
9b5a0d84
AW
1975 (variable-ref var)
1976 (if (not (null? opt-val))
1977 (car opt-val)
1978 (error "Locally unbound variable." v)))))
0f2d19dd
JB
1979
1980;; module-symbol-binding module symbol opt-value
20edfbbd 1981;;
0f2d19dd
JB
1982;; return the binding of a variable specified by name within
1983;; a given module, signalling an error if the variable is unbound.
1984;; If the OPT-VALUE is passed, then instead of signalling an error,
1985;; return OPT-VALUE.
1986;;
1987(define (module-symbol-binding m v . opt-val)
1988 (let ((var (module-variable m v)))
7b07e5ef 1989 (if (and var (variable-bound? var))
9b5a0d84
AW
1990 (variable-ref var)
1991 (if (not (null? opt-val))
1992 (car opt-val)
1993 (error "Unbound variable." v)))))
0f2d19dd
JB
1994
1995
1996\f
3d2ada2f 1997
0f2d19dd
JB
1998;;; {Adding Variables to Modules}
1999;;;
0f2d19dd
JB
2000
2001;; module-make-local-var! module symbol
20edfbbd 2002;;
0f2d19dd
JB
2003;; ensure a variable for V in the local namespace of M.
2004;; If no variable was already there, then create a new and uninitialzied
2005;; variable.
2006;;
d57da08b
MD
2007;; This function is used in modules.c.
2008;;
0f2d19dd
JB
2009(define (module-make-local-var! m v)
2010 (or (let ((b (module-obarray-ref (module-obarray m) v)))
9b5a0d84
AW
2011 (and (variable? b)
2012 (begin
2013 ;; Mark as modified since this function is called when
2014 ;; the standard eval closure defines a binding
2015 (module-modified m)
2016 b)))
0c5f718b 2017
608860a5
LC
2018 ;; Create a new local variable.
2019 (let ((local-var (make-undefined-variable)))
2020 (module-add! m v local-var)
2021 local-var)))
0f2d19dd 2022
89d06712 2023;; module-ensure-local-variable! module symbol
9540368e 2024;;
89d06712
MV
2025;; Ensure that there is a local variable in MODULE for SYMBOL. If
2026;; there is no binding for SYMBOL, create a new uninitialized
2027;; variable. Return the local variable.
9540368e 2028;;
89d06712
MV
2029(define (module-ensure-local-variable! module symbol)
2030 (or (module-local-variable module symbol)
9540368e 2031 (let ((var (make-undefined-variable)))
9b5a0d84
AW
2032 (module-add! module symbol var)
2033 var)))
9540368e 2034
0f2d19dd 2035;; module-add! module symbol var
20edfbbd 2036;;
0f2d19dd
JB
2037;; ensure a particular variable for V in the local namespace of M.
2038;;
2039(define (module-add! m v var)
2040 (if (not (variable? var))
2041 (error "Bad variable to module-add!" var))
1777c18b 2042 (module-obarray-set! (module-obarray m) v var)
1a961d7e 2043 (module-modified m))
0f2d19dd 2044
20edfbbd
TTN
2045;; module-remove!
2046;;
0f2d19dd
JB
2047;; make sure that a symbol is undefined in the local namespace of M.
2048;;
2049(define (module-remove! m v)
c35738c1 2050 (module-obarray-remove! (module-obarray m) v)
1a961d7e 2051 (module-modified m))
0f2d19dd
JB
2052
2053(define (module-clear! m)
c35738c1 2054 (hash-clear! (module-obarray m))
1a961d7e 2055 (module-modified m))
0f2d19dd
JB
2056
2057;; MODULE-FOR-EACH -- exported
20edfbbd 2058;;
0f2d19dd
JB
2059;; Call PROC on each symbol in MODULE, with arguments of (SYMBOL VARIABLE).
2060;;
2061(define (module-for-each proc module)
c35738c1 2062 (hash-for-each proc (module-obarray module)))
0f2d19dd
JB
2063
2064(define (module-map proc module)
711a9fd7 2065 (hash-map->list proc (module-obarray module)))
c35738c1 2066
0f27ab8a
AW
2067;; Submodules
2068;;
2069;; Modules exist in a separate namespace from values, because you generally do
2070;; not want the name of a submodule, which you might not even use, to collide
2071;; with local variables that happen to be named the same as the submodule.
2072;;
2073(define (module-ref-submodule module name)
81fc66cf
AW
2074 (or (hashq-ref (module-submodules module) name)
2075 (and (module-submodule-binder module)
2076 ((module-submodule-binder module) module name))))
0f27ab8a
AW
2077
2078(define (module-define-submodule! module name submodule)
f6a5308b 2079 (hashq-set! (module-submodules module) name submodule))
0f27ab8a 2080
dcb68c09
AW
2081;; It used to be, however, that module names were also present in the
2082;; value namespace. When we enable deprecated code, we preserve this
2083;; legacy behavior.
2084;;
2085;; These shims are defined here instead of in deprecated.scm because we
2086;; need their definitions before loading other modules.
2087;;
2088(begin-deprecated
2089 (define (module-ref-submodule module name)
2090 (or (hashq-ref (module-submodules module) name)
2091 (and (module-submodule-binder module)
2092 ((module-submodule-binder module) module name))
2093 (let ((var (module-local-variable module name)))
2094 (and var (variable-bound? var) (module? (variable-ref var))
2095 (begin
2096 (warn "module" module "not in submodules table")
2097 (variable-ref var))))))
2098
2099 (define (module-define-submodule! module name submodule)
2100 (let ((var (module-local-variable module name)))
2101 (if (and var
2102 (or (not (variable-bound? var))
2103 (not (module? (variable-ref var)))))
2104 (warn "defining module" module ": not overriding local definition" var)
2105 (module-define! module name submodule)))
2106 (hashq-set! (module-submodules module) name submodule)))
2107
0f2d19dd
JB
2108\f
2109
0f2d19dd
JB
2110;;; {Module-based Loading}
2111;;;
2112
2113(define (save-module-excursion thunk)
2114 (let ((inner-module (current-module))
9b5a0d84 2115 (outer-module #f))
0f2d19dd 2116 (dynamic-wind (lambda ()
9b5a0d84
AW
2117 (set! outer-module (current-module))
2118 (set-current-module inner-module)
2119 (set! inner-module #f))
2120 thunk
2121 (lambda ()
2122 (set! inner-module (current-module))
2123 (set-current-module outer-module)
2124 (set! outer-module #f)))))
0f2d19dd 2125
0f2d19dd 2126\f
3d2ada2f 2127
44cf1f0f 2128;;; {MODULE-REF -- exported}
3d2ada2f
DH
2129;;;
2130
0f2d19dd
JB
2131;; Returns the value of a variable called NAME in MODULE or any of its
2132;; used modules. If there is no such variable, then if the optional third
2133;; argument DEFAULT is present, it is returned; otherwise an error is signaled.
20edfbbd 2134;;
0f2d19dd
JB
2135(define (module-ref module name . rest)
2136 (let ((variable (module-variable module name)))
2137 (if (and variable (variable-bound? variable))
9b5a0d84
AW
2138 (variable-ref variable)
2139 (if (null? rest)
2140 (error "No variable named" name 'in module)
2141 (car rest) ; default value
2142 ))))
0f2d19dd
JB
2143
2144;; MODULE-SET! -- exported
2145;;
2146;; Sets the variable called NAME in MODULE (or in a module that MODULE uses)
2147;; to VALUE; if there is no such variable, an error is signaled.
20edfbbd 2148;;
0f2d19dd
JB
2149(define (module-set! module name value)
2150 (let ((variable (module-variable module name)))
2151 (if variable
9b5a0d84
AW
2152 (variable-set! variable value)
2153 (error "No variable named" name 'in module))))
0f2d19dd
JB
2154
2155;; MODULE-DEFINE! -- exported
2156;;
2157;; Sets the variable called NAME in MODULE to VALUE; if there is no such
2158;; variable, it is added first.
20edfbbd 2159;;
0f2d19dd
JB
2160(define (module-define! module name value)
2161 (let ((variable (module-local-variable module name)))
2162 (if variable
9b5a0d84
AW
2163 (begin
2164 (variable-set! variable value)
2165 (module-modified module))
2166 (let ((variable (make-variable value)))
2167 (module-add! module name variable)))))
0f2d19dd 2168
ed218d98
MV
2169;; MODULE-DEFINED? -- exported
2170;;
2171;; Return #t iff NAME is defined in MODULE (or in a module that MODULE
2172;; uses)
2173;;
2174(define (module-defined? module name)
2175 (let ((variable (module-variable module name)))
2176 (and variable (variable-bound? variable))))
2177
0f2d19dd
JB
2178;; MODULE-USE! module interface
2179;;
2180;; Add INTERFACE to the list of interfaces used by MODULE.
20edfbbd 2181;;
0f2d19dd 2182(define (module-use! module interface)
b1907902
AW
2183 (if (not (or (eq? module interface)
2184 (memq interface (module-uses module))))
608860a5
LC
2185 (begin
2186 ;; Newly used modules must be appended rather than consed, so that
2187 ;; `module-variable' traverses the use list starting from the first
2188 ;; used module.
51c0fd80
AR
2189 (set-module-uses! module (append (module-uses module)
2190 (list interface)))
8f44138a 2191 (hash-clear! (module-import-obarray module))
608860a5 2192 (module-modified module))))
0f2d19dd 2193
7b07e5ef
MD
2194;; MODULE-USE-INTERFACES! module interfaces
2195;;
8d795c83
AW
2196;; Same as MODULE-USE!, but only notifies module observers after all
2197;; interfaces are added to the inports list.
7b07e5ef
MD
2198;;
2199(define (module-use-interfaces! module interfaces)
8d795c83
AW
2200 (let* ((cur (module-uses module))
2201 (new (let lp ((in interfaces) (out '()))
2202 (if (null? in)
2203 (reverse out)
2204 (lp (cdr in)
2205 (let ((iface (car in)))
2206 (if (or (memq iface cur) (memq iface out))
2207 out
2208 (cons iface out))))))))
2209 (set-module-uses! module (append cur new))
4181e920
AW
2210 (hash-clear! (module-import-obarray module))
2211 (module-modified module)))
7b07e5ef 2212
0f2d19dd 2213\f
3d2ada2f 2214
0f2d19dd
JB
2215;;; {Recursive Namespaces}
2216;;;
0f2d19dd 2217;;; A hierarchical namespace emerges if we consider some module to be
b910c4ac 2218;;; root, and submodules of that module to be nested namespaces.
0f2d19dd 2219;;;
b910c4ac 2220;;; The routines here manage variable names in hierarchical namespace.
0f2d19dd
JB
2221;;; Each variable name is a list of elements, looked up in successively nested
2222;;; modules.
2223;;;
9b5a0d84 2224;;; (nested-ref some-root-module '(foo bar baz))
b910c4ac
AW
2225;;; => <value of a variable named baz in the submodule bar of
2226;;; the submodule foo of some-root-module>
0f2d19dd
JB
2227;;;
2228;;;
2229;;; There are:
2230;;;
9b5a0d84
AW
2231;;; ;; a-root is a module
2232;;; ;; name is a list of symbols
0f2d19dd 2233;;;
9b5a0d84
AW
2234;;; nested-ref a-root name
2235;;; nested-set! a-root name val
2236;;; nested-define! a-root name val
2237;;; nested-remove! a-root name
0f2d19dd 2238;;;
b910c4ac
AW
2239;;; These functions manipulate values in namespaces. For referencing the
2240;;; namespaces themselves, use the following:
0f2d19dd 2241;;;
b910c4ac
AW
2242;;; nested-ref-module a-root name
2243;;; nested-define-module! a-root name mod
2244;;;
2245;;; (current-module) is a natural choice for a root so for convenience there are
0f2d19dd
JB
2246;;; also:
2247;;;
b910c4ac
AW
2248;;; local-ref name == nested-ref (current-module) name
2249;;; local-set! name val == nested-set! (current-module) name val
2250;;; local-define name val == nested-define! (current-module) name val
2251;;; local-remove name == nested-remove! (current-module) name
2252;;; local-ref-module name == nested-ref-module (current-module) name
2253;;; local-define-module! name m == nested-define-module! (current-module) name m
0f2d19dd
JB
2254;;;
2255
2256
0dd5491c 2257(define (nested-ref root names)
b910c4ac
AW
2258 (if (null? names)
2259 root
2260 (let loop ((cur root)
2261 (head (car names))
2262 (tail (cdr names)))
2263 (if (null? tail)
2264 (module-ref cur head #f)
2265 (let ((cur (module-ref-submodule cur head)))
2266 (and cur
2267 (loop cur (car tail) (cdr tail))))))))
0f2d19dd 2268
0dd5491c 2269(define (nested-set! root names val)
0f2d19dd 2270 (let loop ((cur root)
b910c4ac
AW
2271 (head (car names))
2272 (tail (cdr names)))
2273 (if (null? tail)
2274 (module-set! cur head val)
2275 (let ((cur (module-ref-submodule cur head)))
2276 (if (not cur)
2277 (error "failed to resolve module" names)
2278 (loop cur (car tail) (cdr tail)))))))
0f2d19dd 2279
0dd5491c 2280(define (nested-define! root names val)
0f2d19dd 2281 (let loop ((cur root)
b910c4ac
AW
2282 (head (car names))
2283 (tail (cdr names)))
2284 (if (null? tail)
2285 (module-define! cur head val)
2286 (let ((cur (module-ref-submodule cur head)))
2287 (if (not cur)
2288 (error "failed to resolve module" names)
2289 (loop cur (car tail) (cdr tail)))))))
0f2d19dd 2290
0dd5491c 2291(define (nested-remove! root names)
0f2d19dd 2292 (let loop ((cur root)
b910c4ac
AW
2293 (head (car names))
2294 (tail (cdr names)))
2295 (if (null? tail)
2296 (module-remove! cur head)
2297 (let ((cur (module-ref-submodule cur head)))
2298 (if (not cur)
2299 (error "failed to resolve module" names)
2300 (loop cur (car tail) (cdr tail)))))))
2301
2302
2303(define (nested-ref-module root names)
2304 (let loop ((cur root)
2305 (names names))
2306 (if (null? names)
2307 cur
2308 (let ((cur (module-ref-submodule cur (car names))))
2309 (and cur
2310 (loop cur (cdr names)))))))
2311
2312(define (nested-define-module! root names module)
2313 (if (null? names)
2314 (error "can't redefine root module" root module)
2315 (let loop ((cur root)
2316 (head (car names))
2317 (tail (cdr names)))
2318 (if (null? tail)
2319 (module-define-submodule! cur head module)
2320 (let ((cur (or (module-ref-submodule cur head)
2321 (let ((m (make-module 31)))
2322 (set-module-kind! m 'directory)
2323 (set-module-name! m (append (module-name cur)
2324 (list head)))
2325 (module-define-submodule! cur head m)
2326 m))))
2327 (loop cur (car tail) (cdr tail)))))))
2328
0f2d19dd 2329
1623ca68
AW
2330(define (local-ref names)
2331 (nested-ref (current-module) names))
2332
2333(define (local-set! names val)
2334 (nested-set! (current-module) names val))
2335
2336(define (local-define names val)
2337 (nested-define! (current-module) names val))
2338
2339(define (local-remove names)
2340 (nested-remove! (current-module) names))
2341
2342(define (local-ref-module names)
2343 (nested-ref-module (current-module) names))
2344
2345(define (local-define-module names mod)
2346 (nested-define-module! (current-module) names mod))
b910c4ac 2347
0f2d19dd
JB
2348
2349
2350\f
3d2ada2f 2351
cb67c838 2352;;; {The (guile) module}
0f2d19dd 2353;;;
cb67c838
AW
2354;;; The standard module, which has the core Guile bindings. Also called the
2355;;; "root module", as it is imported by many other modules, but it is not
2356;;; necessarily the root of anything; and indeed, the module named '() might be
2357;;; better thought of as a root.
0f2d19dd 2358;;;
bbd1d133 2359
edc185c7
MD
2360(define (set-system-module! m s)
2361 (set-procedure-property! (module-eval-closure m) 'system-module s))
0f2d19dd 2362
76aea207
AW
2363;; The root module uses the pre-modules-obarray as its obarray. This
2364;; special obarray accumulates all bindings that have been established
2365;; before the module system is fully booted.
2366;;
2367;; (The obarray continues to be used by code that has been closed over
2368;; before the module system has been booted.)
2369;;
2370(define the-root-module
2371 (let ((m (make-module 0)))
2372 (set-module-obarray! m (%get-pre-modules-obarray))
2373 (set-module-name! m '(guile))
2374 (set-system-module! m #t)
2375 m))
2376
2377;; The root interface is a module that uses the same obarray as the
2378;; root module. It does not allow new definitions, tho.
2379;;
2380(define the-scm-module
2381 (let ((m (make-module 0)))
2382 (set-module-obarray! m (%get-pre-modules-obarray))
2383 (set-module-eval-closure! m (standard-interface-eval-closure m))
2384 (set-module-name! m '(guile))
2385 (set-module-kind! m 'interface)
2386 (set-system-module! m #t)
7354a105
LC
2387
2388 ;; In Guile 1.8 and earlier M was its own public interface.
2389 (set-module-public-interface! m m)
2390
76aea207
AW
2391 m))
2392
2393(set-module-public-interface! the-root-module the-scm-module)
bbd1d133
AW
2394
2395\f
2396
2397;; Now that we have a root module, even though modules aren't fully booted,
2398;; expand the definition of resolve-module.
2399;;
2400(define (resolve-module name . args)
2401 (if (equal? name '(guile))
2402 the-root-module
2403 (error "unexpected module to resolve during module boot" name)))
2404
2405;; Cheat. These bindings are needed by modules.c, but we don't want
2406;; to move their real definition here because that would be unnatural.
2407;;
57ced5b9 2408(define define-module* #f)
bbd1d133
AW
2409(define process-use-modules #f)
2410(define module-export! #f)
2411(define default-duplicate-binding-procedures #f)
2412
2413;; This boots the module system. All bindings needed by modules.c
2414;; must have been defined by now.
296ff5e7 2415;;
bbd1d133
AW
2416(set-current-module the-root-module)
2417
2418
2419\f
2420
2421;; Now that modules are booted, give module-name its final definition.
2422;;
2423(define module-name
2424 (let ((accessor (record-accessor module-type 'name)))
2425 (lambda (mod)
2426 (or (accessor mod)
2427 (let ((name (list (gensym))))
cb67c838
AW
2428 ;; Name MOD and bind it in the module root so that it's visible to
2429 ;; `resolve-module'. This is important as `psyntax' stores module
2430 ;; names and relies on being able to `resolve-module' them.
bbd1d133 2431 (set-module-name! mod name)
9e0bfdba 2432 (nested-define-module! (resolve-module '() #f) name mod)
bbd1d133
AW
2433 (accessor mod))))))
2434
296ff5e7 2435(define (make-modules-in module name)
9e0bfdba
AW
2436 (or (nested-ref-module module name)
2437 (let ((m (make-module 31)))
2438 (set-module-kind! m 'directory)
2439 (set-module-name! m (append (module-name module) name))
2440 (nested-define-module! module name m)
2441 m)))
0f2d19dd 2442
296ff5e7
MV
2443(define (beautify-user-module! module)
2444 (let ((interface (module-public-interface module)))
2445 (if (or (not interface)
9b5a0d84
AW
2446 (eq? interface module))
2447 (let ((interface (make-module 31)))
2448 (set-module-name! interface (module-name module))
dca14012 2449 (set-module-version! interface (module-version module))
9b5a0d84
AW
2450 (set-module-kind! interface 'interface)
2451 (set-module-public-interface! module interface))))
296ff5e7 2452 (if (and (not (memq the-scm-module (module-uses module)))
9b5a0d84 2453 (not (eq? module the-root-module)))
608860a5
LC
2454 ;; Import the default set of bindings (from the SCM module) in MODULE.
2455 (module-use! module the-scm-module)))
432558b9 2456
dca14012 2457(define (version-matches? version-ref target)
dca14012
JG
2458 (define (sub-versions-match? v-refs t)
2459 (define (sub-version-matches? v-ref t)
befd1df9
AW
2460 (let ((matches? (lambda (v) (sub-version-matches? v t))))
2461 (cond
2462 ((number? v-ref) (eqv? v-ref t))
2463 ((list? v-ref)
2464 (case (car v-ref)
2465 ((>=) (>= t (cadr v-ref)))
2466 ((<=) (<= t (cadr v-ref)))
2467 ((and) (and-map matches? (cdr v-ref)))
2468 ((or) (or-map matches? (cdr v-ref)))
2469 ((not) (not (matches? (cadr v-ref))))
2470 (else (error "Invalid sub-version reference" v-ref))))
2471 (else (error "Invalid sub-version reference" v-ref)))))
dca14012
JG
2472 (or (null? v-refs)
2473 (and (not (null? t))
2474 (sub-version-matches? (car v-refs) (car t))
2475 (sub-versions-match? (cdr v-refs) (cdr t)))))
befd1df9
AW
2476
2477 (let ((matches? (lambda (v) (version-matches? v target))))
2478 (or (null? version-ref)
2479 (case (car version-ref)
2480 ((and) (and-map matches? (cdr version-ref)))
2481 ((or) (or-map matches? (cdr version-ref)))
2482 ((not) (not (matches? (cadr version-ref))))
2483 (else (sub-versions-match? version-ref target))))))
dca14012 2484
f95f82f8
AW
2485(define (make-fresh-user-module)
2486 (let ((m (make-module)))
2487 (beautify-user-module! m)
2488 m))
2489
1f60d9d2
MD
2490;; NOTE: This binding is used in libguile/modules.c.
2491;;
53f84bc8 2492(define resolve-module
cb67c838
AW
2493 (let ((root (make-module)))
2494 (set-module-name! root '())
2495 ;; Define the-root-module as '(guile).
d58ccc66 2496 (module-define-submodule! root 'guile the-root-module)
cb67c838 2497
7e314766 2498 (lambda* (name #:optional (autoload #t) (version #f) #:key (ensure #t))
6b7d701e 2499 (let ((already (nested-ref-module root name)))
cb67c838 2500 (cond
d58ccc66 2501 ((and already
cb67c838
AW
2502 (or (not autoload) (module-public-interface already)))
2503 ;; A hit, a palpable hit.
e44d2e4d 2504 (if (and version
cb67c838
AW
2505 (not (version-matches? version (module-version already))))
2506 (error "incompatible module version already loaded" name))
2507 already)
2508 (autoload
2509 ;; Try to autoload the module, and recurse.
2510 (try-load-module name version)
7e314766 2511 (resolve-module name #f #:ensure ensure))
cb67c838 2512 (else
51b22dbb 2513 ;; No module found (or if one was, it had no public interface), and
7e314766
AW
2514 ;; we're not autoloading. Make an empty module if #:ensure is true.
2515 (or already
2516 (and ensure
2517 (make-modules-in root name)))))))))
cb67c838 2518
296ff5e7 2519
dca14012
JG
2520(define (try-load-module name version)
2521 (try-module-autoload name version))
0f2d19dd 2522
c9b16cee 2523(define (reload-module m)
cdab9fc6 2524 "Revisit the source file corresponding to the module @var{m}."
c9b16cee
AW
2525 (let ((f (module-filename m)))
2526 (if f
2527 (save-module-excursion
2528 (lambda ()
2529 ;; Re-set the initial environment, as in try-module-autoload.
2530 (set-current-module (make-fresh-user-module))
2531 (primitive-load-path f)
2532 m))
2533 ;; Though we could guess, we *should* know it.
2534 (error "unknown file name for module" m))))
2535
90847923
MD
2536(define (purify-module! module)
2537 "Removes bindings in MODULE which are inherited from the (guile) module."
2538 (let ((use-list (module-uses module)))
2539 (if (and (pair? use-list)
9b5a0d84
AW
2540 (eq? (car (last-pair use-list)) the-scm-module))
2541 (set-module-uses! module (reverse (cdr (reverse use-list)))))))
90847923 2542
4eecfeb7 2543;; Return a module that is an interface to the module designated by
532cf805
MV
2544;; NAME.
2545;;
c614a00b 2546;; `resolve-interface' takes four keyword arguments:
532cf805
MV
2547;;
2548;; #:select SELECTION
2549;;
2550;; SELECTION is a list of binding-specs to be imported; A binding-spec
2551;; is either a symbol or a pair of symbols (ORIG . SEEN), where ORIG
2552;; is the name in the used module and SEEN is the name in the using
2553;; module. Note that SEEN is also passed through RENAMER, below. The
2554;; default is to select all bindings. If you specify no selection but
4eecfeb7 2555;; a renamer, only the bindings that already exist in the used module
532cf805
MV
2556;; are made available in the interface. Bindings that are added later
2557;; are not picked up.
2558;;
c614a00b 2559;; #:hide BINDINGS
532cf805 2560;;
c614a00b 2561;; BINDINGS is a list of bindings which should not be imported.
f595ccfe
MD
2562;;
2563;; #:prefix PREFIX
2564;;
2565;; PREFIX is a symbol that will be appended to each exported name.
2566;; The default is to not perform any renaming.
532cf805 2567;;
c614a00b
MD
2568;; #:renamer RENAMER
2569;;
2570;; RENAMER is a procedure that takes a symbol and returns its new
2571;; name. The default is not perform any renaming.
2572;;
532cf805
MV
2573;; Signal "no code for module" error if module name is not resolvable
2574;; or its public interface is not available. Signal "no binding"
2575;; error if selected binding does not exist in the used module.
2576;;
36d58fc3
AW
2577(define* (resolve-interface name #:key
2578 (select #f)
2579 (hide '())
2580 (prefix #f)
2581 (renamer (if prefix
2582 (symbol-prefix-proc prefix)
2583 identity))
2584 version)
47aabe86 2585 (let* ((module (resolve-module name #t version #:ensure #f))
b622dec7
TTN
2586 (public-i (and module (module-public-interface module))))
2587 (and (or (not module) (not public-i))
2588 (error "no code for module" name))
c614a00b 2589 (if (and (not select) (null? hide) (eq? renamer identity))
b622dec7 2590 public-i
532cf805 2591 (let ((selection (or select (module-map (lambda (sym var) sym)
9b5a0d84 2592 public-i)))
b622dec7 2593 (custom-i (make-module 31)))
c614a00b 2594 (set-module-kind! custom-i 'custom-interface)
9b5a0d84
AW
2595 (set-module-name! custom-i name)
2596 ;; XXX - should use a lazy binder so that changes to the
2597 ;; used module are picked up automatically.
2598 (for-each (lambda (bspec)
2599 (let* ((direct? (symbol? bspec))
2600 (orig (if direct? bspec (car bspec)))
2601 (seen (if direct? bspec (cdr bspec)))
2602 (var (or (module-local-variable public-i orig)
2603 (module-local-variable module orig)
2604 (error
2605 ;; fixme: format manually for now
2606 (simple-format
2607 #f "no binding `~A' in module ~A"
2608 orig name)))))
2609 (if (memq orig hide)
2610 (set! hide (delq! orig hide))
2611 (module-add! custom-i
2612 (renamer seen)
2613 var))))
2614 selection)
2615 ;; Check that we are not hiding bindings which don't exist
2616 (for-each (lambda (binding)
2617 (if (not (module-local-variable public-i binding))
2618 (error
2619 (simple-format
2620 #f "no binding `~A' to hide in module ~A"
2621 binding name))))
2622 hide)
b622dec7 2623 custom-i))))
fb1b76f4
TTN
2624
2625(define (symbol-prefix-proc prefix)
2626 (lambda (symbol)
2627 (symbol-append prefix symbol)))
0f2d19dd 2628
57ced5b9
AW
2629;; This function is called from "modules.c". If you change it, be
2630;; sure to update "modules.c" as well.
2631
f7f62d3a
AW
2632(define* (define-module* name
2633 #:key filename pure version (duplicates '())
2634 (imports '()) (exports '()) (replacements '())
2635 (re-exports '()) (autoloads '()) transformer)
2636 (define (list-of pred l)
2637 (or (null? l)
2638 (and (pair? l) (pred (car l)) (list-of pred (cdr l)))))
2639 (define (valid-export? x)
2640 (or (symbol? x) (and (pair? x) (symbol? (car x)) (symbol? (cdr x)))))
2641 (define (valid-autoload? x)
2642 (and (pair? x) (list-of symbol? (car x)) (list-of symbol? (cdr x))))
2643
2644 (define (resolve-imports imports)
2645 (define (resolve-import import-spec)
2646 (if (list? import-spec)
2647 (apply resolve-interface import-spec)
2648 (error "unexpected use-module specification" import-spec)))
2649 (let lp ((imports imports) (out '()))
2650 (cond
2651 ((null? imports) (reverse! out))
2652 ((pair? imports)
2653 (lp (cdr imports)
2654 (cons (resolve-import (car imports)) out)))
2655 (else (error "unexpected tail of imports list" imports)))))
2656
2657 ;; We could add a #:no-check arg, set by the define-module macro, if
2658 ;; these checks are taking too much time.
2659 ;;
2660 (let ((module (resolve-module name #f)))
2661 (beautify-user-module! module)
2662 (if filename
2663 (set-module-filename! module filename))
2664 (if pure
2665 (purify-module! module))
2666 (if version
2667 (begin
2668 (if (not (list-of integer? version))
2669 (error "expected list of integers for version"))
2670 (set-module-version! module version)
2671 (set-module-version! (module-public-interface module) version)))
f7f62d3a
AW
2672 (let ((imports (resolve-imports imports)))
2673 (call-with-deferred-observers
2674 (lambda ()
2675 (if (pair? imports)
2676 (module-use-interfaces! module imports))
2677 (if (list-of valid-export? exports)
2678 (if (pair? exports)
2679 (module-export! module exports))
2680 (error "expected exports to be a list of symbols or symbol pairs"))
2681 (if (list-of valid-export? replacements)
2682 (if (pair? replacements)
2683 (module-replace! module replacements))
2684 (error "expected replacements to be a list of symbols or symbol pairs"))
2685 (if (list-of valid-export? re-exports)
2686 (if (pair? re-exports)
2687 (module-re-export! module re-exports))
2688 (error "expected re-exports to be a list of symbols or symbol pairs"))
2689 ;; FIXME
2690 (if (not (null? autoloads))
6b1c5d9d
AW
2691 (apply module-autoload! module autoloads))
2692 ;; Wait until modules have been loaded to resolve duplicates
2693 ;; handlers.
2694 (if (pair? duplicates)
2695 (let ((handlers (lookup-duplicates-handlers duplicates)))
2696 (set-module-duplicates-handlers! module handlers))))))
f7f62d3a
AW
2697
2698 (if transformer
2699 (if (and (pair? transformer) (list-of symbol? transformer))
2700 (let ((iface (resolve-interface transformer))
2701 (sym (car (last-pair transformer))))
2702 (set-module-transformer! module (module-ref iface sym)))
2703 (error "expected transformer to be a module name" transformer)))
2704
2705 (run-hook module-defined-hook module)
2706 module))
2707
db853761
NJ
2708;; `module-defined-hook' is a hook that is run whenever a new module
2709;; is defined. Its members are called with one argument, the new
2710;; module.
2711(define module-defined-hook (make-hook 1))
2712
3d2ada2f
DH
2713\f
2714
71225060 2715;;; {Autoload}
3d2ada2f 2716;;;
71225060
MD
2717
2718(define (make-autoload-interface module name bindings)
2719 (let ((b (lambda (a sym definep)
9b5a0d84
AW
2720 (and (memq sym bindings)
2721 (let ((i (module-public-interface (resolve-module name))))
2722 (if (not i)
2723 (error "missing interface for module" name))
2724 (let ((autoload (memq a (module-uses module))))
2725 ;; Replace autoload-interface with actual interface if
2726 ;; that has not happened yet.
2727 (if (pair? autoload)
2728 (set-car! autoload i)))
2729 (module-local-variable i sym))))))
608860a5 2730 (module-constructor (make-hash-table 0) '() b #f #f name 'autoload #f
f905381d 2731 (make-hash-table 0) '() (make-weak-value-hash-table 31) #f
78f79f18 2732 (make-hash-table 0) #f #f #f)))
608860a5
LC
2733
2734(define (module-autoload! module . args)
2735 "Have @var{module} automatically load the module named @var{name} when one
2736of the symbols listed in @var{bindings} is looked up. @var{args} should be a
2737list of module-name/binding-list pairs, e.g., as in @code{(module-autoload!
2738module '(ice-9 q) '(make-q q-length))}."
2739 (let loop ((args args))
2740 (cond ((null? args)
2741 #t)
2742 ((null? (cdr args))
2743 (error "invalid name+binding autoload list" args))
2744 (else
2745 (let ((name (car args))
2746 (bindings (cadr args)))
2747 (module-use! module (make-autoload-interface module
2748 name bindings))
2749 (loop (cddr args)))))))
2750
71225060 2751
0f2d19dd 2752\f
3d2ada2f 2753
44cf1f0f 2754;;; {Autoloading modules}
3d2ada2f 2755;;;
0f2d19dd
JB
2756
2757(define autoloads-in-progress '())
2758
482a28f9
MV
2759;; This function is called from "modules.c". If you change it, be
2760;; sure to update "modules.c" as well.
2761
d9113d47 2762(define* (try-module-autoload module-name #:optional version)
0f2d19dd 2763 (let* ((reverse-name (reverse module-name))
9b5a0d84
AW
2764 (name (symbol->string (car reverse-name)))
2765 (dir-hint-module-name (reverse (cdr reverse-name)))
2766 (dir-hint (apply string-append
2767 (map (lambda (elt)
2768 (string-append (symbol->string elt) "/"))
2769 dir-hint-module-name))))
0209ca9a 2770 (resolve-module dir-hint-module-name #f)
0f2d19dd 2771 (and (not (autoload-done-or-in-progress? dir-hint name))
9b5a0d84
AW
2772 (let ((didit #f))
2773 (dynamic-wind
2774 (lambda () (autoload-in-progress! dir-hint name))
2775 (lambda ()
eddd16d7
AW
2776 (with-fluids ((current-reader #f))
2777 (save-module-excursion
2778 (lambda ()
39392995
AW
2779 ;; The initial environment when loading a module is a fresh
2780 ;; user module.
2781 (set-current-module (make-fresh-user-module))
e44d2e4d
AW
2782 ;; Here we could allow some other search strategy (other than
2783 ;; primitive-load-path), for example using versions encoded
2784 ;; into the file system -- but then we would have to figure
6f06e8d3 2785 ;; out how to locate the compiled file, do auto-compilation,
e44d2e4d
AW
2786 ;; etc. Punt for now, and don't use versions when locating
2787 ;; the file.
2788 (primitive-load-path (in-vicinity dir-hint name) #f)
eddd16d7 2789 (set! didit #t)))))
9b5a0d84
AW
2790 (lambda () (set-autoloaded! dir-hint name didit)))
2791 didit))))
0f2d19dd 2792
71225060 2793\f
3d2ada2f
DH
2794
2795;;; {Dynamic linking of modules}
2796;;;
d0cbd20c 2797
0f2d19dd
JB
2798(define autoloads-done '((guile . guile)))
2799
2800(define (autoload-done-or-in-progress? p m)
2801 (let ((n (cons p m)))
2802 (->bool (or (member n autoloads-done)
9b5a0d84 2803 (member n autoloads-in-progress)))))
0f2d19dd
JB
2804
2805(define (autoload-done! p m)
2806 (let ((n (cons p m)))
2807 (set! autoloads-in-progress
9b5a0d84 2808 (delete! n autoloads-in-progress))
0f2d19dd 2809 (or (member n autoloads-done)
9b5a0d84 2810 (set! autoloads-done (cons n autoloads-done)))))
0f2d19dd
JB
2811
2812(define (autoload-in-progress! p m)
2813 (let ((n (cons p m)))
2814 (set! autoloads-done
9b5a0d84 2815 (delete! n autoloads-done))
0f2d19dd
JB
2816 (set! autoloads-in-progress (cons n autoloads-in-progress))))
2817
2818(define (set-autoloaded! p m done?)
2819 (if done?
2820 (autoload-done! p m)
2821 (let ((n (cons p m)))
9b5a0d84
AW
2822 (set! autoloads-done (delete! n autoloads-done))
2823 (set! autoloads-in-progress (delete! n autoloads-in-progress)))))
0f2d19dd 2824
0f2d19dd
JB
2825\f
2826
83b38198 2827;;; {Run-time options}
3d2ada2f 2828;;;
83b38198 2829
122f296d
AW
2830(define-syntax define-option-interface
2831 (syntax-rules ()
2832 ((_ (interface (options enable disable) (option-set!)))
2833 (begin
2834 (define options
2835 (case-lambda
2836 (() (interface))
2837 ((arg)
2838 (if (list? arg)
2839 (begin (interface arg) (interface))
2840 (for-each
2841 (lambda (option)
2842 (apply (lambda (name value documentation)
2843 (display name)
2844 (if (< (string-length (symbol->string name)) 8)
2845 (display #\tab))
2846 (display #\tab)
2847 (display value)
2848 (display #\tab)
2849 (display documentation)
2850 (newline))
2851 option))
2852 (interface #t))))))
2853 (define (enable . flags)
2854 (interface (append flags (interface)))
2855 (interface))
2856 (define (disable . flags)
2857 (let ((options (interface)))
2858 (for-each (lambda (flag) (set! options (delq! flag options)))
2859 flags)
2860 (interface options)
2861 (interface)))
0c65f52c
AW
2862 (define-syntax-rule (option-set! opt val)
2863 (eval-when (eval load compile expand)
2864 (options (append (options) (list 'opt val)))))))))
e9bab9df 2865
e9bab9df
DH
2866(define-option-interface
2867 (debug-options-interface
2868 (debug-options debug-enable debug-disable)
2869 (debug-set!)))
2870
e9bab9df
DH
2871(define-option-interface
2872 (read-options-interface
2873 (read-options read-enable read-disable)
2874 (read-set!)))
2875
2876(define-option-interface
2877 (print-options-interface
2878 (print-options print-enable print-disable)
2879 (print-set!)))
83b38198
MD
2880
2881\f
2882
410e83c0
AW
2883;;; {The Unspecified Value}
2884;;;
2885;;; Currently Guile represents unspecified values via one particular value,
2886;;; which may be obtained by evaluating (if #f #f). It would be nice in the
2887;;; future if we could replace this with a return of 0 values, though.
9346b857 2888;;;
410e83c0
AW
2889
2890(define-syntax *unspecified*
2891 (identifier-syntax (if #f #f)))
2892
2893(define (unspecified? v) (eq? v *unspecified*))
2894
2895
2896\f
2897
90de5c4c
AW
2898;;; {Parameters}
2899;;;
2900
2901(define <parameter>
2902 ;; Three fields: the procedure itself, the fluid, and the converter.
2903 (make-struct <applicable-struct-vtable> 0 'pwprpr))
2904(set-struct-vtable-name! <parameter> '<parameter>)
2905
2906(define* (make-parameter init #:optional (conv (lambda (x) x)))
2907 (let ((fluid (make-fluid (conv init))))
2908 (make-struct <parameter> 0
2909 (case-lambda
2910 (() (fluid-ref fluid))
13dd74c8
AW
2911 ((x) (let ((prev (fluid-ref fluid)))
2912 (fluid-set! fluid (conv x))
2913 prev)))
90de5c4c
AW
2914 fluid conv)))
2915
2916(define (parameter? x)
2917 (and (struct? x) (eq? (struct-vtable x) <parameter>)))
2918
2919(define (parameter-fluid p)
2920 (if (parameter? p)
2921 (struct-ref p 1)
2922 (scm-error 'wrong-type-arg "parameter-fluid"
2923 "Not a parameter: ~S" (list p) #f)))
2924
2925(define (parameter-converter p)
2926 (if (parameter? p)
2927 (struct-ref p 2)
2928 (scm-error 'wrong-type-arg "parameter-fluid"
2929 "Not a parameter: ~S" (list p) #f)))
2930
2931(define-syntax parameterize
2932 (lambda (x)
2933 (syntax-case x ()
2934 ((_ ((param value) ...) body body* ...)
2935 (with-syntax (((p ...) (generate-temporaries #'(param ...))))
2936 #'(let ((p param) ...)
2937 (if (not (parameter? p))
2938 (scm-error 'wrong-type-arg "parameterize"
2939 "Not a parameter: ~S" (list p) #f))
2940 ...
2941 (with-fluids (((struct-ref p 1) ((struct-ref p 2) value))
2942 ...)
2943 body body* ...)))))))
2944
2945\f
9670f238
AW
2946;;;
2947;;; Current ports as parameters.
2948;;;
2949
2950(let ((fluid->parameter
2951 (lambda (fluid conv)
2952 (make-struct <parameter> 0
2953 (case-lambda
2954 (() (fluid-ref fluid))
2955 ((x) (let ((prev (fluid-ref fluid)))
2956 (fluid-set! fluid (conv x))
2957 prev)))
2958 fluid conv))))
2959 (define-syntax-rule (port-parameterize! binding fluid predicate msg)
2960 (begin
2961 (set! binding (fluid->parameter (module-ref (current-module) 'fluid)
2962 (lambda (x)
2963 (if (predicate x) x
2964 (error msg x)))))
2965 (module-remove! (current-module) 'fluid)))
2966
2967 (port-parameterize! current-input-port %current-input-port-fluid
2968 input-port? "expected an input port")
2969 (port-parameterize! current-output-port %current-output-port-fluid
2970 output-port? "expected an output port")
2971 (port-parameterize! current-error-port %current-error-port-fluid
2972 output-port? "expected an output port"))
2973
2974
2975\f
3972de76
AW
2976;;;
2977;;; Warnings.
2978;;;
2979
2980(define current-warning-port
2981 (make-parameter (current-error-port)
2982 (lambda (x)
2983 (if (output-port? x)
2984 x
2985 (error "expected an output port" x)))))
2986
2987
2988\f
90de5c4c 2989
0f2d19dd
JB
2990;;; {Running Repls}
2991;;;
2992
9447207f 2993(define *repl-stack* (make-fluid '()))
1fdd5bec 2994
9346b857
AW
2995;; Programs can call `batch-mode?' to see if they are running as part of a
2996;; script or if they are running interactively. REPL implementations ensure that
2997;; `batch-mode?' returns #f during their extent.
2998;;
1fdd5bec 2999(define (batch-mode?)
9447207f 3000 (null? (fluid-ref *repl-stack*)))
1fdd5bec 3001
9346b857 3002;; Programs can re-enter batch mode, for example after a fork, by calling
0feb833d
AW
3003;; `ensure-batch-mode!'. It's not a great interface, though; it would be better
3004;; to abort to the outermost prompt, and call a thunk there.
1fdd5bec 3005;;
9346b857 3006(define (ensure-batch-mode!)
9d2136ba 3007 (set! batch-mode? (lambda () #t)))
4bbbcd5c 3008
0f2d19dd
JB
3009(define (quit . args)
3010 (apply throw 'quit args))
3011
7950df7c
GH
3012(define exit quit)
3013
0f2d19dd
JB
3014(define (gc-run-time)
3015 (cdr (assq 'gc-time-taken (gc-stats))))
3016
8942e7a1
AW
3017(define abort-hook (make-hook))
3018(define before-error-hook (make-hook))
3019(define after-error-hook (make-hook))
3020(define before-backtrace-hook (make-hook))
3021(define after-backtrace-hook (make-hook))
3022
3e3cec45
MD
3023(define before-read-hook (make-hook))
3024(define after-read-hook (make-hook))
870777d7
KN
3025(define before-eval-hook (make-hook 1))
3026(define after-eval-hook (make-hook 1))
3027(define before-print-hook (make-hook 1))
3028(define after-print-hook (make-hook 1))
1c6cd8e8 3029
c592de96
AW
3030;;; This hook is run at the very end of an interactive session.
3031;;;
3032(define exit-hook (make-hook))
3033
dc5c2038
MD
3034;;; The default repl-reader function. We may override this if we've
3035;;; the readline library.
3036(define repl-reader
17ee350c 3037 (lambda* (prompt #:optional (reader (fluid-ref current-reader)))
0becb8f3 3038 (if (not (char-ready?))
dceb7829
AW
3039 (begin
3040 (display (if (string? prompt) prompt (prompt)))
3041 ;; An interesting situation. The printer resets the column to
3042 ;; 0 by printing a newline, but we then advance it by printing
3043 ;; the prompt. However the port-column of the output port
3044 ;; does not typically correspond with the actual column on the
b3da54d1 3045 ;; screen, because the input is echoed back! Since the
dceb7829
AW
3046 ;; input is line-buffered and thus ends with a newline, the
3047 ;; output will really start on column zero. So, here we zero
3048 ;; it out. See bug 9664.
3049 ;;
3050 ;; Note that for similar reasons, the output-line will not
3051 ;; reflect the actual line on the screen. But given the
3052 ;; possibility of multiline input, the fix is not as
3053 ;; straightforward, so we don't bother.
3054 ;;
3055 ;; Also note that the readline implementation papers over
3056 ;; these concerns, because it's readline itself printing the
3057 ;; prompt, and not Guile.
3058 (set-port-column! (current-output-port) 0)))
dc5c2038 3059 (force-output)
04efd24d 3060 (run-hook before-read-hook)
17ee350c 3061 ((or reader read) (current-input-port))))
dc5c2038 3062
0f2d19dd 3063
0f2d19dd 3064\f
3d2ada2f 3065
44cf1f0f 3066;;; {IOTA functions: generating lists of numbers}
3d2ada2f 3067;;;
0f2d19dd 3068
e69cd299
MD
3069(define (iota n)
3070 (let loop ((count (1- n)) (result '()))
3071 (if (< count 0) result
3072 (loop (1- count) (cons count result)))))
0f2d19dd
JB
3073
3074\f
3d2ada2f 3075
773abfbb
KR
3076;;; {While}
3077;;;
3078;;; with `continue' and `break'.
3079;;;
3080
10e69149
AW
3081;; The inliner will remove the prompts at compile-time if it finds that
3082;; `continue' or `break' are not used.
3083;;
3084(define-syntax while
3085 (lambda (x)
3086 (syntax-case x ()
3087 ((while cond body ...)
3088 #`(let ((break-tag (make-prompt-tag "break"))
3089 (continue-tag (make-prompt-tag "continue")))
3090 (call-with-prompt
3091 break-tag
3092 (lambda ()
3093 (define-syntax #,(datum->syntax #'while 'break)
3094 (lambda (x)
3095 (syntax-case x ()
91956a94
AW
3096 ((_ arg (... ...))
3097 #'(abort-to-prompt break-tag arg (... ...)))
10e69149 3098 (_
91956a94
AW
3099 #'(lambda args
3100 (apply abort-to-prompt break-tag args))))))
10e69149
AW
3101 (let lp ()
3102 (call-with-prompt
3103 continue-tag
3104 (lambda ()
3105 (define-syntax #,(datum->syntax #'while 'continue)
3106 (lambda (x)
3107 (syntax-case x ()
3108 ((_)
3109 #'(abort-to-prompt continue-tag))
3110 ((_ . args)
3111 (syntax-violation 'continue "too many arguments" x))
3112 (_
ddf134cf
MW
3113 #'(lambda ()
3114 (abort-to-prompt continue-tag))))))
91956a94 3115 (do () ((not cond) #f) body ...))
10e69149 3116 (lambda (k) (lp)))))
91956a94
AW
3117 (lambda (k . args)
3118 (if (null? args)
3119 #t
3120 (apply values args)))))))))
5578a53f 3121
773abfbb 3122
0f2d19dd 3123\f
3d2ada2f 3124
0f2d19dd
JB
3125;;; {Module System Macros}
3126;;;
3127
532cf805
MV
3128;; Return a list of expressions that evaluate to the appropriate
3129;; arguments for resolve-interface according to SPEC.
3130
1fdd5bec
AW
3131(eval-when (compile)
3132 (if (memq 'prefix (read-options))
3133 (error "boot-9 must be compiled with #:kw, not :kw")))
1a1a10d3 3134
532cf805
MV
3135(define (keyword-like-symbol->keyword sym)
3136 (symbol->keyword (string->symbol (substring (symbol->string sym) 1))))
3137
074e036e
AW
3138(define-syntax define-module
3139 (lambda (x)
3140 (define (keyword-like? stx)
3141 (let ((dat (syntax->datum stx)))
3142 (and (symbol? dat)
3143 (eqv? (string-ref (symbol->string dat) 0) #\:))))
3144 (define (->keyword sym)
3145 (symbol->keyword (string->symbol (substring (symbol->string sym) 1))))
3146
cd8c3519 3147 (define (parse-iface args)
074e036e
AW
3148 (let loop ((in args) (out '()))
3149 (syntax-case in ()
3150 (() (reverse! out))
3151 ;; The user wanted #:foo, but wrote :foo. Fix it.
3152 ((sym . in) (keyword-like? #'sym)
3153 (loop #`(#,(->keyword (syntax->datum #'sym)) . in) out))
3154 ((kw . in) (not (keyword? (syntax->datum #'kw)))
3155 (syntax-violation 'define-module "expected keyword arg" x #'kw))
3156 ((#:renamer renamer . in)
cd8c3519 3157 (loop #'in (cons* #',renamer #:renamer out)))
074e036e 3158 ((kw val . in)
cd8c3519 3159 (loop #'in (cons* #'val #'kw out))))))
074e036e 3160
cd8c3519 3161 (define (parse args imp exp rex rep aut)
074e036e
AW
3162 ;; Just quote everything except #:use-module and #:use-syntax. We
3163 ;; need to know about all arguments regardless since we want to turn
3164 ;; symbols that look like keywords into real keywords, and the
3165 ;; keyword args in a define-module form are not regular
3166 ;; (i.e. no-backtrace doesn't take a value).
cd8c3519
AW
3167 (syntax-case args ()
3168 (()
3169 (let ((imp (if (null? imp) '() #`(#:imports `#,imp)))
3170 (exp (if (null? exp) '() #`(#:exports '#,exp)))
3171 (rex (if (null? rex) '() #`(#:re-exports '#,rex)))
3172 (rep (if (null? rep) '() #`(#:replacements '#,rep)))
3173 (aut (if (null? aut) '() #`(#:autoloads '#,aut))))
3174 #`(#,@imp #,@exp #,@rex #,@rep #,@aut)))
3175 ;; The user wanted #:foo, but wrote :foo. Fix it.
3176 ((sym . args) (keyword-like? #'sym)
3177 (parse #`(#,(->keyword (syntax->datum #'sym)) . args)
3178 imp exp rex rep aut))
3179 ((kw . args) (not (keyword? (syntax->datum #'kw)))
3180 (syntax-violation 'define-module "expected keyword arg" x #'kw))
3181 ((#:no-backtrace . args)
3182 ;; Ignore this one.
3183 (parse #'args imp exp rex rep aut))
3184 ((#:pure . args)
3185 #`(#:pure #t . #,(parse #'args imp exp rex rep aut)))
3186 ((kw)
3187 (syntax-violation 'define-module "keyword arg without value" x #'kw))
3188 ((#:version (v ...) . args)
3189 #`(#:version '(v ...) . #,(parse #'args imp exp rex rep aut)))
3190 ((#:duplicates (d ...) . args)
3191 #`(#:duplicates '(d ...) . #,(parse #'args imp exp rex rep aut)))
3192 ((#:filename f . args)
3193 #`(#:filename 'f . #,(parse #'args imp exp rex rep aut)))
3194 ((#:use-module (name name* ...) . args)
3195 (and (and-map symbol? (syntax->datum #'(name name* ...))))
ad4bd7c2 3196 (parse #'args #`(#,@imp ((name name* ...))) exp rex rep aut))
cd8c3519
AW
3197 ((#:use-syntax (name name* ...) . args)
3198 (and (and-map symbol? (syntax->datum #'(name name* ...))))
3199 #`(#:transformer '(name name* ...)
ad4bd7c2 3200 . #,(parse #'args #`(#,@imp ((name name* ...))) exp rex rep aut)))
cd8c3519
AW
3201 ((#:use-module ((name name* ...) arg ...) . args)
3202 (and (and-map symbol? (syntax->datum #'(name name* ...))))
3203 (parse #'args
ad4bd7c2 3204 #`(#,@imp ((name name* ...) #,@(parse-iface #'(arg ...))))
cd8c3519
AW
3205 exp rex rep aut))
3206 ((#:export (ex ...) . args)
3207 (parse #'args imp #`(#,@exp ex ...) rex rep aut))
3208 ((#:export-syntax (ex ...) . args)
3209 (parse #'args imp #`(#,@exp ex ...) rex rep aut))
3210 ((#:re-export (re ...) . args)
3211 (parse #'args imp exp #`(#,@rex re ...) rep aut))
3212 ((#:re-export-syntax (re ...) . args)
3213 (parse #'args imp exp #`(#,@rex re ...) rep aut))
3214 ((#:replace (r ...) . args)
3215 (parse #'args imp exp rex #`(#,@rep r ...) aut))
3216 ((#:replace-syntax (r ...) . args)
3217 (parse #'args imp exp rex #`(#,@rep r ...) aut))
3218 ((#:autoload name bindings . args)
3219 (parse #'args imp exp rex rep #`(#,@aut name bindings)))
3220 ((kw val . args)
3221 (syntax-violation 'define-module "unknown keyword or bad argument"
3222 #'kw #'val))))
074e036e
AW
3223
3224 (syntax-case x ()
3225 ((_ (name name* ...) arg ...)
cd8c3519
AW
3226 (and-map symbol? (syntax->datum #'(name name* ...)))
3227 (with-syntax (((quoted-arg ...)
3228 (parse #'(arg ...) '() '() '() '() '()))
c415fe08
AW
3229 ;; Ideally the filename is either a string or #f;
3230 ;; this hack is to work around a case in which
3231 ;; port-filename returns a symbol (`socket') for
3232 ;; sockets.
3233 (filename (let ((f (assq-ref (or (syntax-source x) '())
3234 'filename)))
3235 (and (string? f) f))))
d9b1c71a 3236 #'(eval-when (eval load compile expand)
cd8c3519
AW
3237 (let ((m (define-module* '(name name* ...)
3238 #:filename filename quoted-arg ...)))
074e036e
AW
3239 (set-current-module m)
3240 m)))))))
0f2d19dd 3241
532cf805
MV
3242;; The guts of the use-modules macro. Add the interfaces of the named
3243;; modules to the use-list of the current module, in order.
3244
482a28f9
MV
3245;; This function is called by "modules.c". If you change it, be sure
3246;; to change scm_c_use_module as well.
3247
532cf805 3248(define (process-use-modules module-interface-args)
d57da08b 3249 (let ((interfaces (map (lambda (mif-args)
9b5a0d84
AW
3250 (or (apply resolve-interface mif-args)
3251 (error "no such module" mif-args)))
3252 module-interface-args)))
d57da08b
MD
3253 (call-with-deferred-observers
3254 (lambda ()
3255 (module-use-interfaces! (current-module) interfaces)))))
89da9036 3256
4e3328ce
AW
3257(define-syntax use-modules
3258 (lambda (x)
3259 (define (keyword-like? stx)
3260 (let ((dat (syntax->datum stx)))
3261 (and (symbol? dat)
3262 (eqv? (string-ref (symbol->string dat) 0) #\:))))
3263 (define (->keyword sym)
3264 (symbol->keyword (string->symbol (substring (symbol->string sym) 1))))
3265
3266 (define (quotify-iface args)
3267 (let loop ((in args) (out '()))
3268 (syntax-case in ()
3269 (() (reverse! out))
3270 ;; The user wanted #:foo, but wrote :foo. Fix it.
3271 ((sym . in) (keyword-like? #'sym)
3272 (loop #`(#,(->keyword (syntax->datum #'sym)) . in) out))
3273 ((kw . in) (not (keyword? (syntax->datum #'kw)))
3274 (syntax-violation 'define-module "expected keyword arg" x #'kw))
3275 ((#:renamer renamer . in)
3276 (loop #'in (cons* #'renamer #:renamer out)))
3277 ((kw val . in)
3278 (loop #'in (cons* #''val #'kw out))))))
3279
3280 (define (quotify specs)
3281 (let lp ((in specs) (out '()))
3282 (syntax-case in ()
3283 (() (reverse out))
3284 (((name name* ...) . in)
3285 (and-map symbol? (syntax->datum #'(name name* ...)))
3286 (lp #'in (cons #''((name name* ...)) out)))
3287 ((((name name* ...) arg ...) . in)
3288 (and-map symbol? (syntax->datum #'(name name* ...)))
3289 (with-syntax (((quoted-arg ...) (quotify-iface #'(arg ...))))
3290 (lp #'in (cons #`(list '(name name* ...) quoted-arg ...)
3291 out)))))))
3292
3293 (syntax-case x ()
3294 ((_ spec ...)
3295 (with-syntax (((quoted-args ...) (quotify #'(spec ...))))
520caaeb 3296 #'(eval-when (eval load compile expand)
4e3328ce
AW
3297 (process-use-modules (list quoted-args ...))
3298 *unspecified*))))))
3299
0c65f52c
AW
3300(define-syntax-rule (use-syntax spec ...)
3301 (begin
3302 (eval-when (eval load compile expand)
3303 (issue-deprecation-warning
3304 "`use-syntax' is deprecated. Please contact guile-devel for more info."))
3305 (use-modules spec ...)))
0f2d19dd 3306
b1e4c7cc
JG
3307(include-from-path "ice-9/r6rs-libraries")
3308
0c65f52c
AW
3309(define-syntax-rule (define-private foo bar)
3310 (define foo bar))
13182603
AW
3311
3312(define-syntax define-public
3313 (syntax-rules ()
3314 ((_ (name . args) . body)
3315 (define-public name (lambda args . body)))
3316 ((_ name val)
3317 (begin
3318 (define name val)
3319 (export name)))))
3320
0c65f52c
AW
3321(define-syntax-rule (defmacro-public name args body ...)
3322 (begin
3323 (defmacro name args body ...)
3324 (export-syntax name)))
0f2d19dd 3325
87e00370 3326;; And now for the most important macro.
0c65f52c
AW
3327(define-syntax-rule (λ formals body ...)
3328 (lambda formals body ...))
87e00370
LC
3329
3330\f
89d06712 3331;; Export a local variable
482a28f9
MV
3332
3333;; This function is called from "modules.c". If you change it, be
3334;; sure to update "modules.c" as well.
3335
90847923
MD
3336(define (module-export! m names)
3337 (let ((public-i (module-public-interface m)))
3338 (for-each (lambda (name)
78c22f5e
JG
3339 (let* ((internal-name (if (pair? name) (car name) name))
3340 (external-name (if (pair? name) (cdr name) name))
3341 (var (module-ensure-local-variable! m internal-name)))
3342 (module-add! public-i external-name var)))
9b5a0d84 3343 names)))
89d06712 3344
f595ccfe
MD
3345(define (module-replace! m names)
3346 (let ((public-i (module-public-interface m)))
3347 (for-each (lambda (name)
78c22f5e
JG
3348 (let* ((internal-name (if (pair? name) (car name) name))
3349 (external-name (if (pair? name) (cdr name) name))
3350 (var (module-ensure-local-variable! m internal-name)))
eceee4ef
AW
3351 ;; FIXME: use a bit on variables instead of object
3352 ;; properties.
9b5a0d84 3353 (set-object-property! var 'replace #t)
78c22f5e 3354 (module-add! public-i external-name var)))
9b5a0d84 3355 names)))
f595ccfe 3356
d2b7b761
AW
3357;; Export all local variables from a module
3358;;
3359(define (module-export-all! mod)
3360 (define (fresh-interface!)
3361 (let ((iface (make-module)))
3362 (set-module-name! iface (module-name mod))
e5602ce7 3363 (set-module-version! iface (module-version mod))
d2b7b761
AW
3364 (set-module-kind! iface 'interface)
3365 (set-module-public-interface! mod iface)
3366 iface))
3367 (let ((iface (or (module-public-interface mod)
3368 (fresh-interface!))))
3369 (set-module-obarray! iface (module-obarray mod))))
3370
89d06712
MV
3371;; Re-export a imported variable
3372;;
3373(define (module-re-export! m names)
3374 (let ((public-i (module-public-interface m)))
3375 (for-each (lambda (name)
78c22f5e
JG
3376 (let* ((internal-name (if (pair? name) (car name) name))
3377 (external-name (if (pair? name) (cdr name) name))
3378 (var (module-variable m internal-name)))
9b5a0d84 3379 (cond ((not var)
78c22f5e
JG
3380 (error "Undefined variable:" internal-name))
3381 ((eq? var (module-local-variable m internal-name))
3382 (error "re-exporting local variable:" internal-name))
9b5a0d84 3383 (else
78c22f5e 3384 (module-add! public-i external-name var)))))
9b5a0d84 3385 names)))
90847923 3386
0c65f52c
AW
3387(define-syntax-rule (export name ...)
3388 (eval-when (eval load compile expand)
3389 (call-with-deferred-observers
3390 (lambda ()
3391 (module-export! (current-module) '(name ...))))))
a0cc0a01 3392
0c65f52c
AW
3393(define-syntax-rule (re-export name ...)
3394 (eval-when (eval load compile expand)
3395 (call-with-deferred-observers
3396 (lambda ()
3397 (module-re-export! (current-module) '(name ...))))))
89d06712 3398
0c65f52c
AW
3399(define-syntax-rule (export! name ...)
3400 (eval-when (eval load compile expand)
3401 (call-with-deferred-observers
3402 (lambda ()
3403 (module-replace! (current-module) '(name ...))))))
1052739b 3404
0c65f52c
AW
3405(define-syntax-rule (export-syntax name ...)
3406 (export name ...))
a0cc0a01 3407
0c65f52c
AW
3408(define-syntax-rule (re-export-syntax name ...)
3409 (re-export name ...))
a0cc0a01 3410
3de80ed5
AW
3411\f
3412
f595ccfe
MD
3413;;; {Parameters}
3414;;;
3415
e9729cbb 3416(define* (make-mutable-parameter init #:optional (converter identity))
9447207f 3417 (let ((fluid (make-fluid (converter init))))
e9729cbb
AW
3418 (case-lambda
3419 (() (fluid-ref fluid))
3420 ((val) (fluid-set! fluid (converter val))))))
3421
f595ccfe
MD
3422
3423\f
3d2ada2f 3424
7b07e5ef
MD
3425;;; {Handling of duplicate imported bindings}
3426;;;
3427
3428;; Duplicate handlers take the following arguments:
3429;;
3430;; module importing module
9b5a0d84
AW
3431;; name conflicting name
3432;; int1 old interface where name occurs
3433;; val1 value of binding in old interface
3434;; int2 new interface where name occurs
3435;; val2 value of binding in new interface
3436;; var previous resolution or #f
3437;; val value of previous resolution
7b07e5ef
MD
3438;;
3439;; A duplicate handler can take three alternative actions:
3440;;
3441;; 1. return #f => leave responsibility to next handler
3442;; 2. exit with an error
3443;; 3. return a variable resolving the conflict
3444;;
3445
3446(define duplicate-handlers
3447 (let ((m (make-module 7)))
f595ccfe
MD
3448
3449 (define (check module name int1 val1 int2 val2 var val)
3450 (scm-error 'misc-error
9b5a0d84
AW
3451 #f
3452 "~A: `~A' imported from both ~A and ~A"
3453 (list (module-name module)
3454 name
3455 (module-name int1)
3456 (module-name int2))
3457 #f))
f595ccfe 3458
65bed4aa 3459 (define (warn module name int1 val1 int2 val2 var val)
2c27dd57 3460 (format (current-warning-port)
9b5a0d84
AW
3461 "WARNING: ~A: `~A' imported from both ~A and ~A\n"
3462 (module-name module)
3463 name
3464 (module-name int1)
3465 (module-name int2))
65bed4aa 3466 #f)
f595ccfe
MD
3467
3468 (define (replace module name int1 val1 int2 val2 var val)
3469 (let ((old (or (and var (object-property var 'replace) var)
9b5a0d84
AW
3470 (module-variable int1 name)))
3471 (new (module-variable int2 name)))
3472 (if (object-property old 'replace)
3473 (and (or (eq? old new)
3474 (not (object-property new 'replace)))
3475 old)
3476 (and (object-property new 'replace)
3477 new))))
f595ccfe 3478
65bed4aa
MD
3479 (define (warn-override-core module name int1 val1 int2 val2 var val)
3480 (and (eq? int1 the-scm-module)
9b5a0d84 3481 (begin
2c27dd57 3482 (format (current-warning-port)
9b5a0d84
AW
3483 "WARNING: ~A: imported module ~A overrides core binding `~A'\n"
3484 (module-name module)
3485 (module-name int2)
3486 name)
3487 (module-local-variable int2 name))))
f595ccfe 3488
65bed4aa
MD
3489 (define (first module name int1 val1 int2 val2 var val)
3490 (or var (module-local-variable int1 name)))
f595ccfe 3491
65bed4aa
MD
3492 (define (last module name int1 val1 int2 val2 var val)
3493 (module-local-variable int2 name))
f595ccfe 3494
65bed4aa
MD
3495 (define (noop module name int1 val1 int2 val2 var val)
3496 #f)
3497
7b07e5ef
MD
3498 (set-module-name! m 'duplicate-handlers)
3499 (set-module-kind! m 'interface)
f595ccfe
MD
3500 (module-define! m 'check check)
3501 (module-define! m 'warn warn)
3502 (module-define! m 'replace replace)
3503 (module-define! m 'warn-override-core warn-override-core)
3504 (module-define! m 'first first)
3505 (module-define! m 'last last)
65bed4aa
MD
3506 (module-define! m 'merge-generics noop)
3507 (module-define! m 'merge-accessors noop)
7b07e5ef
MD
3508 m))
3509
f595ccfe 3510(define (lookup-duplicates-handlers handler-names)
109c2c9f
MD
3511 (and handler-names
3512 (map (lambda (handler-name)
9b5a0d84
AW
3513 (or (module-symbol-local-binding
3514 duplicate-handlers handler-name #f)
3515 (error "invalid duplicate handler name:"
3516 handler-name)))
3517 (if (list? handler-names)
3518 handler-names
3519 (list handler-names)))))
f595ccfe 3520
70a459e3
MD
3521(define default-duplicate-binding-procedures
3522 (make-mutable-parameter #f))
3523
3524(define default-duplicate-binding-handler
6496a663 3525 (make-mutable-parameter '(replace warn-override-core warn last)
9b5a0d84
AW
3526 (lambda (handler-names)
3527 (default-duplicate-binding-procedures
3528 (lookup-duplicates-handlers handler-names))
3529 handler-names)))
f595ccfe 3530
7b07e5ef 3531\f
7f24bc58 3532
c50775e2
AW
3533;;; {`load'.}
3534;;;
3535;;; Load is tricky when combined with relative paths, compilation, and
b3da54d1 3536;;; the file system. If a path is relative, what is it relative to? The
c50775e2
AW
3537;;; path of the source file at the time it was compiled? The path of
3538;;; the compiled file? What if both or either were installed? And how
3539;;; do you get that information? Tricky, I say.
3540;;;
3541;;; To get around all of this, we're going to do something nasty, and
3542;;; turn `load' into a macro. That way it can know the path of the
3543;;; source file with respect to which it was invoked, so it can resolve
3544;;; relative paths with respect to the original source path.
3545;;;
3546;;; There is an exception, and that is that if the source file was in
3547;;; the load path when it was compiled, instead of looking up against
3548;;; the absolute source location, we load-from-path against the relative
3549;;; source location.
3550;;;
3551
5a79300f
LC
3552(define %auto-compilation-options
3553 ;; Default `compile-file' option when auto-compiling.
f86f748d 3554 '(#:warnings (unbound-variable arity-mismatch format)))
5a79300f 3555
c50775e2 3556(define* (load-in-vicinity dir path #:optional reader)
6934d9e7
AW
3557 (define (canonical->suffix canon)
3558 (cond
3559 ((string-prefix? "/" canon) canon)
3560 ((and (> (string-length canon) 2)
3561 (eqv? (string-ref canon 1) #\:))
3562 ;; Paths like C:... transform to /C...
3563 (string-append "/" (substring canon 0 1) (substring canon 2)))
3564 (else canon)))
3565
c50775e2
AW
3566 ;; Returns the .go file corresponding to `name'. Does not search load
3567 ;; paths, only the fallback path. If the .go file is missing or out of
6f06e8d3 3568 ;; date, and auto-compilation is enabled, will try auto-compilation, just
c50775e2 3569 ;; as primitive-load-path does internally. primitive-load is
6f06e8d3 3570 ;; unaffected. Returns #f if auto-compilation failed or was disabled.
c50775e2
AW
3571 ;;
3572 ;; NB: Unless we need to compile the file, this function should not cause
3573 ;; (system base compile) to be loaded up. For that reason compiled-file-name
3574 ;; partially duplicates functionality from (system base compile).
3575 ;;
3576 (define (compiled-file-name canon-path)
6934d9e7
AW
3577 ;; FIXME: would probably be better just to append SHA1(canon-path)
3578 ;; to the %compile-fallback-path, to avoid deep directory stats.
c50775e2
AW
3579 (and %compile-fallback-path
3580 (string-append
3581 %compile-fallback-path
6934d9e7 3582 (canonical->suffix canon-path)
c50775e2
AW
3583 (cond ((or (null? %load-compiled-extensions)
3584 (string-null? (car %load-compiled-extensions)))
3585 (warn "invalid %load-compiled-extensions"
3586 %load-compiled-extensions)
3587 ".go")
3588 (else (car %load-compiled-extensions))))))
3589
3590 (define (fresh-compiled-file-name name go-path)
3591 (catch #t
3592 (lambda ()
3593 (let* ((scmstat (stat name))
1e56cff2
AW
3594 (gostat (and (not %fresh-auto-compile)
3595 (stat go-path #f))))
c50775e2
AW
3596 (if (and gostat
3597 (or (> (stat:mtime gostat) (stat:mtime scmstat))
3598 (and (= (stat:mtime gostat) (stat:mtime scmstat))
3599 (>= (stat:mtimensec gostat)
3600 (stat:mtimensec scmstat)))))
3601 go-path
3602 (begin
3603 (if gostat
2c27dd57 3604 (format (current-warning-port)
c50775e2
AW
3605 ";;; note: source file ~a\n;;; newer than compiled ~a\n"
3606 name go-path))
3607 (cond
6f06e8d3
AW
3608 (%load-should-auto-compile
3609 (%warn-auto-compilation-enabled)
2c27dd57 3610 (format (current-warning-port) ";;; compiling ~a\n" name)
5a79300f
LC
3611 (let ((cfn
3612 ((module-ref
c50775e2
AW
3613 (resolve-interface '(system base compile))
3614 'compile-file)
3615 name
5a79300f 3616 #:opts %auto-compilation-options
c50775e2 3617 #:env (current-module))))
2c27dd57 3618 (format (current-warning-port) ";;; compiled ~a\n" cfn)
c50775e2
AW
3619 cfn))
3620 (else #f))))))
3621 (lambda (k . args)
2c27dd57 3622 (format (current-warning-port)
669ea4eb
AW
3623 ";;; WARNING: compilation of ~a failed:\n" name)
3624 (for-each (lambda (s)
3625 (if (not (string-null? s))
2c27dd57 3626 (format (current-warning-port) ";;; ~a\n" s)))
669ea4eb
AW
3627 (string-split
3628 (call-with-output-string
3629 (lambda (port) (print-exception port #f k args)))
3630 #\newline))
c50775e2
AW
3631 #f)))
3632
3633 (define (absolute-path? path)
3634 (string-prefix? "/" path))
3635
3636 (define (load-absolute abs-path)
3637 (let ((cfn (let ((canon (false-if-exception (canonicalize-path abs-path))))
3638 (and canon
3639 (let ((go-path (compiled-file-name canon)))
3640 (and go-path
3641 (fresh-compiled-file-name abs-path go-path)))))))
3642 (if cfn
dcada7d8
AW
3643 (begin
3644 (if %load-hook
3645 (%load-hook abs-path))
3646 (load-compiled cfn))
c50775e2
AW
3647 (start-stack 'load-stack
3648 (primitive-load abs-path)))))
3649
3650 (save-module-excursion
3651 (lambda ()
3652 (with-fluids ((current-reader reader)
3653 (%file-port-name-canonicalization 'relative))
3654 (cond
3655 ((or (absolute-path? path))
3656 (load-absolute path))
3657 ((absolute-path? dir)
3658 (load-absolute (in-vicinity dir path)))
3659 (else
3660 (load-from-path (in-vicinity dir path))))))))
3661
3662(define-syntax load
3663 (make-variable-transformer
3664 (lambda (x)
3665 (let* ((src (syntax-source x))
3666 (file (and src (assq-ref src 'filename)))
3667 (dir (and (string? file) (dirname file))))
3668 (syntax-case x ()
3669 ((_ arg ...)
3670 #`(load-in-vicinity #,(or dir #'(getcwd)) arg ...))
3671 (id
3672 (identifier? #'id)
3673 #`(lambda args
3674 (apply load-in-vicinity #,(or dir #'(getcwd)) args))))))))
3675
3676\f
3677
7f24bc58
MG
3678;;; {`cond-expand' for SRFI-0 support.}
3679;;;
3680;;; This syntactic form expands into different commands or
3681;;; definitions, depending on the features provided by the Scheme
3682;;; implementation.
3683;;;
3684;;; Syntax:
3685;;;
3686;;; <cond-expand>
3687;;; --> (cond-expand <cond-expand-clause>+)
3688;;; | (cond-expand <cond-expand-clause>* (else <command-or-definition>))
3689;;; <cond-expand-clause>
3690;;; --> (<feature-requirement> <command-or-definition>*)
3691;;; <feature-requirement>
3692;;; --> <feature-identifier>
3693;;; | (and <feature-requirement>*)
3694;;; | (or <feature-requirement>*)
3695;;; | (not <feature-requirement>)
3696;;; <feature-identifier>
3697;;; --> <a symbol which is the name or alias of a SRFI>
3698;;;
3699;;; Additionally, this implementation provides the
3700;;; <feature-identifier>s `guile' and `r5rs', so that programs can
3701;;; determine the implementation type and the supported standard.
3702;;;
3703;;; Currently, the following feature identifiers are supported:
3704;;;
08b609aa 3705;;; guile r5rs srfi-0 srfi-4 srfi-6 srfi-13 srfi-14 srfi-55 srfi-61
7f24bc58
MG
3706;;;
3707;;; Remember to update the features list when adding more SRFIs.
3d2ada2f 3708;;;
7f24bc58 3709
b9b8f9da 3710(define %cond-expand-features
f41be016 3711 ;; Adjust the above comment when changing this.
018733ff 3712 '(guile
60c8ad9e 3713 guile-2
018733ff
KR
3714 r5rs
3715 srfi-0 ;; cond-expand itself
85acb35f 3716 srfi-4 ;; homogenous numeric vectors
018733ff 3717 srfi-6 ;; open-input-string etc, in the guile core
4a276c08
MV
3718 srfi-13 ;; string library
3719 srfi-14 ;; character sets
9670f238
AW
3720 srfi-23 ;; `error` procedure
3721 srfi-39 ;; parameterize
344d68d5 3722 srfi-55 ;; require-extension
08b609aa 3723 srfi-61 ;; general cond clause
018733ff 3724 ))
1d00af09 3725
b9b8f9da
MG
3726;; This table maps module public interfaces to the list of features.
3727;;
3728(define %cond-expand-table (make-hash-table 31))
3729
3730;; Add one or more features to the `cond-expand' feature list of the
3731;; module `module'.
3732;;
3733(define (cond-expand-provide module features)
3734 (let ((mod (module-public-interface module)))
3735 (and mod
9b5a0d84
AW
3736 (hashq-set! %cond-expand-table mod
3737 (append (hashq-ref %cond-expand-table mod '())
3738 features)))))
b9b8f9da 3739
1fdd5bec
AW
3740(define-syntax cond-expand
3741 (lambda (x)
3742 (define (module-has-feature? mod sym)
3743 (or-map (lambda (mod)
3744 (memq sym (hashq-ref %cond-expand-table mod '())))
3745 (module-uses mod)))
3746
3747 (define (condition-matches? condition)
3748 (syntax-case condition (and or not)
3749 ((and c ...)
3750 (and-map condition-matches? #'(c ...)))
3751 ((or c ...)
3752 (or-map condition-matches? #'(c ...)))
3753 ((not c)
3754 (if (condition-matches? #'c) #f #t))
3755 (c
3756 (identifier? #'c)
3757 (let ((sym (syntax->datum #'c)))
3758 (if (memq sym %cond-expand-features)
3759 #t
3760 (module-has-feature? (current-module) sym))))))
3761
3762 (define (match clauses alternate)
3763 (syntax-case clauses ()
3764 (((condition form ...) . rest)
3765 (if (condition-matches? #'condition)
3766 #'(begin form ...)
3767 (match #'rest alternate)))
3768 (() (alternate))))
3769
3770 (syntax-case x (else)
3771 ((_ clause ... (else form ...))
3772 (match #'(clause ...)
3773 (lambda ()
3774 #'(begin form ...))))
3775 ((_ clause ...)
3776 (match #'(clause ...)
3777 (lambda ()
3778 (syntax-violation 'cond-expand "unfulfilled cond-expand" x)))))))
0f2d19dd 3779
f41be016
MG
3780;; This procedure gets called from the startup code with a list of
3781;; numbers, which are the numbers of the SRFIs to be loaded on startup.
3782;;
3783(define (use-srfis srfis)
9a18d8d4
KR
3784 (process-use-modules
3785 (map (lambda (num)
9b5a0d84
AW
3786 (list (list 'srfi (string->symbol
3787 (string-append "srfi-" (number->string num))))))
3788 srfis)))
f8a502cb 3789
0f2d19dd 3790\f
9d774814 3791
344d68d5
RB
3792;;; srfi-55: require-extension
3793;;;
3794
6669cd81
AW
3795(define-syntax require-extension
3796 (lambda (x)
3797 (syntax-case x (srfi)
3798 ((_ (srfi n ...))
3799 (and-map integer? (syntax->datum #'(n ...)))
3800 (with-syntax
3801 (((srfi-n ...)
3802 (map (lambda (n)
3803 (datum->syntax x (symbol-append 'srfi- n)))
3804 (map string->symbol
3805 (map number->string (syntax->datum #'(n ...)))))))
3806 #'(use-modules (srfi srfi-n) ...)))
3807 ((_ (type arg ...))
3808 (identifier? #'type)
3809 (syntax-violation 'require-extension "Not a recognized extension type"
3810 x)))))
344d68d5
RB
3811
3812\f
165b10dd
AR
3813;;; Defining transparently inlinable procedures
3814;;;
3815
3816(define-syntax define-inlinable
3817 ;; Define a macro and a procedure such that direct calls are inlined, via
3818 ;; the macro expansion, whereas references in non-call contexts refer to
3819 ;; the procedure. Inspired by the `define-integrable' macro by Dybvig et al.
3820 (lambda (x)
3821 ;; Use a space in the prefix to avoid potential -Wunused-toplevel
3822 ;; warning
3823 (define prefix (string->symbol "% "))
3824 (define (make-procedure-name name)
3825 (datum->syntax name
3826 (symbol-append prefix (syntax->datum name)
3827 '-procedure)))
3828
3829 (syntax-case x ()
3830 ((_ (name formals ...) body ...)
3831 (identifier? #'name)
3832 (with-syntax ((proc-name (make-procedure-name #'name))
3833 ((args ...) (generate-temporaries #'(formals ...))))
3834 #`(begin
3835 (define (proc-name formals ...)
449bf60b 3836 (syntax-parameterize ((name (identifier-syntax proc-name)))
2844ab85 3837 body ...))
449bf60b 3838 (define-syntax-parameter name
165b10dd
AR
3839 (lambda (x)
3840 (syntax-case x ()
3841 ((_ args ...)
449bf60b 3842 #'((syntax-parameterize ((name (identifier-syntax proc-name)))
2844ab85
AW
3843 (lambda (formals ...)
3844 body ...))
165b10dd
AR
3845 args ...))
3846 (_
3847 (identifier? x)
3848 #'proc-name))))))))))
3849
3850\f
344d68d5 3851
755457ec
MD
3852(define using-readline?
3853 (let ((using-readline? (make-fluid)))
3854 (make-procedure-with-setter
3855 (lambda () (fluid-ref using-readline?))
3856 (lambda (v) (fluid-set! using-readline? v)))))
3857
4d31f0da 3858\f
3d2ada2f
DH
3859
3860;;; {Deprecated stuff}
3861;;;
3862
3d2ada2f 3863(begin-deprecated
0ea72faa 3864 (module-use! the-scm-module (resolve-interface '(ice-9 deprecated))))
3d2ada2f
DH
3865
3866\f
3867
3868;;; Place the user in the guile-user module.
3869;;;
6eb396fe 3870
a2689737
AW
3871;; FIXME:
3872(module-use! the-scm-module (resolve-interface '(srfi srfi-4)))
3873
7cf64a0a 3874;; Set filename to #f to prevent reload.
68623e8e 3875(define-module (guile-user)
7cf64a0a
AW
3876 #:autoload (system base compile) (compile compile-file)
3877 #:filename #f)
6d36532c 3878
7385dc12
LC
3879;; Remain in the `(guile)' module at compilation-time so that the
3880;; `-Wunused-toplevel' warning works as expected.
3881(eval-when (compile) (set-current-module the-root-module))
3882
20edfbbd 3883;;; boot-9.scm ends here