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