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