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