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