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