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