*** empty log message ***
[bpt/guile.git] / ice-9 / boot-9.scm
CommitLineData
0f2d19dd
JB
1;;; installed-scm-file
2
cf743aea 3;;;; Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002, 2003 Free Software Foundation, Inc.
20edfbbd 4;;;;
73be1d9e
MV
5;;;; This library is free software; you can redistribute it and/or
6;;;; modify it under the terms of the GNU Lesser General Public
7;;;; License as published by the Free Software Foundation; either
8;;;; version 2.1 of the License, or (at your option) any later version.
9;;;;
10;;;; This library is distributed in the hope that it will be useful,
0f2d19dd 11;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
12;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13;;;; Lesser General Public License for more details.
14;;;;
15;;;; You should have received a copy of the GNU Lesser General Public
16;;;; License along with this library; if not, write to the Free Software
17;;;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
a482f2cc 18;;;;
0f2d19dd
JB
19\f
20
20edfbbd
TTN
21;;; Commentary:
22
0f2d19dd
JB
23;;; This file is the first thing loaded into Guile. It adds many mundane
24;;; definitions and a few that are interesting.
25;;;
20edfbbd 26;;; The module system (hence the hierarchical namespace) are defined in this
0f2d19dd
JB
27;;; file.
28;;;
29
20edfbbd
TTN
30;;; Code:
31
0f2d19dd 32\f
9fb41cea
MV
33;;; {Deprecation}
34;;;
35
36;; We don't have macros here, but we do want to define
37;; `begin-deprecated' early.
38
39(define begin-deprecated
40 (procedure->memoizing-macro
41 (lambda (exp env)
42 (if (include-deprecated-features)
43 `(begin ,@(cdr exp))
44 `#f))))
45
46\f
21ed9efe
MD
47;;; {Features}
48;;
49
50(define (provide sym)
51 (if (not (memq sym *features*))
52 (set! *features* (cons sym *features*))))
53
50706e94
JB
54;;; Return #t iff FEATURE is available to this Guile interpreter.
55;;; In SLIB, provided? also checks to see if the module is available.
56;;; We should do that too, but don't.
57(define (provided? feature)
58 (and (memq feature *features*) #t))
59
8c494e99 60(begin-deprecated
f4232aa6
MV
61 (define (feature? sym)
62 (issue-deprecation-warning
63 "`feature?' is deprecated. Use `provided?' instead.")
64 (provided? sym)))
52cfc69b 65
8641dd9e
GB
66;;; let format alias simple-format until the more complete version is loaded
67(define format simple-format)
68
21ed9efe 69\f
79451588
JB
70;;; {R4RS compliance}
71
72(primitive-load-path "ice-9/r4rs.scm")
73
74\f
48fdec21
MV
75;;; {Deprecated stuff}
76
77(begin-deprecated
78 (primitive-load-path "ice-9/deprecated.scm"))
79
80\f
81
44cf1f0f 82;;; {Simple Debugging Tools}
0f2d19dd
JB
83;;
84
85
86;; peek takes any number of arguments, writes them to the
87;; current ouput port, and returns the last argument.
88;; It is handy to wrap around an expression to look at
89;; a value each time is evaluated, e.g.:
90;;
91;; (+ 10 (troublesome-fn))
92;; => (+ 10 (pk 'troublesome-fn-returned (troublesome-fn)))
93;;
94
95(define (peek . stuff)
96 (newline)
97 (display ";;; ")
98 (write stuff)
99 (newline)
100 (car (last-pair stuff)))
101
102(define pk peek)
103
104(define (warn . stuff)
105 (with-output-to-port (current-error-port)
106 (lambda ()
107 (newline)
108 (display ";;; WARNING ")
6355358a 109 (display stuff)
0f2d19dd
JB
110 (newline)
111 (car (last-pair stuff)))))
112
113\f
79451588 114;;; {Trivial Functions}
0f2d19dd 115;;;
79451588 116
6b08d75b 117(define (identity x) x)
79451588 118(define (1+ n) (+ n 1))
5cd06d5e 119(define (1- n) (+ n -1))
132e5fac 120(define (and=> value procedure) (and value (procedure value)))
e8ed460e 121(define call/cc call-with-current-continuation)
79451588 122
5cd06d5e 123;;; apply-to-args is functionally redundant with apply and, worse,
0f2d19dd
JB
124;;; is less general than apply since it only takes two arguments.
125;;;
20edfbbd 126;;; On the other hand, apply-to-args is a syntacticly convenient way to
0f2d19dd
JB
127;;; perform binding in many circumstances when the "let" family of
128;;; of forms don't cut it. E.g.:
129;;;
130;;; (apply-to-args (return-3d-mouse-coords)
20edfbbd 131;;; (lambda (x y z)
0f2d19dd
JB
132;;; ...))
133;;;
134
135(define (apply-to-args args fn) (apply fn args))
136
137\f
6b08d75b 138
0f2d19dd
JB
139;;; {Symbol Properties}
140;;;
141
142(define (symbol-property sym prop)
143 (let ((pair (assoc prop (symbol-pref sym))))
144 (and pair (cdr pair))))
145
146(define (set-symbol-property! sym prop val)
147 (let ((pair (assoc prop (symbol-pref sym))))
148 (if pair
149 (set-cdr! pair val)
150 (symbol-pset! sym (acons prop val (symbol-pref sym))))))
151
152(define (symbol-property-remove! sym prop)
153 (let ((pair (assoc prop (symbol-pref sym))))
154 (if pair
155 (symbol-pset! sym (delq! pair (symbol-pref sym))))))
156
2d55a919 157;;; {General Properties}
5cd06d5e 158;;;
2d55a919
MV
159
160;; This is a more modern interface to properties. It will replace all
161;; other property-like things eventually.
162
163(define (make-object-property)
164 (let ((prop (primitive-make-property #f)))
165 (make-procedure-with-setter
166 (lambda (obj) (primitive-property-ref prop obj))
167 (lambda (obj val) (primitive-property-set! prop obj val)))))
168
0f2d19dd 169\f
1e531c3a 170
0f2d19dd
JB
171;;; {Arrays}
172;;;
173
afe5177e
GH
174(if (provided? 'array)
175 (primitive-load-path "ice-9/arrays.scm"))
0f2d19dd
JB
176
177\f
178;;; {Keywords}
179;;;
180
181(define (symbol->keyword symbol)
182 (make-keyword-from-dash-symbol (symbol-append '- symbol)))
183
184(define (keyword->symbol kw)
06f0414c 185 (let ((sym (symbol->string (keyword-dash-symbol kw))))
11b05261 186 (string->symbol (substring sym 1 (string-length sym)))))
0f2d19dd
JB
187
188(define (kw-arg-ref args kw)
189 (let ((rem (member kw args)))
190 (and rem (pair? (cdr rem)) (cadr rem))))
191
192\f
fa7e9274 193
9f9aa47b 194;;; {Structs}
fa7e9274
MV
195
196(define (struct-layout s)
9f9aa47b 197 (struct-ref (struct-vtable s) vtable-index-layout))
fa7e9274
MV
198
199\f
d7faeb2e
MD
200
201;;; Environments
202
203(define the-environment
204 (procedure->syntax
205 (lambda (x e)
206 e)))
207
208(define the-root-environment (the-environment))
209
210(define (environment-module env)
211 (let ((closure (and (pair? env) (car (last-pair env)))))
212 (and closure (procedure-property closure 'module))))
213
214\f
0f2d19dd
JB
215;;; {Records}
216;;;
217
fa7e9274
MV
218;; Printing records: by default, records are printed as
219;;
220;; #<type-name field1: val1 field2: val2 ...>
221;;
222;; You can change that by giving a custom printing function to
223;; MAKE-RECORD-TYPE (after the list of field symbols). This function
224;; will be called like
225;;
226;; (<printer> object port)
227;;
228;; It should print OBJECT to PORT.
229
cf8f1a90 230(define (inherit-print-state old-port new-port)
8a30733e
MD
231 (if (get-print-state old-port)
232 (port-with-print-state new-port (get-print-state old-port))
cf8f1a90
MV
233 new-port))
234
9f9aa47b 235;; 0: type-name, 1: fields
20edfbbd 236(define record-type-vtable
9f9aa47b
MD
237 (make-vtable-vtable "prpr" 0
238 (lambda (s p)
239 (cond ((eq? s record-type-vtable)
240 (display "#<record-type-vtable>" p))
241 (else
242 (display "#<record-type " p)
243 (display (record-type-name s) p)
244 (display ">" p))))))
0f2d19dd
JB
245
246(define (record-type? obj)
247 (and (struct? obj) (eq? record-type-vtable (struct-vtable obj))))
248
249(define (make-record-type type-name fields . opt)
8e693424 250 (let ((printer-fn (and (pair? opt) (car opt))))
0f2d19dd 251 (let ((struct (make-struct record-type-vtable 0
c7c03b9f 252 (make-struct-layout
06f0414c 253 (apply string-append
c7c03b9f 254 (map (lambda (f) "pw") fields)))
9f9aa47b
MD
255 (or printer-fn
256 (lambda (s p)
257 (display "#<" p)
258 (display type-name p)
259 (let loop ((fields fields)
260 (off 0))
261 (cond
262 ((not (null? fields))
263 (display " " p)
264 (display (car fields) p)
265 (display ": " p)
266 (display (struct-ref s off) p)
267 (loop (cdr fields) (+ 1 off)))))
268 (display ">" p)))
0f2d19dd
JB
269 type-name
270 (copy-tree fields))))
c8eed875
MD
271 ;; Temporary solution: Associate a name to the record type descriptor
272 ;; so that the object system can create a wrapper class for it.
273 (set-struct-vtable-name! struct (if (symbol? type-name)
274 type-name
275 (string->symbol type-name)))
0f2d19dd
JB
276 struct)))
277
278(define (record-type-name obj)
279 (if (record-type? obj)
9f9aa47b 280 (struct-ref obj vtable-offset-user)
0f2d19dd
JB
281 (error 'not-a-record-type obj)))
282
283(define (record-type-fields obj)
284 (if (record-type? obj)
9f9aa47b 285 (struct-ref obj (+ 1 vtable-offset-user))
0f2d19dd
JB
286 (error 'not-a-record-type obj)))
287
288(define (record-constructor rtd . opt)
8e693424 289 (let ((field-names (if (pair? opt) (car opt) (record-type-fields rtd))))
d7faeb2e
MD
290 (local-eval `(lambda ,field-names
291 (make-struct ',rtd 0 ,@(map (lambda (f)
292 (if (memq f field-names)
293 f
294 #f))
295 (record-type-fields rtd))))
296 the-root-environment)))
0f2d19dd
JB
297
298(define (record-predicate rtd)
299 (lambda (obj) (and (struct? obj) (eq? rtd (struct-vtable obj)))))
300
301(define (record-accessor rtd field-name)
302 (let* ((pos (list-index (record-type-fields rtd) field-name)))
303 (if (not pos)
304 (error 'no-such-field field-name))
d7faeb2e
MD
305 (local-eval `(lambda (obj)
306 (and (eq? ',rtd (record-type-descriptor obj))
307 (struct-ref obj ,pos)))
308 the-root-environment)))
0f2d19dd
JB
309
310(define (record-modifier rtd field-name)
311 (let* ((pos (list-index (record-type-fields rtd) field-name)))
312 (if (not pos)
313 (error 'no-such-field field-name))
d7faeb2e
MD
314 (local-eval `(lambda (obj val)
315 (and (eq? ',rtd (record-type-descriptor obj))
316 (struct-set! obj ,pos val)))
317 the-root-environment)))
0f2d19dd
JB
318
319
320(define (record? obj)
321 (and (struct? obj) (record-type? (struct-vtable obj))))
322
323(define (record-type-descriptor obj)
324 (if (struct? obj)
325 (struct-vtable obj)
326 (error 'not-a-record obj)))
327
21ed9efe
MD
328(provide 'record)
329
0f2d19dd
JB
330\f
331;;; {Booleans}
332;;;
333
334(define (->bool x) (not (not x)))
335
336\f
337;;; {Symbols}
338;;;
339
340(define (symbol-append . args)
06f0414c 341 (string->symbol (apply string-append (map symbol->string args))))
0f2d19dd
JB
342
343(define (list->symbol . args)
344 (string->symbol (apply list->string args)))
345
346(define (symbol . args)
347 (string->symbol (apply string args)))
348
0f2d19dd
JB
349\f
350;;; {Lists}
351;;;
352
353(define (list-index l k)
354 (let loop ((n 0)
355 (l l))
356 (and (not (null? l))
357 (if (eq? (car l) k)
358 n
359 (loop (+ n 1) (cdr l))))))
360
75fd4fb6
JB
361(define (make-list n . init)
362 (if (pair? init) (set! init (car init)))
0f2d19dd
JB
363 (let loop ((answer '())
364 (n n))
365 (if (<= n 0)
366 answer
367 (loop (cons init answer) (- n 1)))))
368
1729d8ff 369\f
3e3cec45 370;;; {and-map and or-map}
0f2d19dd
JB
371;;;
372;;; (and-map fn lst) is like (and (fn (car lst)) (fn (cadr lst)) (fn...) ...)
373;;; (or-map fn lst) is like (or (fn (car lst)) (fn (cadr lst)) (fn...) ...)
0f2d19dd
JB
374;;;
375
376;; and-map f l
377;;
378;; Apply f to successive elements of l until exhaustion or f returns #f.
379;; If returning early, return #f. Otherwise, return the last value returned
380;; by f. If f has never been called because l is empty, return #t.
20edfbbd 381;;
0f2d19dd
JB
382(define (and-map f lst)
383 (let loop ((result #t)
384 (l lst))
385 (and result
386 (or (and (null? l)
387 result)
388 (loop (f (car l)) (cdr l))))))
389
390;; or-map f l
391;;
392;; Apply f to successive elements of l until exhaustion or while f returns #f.
393;; If returning early, return the return value of f.
394;;
395(define (or-map f lst)
396 (let loop ((result #f)
397 (l lst))
398 (or result
399 (and (not (null? l))
400 (loop (f (car l)) (cdr l))))))
401
59e1116d 402\f
0f2d19dd 403
52cfc69b
GH
404(if (provided? 'posix)
405 (primitive-load-path "ice-9/posix.scm"))
6fa8995c 406
52cfc69b
GH
407(if (provided? 'socket)
408 (primitive-load-path "ice-9/networking.scm"))
3afb28ce 409
6fa8995c 410(define file-exists?
52cfc69b 411 (if (provided? 'posix)
6fa8995c
GH
412 (lambda (str)
413 (access? str F_OK))
414 (lambda (str)
415 (let ((port (catch 'system-error (lambda () (open-file str OPEN_READ))
416 (lambda args #f))))
417 (if port (begin (close-port port) #t)
418 #f)))))
419
420(define file-is-directory?
52cfc69b 421 (if (provided? 'posix)
6fa8995c 422 (lambda (str)
3afb28ce 423 (eq? (stat:type (stat str)) 'directory))
6fa8995c 424 (lambda (str)
6fa8995c
GH
425 (let ((port (catch 'system-error
426 (lambda () (open-file (string-append str "/.")
427 OPEN_READ))
428 (lambda args #f))))
429 (if port (begin (close-port port) #t)
430 #f)))))
0f2d19dd
JB
431
432(define (has-suffix? str suffix)
433 (let ((sufl (string-length suffix))
434 (sl (string-length str)))
435 (and (> sl sufl)
436 (string=? (substring str (- sl sufl) sl) suffix))))
437
019ac1c9
MV
438(define (system-error-errno args)
439 (if (eq? (car args) 'system-error)
440 (car (list-ref args 4))
441 #f))
442
0f2d19dd
JB
443\f
444;;; {Error Handling}
445;;;
446
0f2d19dd 447(define (error . args)
21ed9efe 448 (save-stack)
2194b6f0 449 (if (null? args)
5552355a 450 (scm-error 'misc-error #f "?" #f #f)
8641dd9e 451 (let loop ((msg "~A")
2194b6f0
GH
452 (rest (cdr args)))
453 (if (not (null? rest))
8641dd9e 454 (loop (string-append msg " ~S")
2194b6f0 455 (cdr rest))
5552355a 456 (scm-error 'misc-error #f msg args #f)))))
be2d2c70 457
1349bd53 458;; bad-throw is the hook that is called upon a throw to a an unhandled
9a0d70e2
GH
459;; key (unless the throw has four arguments, in which case
460;; it's usually interpreted as an error throw.)
461;; If the key has a default handler (a throw-handler-default property),
0f2d19dd
JB
462;; it is applied to the throw.
463;;
1349bd53 464(define (bad-throw key . args)
0f2d19dd
JB
465 (let ((default (symbol-property key 'throw-handler-default)))
466 (or (and default (apply default key args))
2194b6f0 467 (apply error "unhandled-exception:" key args))))
0f2d19dd 468
0f2d19dd 469\f
bce074ee 470
708bf0f3
GH
471(define (tm:sec obj) (vector-ref obj 0))
472(define (tm:min obj) (vector-ref obj 1))
473(define (tm:hour obj) (vector-ref obj 2))
474(define (tm:mday obj) (vector-ref obj 3))
475(define (tm:mon obj) (vector-ref obj 4))
476(define (tm:year obj) (vector-ref obj 5))
477(define (tm:wday obj) (vector-ref obj 6))
478(define (tm:yday obj) (vector-ref obj 7))
479(define (tm:isdst obj) (vector-ref obj 8))
480(define (tm:gmtoff obj) (vector-ref obj 9))
481(define (tm:zone obj) (vector-ref obj 10))
482
483(define (set-tm:sec obj val) (vector-set! obj 0 val))
484(define (set-tm:min obj val) (vector-set! obj 1 val))
485(define (set-tm:hour obj val) (vector-set! obj 2 val))
486(define (set-tm:mday obj val) (vector-set! obj 3 val))
487(define (set-tm:mon obj val) (vector-set! obj 4 val))
488(define (set-tm:year obj val) (vector-set! obj 5 val))
489(define (set-tm:wday obj val) (vector-set! obj 6 val))
490(define (set-tm:yday obj val) (vector-set! obj 7 val))
491(define (set-tm:isdst obj val) (vector-set! obj 8 val))
492(define (set-tm:gmtoff obj val) (vector-set! obj 9 val))
493(define (set-tm:zone obj val) (vector-set! obj 10 val))
494
6afcd3b2
GH
495(define (tms:clock obj) (vector-ref obj 0))
496(define (tms:utime obj) (vector-ref obj 1))
497(define (tms:stime obj) (vector-ref obj 2))
498(define (tms:cutime obj) (vector-ref obj 3))
499(define (tms:cstime obj) (vector-ref obj 4))
500
1334c61a
GH
501(define file-position ftell)
502(define (file-set-position port offset . whence)
503 (let ((whence (if (eq? whence '()) SEEK_SET (car whence))))
504 (seek port offset whence)))
8b13c6b3 505
e38303a2
GH
506(define (move->fdes fd/port fd)
507 (cond ((integer? fd/port)
7a6f1ffa 508 (dup->fdes fd/port fd)
e38303a2
GH
509 (close fd/port)
510 fd)
511 (else
512 (primitive-move->fdes fd/port fd)
513 (set-port-revealed! fd/port 1)
514 fd/port)))
8b13c6b3
GH
515
516(define (release-port-handle port)
517 (let ((revealed (port-revealed port)))
518 (if (> revealed 0)
519 (set-port-revealed! port (- revealed 1)))))
0f2d19dd 520
e38303a2 521(define (dup->port port/fd mode . maybe-fd)
7a6f1ffa 522 (let ((port (fdopen (apply dup->fdes port/fd maybe-fd)
e38303a2
GH
523 mode)))
524 (if (pair? maybe-fd)
525 (set-port-revealed! port 1))
526 port))
20edfbbd 527
e38303a2
GH
528(define (dup->inport port/fd . maybe-fd)
529 (apply dup->port port/fd "r" maybe-fd))
530
531(define (dup->outport port/fd . maybe-fd)
532 (apply dup->port port/fd "w" maybe-fd))
533
e38303a2
GH
534(define (dup port/fd . maybe-fd)
535 (if (integer? port/fd)
536 (apply dup->fdes port/fd maybe-fd)
537 (apply dup->port port/fd (port-mode port/fd) maybe-fd)))
538
539(define (duplicate-port port modes)
540 (dup->port port modes))
541
542(define (fdes->inport fdes)
543 (let loop ((rest-ports (fdes->ports fdes)))
544 (cond ((null? rest-ports)
545 (let ((result (fdopen fdes "r")))
546 (set-port-revealed! result 1)
547 result))
548 ((input-port? (car rest-ports))
549 (set-port-revealed! (car rest-ports)
550 (+ (port-revealed (car rest-ports)) 1))
551 (car rest-ports))
552 (else
553 (loop (cdr rest-ports))))))
554
555(define (fdes->outport fdes)
556 (let loop ((rest-ports (fdes->ports fdes)))
557 (cond ((null? rest-ports)
558 (let ((result (fdopen fdes "w")))
559 (set-port-revealed! result 1)
560 result))
561 ((output-port? (car rest-ports))
562 (set-port-revealed! (car rest-ports)
563 (+ (port-revealed (car rest-ports)) 1))
564 (car rest-ports))
565 (else
566 (loop (cdr rest-ports))))))
567
568(define (port->fdes port)
569 (set-port-revealed! port (+ (port-revealed port) 1))
570 (fileno port))
571
956055a9
GH
572(define (setenv name value)
573 (if value
574 (putenv (string-append name "=" value))
575 (putenv name)))
576
5c1254da
MV
577(define (unsetenv name)
578 "Remove the entry for NAME from the environment."
579 (putenv name))
580
0f2d19dd
JB
581\f
582;;; {Load Paths}
583;;;
584
0f2d19dd
JB
585;;; Here for backward compatability
586;;
587(define scheme-file-suffix (lambda () ".scm"))
588
3cab8392
JB
589(define (in-vicinity vicinity file)
590 (let ((tail (let ((len (string-length vicinity)))
534a0099
MD
591 (if (zero? len)
592 #f
3cab8392
JB
593 (string-ref vicinity (- len 1))))))
594 (string-append vicinity
534a0099
MD
595 (if (or (not tail)
596 (eq? tail #\/))
597 ""
598 "/")
3cab8392 599 file)))
02ceadb8 600
0f2d19dd 601\f
ef00e7f4
JB
602;;; {Help for scm_shell}
603;;; The argument-processing code used by Guile-based shells generates
604;;; Scheme code based on the argument list. This page contains help
605;;; functions for the code it generates.
606
ef00e7f4
JB
607(define (command-line) (program-arguments))
608
5aa7fe69
JB
609;; This is mostly for the internal use of the code generated by
610;; scm_compile_shell_switches.
eef6519b
MV
611
612(define (turn-on-debugging)
613 (debug-enable 'debug)
614 (debug-enable 'backtrace)
615 (read-enable 'positions))
4eecfeb7 616
ef00e7f4 617(define (load-user-init)
1f08acd9
GH
618 (let* ((home (or (getenv "HOME")
619 (false-if-exception (passwd:dir (getpwuid (getuid))))
620 "/")) ;; fallback for cygwin etc.
621 (init-file (in-vicinity home ".guile")))
622 (if (file-exists? init-file)
623 (primitive-load init-file))))
ef00e7f4
JB
624
625\f
a06181a2
JB
626;;; {Loading by paths}
627
628;;; Load a Scheme source file named NAME, searching for it in the
629;;; directories listed in %load-path, and applying each of the file
630;;; name extensions listed in %load-extensions.
631(define (load-from-path name)
632 (start-stack 'load-stack
75a97b92 633 (primitive-load-path name)))
0f2d19dd 634
5552355a 635
0f2d19dd 636\f
0f2d19dd
JB
637;;; {Transcendental Functions}
638;;;
639;;; Derived from "Transcen.scm", Complex trancendental functions for SCM.
0543c9b7 640;;; Written by Jerry D. Hedden, (C) FSF.
0f2d19dd
JB
641;;; See the file `COPYING' for terms applying to this program.
642;;;
643
644(define (exp z)
645 (if (real? z) ($exp z)
646 (make-polar ($exp (real-part z)) (imag-part z))))
647
648(define (log z)
649 (if (and (real? z) (>= z 0))
650 ($log z)
651 (make-rectangular ($log (magnitude z)) (angle z))))
652
653(define (sqrt z)
654 (if (real? z)
655 (if (negative? z) (make-rectangular 0 ($sqrt (- z)))
0ac6420c 656 ($sqrt z))
0f2d19dd
JB
657 (make-polar ($sqrt (magnitude z)) (/ (angle z) 2))))
658
659(define expt
660 (let ((integer-expt integer-expt))
661 (lambda (z1 z2)
22381005 662 (cond ((integer? z2)
0ad7cc4f
RB
663 (if (negative? z2)
664 (/ 1 (integer-expt z1 (- z2)))
665 (integer-expt z1 z2)))
0f2d19dd
JB
666 ((and (real? z2) (real? z1) (>= z1 0))
667 ($expt z1 z2))
668 (else
669 (exp (* z2 (log z1))))))))
670
671(define (sinh z)
672 (if (real? z) ($sinh z)
673 (let ((x (real-part z)) (y (imag-part z)))
674 (make-rectangular (* ($sinh x) ($cos y))
675 (* ($cosh x) ($sin y))))))
676(define (cosh z)
677 (if (real? z) ($cosh z)
678 (let ((x (real-part z)) (y (imag-part z)))
679 (make-rectangular (* ($cosh x) ($cos y))
680 (* ($sinh x) ($sin y))))))
681(define (tanh z)
682 (if (real? z) ($tanh z)
683 (let* ((x (* 2 (real-part z)))
684 (y (* 2 (imag-part z)))
685 (w (+ ($cosh x) ($cos y))))
686 (make-rectangular (/ ($sinh x) w) (/ ($sin y) w)))))
687
688(define (asinh z)
689 (if (real? z) ($asinh z)
690 (log (+ z (sqrt (+ (* z z) 1))))))
691
692(define (acosh z)
693 (if (and (real? z) (>= z 1))
694 ($acosh z)
695 (log (+ z (sqrt (- (* z z) 1))))))
696
697(define (atanh z)
698 (if (and (real? z) (> z -1) (< z 1))
699 ($atanh z)
700 (/ (log (/ (+ 1 z) (- 1 z))) 2)))
701
702(define (sin z)
703 (if (real? z) ($sin z)
704 (let ((x (real-part z)) (y (imag-part z)))
705 (make-rectangular (* ($sin x) ($cosh y))
706 (* ($cos x) ($sinh y))))))
707(define (cos z)
708 (if (real? z) ($cos z)
709 (let ((x (real-part z)) (y (imag-part z)))
710 (make-rectangular (* ($cos x) ($cosh y))
711 (- (* ($sin x) ($sinh y)))))))
712(define (tan z)
713 (if (real? z) ($tan z)
714 (let* ((x (* 2 (real-part z)))
715 (y (* 2 (imag-part z)))
716 (w (+ ($cos x) ($cosh y))))
717 (make-rectangular (/ ($sin x) w) (/ ($sinh y) w)))))
718
719(define (asin z)
720 (if (and (real? z) (>= z -1) (<= z 1))
721 ($asin z)
722 (* -i (asinh (* +i z)))))
723
724(define (acos z)
725 (if (and (real? z) (>= z -1) (<= z 1))
726 ($acos z)
727 (+ (/ (angle -1) 2) (* +i (asinh (* +i z))))))
728
729(define (atan z . y)
730 (if (null? y)
731 (if (real? z) ($atan z)
732 (/ (log (/ (- +i z) (+ +i z))) +2i))
733 ($atan2 z (car y))))
734
65495221
GH
735(define (log10 arg)
736 (/ (log arg) (log 10)))
737
0f2d19dd 738\f
0f2d19dd
JB
739
740;;; {Reader Extensions}
741;;;
742
743;;; Reader code for various "#c" forms.
744;;;
745
75a97b92
GH
746(read-hash-extend #\' (lambda (c port)
747 (read port)))
600c9584
RB
748
749(define read-eval? (make-fluid))
750(fluid-set! read-eval? #f)
751(read-hash-extend #\.
752 (lambda (c port)
753 (if (fluid-ref read-eval?)
754 (eval (read port) (interaction-environment))
755 (error
71335c0d 756 "#. read expansion found and read-eval? is #f."))))
75a97b92 757
0f2d19dd
JB
758\f
759;;; {Command Line Options}
760;;;
761
762(define (get-option argv kw-opts kw-args return)
763 (cond
764 ((null? argv)
765 (return #f #f argv))
766
767 ((or (not (eq? #\- (string-ref (car argv) 0)))
768 (eq? (string-length (car argv)) 1))
769 (return 'normal-arg (car argv) (cdr argv)))
770
771 ((eq? #\- (string-ref (car argv) 1))
772 (let* ((kw-arg-pos (or (string-index (car argv) #\=)
773 (string-length (car argv))))
774 (kw (symbol->keyword (substring (car argv) 2 kw-arg-pos)))
775 (kw-opt? (member kw kw-opts))
776 (kw-arg? (member kw kw-args))
777 (arg (or (and (not (eq? kw-arg-pos (string-length (car argv))))
778 (substring (car argv)
779 (+ kw-arg-pos 1)
780 (string-length (car argv))))
781 (and kw-arg?
782 (begin (set! argv (cdr argv)) (car argv))))))
783 (if (or kw-opt? kw-arg?)
784 (return kw arg (cdr argv))
785 (return 'usage-error kw (cdr argv)))))
786
787 (else
788 (let* ((char (substring (car argv) 1 2))
789 (kw (symbol->keyword char)))
790 (cond
791
792 ((member kw kw-opts)
793 (let* ((rest-car (substring (car argv) 2 (string-length (car argv))))
794 (new-argv (if (= 0 (string-length rest-car))
795 (cdr argv)
796 (cons (string-append "-" rest-car) (cdr argv)))))
797 (return kw #f new-argv)))
798
799 ((member kw kw-args)
800 (let* ((rest-car (substring (car argv) 2 (string-length (car argv))))
801 (arg (if (= 0 (string-length rest-car))
802 (cadr argv)
803 rest-car))
804 (new-argv (if (= 0 (string-length rest-car))
805 (cddr argv)
806 (cdr argv))))
807 (return kw arg new-argv)))
808
809 (else (return 'usage-error kw argv)))))))
810
811(define (for-next-option proc argv kw-opts kw-args)
812 (let loop ((argv argv))
813 (get-option argv kw-opts kw-args
814 (lambda (opt opt-arg argv)
815 (and opt (proc opt opt-arg argv loop))))))
816
817(define (display-usage-report kw-desc)
818 (for-each
819 (lambda (kw)
820 (or (eq? (car kw) #t)
821 (eq? (car kw) 'else)
822 (let* ((opt-desc kw)
823 (help (cadr opt-desc))
824 (opts (car opt-desc))
825 (opts-proper (if (string? (car opts)) (cdr opts) opts))
826 (arg-name (if (string? (car opts))
827 (string-append "<" (car opts) ">")
828 ""))
829 (left-part (string-append
830 (with-output-to-string
831 (lambda ()
832 (map (lambda (x) (display (keyword-symbol x)) (display " "))
833 opts-proper)))
834 arg-name))
11b05261
MD
835 (middle-part (if (and (< (string-length left-part) 30)
836 (< (string-length help) 40))
837 (make-string (- 30 (string-length left-part)) #\ )
0f2d19dd
JB
838 "\n\t")))
839 (display left-part)
840 (display middle-part)
841 (display help)
842 (newline))))
843 kw-desc))
0f2d19dd 844
20edfbbd
TTN
845
846
0f2d19dd
JB
847(define (transform-usage-lambda cases)
848 (let* ((raw-usage (delq! 'else (map car cases)))
849 (usage-sans-specials (map (lambda (x)
850 (or (and (not (list? x)) x)
851 (and (symbol? (car x)) #t)
852 (and (boolean? (car x)) #t)
853 x))
854 raw-usage))
ed440df5 855 (usage-desc (delq! #t usage-sans-specials))
0f2d19dd
JB
856 (kw-desc (map car usage-desc))
857 (kw-opts (apply append (map (lambda (x) (and (not (string? (car x))) x)) kw-desc)))
858 (kw-args (apply append (map (lambda (x) (and (string? (car x)) (cdr x))) kw-desc)))
859 (transmogrified-cases (map (lambda (case)
860 (cons (let ((opts (car case)))
861 (if (or (boolean? opts) (eq? 'else opts))
862 opts
863 (cond
864 ((symbol? (car opts)) opts)
865 ((boolean? (car opts)) opts)
866 ((string? (caar opts)) (cdar opts))
867 (else (car opts)))))
868 (cdr case)))
869 cases)))
870 `(let ((%display-usage (lambda () (display-usage-report ',usage-desc))))
871 (lambda (%argv)
872 (let %next-arg ((%argv %argv))
873 (get-option %argv
874 ',kw-opts
875 ',kw-args
876 (lambda (%opt %arg %new-argv)
877 (case %opt
878 ,@ transmogrified-cases))))))))
879
880
881\f
882
883;;; {Low Level Modules}
884;;;
885;;; These are the low level data structures for modules.
886;;;
887;;; !!! warning: The interface to lazy binder procedures is going
888;;; to be changed in an incompatible way to permit all the basic
889;;; module ops to be virtualized.
890;;;
891;;; (make-module size use-list lazy-binding-proc) => module
892;;; module-{obarray,uses,binder}[|-set!]
893;;; (module? obj) => [#t|#f]
894;;; (module-locally-bound? module symbol) => [#t|#f]
895;;; (module-bound? module symbol) => [#t|#f]
896;;; (module-symbol-locally-interned? module symbol) => [#t|#f]
897;;; (module-symbol-interned? module symbol) => [#t|#f]
898;;; (module-local-variable module symbol) => [#<variable ...> | #f]
899;;; (module-variable module symbol) => [#<variable ...> | #f]
900;;; (module-symbol-binding module symbol opt-value)
901;;; => [ <obj> | opt-value | an error occurs ]
902;;; (module-make-local-var! module symbol) => #<variable...>
903;;; (module-add! module symbol var) => unspecified
904;;; (module-remove! module symbol) => unspecified
905;;; (module-for-each proc module) => unspecified
906;;; (make-scm-module) => module ; a lazy copy of the symhash module
907;;; (set-current-module module) => unspecified
908;;; (current-module) => #<module...>
909;;;
910;;;
911
912\f
44cf1f0f
JB
913;;; {Printing Modules}
914;; This is how modules are printed. You can re-define it.
fa7e9274
MV
915;; (Redefining is actually more complicated than simply redefining
916;; %print-module because that would only change the binding and not
917;; the value stored in the vtable that determines how record are
918;; printed. Sigh.)
919
920(define (%print-module mod port) ; unused args: depth length style table)
0f2d19dd
JB
921 (display "#<" port)
922 (display (or (module-kind mod) "module") port)
923 (let ((name (module-name mod)))
924 (if name
925 (begin
926 (display " " port)
927 (display name port))))
928 (display " " port)
929 (display (number->string (object-address mod) 16) port)
930 (display ">" port))
931
932;; module-type
933;;
934;; A module is characterized by an obarray in which local symbols
935;; are interned, a list of modules, "uses", from which non-local
936;; bindings can be inherited, and an optional lazy-binder which
31d50456 937;; is a (CLOSURE module symbol) which, as a last resort, can provide
0f2d19dd
JB
938;; bindings that would otherwise not be found locally in the module.
939;;
d7faeb2e
MD
940;; NOTE: If you change here, you also need to change libguile/modules.h.
941;;
0f2d19dd 942(define module-type
7a0ff2f8 943 (make-record-type 'module
1777c18b 944 '(obarray uses binder eval-closure transformer name kind
8d8dac1f
MD
945 duplicates-handlers duplicates-interface
946 observers weak-observers observer-id)
8b718458 947 %print-module))
0f2d19dd 948
8b718458 949;; make-module &opt size uses binder
0f2d19dd 950;;
8b718458
JB
951;; Create a new module, perhaps with a particular size of obarray,
952;; initial uses list, or binding procedure.
0f2d19dd 953;;
0f2d19dd
JB
954(define make-module
955 (lambda args
0f2d19dd 956
8b718458
JB
957 (define (parse-arg index default)
958 (if (> (length args) index)
959 (list-ref args index)
960 default))
961
962 (if (> (length args) 3)
963 (error "Too many args to make-module." args))
0f2d19dd 964
231a4ea8 965 (let ((size (parse-arg 0 31))
8b718458
JB
966 (uses (parse-arg 1 '()))
967 (binder (parse-arg 2 #f)))
0f2d19dd 968
8b718458
JB
969 (if (not (integer? size))
970 (error "Illegal size to make-module." size))
971 (if (not (and (list? uses)
972 (and-map module? uses)))
973 (error "Incorrect use list." uses))
0f2d19dd
JB
974 (if (and binder (not (procedure? binder)))
975 (error
976 "Lazy-binder expected to be a procedure or #f." binder))
977
231a4ea8
MD
978 (let ((module (module-constructor (and (not (zero? size))
979 (make-hash-table size))
8d8dac1f 980 uses binder #f #f #f #f #f #f
1777c18b
MD
981 '()
982 (make-weak-value-hash-table 31)
983 0)))
8b718458
JB
984
985 ;; We can't pass this as an argument to module-constructor,
986 ;; because we need it to close over a pointer to the module
987 ;; itself.
6906bd0d 988 (set-module-eval-closure! module (standard-eval-closure module))
8b718458
JB
989
990 module))))
0f2d19dd 991
8b718458 992(define module-constructor (record-constructor module-type))
0f2d19dd
JB
993(define module-obarray (record-accessor module-type 'obarray))
994(define set-module-obarray! (record-modifier module-type 'obarray))
995(define module-uses (record-accessor module-type 'uses))
996(define set-module-uses! (record-modifier module-type 'uses))
997(define module-binder (record-accessor module-type 'binder))
998(define set-module-binder! (record-modifier module-type 'binder))
631c1902
MD
999
1000;; NOTE: This binding is used in libguile/modules.c.
31d50456 1001(define module-eval-closure (record-accessor module-type 'eval-closure))
631c1902 1002
7a0ff2f8
MD
1003(define module-transformer (record-accessor module-type 'transformer))
1004(define set-module-transformer! (record-modifier module-type 'transformer))
0f2d19dd
JB
1005(define module-name (record-accessor module-type 'name))
1006(define set-module-name! (record-modifier module-type 'name))
1007(define module-kind (record-accessor module-type 'kind))
1008(define set-module-kind! (record-modifier module-type 'kind))
8d8dac1f
MD
1009(define module-duplicates-handlers
1010 (record-accessor module-type 'duplicates-handlers))
1011(define set-module-duplicates-handlers!
1012 (record-modifier module-type 'duplicates-handlers))
1013(define module-duplicates-interface
1014 (record-accessor module-type 'duplicates-interface))
1015(define set-module-duplicates-interface!
1016 (record-modifier module-type 'duplicates-interface))
1777c18b
MD
1017(define module-observers (record-accessor module-type 'observers))
1018(define set-module-observers! (record-modifier module-type 'observers))
1019(define module-weak-observers (record-accessor module-type 'weak-observers))
1020(define module-observer-id (record-accessor module-type 'observer-id))
1021(define set-module-observer-id! (record-modifier module-type 'observer-id))
0f2d19dd
JB
1022(define module? (record-predicate module-type))
1023
edc185c7
MD
1024(define set-module-eval-closure!
1025 (let ((setter (record-modifier module-type 'eval-closure)))
1026 (lambda (module closure)
1027 (setter module closure)
1028 ;; Make it possible to lookup the module from the environment.
1029 ;; This implementation is correct since an eval closure can belong
1030 ;; to maximally one module.
1031 (set-procedure-property! closure 'module module))))
8b718458 1032
0f2d19dd 1033\f
1777c18b
MD
1034;;; {Observer protocol}
1035;;;
1036
1037(define (module-observe module proc)
1038 (set-module-observers! module (cons proc (module-observers module)))
1039 (cons module proc))
1040
1041(define (module-observe-weak module proc)
1042 (let ((id (module-observer-id module)))
1043 (hash-set! (module-weak-observers module) id proc)
1044 (set-module-observer-id! module (+ 1 id))
1045 (cons module id)))
1046
1047(define (module-unobserve token)
1048 (let ((module (car token))
1049 (id (cdr token)))
1050 (if (integer? id)
1051 (hash-remove! (module-weak-observers module) id)
1052 (set-module-observers! module (delq1! id (module-observers module)))))
1053 *unspecified*)
1054
d57da08b
MD
1055(define module-defer-observers #f)
1056(define module-defer-observers-mutex (make-mutex))
1057(define module-defer-observers-table (make-hash-table))
1058
1a961d7e 1059(define (module-modified m)
d57da08b
MD
1060 (if module-defer-observers
1061 (hash-set! module-defer-observers-table m #t)
1062 (module-call-observers m)))
1063
1064;;; This function can be used to delay calls to observers so that they
1065;;; can be called once only in the face of massive updating of modules.
1066;;;
1067(define (call-with-deferred-observers thunk)
1068 (dynamic-wind
1069 (lambda ()
1070 (lock-mutex module-defer-observers-mutex)
1071 (set! module-defer-observers #t))
1072 thunk
1073 (lambda ()
1074 (set! module-defer-observers #f)
1075 (hash-for-each (lambda (m dummy)
1076 (module-call-observers m))
1077 module-defer-observers-table)
1078 (hash-clear! module-defer-observers-table)
1079 (unlock-mutex module-defer-observers-mutex))))
1080
1081(define (module-call-observers m)
1777c18b
MD
1082 (for-each (lambda (proc) (proc m)) (module-observers m))
1083 (hash-fold (lambda (id proc res) (proc m)) #f (module-weak-observers m)))
1084
1085\f
0f2d19dd
JB
1086;;; {Module Searching in General}
1087;;;
1088;;; We sometimes want to look for properties of a symbol
1089;;; just within the obarray of one module. If the property
1090;;; holds, then it is said to hold ``locally'' as in, ``The symbol
1091;;; DISPLAY is locally rebound in the module `safe-guile'.''
1092;;;
1093;;;
1094;;; Other times, we want to test for a symbol property in the obarray
1095;;; of M and, if it is not found there, try each of the modules in the
1096;;; uses list of M. This is the normal way of testing for some
1097;;; property, so we state these properties without qualification as
1098;;; in: ``The symbol 'fnord is interned in module M because it is
1099;;; interned locally in module M2 which is a member of the uses list
1100;;; of M.''
1101;;;
1102
1103;; module-search fn m
20edfbbd 1104;;
0f2d19dd
JB
1105;; return the first non-#f result of FN applied to M and then to
1106;; the modules in the uses of m, and so on recursively. If all applications
1107;; return #f, then so does this function.
1108;;
1109(define (module-search fn m v)
1110 (define (loop pos)
1111 (and (pair? pos)
1112 (or (module-search fn (car pos) v)
1113 (loop (cdr pos)))))
1114 (or (fn m v)
1115 (loop (module-uses m))))
1116
1117
1118;;; {Is a symbol bound in a module?}
1119;;;
1120;;; Symbol S in Module M is bound if S is interned in M and if the binding
1121;;; of S in M has been set to some well-defined value.
1122;;;
1123
1124;; module-locally-bound? module symbol
1125;;
1126;; Is a symbol bound (interned and defined) locally in a given module?
1127;;
1128(define (module-locally-bound? m v)
1129 (let ((var (module-local-variable m v)))
1130 (and var
1131 (variable-bound? var))))
1132
1133;; module-bound? module symbol
1134;;
1135;; Is a symbol bound (interned and defined) anywhere in a given module
1136;; or its uses?
1137;;
1138(define (module-bound? m v)
1139 (module-search module-locally-bound? m v))
1140
1141;;; {Is a symbol interned in a module?}
1142;;;
20edfbbd 1143;;; Symbol S in Module M is interned if S occurs in
0f2d19dd
JB
1144;;; of S in M has been set to some well-defined value.
1145;;;
1146;;; It is possible to intern a symbol in a module without providing
1147;;; an initial binding for the corresponding variable. This is done
1148;;; with:
1149;;; (module-add! module symbol (make-undefined-variable))
1150;;;
1151;;; In that case, the symbol is interned in the module, but not
1152;;; bound there. The unbound symbol shadows any binding for that
1153;;; symbol that might otherwise be inherited from a member of the uses list.
1154;;;
1155
1156(define (module-obarray-get-handle ob key)
1157 ((if (symbol? key) hashq-get-handle hash-get-handle) ob key))
1158
1159(define (module-obarray-ref ob key)
1160 ((if (symbol? key) hashq-ref hash-ref) ob key))
1161
1162(define (module-obarray-set! ob key val)
1163 ((if (symbol? key) hashq-set! hash-set!) ob key val))
1164
1165(define (module-obarray-remove! ob key)
1166 ((if (symbol? key) hashq-remove! hash-remove!) ob key))
1167
1168;; module-symbol-locally-interned? module symbol
20edfbbd 1169;;
0f2d19dd
JB
1170;; is a symbol interned (not neccessarily defined) locally in a given module
1171;; or its uses? Interned symbols shadow inherited bindings even if
1172;; they are not themselves bound to a defined value.
1173;;
1174(define (module-symbol-locally-interned? m v)
1175 (not (not (module-obarray-get-handle (module-obarray m) v))))
1176
1177;; module-symbol-interned? module symbol
20edfbbd 1178;;
0f2d19dd
JB
1179;; is a symbol interned (not neccessarily defined) anywhere in a given module
1180;; or its uses? Interned symbols shadow inherited bindings even if
1181;; they are not themselves bound to a defined value.
1182;;
1183(define (module-symbol-interned? m v)
1184 (module-search module-symbol-locally-interned? m v))
1185
1186
1187;;; {Mapping modules x symbols --> variables}
1188;;;
1189
1190;; module-local-variable module symbol
1191;; return the local variable associated with a MODULE and SYMBOL.
1192;;
1193;;; This function is very important. It is the only function that can
1194;;; return a variable from a module other than the mutators that store
1195;;; new variables in modules. Therefore, this function is the location
1196;;; of the "lazy binder" hack.
1197;;;
1198;;; If symbol is defined in MODULE, and if the definition binds symbol
1199;;; to a variable, return that variable object.
1200;;;
1201;;; If the symbols is not found at first, but the module has a lazy binder,
1202;;; then try the binder.
1203;;;
1204;;; If the symbol is not found at all, return #f.
1205;;;
1206(define (module-local-variable m v)
6fa8995c
GH
1207; (caddr
1208; (list m v
0f2d19dd
JB
1209 (let ((b (module-obarray-ref (module-obarray m) v)))
1210 (or (and (variable? b) b)
1211 (and (module-binder m)
6fa8995c
GH
1212 ((module-binder m) m v #f)))))
1213;))
0f2d19dd
JB
1214
1215;; module-variable module symbol
20edfbbd
TTN
1216;;
1217;; like module-local-variable, except search the uses in the
0f2d19dd
JB
1218;; case V is not found in M.
1219;;
6906bd0d
MD
1220;; NOTE: This function is superseded with C code (see modules.c)
1221;;; when using the standard eval closure.
1222;;
0f2d19dd
JB
1223(define (module-variable m v)
1224 (module-search module-local-variable m v))
1225
1226
1227;;; {Mapping modules x symbols --> bindings}
1228;;;
1229;;; These are similar to the mapping to variables, except that the
1230;;; variable is dereferenced.
1231;;;
1232
1233;; module-symbol-binding module symbol opt-value
20edfbbd 1234;;
0f2d19dd
JB
1235;; return the binding of a variable specified by name within
1236;; a given module, signalling an error if the variable is unbound.
1237;; If the OPT-VALUE is passed, then instead of signalling an error,
1238;; return OPT-VALUE.
1239;;
1240(define (module-symbol-local-binding m v . opt-val)
1241 (let ((var (module-local-variable m v)))
7b07e5ef 1242 (if (and var (variable-bound? var))
0f2d19dd
JB
1243 (variable-ref var)
1244 (if (not (null? opt-val))
1245 (car opt-val)
1246 (error "Locally unbound variable." v)))))
1247
1248;; module-symbol-binding module symbol opt-value
20edfbbd 1249;;
0f2d19dd
JB
1250;; return the binding of a variable specified by name within
1251;; a given module, signalling an error if the variable is unbound.
1252;; If the OPT-VALUE is passed, then instead of signalling an error,
1253;; return OPT-VALUE.
1254;;
1255(define (module-symbol-binding m v . opt-val)
1256 (let ((var (module-variable m v)))
7b07e5ef 1257 (if (and var (variable-bound? var))
0f2d19dd
JB
1258 (variable-ref var)
1259 (if (not (null? opt-val))
1260 (car opt-val)
1261 (error "Unbound variable." v)))))
1262
1263
1264\f
1265;;; {Adding Variables to Modules}
1266;;;
1267;;;
1268
1269
1270;; module-make-local-var! module symbol
20edfbbd 1271;;
0f2d19dd
JB
1272;; ensure a variable for V in the local namespace of M.
1273;; If no variable was already there, then create a new and uninitialzied
1274;; variable.
1275;;
d57da08b
MD
1276;; This function is used in modules.c.
1277;;
0f2d19dd
JB
1278(define (module-make-local-var! m v)
1279 (or (let ((b (module-obarray-ref (module-obarray m) v)))
1777c18b
MD
1280 (and (variable? b)
1281 (begin
d57da08b
MD
1282 ;; Mark as modified since this function is called when
1283 ;; the standard eval closure defines a binding
1a961d7e 1284 (module-modified m)
1777c18b 1285 b)))
0f2d19dd
JB
1286 (and (module-binder m)
1287 ((module-binder m) m v #t))
1288 (begin
296ff5e7 1289 (let ((answer (make-undefined-variable)))
d57da08b 1290 (module-add! m v answer)
0f2d19dd
JB
1291 answer))))
1292
89d06712 1293;; module-ensure-local-variable! module symbol
9540368e 1294;;
89d06712
MV
1295;; Ensure that there is a local variable in MODULE for SYMBOL. If
1296;; there is no binding for SYMBOL, create a new uninitialized
1297;; variable. Return the local variable.
9540368e 1298;;
89d06712
MV
1299(define (module-ensure-local-variable! module symbol)
1300 (or (module-local-variable module symbol)
9540368e 1301 (let ((var (make-undefined-variable)))
9540368e
MV
1302 (module-add! module symbol var)
1303 var)))
1304
0f2d19dd 1305;; module-add! module symbol var
20edfbbd 1306;;
0f2d19dd
JB
1307;; ensure a particular variable for V in the local namespace of M.
1308;;
1309(define (module-add! m v var)
1310 (if (not (variable? var))
1311 (error "Bad variable to module-add!" var))
1777c18b 1312 (module-obarray-set! (module-obarray m) v var)
1a961d7e 1313 (module-modified m))
0f2d19dd 1314
20edfbbd
TTN
1315;; module-remove!
1316;;
0f2d19dd
JB
1317;; make sure that a symbol is undefined in the local namespace of M.
1318;;
1319(define (module-remove! m v)
c35738c1 1320 (module-obarray-remove! (module-obarray m) v)
1a961d7e 1321 (module-modified m))
0f2d19dd
JB
1322
1323(define (module-clear! m)
c35738c1 1324 (hash-clear! (module-obarray m))
1a961d7e 1325 (module-modified m))
0f2d19dd
JB
1326
1327;; MODULE-FOR-EACH -- exported
20edfbbd 1328;;
0f2d19dd
JB
1329;; Call PROC on each symbol in MODULE, with arguments of (SYMBOL VARIABLE).
1330;;
1331(define (module-for-each proc module)
c35738c1 1332 (hash-for-each proc (module-obarray module)))
0f2d19dd
JB
1333
1334(define (module-map proc module)
c35738c1
MD
1335 (hash-map proc (module-obarray module)))
1336
0f2d19dd
JB
1337\f
1338
1339;;; {Low Level Bootstrapping}
1340;;;
1341
20edfbbd 1342;; make-root-module
0f2d19dd 1343
296ff5e7
MV
1344;; A root module uses the pre-modules-obarray as its obarray. This
1345;; special obarray accumulates all bindings that have been established
1346;; before the module system is fully booted.
0f2d19dd 1347;;
296ff5e7
MV
1348;; (The obarray continues to be used by code that has been closed over
1349;; before the module system has been booted.)
0f2d19dd
JB
1350
1351(define (make-root-module)
296ff5e7
MV
1352 (let ((m (make-module 0)))
1353 (set-module-obarray! m (%get-pre-modules-obarray))
1354 m))
0f2d19dd 1355
b622dec7 1356;; make-scm-module
0f2d19dd 1357
296ff5e7
MV
1358;; The root interface is a module that uses the same obarray as the
1359;; root module. It does not allow new definitions, tho.
0f2d19dd 1360
6906bd0d 1361(define (make-scm-module)
296ff5e7
MV
1362 (let ((m (make-module 0)))
1363 (set-module-obarray! m (%get-pre-modules-obarray))
1364 (set-module-eval-closure! m (standard-interface-eval-closure m))
1365 m))
0f2d19dd
JB
1366
1367
0f2d19dd
JB
1368\f
1369;;; {Module-based Loading}
1370;;;
1371
1372(define (save-module-excursion thunk)
1373 (let ((inner-module (current-module))
1374 (outer-module #f))
1375 (dynamic-wind (lambda ()
1376 (set! outer-module (current-module))
1377 (set-current-module inner-module)
1378 (set! inner-module #f))
1379 thunk
1380 (lambda ()
1381 (set! inner-module (current-module))
1382 (set-current-module outer-module)
1383 (set! outer-module #f)))))
1384
0f2d19dd
JB
1385(define basic-load load)
1386
c6775c40
MD
1387(define (load-module filename)
1388 (save-module-excursion
1389 (lambda ()
1390 (let ((oldname (and (current-load-port)
1391 (port-filename (current-load-port)))))
1392 (basic-load (if (and oldname
1393 (> (string-length filename) 0)
1394 (not (char=? (string-ref filename 0) #\/))
1395 (not (string=? (dirname oldname) ".")))
1396 (string-append (dirname oldname) "/" filename)
1397 filename))))))
0f2d19dd
JB
1398
1399
1400\f
44cf1f0f 1401;;; {MODULE-REF -- exported}
0f2d19dd
JB
1402;;
1403;; Returns the value of a variable called NAME in MODULE or any of its
1404;; used modules. If there is no such variable, then if the optional third
1405;; argument DEFAULT is present, it is returned; otherwise an error is signaled.
20edfbbd 1406;;
0f2d19dd
JB
1407(define (module-ref module name . rest)
1408 (let ((variable (module-variable module name)))
1409 (if (and variable (variable-bound? variable))
1410 (variable-ref variable)
1411 (if (null? rest)
1412 (error "No variable named" name 'in module)
1413 (car rest) ; default value
1414 ))))
1415
1416;; MODULE-SET! -- exported
1417;;
1418;; Sets the variable called NAME in MODULE (or in a module that MODULE uses)
1419;; to VALUE; if there is no such variable, an error is signaled.
20edfbbd 1420;;
0f2d19dd
JB
1421(define (module-set! module name value)
1422 (let ((variable (module-variable module name)))
1423 (if variable
1424 (variable-set! variable value)
1425 (error "No variable named" name 'in module))))
1426
1427;; MODULE-DEFINE! -- exported
1428;;
1429;; Sets the variable called NAME in MODULE to VALUE; if there is no such
1430;; variable, it is added first.
20edfbbd 1431;;
0f2d19dd
JB
1432(define (module-define! module name value)
1433 (let ((variable (module-local-variable module name)))
1434 (if variable
1777c18b
MD
1435 (begin
1436 (variable-set! variable value)
1a961d7e 1437 (module-modified module))
296ff5e7 1438 (let ((variable (make-variable value)))
296ff5e7 1439 (module-add! module name variable)))))
0f2d19dd 1440
ed218d98
MV
1441;; MODULE-DEFINED? -- exported
1442;;
1443;; Return #t iff NAME is defined in MODULE (or in a module that MODULE
1444;; uses)
1445;;
1446(define (module-defined? module name)
1447 (let ((variable (module-variable module name)))
1448 (and variable (variable-bound? variable))))
1449
0f2d19dd
JB
1450;; MODULE-USE! module interface
1451;;
1452;; Add INTERFACE to the list of interfaces used by MODULE.
20edfbbd 1453;;
0f2d19dd
JB
1454(define (module-use! module interface)
1455 (set-module-uses! module
c614a00b
MD
1456 (cons interface
1457 (filter (lambda (m)
1458 (not (equal? (module-name m)
1459 (module-name interface))))
1460 (module-uses module))))
1a961d7e 1461 (module-modified module))
0f2d19dd 1462
7b07e5ef
MD
1463;; MODULE-USE-INTERFACES! module interfaces
1464;;
1465;; Same as MODULE-USE! but add multiple interfaces and check for duplicates
1466;;
1467(define (module-use-interfaces! module interfaces)
8d8dac1f 1468 (let* ((duplicates-handlers? (or (module-duplicates-handlers module)
70a459e3 1469 (default-duplicate-binding-procedures)))
7b07e5ef
MD
1470 (uses (module-uses module)))
1471 ;; remove duplicates-interface
8d8dac1f 1472 (set! uses (delq! (module-duplicates-interface module) uses))
7b07e5ef
MD
1473 ;; remove interfaces to be added
1474 (for-each (lambda (interface)
c614a00b
MD
1475 (set! uses
1476 (filter (lambda (m)
1477 (not (equal? (module-name m)
1478 (module-name interface))))
1479 uses)))
7b07e5ef
MD
1480 interfaces)
1481 ;; add interfaces to use list
1482 (set-module-uses! module uses)
1483 (for-each (lambda (interface)
1484 (and duplicates-handlers?
1485 ;; perform duplicate checking
1486 (process-duplicates module interface))
1487 (set! uses (cons interface uses))
1488 (set-module-uses! module uses))
1489 interfaces)
1490 ;; add duplicates interface
8d8dac1f
MD
1491 (if (module-duplicates-interface module)
1492 (set-module-uses! module
1493 (cons (module-duplicates-interface module) uses)))
7b07e5ef
MD
1494 (module-modified module)))
1495
0f2d19dd 1496\f
0f2d19dd
JB
1497;;; {Recursive Namespaces}
1498;;;
1499;;;
1500;;; A hierarchical namespace emerges if we consider some module to be
1501;;; root, and variables bound to modules as nested namespaces.
1502;;;
1503;;; The routines in this file manage variable names in hierarchical namespace.
1504;;; Each variable name is a list of elements, looked up in successively nested
1505;;; modules.
1506;;;
0dd5491c 1507;;; (nested-ref some-root-module '(foo bar baz))
20edfbbd 1508;;; => <value of a variable named baz in the module bound to bar in
0f2d19dd
JB
1509;;; the module bound to foo in some-root-module>
1510;;;
1511;;;
1512;;; There are:
1513;;;
1514;;; ;; a-root is a module
1515;;; ;; name is a list of symbols
1516;;;
0dd5491c
MD
1517;;; nested-ref a-root name
1518;;; nested-set! a-root name val
1519;;; nested-define! a-root name val
1520;;; nested-remove! a-root name
0f2d19dd
JB
1521;;;
1522;;;
1523;;; (current-module) is a natural choice for a-root so for convenience there are
1524;;; also:
1525;;;
0dd5491c
MD
1526;;; local-ref name == nested-ref (current-module) name
1527;;; local-set! name val == nested-set! (current-module) name val
1528;;; local-define! name val == nested-define! (current-module) name val
1529;;; local-remove! name == nested-remove! (current-module) name
0f2d19dd
JB
1530;;;
1531
1532
0dd5491c 1533(define (nested-ref root names)
0f2d19dd
JB
1534 (let loop ((cur root)
1535 (elts names))
1536 (cond
1537 ((null? elts) cur)
1538 ((not (module? cur)) #f)
1539 (else (loop (module-ref cur (car elts) #f) (cdr elts))))))
1540
0dd5491c 1541(define (nested-set! root names val)
0f2d19dd
JB
1542 (let loop ((cur root)
1543 (elts names))
1544 (if (null? (cdr elts))
1545 (module-set! cur (car elts) val)
1546 (loop (module-ref cur (car elts)) (cdr elts)))))
1547
0dd5491c 1548(define (nested-define! root names val)
0f2d19dd
JB
1549 (let loop ((cur root)
1550 (elts names))
1551 (if (null? (cdr elts))
1552 (module-define! cur (car elts) val)
1553 (loop (module-ref cur (car elts)) (cdr elts)))))
1554
0dd5491c 1555(define (nested-remove! root names)
0f2d19dd
JB
1556 (let loop ((cur root)
1557 (elts names))
1558 (if (null? (cdr elts))
1559 (module-remove! cur (car elts))
1560 (loop (module-ref cur (car elts)) (cdr elts)))))
1561
0dd5491c
MD
1562(define (local-ref names) (nested-ref (current-module) names))
1563(define (local-set! names val) (nested-set! (current-module) names val))
1564(define (local-define names val) (nested-define! (current-module) names val))
1565(define (local-remove names) (nested-remove! (current-module) names))
0f2d19dd
JB
1566
1567
1568\f
8bb7330c 1569;;; {The (app) module}
0f2d19dd
JB
1570;;;
1571;;; The root of conventionally named objects not directly in the top level.
1572;;;
8bb7330c
JB
1573;;; (app modules)
1574;;; (app modules guile)
0f2d19dd
JB
1575;;;
1576;;; The directory of all modules and the standard root module.
1577;;;
1578
edc185c7
MD
1579(define (module-public-interface m)
1580 (module-ref m '%module-public-interface #f))
1581(define (set-module-public-interface! m i)
1582 (module-define! m '%module-public-interface i))
1583(define (set-system-module! m s)
1584 (set-procedure-property! (module-eval-closure m) 'system-module s))
0f2d19dd
JB
1585(define the-root-module (make-root-module))
1586(define the-scm-module (make-scm-module))
1587(set-module-public-interface! the-root-module the-scm-module)
d5504515
MD
1588(set-module-name! the-root-module '(guile))
1589(set-module-name! the-scm-module '(guile))
1590(set-module-kind! the-scm-module 'interface)
edc185c7 1591(for-each set-system-module! (list the-root-module the-scm-module) '(#t #t))
0f2d19dd 1592
296ff5e7
MV
1593;; NOTE: This binding is used in libguile/modules.c.
1594;;
1595(define (make-modules-in module name)
1596 (if (null? name)
1597 module
1598 (cond
1599 ((module-ref module (car name) #f)
1600 => (lambda (m) (make-modules-in m (cdr name))))
1601 (else (let ((m (make-module 31)))
1602 (set-module-kind! m 'directory)
1603 (set-module-name! m (append (or (module-name module)
1604 '())
1605 (list (car name))))
1606 (module-define! module (car name) m)
1607 (make-modules-in m (cdr name)))))))
0f2d19dd 1608
296ff5e7
MV
1609(define (beautify-user-module! module)
1610 (let ((interface (module-public-interface module)))
1611 (if (or (not interface)
1612 (eq? interface module))
1613 (let ((interface (make-module 31)))
1614 (set-module-name! interface (module-name module))
1615 (set-module-kind! interface 'interface)
8d8dac1f 1616 (set-module-public-interface! module interface))))
296ff5e7
MV
1617 (if (and (not (memq the-scm-module (module-uses module)))
1618 (not (eq? module the-root-module)))
7b07e5ef
MD
1619 (set-module-uses! module
1620 (append (module-uses module) (list the-scm-module)))))
432558b9 1621
1f60d9d2
MD
1622;; NOTE: This binding is used in libguile/modules.c.
1623;;
0209ca9a 1624(define (resolve-module name . maybe-autoload)
0f2d19dd 1625 (let ((full-name (append '(app modules) name)))
0dd5491c 1626 (let ((already (local-ref full-name)))
432558b9
MD
1627 (if already
1628 ;; The module already exists...
1629 (if (and (or (null? maybe-autoload) (car maybe-autoload))
fb1b76f4 1630 (not (module-public-interface already)))
432558b9
MD
1631 ;; ...but we are told to load and it doesn't contain source, so
1632 (begin
1633 (try-load-module name)
1634 already)
1635 ;; simply return it.
1636 already)
3e3cec45 1637 (begin
432558b9 1638 ;; Try to autoload it if we are told so
3e3cec45 1639 (if (or (null? maybe-autoload) (car maybe-autoload))
432558b9
MD
1640 (try-load-module name))
1641 ;; Get/create it.
3e3cec45 1642 (make-modules-in (current-module) full-name))))))
20edfbbd 1643
d866f445
MV
1644;; Cheat. These bindings are needed by modules.c, but we don't want
1645;; to move their real definition here because that would be unnatural.
1646;;
296ff5e7 1647(define try-module-autoload #f)
d866f445
MV
1648(define process-define-module #f)
1649(define process-use-modules #f)
1650(define module-export! #f)
296ff5e7
MV
1651
1652;; This boots the module system. All bindings needed by modules.c
1653;; must have been defined by now.
1654;;
1655(set-current-module the-root-module)
1656
1657(define app (make-module 31))
1658(local-define '(app modules) (make-module 31))
1659(local-define '(app modules guile) the-root-module)
1660
1661;; (define-special-value '(app modules new-ws) (lambda () (make-scm-module)))
1662
1663(define (try-load-module name)
48fdec21
MV
1664 (or (begin-deprecated (try-module-linked name))
1665 (try-module-autoload name)
1666 (begin-deprecated (try-module-dynamic-link name))))
0f2d19dd 1667
90847923
MD
1668(define (purify-module! module)
1669 "Removes bindings in MODULE which are inherited from the (guile) module."
1670 (let ((use-list (module-uses module)))
1671 (if (and (pair? use-list)
1672 (eq? (car (last-pair use-list)) the-scm-module))
1673 (set-module-uses! module (reverse (cdr (reverse use-list)))))))
1674
4eecfeb7 1675;; Return a module that is an interface to the module designated by
532cf805
MV
1676;; NAME.
1677;;
c614a00b 1678;; `resolve-interface' takes four keyword arguments:
532cf805
MV
1679;;
1680;; #:select SELECTION
1681;;
1682;; SELECTION is a list of binding-specs to be imported; A binding-spec
1683;; is either a symbol or a pair of symbols (ORIG . SEEN), where ORIG
1684;; is the name in the used module and SEEN is the name in the using
1685;; module. Note that SEEN is also passed through RENAMER, below. The
1686;; default is to select all bindings. If you specify no selection but
4eecfeb7 1687;; a renamer, only the bindings that already exist in the used module
532cf805
MV
1688;; are made available in the interface. Bindings that are added later
1689;; are not picked up.
1690;;
c614a00b 1691;; #:hide BINDINGS
532cf805 1692;;
c614a00b 1693;; BINDINGS is a list of bindings which should not be imported.
f595ccfe
MD
1694;;
1695;; #:prefix PREFIX
1696;;
1697;; PREFIX is a symbol that will be appended to each exported name.
1698;; The default is to not perform any renaming.
532cf805 1699;;
c614a00b
MD
1700;; #:renamer RENAMER
1701;;
1702;; RENAMER is a procedure that takes a symbol and returns its new
1703;; name. The default is not perform any renaming.
1704;;
532cf805
MV
1705;; Signal "no code for module" error if module name is not resolvable
1706;; or its public interface is not available. Signal "no binding"
1707;; error if selected binding does not exist in the used module.
1708;;
1709(define (resolve-interface name . args)
1710
1711 (define (get-keyword-arg args kw def)
1712 (cond ((memq kw args)
1713 => (lambda (kw-arg)
1714 (if (null? (cdr kw-arg))
1715 (error "keyword without value: " kw))
1716 (cadr kw-arg)))
1717 (else
1718 def)))
1719
1720 (let* ((select (get-keyword-arg args #:select #f))
c614a00b 1721 (hide (get-keyword-arg args #:hide '()))
f595ccfe
MD
1722 (renamer (or (get-keyword-arg args #:renamer #f)
1723 (let ((prefix (get-keyword-arg args #:prefix #f)))
1724 (and prefix (symbol-prefix-proc prefix)))
1725 identity))
b622dec7
TTN
1726 (module (resolve-module name))
1727 (public-i (and module (module-public-interface module))))
1728 (and (or (not module) (not public-i))
1729 (error "no code for module" name))
c614a00b 1730 (if (and (not select) (null? hide) (eq? renamer identity))
b622dec7 1731 public-i
532cf805
MV
1732 (let ((selection (or select (module-map (lambda (sym var) sym)
1733 public-i)))
b622dec7 1734 (custom-i (make-module 31)))
c614a00b
MD
1735 (set-module-kind! custom-i 'custom-interface)
1736 (set-module-name! custom-i name)
532cf805
MV
1737 ;; XXX - should use a lazy binder so that changes to the
1738 ;; used module are picked up automatically.
d57da08b
MD
1739 (for-each (lambda (bspec)
1740 (let* ((direct? (symbol? bspec))
1741 (orig (if direct? bspec (car bspec)))
1742 (seen (if direct? bspec (cdr bspec)))
c614a00b
MD
1743 (var (or (module-local-variable public-i orig)
1744 (module-local-variable module orig)
1745 (error
1746 ;; fixme: format manually for now
1747 (simple-format
1748 #f "no binding `~A' in module ~A"
1749 orig name)))))
1750 (if (memq orig hide)
1751 (set! hide (delq! orig hide))
1752 (module-add! custom-i
1753 (renamer seen)
1754 var))))
d57da08b 1755 selection)
c614a00b
MD
1756 ;; Check that we are not hiding bindings which don't exist
1757 (for-each (lambda (binding)
1758 (if (not (module-local-variable public-i binding))
1759 (error
1760 (simple-format
1761 #f "no binding `~A' to hide in module ~A"
1762 binding name))))
1763 hide)
b622dec7 1764 custom-i))))
fb1b76f4
TTN
1765
1766(define (symbol-prefix-proc prefix)
1767 (lambda (symbol)
1768 (symbol-append prefix symbol)))
0f2d19dd 1769
482a28f9
MV
1770;; This function is called from "modules.c". If you change it, be
1771;; sure to update "modules.c" as well.
1772
0f2d19dd 1773(define (process-define-module args)
f8a502cb
TTN
1774 (let* ((module-id (car args))
1775 (module (resolve-module module-id #f))
1776 (kws (cdr args))
1777 (unrecognized (lambda (arg)
1778 (error "unrecognized define-module argument" arg))))
0f2d19dd 1779 (beautify-user-module! module)
0209ca9a 1780 (let loop ((kws kws)
44484f52 1781 (reversed-interfaces '())
5d20b8c7 1782 (exports '())
f595ccfe
MD
1783 (re-exports '())
1784 (replacements '()))
0209ca9a 1785 (if (null? kws)
d57da08b
MD
1786 (call-with-deferred-observers
1787 (lambda ()
1788 (module-use-interfaces! module (reverse reversed-interfaces))
1789 (module-export! module exports)
1790 (module-replace! module replacements)
1791 (module-re-export! module re-exports)))
532cf805
MV
1792 (case (car kws)
1793 ((#:use-module #:use-syntax)
1794 (or (pair? (cdr kws))
1795 (unrecognized kws))
1796 (let* ((interface-args (cadr kws))
1797 (interface (apply resolve-interface interface-args)))
88c4ba2a
KN
1798 (and (eq? (car kws) #:use-syntax)
1799 (or (symbol? (caar interface-args))
532cf805 1800 (error "invalid module name for use-syntax"
88c4ba2a 1801 (car interface-args)))
532cf805
MV
1802 (set-module-transformer!
1803 module
88c4ba2a
KN
1804 (module-ref interface
1805 (car (last-pair (car interface-args)))
532cf805 1806 #f)))
44484f52 1807 (loop (cddr kws)
532cf805 1808 (cons interface reversed-interfaces)
5d20b8c7 1809 exports
f595ccfe
MD
1810 re-exports
1811 replacements)))
532cf805
MV
1812 ((#:autoload)
1813 (or (and (pair? (cdr kws)) (pair? (cddr kws)))
1814 (unrecognized kws))
1815 (loop (cdddr kws)
1816 (cons (make-autoload-interface module
1817 (cadr kws)
1818 (caddr kws))
1819 reversed-interfaces)
5d20b8c7 1820 exports
f595ccfe
MD
1821 re-exports
1822 replacements))
532cf805
MV
1823 ((#:no-backtrace)
1824 (set-system-module! module #t)
f595ccfe 1825 (loop (cdr kws) reversed-interfaces exports re-exports replacements))
532cf805
MV
1826 ((#:pure)
1827 (purify-module! module)
f595ccfe 1828 (loop (cdr kws) reversed-interfaces exports re-exports replacements))
7b07e5ef
MD
1829 ((#:duplicates)
1830 (if (not (pair? (cdr kws)))
1831 (unrecognized kws))
8d8dac1f
MD
1832 (set-module-duplicates-handlers!
1833 module
1834 (lookup-duplicates-handlers (cadr kws)))
f595ccfe 1835 (loop (cddr kws) reversed-interfaces exports re-exports replacements))
39819fa9 1836 ((#:export #:export-syntax)
532cf805
MV
1837 (or (pair? (cdr kws))
1838 (unrecognized kws))
1839 (loop (cddr kws)
1840 reversed-interfaces
5d20b8c7 1841 (append (cadr kws) exports)
f595ccfe
MD
1842 re-exports
1843 replacements))
39819fa9 1844 ((#:re-export #:re-export-syntax)
5d20b8c7
MD
1845 (or (pair? (cdr kws))
1846 (unrecognized kws))
1847 (loop (cddr kws)
1848 reversed-interfaces
1849 exports
f595ccfe
MD
1850 (append (cadr kws) re-exports)
1851 replacements))
1852 ((#:replace #:replace-syntax)
1853 (or (pair? (cdr kws))
1854 (unrecognized kws))
1855 (loop (cddr kws)
1856 reversed-interfaces
1857 exports
1858 re-exports
1859 (append (cadr kws) replacements)))
532cf805
MV
1860 (else
1861 (unrecognized kws)))))
db853761 1862 (run-hook module-defined-hook module)
0f2d19dd 1863 module))
71225060 1864
db853761
NJ
1865;; `module-defined-hook' is a hook that is run whenever a new module
1866;; is defined. Its members are called with one argument, the new
1867;; module.
1868(define module-defined-hook (make-hook 1))
1869
71225060
MD
1870;;; {Autoload}
1871
1872(define (make-autoload-interface module name bindings)
1873 (let ((b (lambda (a sym definep)
1874 (and (memq sym bindings)
1875 (let ((i (module-public-interface (resolve-module name))))
1876 (if (not i)
1877 (error "missing interface for module" name))
1878 ;; Replace autoload-interface with interface
1879 (set-car! (memq a (module-uses module)) i)
1880 (module-local-variable i sym))))))
8d8dac1f 1881 (module-constructor #() '() b #f #f name 'autoload #f #f
6b64c19b 1882 '() (make-weak-value-hash-table 31) 0)))
71225060 1883
ff5546f5
KN
1884;;; {Compiled module}
1885
1886(define load-compiled #f)
1887
0f2d19dd 1888\f
44cf1f0f 1889;;; {Autoloading modules}
0f2d19dd
JB
1890
1891(define autoloads-in-progress '())
1892
482a28f9
MV
1893;; This function is called from "modules.c". If you change it, be
1894;; sure to update "modules.c" as well.
1895
0f2d19dd 1896(define (try-module-autoload module-name)
0f2d19dd 1897 (let* ((reverse-name (reverse module-name))
06f0414c 1898 (name (symbol->string (car reverse-name)))
0f2d19dd 1899 (dir-hint-module-name (reverse (cdr reverse-name)))
06f0414c
MD
1900 (dir-hint (apply string-append
1901 (map (lambda (elt)
1902 (string-append (symbol->string elt) "/"))
1903 dir-hint-module-name))))
0209ca9a 1904 (resolve-module dir-hint-module-name #f)
0f2d19dd
JB
1905 (and (not (autoload-done-or-in-progress? dir-hint name))
1906 (let ((didit #f))
ff5546f5
KN
1907 (define (load-file proc file)
1908 (save-module-excursion (lambda () (proc file)))
1909 (set! didit #t))
0f2d19dd
JB
1910 (dynamic-wind
1911 (lambda () (autoload-in-progress! dir-hint name))
defed517 1912 (lambda ()
ff5546f5
KN
1913 (let ((file (in-vicinity dir-hint name)))
1914 (cond ((and load-compiled
1915 (%search-load-path (string-append file ".go")))
1916 => (lambda (full)
1917 (load-file load-compiled full)))
1918 ((%search-load-path file)
1919 => (lambda (full)
1920 (load-file primitive-load full))))))
0f2d19dd
JB
1921 (lambda () (set-autoloaded! dir-hint name didit)))
1922 didit))))
1923
71225060 1924\f
d0cbd20c
MV
1925;;; Dynamic linking of modules
1926
0f2d19dd
JB
1927(define autoloads-done '((guile . guile)))
1928
1929(define (autoload-done-or-in-progress? p m)
1930 (let ((n (cons p m)))
1931 (->bool (or (member n autoloads-done)
1932 (member n autoloads-in-progress)))))
1933
1934(define (autoload-done! p m)
1935 (let ((n (cons p m)))
1936 (set! autoloads-in-progress
1937 (delete! n autoloads-in-progress))
1938 (or (member n autoloads-done)
1939 (set! autoloads-done (cons n autoloads-done)))))
1940
1941(define (autoload-in-progress! p m)
1942 (let ((n (cons p m)))
1943 (set! autoloads-done
1944 (delete! n autoloads-done))
1945 (set! autoloads-in-progress (cons n autoloads-in-progress))))
1946
1947(define (set-autoloaded! p m done?)
1948 (if done?
1949 (autoload-done! p m)
1950 (let ((n (cons p m)))
1951 (set! autoloads-done (delete! n autoloads-done))
1952 (set! autoloads-in-progress (delete! n autoloads-in-progress)))))
1953
1954
1955
a54e6fa3
KN
1956\f
1957;; {EVAL-CASE}
1958;;
1959;; (eval-case ((situation*) forms)* (else forms)?)
1960;;
1961;; Evaluate certain code based on the situation that eval-case is used
1962;; in. The only defined situation right now is `load-toplevel' which
1963;; triggers for code evaluated at the top-level, for example from the
1964;; REPL or when loading a file.
20edfbbd 1965
a54e6fa3
KN
1966(define eval-case
1967 (procedure->memoizing-macro
1968 (lambda (exp env)
1969 (define (toplevel-env? env)
1970 (or (not (pair? env)) (not (pair? (car env)))))
1971 (define (syntax)
1972 (error "syntax error in eval-case"))
1973 (let loop ((clauses (cdr exp)))
20edfbbd 1974 (cond
a54e6fa3
KN
1975 ((null? clauses)
1976 #f)
1977 ((not (list? (car clauses)))
1978 (syntax))
1979 ((eq? 'else (caar clauses))
1980 (or (null? (cdr clauses))
1981 (syntax))
1982 (cons 'begin (cdar clauses)))
1983 ((not (list? (caar clauses)))
1984 (syntax))
1985 ((and (toplevel-env? env)
1986 (memq 'load-toplevel (caar clauses)))
1987 (cons 'begin (cdar clauses)))
1988 (else
1989 (loop (cdr clauses))))))))
0f2d19dd
JB
1990
1991\f
1992;;; {Macros}
1993;;;
1994
7a0ff2f8
MD
1995(define (primitive-macro? m)
1996 (and (macro? m)
1997 (not (macro-transformer m))))
1998
1999;;; {Defmacros}
2000;;;
231a4ea8
MD
2001(define macro-table (make-weak-key-hash-table 61))
2002(define xformer-table (make-weak-key-hash-table 61))
0f2d19dd
JB
2003
2004(define (defmacro? m) (hashq-ref macro-table m))
2005(define (assert-defmacro?! m) (hashq-set! macro-table m #t))
2006(define (defmacro-transformer m) (hashq-ref xformer-table m))
2007(define (set-defmacro-transformer! m t) (hashq-set! xformer-table m t))
2008
2009(define defmacro:transformer
2010 (lambda (f)
2011 (let* ((xform (lambda (exp env)
2012 (copy-tree (apply f (cdr exp)))))
2013 (a (procedure->memoizing-macro xform)))
2014 (assert-defmacro?! a)
2015 (set-defmacro-transformer! a f)
2016 a)))
2017
2018
2019(define defmacro
2020 (let ((defmacro-transformer
2021 (lambda (name parms . body)
2022 (let ((transformer `(lambda ,parms ,@body)))
8add1522
KN
2023 `(eval-case
2024 ((load-toplevel)
2025 (define ,name (defmacro:transformer ,transformer)))
2026 (else
2027 (error "defmacro can only be used at the top level")))))))
0f2d19dd
JB
2028 (defmacro:transformer defmacro-transformer)))
2029
2030(define defmacro:syntax-transformer
2031 (lambda (f)
2032 (procedure->syntax
2033 (lambda (exp env)
2034 (copy-tree (apply f (cdr exp)))))))
2035
ed218d98
MV
2036
2037;; XXX - should the definition of the car really be looked up in the
2038;; current module?
2039
0f2d19dd
JB
2040(define (macroexpand-1 e)
2041 (cond
2042 ((pair? e) (let* ((a (car e))
ed218d98 2043 (val (and (symbol? a) (local-ref (list a)))))
0f2d19dd
JB
2044 (if (defmacro? val)
2045 (apply (defmacro-transformer val) (cdr e))
2046 e)))
2047 (#t e)))
2048
2049(define (macroexpand e)
2050 (cond
2051 ((pair? e) (let* ((a (car e))
ed218d98 2052 (val (and (symbol? a) (local-ref (list a)))))
0f2d19dd
JB
2053 (if (defmacro? val)
2054 (macroexpand (apply (defmacro-transformer val) (cdr e)))
2055 e)))
2056 (#t e)))
2057
534a0099 2058(provide 'defmacro)
0f2d19dd
JB
2059
2060\f
2061
83b38198
MD
2062;;; {Run-time options}
2063
e9bab9df
DH
2064(define define-option-interface
2065 (let* ((option-name car)
2066 (option-value cadr)
2067 (option-documentation caddr)
2068
2069 (print-option (lambda (option)
2070 (display (option-name option))
2071 (if (< (string-length
2072 (symbol->string (option-name option)))
2073 8)
2074 (display #\tab))
2075 (display #\tab)
2076 (display (option-value option))
2077 (display #\tab)
2078 (display (option-documentation option))
2079 (newline)))
2080
2081 ;; Below follow the macros defining the run-time option interfaces.
2082
2083 (make-options (lambda (interface)
2084 `(lambda args
2085 (cond ((null? args) (,interface))
2086 ((list? (car args))
2087 (,interface (car args)) (,interface))
2088 (else (for-each ,print-option
2089 (,interface #t)))))))
2090
2091 (make-enable (lambda (interface)
83b38198 2092 `(lambda flags
e9bab9df
DH
2093 (,interface (append flags (,interface)))
2094 (,interface))))
2095
2096 (make-disable (lambda (interface)
2097 `(lambda flags
2098 (let ((options (,interface)))
2099 (for-each (lambda (flag)
2100 (set! options (delq! flag options)))
2101 flags)
2102 (,interface options)
0983f67f 2103 (,interface))))))
7c38399f 2104 (procedure->memoizing-macro
83b38198 2105 (lambda (exp env)
0983f67f
NJ
2106 (let* ((option-group (cadr exp))
2107 (interface (car option-group))
2108 (options/enable/disable (cadr option-group)))
2109 `(begin
2110 (define ,(car options/enable/disable)
2111 ,(make-options interface))
2112 (define ,(cadr options/enable/disable)
2113 ,(make-enable interface))
2114 (define ,(caddr options/enable/disable)
2115 ,(make-disable interface))
2116 (defmacro ,(caaddr option-group) (opt val)
2117 `(,,(car options/enable/disable)
3f619266
NJ
2118 (append (,,(car options/enable/disable))
2119 (list ',opt ,val))))))))))
e9bab9df
DH
2120
2121(define-option-interface
2122 (eval-options-interface
2123 (eval-options eval-enable eval-disable)
2124 (eval-set!)))
2125
2126(define-option-interface
2127 (debug-options-interface
2128 (debug-options debug-enable debug-disable)
2129 (debug-set!)))
2130
2131(define-option-interface
2132 (evaluator-traps-interface
2133 (traps trap-enable trap-disable)
2134 (trap-set!)))
2135
2136(define-option-interface
2137 (read-options-interface
2138 (read-options read-enable read-disable)
2139 (read-set!)))
2140
2141(define-option-interface
2142 (print-options-interface
2143 (print-options print-enable print-disable)
2144 (print-set!)))
83b38198
MD
2145
2146\f
2147
0f2d19dd
JB
2148;;; {Running Repls}
2149;;;
2150
2151(define (repl read evaler print)
75a97b92 2152 (let loop ((source (read (current-input-port))))
0f2d19dd 2153 (print (evaler source))
75a97b92 2154 (loop (read (current-input-port)))))
0f2d19dd
JB
2155
2156;; A provisional repl that acts like the SCM repl:
2157;;
2158(define scm-repl-silent #f)
2159(define (assert-repl-silence v) (set! scm-repl-silent v))
2160
21ed9efe
MD
2161(define *unspecified* (if #f #f))
2162(define (unspecified? v) (eq? v *unspecified*))
2163
2164(define scm-repl-print-unspecified #f)
2165(define (assert-repl-print-unspecified v) (set! scm-repl-print-unspecified v))
2166
79451588 2167(define scm-repl-verbose #f)
0f2d19dd
JB
2168(define (assert-repl-verbosity v) (set! scm-repl-verbose v))
2169
e6875011 2170(define scm-repl-prompt "guile> ")
0f2d19dd 2171
e6875011
MD
2172(define (set-repl-prompt! v) (set! scm-repl-prompt v))
2173
d5d34fa1
MD
2174(define (default-lazy-handler key . args)
2175 (save-stack lazy-handler-dispatch)
2176 (apply throw key args))
2177
d5d34fa1 2178(define (lazy-handler-dispatch key . args)
d95c0b76 2179 (apply default-lazy-handler key args))
0f2d19dd 2180
3e3cec45 2181(define abort-hook (make-hook))
59e1116d 2182
28d8ab3c
GH
2183;; these definitions are used if running a script.
2184;; otherwise redefined in error-catching-loop.
2185(define (set-batch-mode?! arg) #t)
2186(define (batch-mode?) #t)
4bbbcd5c 2187
0f2d19dd 2188(define (error-catching-loop thunk)
4bbbcd5c
GH
2189 (let ((status #f)
2190 (interactive #t))
8e44e7a0 2191 (define (loop first)
20edfbbd 2192 (let ((next
8e44e7a0 2193 (catch #t
9a0d70e2 2194
8e44e7a0
GH
2195 (lambda ()
2196 (lazy-catch #t
2197 (lambda ()
bb00edfa 2198 (call-with-unblocked-asyncs
8e44e7a0 2199 (lambda ()
45456413
MD
2200 (with-traps
2201 (lambda ()
2202 (first)
20edfbbd 2203
45456413
MD
2204 ;; This line is needed because mark
2205 ;; doesn't do closures quite right.
2206 ;; Unreferenced locals should be
2207 ;; collected.
2208 ;;
2209 (set! first #f)
2210 (let loop ((v (thunk)))
2211 (loop (thunk)))
bb00edfa 2212 #f)))))
8e44e7a0
GH
2213
2214 lazy-handler-dispatch))
20edfbbd 2215
8e44e7a0
GH
2216 (lambda (key . args)
2217 (case key
2218 ((quit)
8e44e7a0
GH
2219 (set! status args)
2220 #f)
2221
2222 ((switch-repl)
2223 (apply throw 'switch-repl args))
2224
2225 ((abort)
2226 ;; This is one of the closures that require
2227 ;; (set! first #f) above
2228 ;;
2229 (lambda ()
04efd24d 2230 (run-hook abort-hook)
e13c54c4 2231 (force-output (current-output-port))
8e44e7a0
GH
2232 (display "ABORT: " (current-error-port))
2233 (write args (current-error-port))
2234 (newline (current-error-port))
4bbbcd5c 2235 (if interactive
e13c54c4
JB
2236 (begin
2237 (if (and
2238 (not has-shown-debugger-hint?)
2239 (not (memq 'backtrace
2240 (debug-options-interface)))
2241 (stack? (fluid-ref the-last-stack)))
2242 (begin
2243 (newline (current-error-port))
2244 (display
cb546c61 2245 "Type \"(backtrace)\" to get more information or \"(debug)\" to enter the debugger.\n"
e13c54c4
JB
2246 (current-error-port))
2247 (set! has-shown-debugger-hint? #t)))
2248 (force-output (current-error-port)))
2249 (begin
2250 (primitive-exit 1)))
8e44e7a0
GH
2251 (set! stack-saved? #f)))
2252
2253 (else
2254 ;; This is the other cons-leak closure...
2255 (lambda ()
2256 (cond ((= (length args) 4)
2257 (apply handle-system-error key args))
2258 (else
2259 (apply bad-throw key args))))))))))
2260 (if next (loop next) status)))
5f5f2642 2261 (set! set-batch-mode?! (lambda (arg)
20edfbbd 2262 (cond (arg
5f5f2642
MD
2263 (set! interactive #f)
2264 (restore-signals))
2265 (#t
2266 (error "sorry, not implemented")))))
2267 (set! batch-mode? (lambda () (not interactive)))
bb00edfa
MV
2268 (call-with-blocked-asyncs
2269 (lambda () (loop (lambda () #t))))))
0f2d19dd 2270
8bb7f646 2271;;(define the-last-stack (make-fluid)) Defined by scm_init_backtrace ()
8087b6be 2272(define before-signal-stack (make-fluid))
21ed9efe
MD
2273(define stack-saved? #f)
2274
2275(define (save-stack . narrowing)
edc185c7
MD
2276 (or stack-saved?
2277 (cond ((not (memq 'debug (debug-options-interface)))
2278 (fluid-set! the-last-stack #f)
2279 (set! stack-saved? #t))
2280 (else
2281 (fluid-set!
2282 the-last-stack
2283 (case (stack-id #t)
2284 ((repl-stack)
704f4e86 2285 (apply make-stack #t save-stack primitive-eval #t 0 narrowing))
edc185c7
MD
2286 ((load-stack)
2287 (apply make-stack #t save-stack 0 #t 0 narrowing))
2288 ((tk-stack)
2289 (apply make-stack #t save-stack tk-stack-mark #t 0 narrowing))
2290 ((#t)
2291 (apply make-stack #t save-stack 0 1 narrowing))
2292 (else
2293 (let ((id (stack-id #t)))
2294 (and (procedure? id)
2295 (apply make-stack #t save-stack id #t 0 narrowing))))))
2296 (set! stack-saved? #t)))))
1c6cd8e8 2297
3e3cec45
MD
2298(define before-error-hook (make-hook))
2299(define after-error-hook (make-hook))
2300(define before-backtrace-hook (make-hook))
2301(define after-backtrace-hook (make-hook))
1c6cd8e8 2302
21ed9efe
MD
2303(define has-shown-debugger-hint? #f)
2304
35c5db87
GH
2305(define (handle-system-error key . args)
2306 (let ((cep (current-error-port)))
8bb7f646 2307 (cond ((not (stack? (fluid-ref the-last-stack))))
21ed9efe 2308 ((memq 'backtrace (debug-options-interface))
04efd24d 2309 (run-hook before-backtrace-hook)
21ed9efe 2310 (newline cep)
755457ec 2311 (display "Backtrace:\n")
8bb7f646 2312 (display-backtrace (fluid-ref the-last-stack) cep)
21ed9efe 2313 (newline cep)
04efd24d
MD
2314 (run-hook after-backtrace-hook)))
2315 (run-hook before-error-hook)
8bb7f646 2316 (apply display-error (fluid-ref the-last-stack) cep args)
04efd24d 2317 (run-hook after-error-hook)
35c5db87
GH
2318 (force-output cep)
2319 (throw 'abort key)))
21ed9efe 2320
0f2d19dd
JB
2321(define (quit . args)
2322 (apply throw 'quit args))
2323
7950df7c
GH
2324(define exit quit)
2325
d590bbf6
MD
2326;;(define has-shown-backtrace-hint? #f) Defined by scm_init_backtrace ()
2327
2328;; Replaced by C code:
2329;;(define (backtrace)
8bb7f646 2330;; (if (fluid-ref the-last-stack)
d590bbf6
MD
2331;; (begin
2332;; (newline)
8bb7f646 2333;; (display-backtrace (fluid-ref the-last-stack) (current-output-port))
d590bbf6
MD
2334;; (newline)
2335;; (if (and (not has-shown-backtrace-hint?)
2336;; (not (memq 'backtrace (debug-options-interface))))
2337;; (begin
2338;; (display
2339;;"Type \"(debug-enable 'backtrace)\" if you would like a backtrace
2340;;automatically if an error occurs in the future.\n")
2341;; (set! has-shown-backtrace-hint? #t))))
2342;; (display "No backtrace available.\n")))
21ed9efe 2343
0f2d19dd 2344(define (error-catching-repl r e p)
5f89fb13
MV
2345 (error-catching-loop
2346 (lambda ()
2347 (call-with-values (lambda () (e (r)))
2348 (lambda the-values (for-each p the-values))))))
0f2d19dd
JB
2349
2350(define (gc-run-time)
2351 (cdr (assq 'gc-time-taken (gc-stats))))
2352
3e3cec45
MD
2353(define before-read-hook (make-hook))
2354(define after-read-hook (make-hook))
870777d7
KN
2355(define before-eval-hook (make-hook 1))
2356(define after-eval-hook (make-hook 1))
2357(define before-print-hook (make-hook 1))
2358(define after-print-hook (make-hook 1))
1c6cd8e8 2359
dc5c2038
MD
2360;;; The default repl-reader function. We may override this if we've
2361;;; the readline library.
2362(define repl-reader
2363 (lambda (prompt)
2364 (display prompt)
2365 (force-output)
04efd24d 2366 (run-hook before-read-hook)
dc5c2038
MD
2367 (read (current-input-port))))
2368
0f2d19dd 2369(define (scm-style-repl)
9d774814 2370
0f2d19dd
JB
2371 (letrec (
2372 (start-gc-rt #f)
2373 (start-rt #f)
0f2d19dd
JB
2374 (repl-report-start-timing (lambda ()
2375 (set! start-gc-rt (gc-run-time))
2376 (set! start-rt (get-internal-run-time))))
2377 (repl-report (lambda ()
2378 (display ";;; ")
2379 (display (inexact->exact
2380 (* 1000 (/ (- (get-internal-run-time) start-rt)
2381 internal-time-units-per-second))))
2382 (display " msec (")
2383 (display (inexact->exact
2384 (* 1000 (/ (- (gc-run-time) start-gc-rt)
2385 internal-time-units-per-second))))
2386 (display " msec in gc)\n")))
480977d0
JB
2387
2388 (consume-trailing-whitespace
2389 (lambda ()
2390 (let ((ch (peek-char)))
2391 (cond
2392 ((eof-object? ch))
2393 ((or (char=? ch #\space) (char=? ch #\tab))
2394 (read-char)
2395 (consume-trailing-whitespace))
2396 ((char=? ch #\newline)
2397 (read-char))))))
0f2d19dd 2398 (-read (lambda ()
dc5c2038
MD
2399 (let ((val
2400 (let ((prompt (cond ((string? scm-repl-prompt)
2401 scm-repl-prompt)
2402 ((thunk? scm-repl-prompt)
2403 (scm-repl-prompt))
2404 (scm-repl-prompt "> ")
2405 (else ""))))
2406 (repl-reader prompt))))
2407
480977d0 2408 ;; As described in R4RS, the READ procedure updates the
e13c54c4 2409 ;; port to point to the first character past the end of
480977d0
JB
2410 ;; the external representation of the object. This
2411 ;; means that it doesn't consume the newline typically
2412 ;; found after an expression. This means that, when
2413 ;; debugging Guile with GDB, GDB gets the newline, which
2414 ;; it often interprets as a "continue" command, making
2415 ;; breakpoints kind of useless. So, consume any
2416 ;; trailing newline here, as well as any whitespace
2417 ;; before it.
e13c54c4
JB
2418 ;; But not if EOF, for control-D.
2419 (if (not (eof-object? val))
2420 (consume-trailing-whitespace))
04efd24d 2421 (run-hook after-read-hook)
0f2d19dd
JB
2422 (if (eof-object? val)
2423 (begin
7950df7c 2424 (repl-report-start-timing)
0f2d19dd
JB
2425 (if scm-repl-verbose
2426 (begin
2427 (newline)
2428 (display ";;; EOF -- quitting")
2429 (newline)))
2430 (quit 0)))
2431 val)))
2432
2433 (-eval (lambda (sourc)
2434 (repl-report-start-timing)
870777d7
KN
2435 (run-hook before-eval-hook sourc)
2436 (let ((val (start-stack 'repl-stack
2437 ;; If you change this procedure
2438 ;; (primitive-eval), please also
2439 ;; modify the repl-stack case in
2440 ;; save-stack so that stack cutting
2441 ;; continues to work.
2442 (primitive-eval sourc))))
2443 (run-hook after-eval-hook sourc)
2444 val)))
20edfbbd 2445
0f2d19dd 2446
44484f52
MD
2447 (-print (let ((maybe-print (lambda (result)
2448 (if (or scm-repl-print-unspecified
2449 (not (unspecified? result)))
2450 (begin
2451 (write result)
2452 (newline))))))
2453 (lambda (result)
2454 (if (not scm-repl-silent)
2455 (begin
870777d7 2456 (run-hook before-print-hook result)
3923fa6d 2457 (maybe-print result)
870777d7 2458 (run-hook after-print-hook result)
44484f52
MD
2459 (if scm-repl-verbose
2460 (repl-report))
2461 (force-output))))))
0f2d19dd 2462
8e44e7a0 2463 (-quit (lambda (args)
0f2d19dd
JB
2464 (if scm-repl-verbose
2465 (begin
2466 (display ";;; QUIT executed, repl exitting")
2467 (newline)
2468 (repl-report)))
8e44e7a0 2469 args))
0f2d19dd
JB
2470
2471 (-abort (lambda ()
2472 (if scm-repl-verbose
2473 (begin
2474 (display ";;; ABORT executed.")
2475 (newline)
2476 (repl-report)))
2477 (repl -read -eval -print))))
2478
8e44e7a0
GH
2479 (let ((status (error-catching-repl -read
2480 -eval
2481 -print)))
2482 (-quit status))))
20edfbbd 2483
0f2d19dd 2484
0f2d19dd 2485\f
44cf1f0f 2486;;; {IOTA functions: generating lists of numbers}
0f2d19dd 2487
e69cd299
MD
2488(define (iota n)
2489 (let loop ((count (1- n)) (result '()))
2490 (if (< count 0) result
2491 (loop (1- count) (cons count result)))))
0f2d19dd
JB
2492
2493\f
2494;;; {While}
2495;;;
2496;;; with `continue' and `break'.
2497;;;
2498
2499(defmacro while (cond . body)
2500 `(letrec ((continue (lambda () (or (not ,cond) (begin (begin ,@ body) (continue)))))
2501 (break (lambda val (apply throw 'break val))))
2502 (catch 'break
2503 (lambda () (continue))
2504 (lambda v (cadr v)))))
2505
7398c2c2
MD
2506;;; {collect}
2507;;;
2508;;; Similar to `begin' but returns a list of the results of all constituent
2509;;; forms instead of the result of the last form.
2510;;; (The definition relies on the current left-to-right
2511;;; order of evaluation of operands in applications.)
2512
2513(defmacro collect forms
2514 (cons 'list forms))
0f2d19dd 2515
8a6a8671
MV
2516;;; {with-fluids}
2517
2518;; with-fluids is a convenience wrapper for the builtin procedure
2519;; `with-fluids*'. The syntax is just like `let':
2520;;
2521;; (with-fluids ((fluid val)
2522;; ...)
2523;; body)
2524
2525(defmacro with-fluids (bindings . body)
2526 `(with-fluids* (list ,@(map car bindings)) (list ,@(map cadr bindings))
2527 (lambda () ,@body)))
2528
0f2d19dd
JB
2529\f
2530
2531;;; {Macros}
2532;;;
2533
2534;; actually....hobbit might be able to hack these with a little
2535;; coaxing
2536;;
2537
2538(defmacro define-macro (first . rest)
2539 (let ((name (if (symbol? first) first (car first)))
2540 (transformer
2541 (if (symbol? first)
2542 (car rest)
2543 `(lambda ,(cdr first) ,@rest))))
8add1522
KN
2544 `(eval-case
2545 ((load-toplevel)
2546 (define ,name (defmacro:transformer ,transformer)))
2547 (else
2548 (error "define-macro can only be used at the top level")))))
0f2d19dd
JB
2549
2550
2551(defmacro define-syntax-macro (first . rest)
2552 (let ((name (if (symbol? first) first (car first)))
2553 (transformer
2554 (if (symbol? first)
2555 (car rest)
2556 `(lambda ,(cdr first) ,@rest))))
8add1522
KN
2557 `(eval-case
2558 ((load-toplevel)
2559 (define ,name (defmacro:syntax-transformer ,transformer)))
2560 (else
2561 (error "define-syntax-macro can only be used at the top level")))))
645e38d9 2562
0f2d19dd
JB
2563\f
2564;;; {Module System Macros}
2565;;;
2566
532cf805
MV
2567;; Return a list of expressions that evaluate to the appropriate
2568;; arguments for resolve-interface according to SPEC.
2569
2570(define (compile-interface-spec spec)
2571 (define (make-keyarg sym key quote?)
2572 (cond ((or (memq sym spec)
2573 (memq key spec))
2574 => (lambda (rest)
2575 (if quote?
2576 (list key (list 'quote (cadr rest)))
2577 (list key (cadr rest)))))
2578 (else
2579 '())))
2580 (define (map-apply func list)
2581 (map (lambda (args) (apply func args)) list))
bbf5a913 2582 (define keys
532cf805
MV
2583 ;; sym key quote?
2584 '((:select #:select #t)
c614a00b 2585 (:hide #:hide #t)
f595ccfe 2586 (:prefix #:prefix #t)
6672871b 2587 (:renamer #:renamer #f)))
532cf805
MV
2588 (if (not (pair? (car spec)))
2589 `(',spec)
2590 `(',(car spec)
2591 ,@(apply append (map-apply make-keyarg keys)))))
2592
2593(define (keyword-like-symbol->keyword sym)
2594 (symbol->keyword (string->symbol (substring (symbol->string sym) 1))))
2595
2596(define (compile-define-module-args args)
2597 ;; Just quote everything except #:use-module and #:use-syntax. We
2598 ;; need to know about all arguments regardless since we want to turn
2599 ;; symbols that look like keywords into real keywords, and the
2600 ;; keyword args in a define-module form are not regular
2601 ;; (i.e. no-backtrace doesn't take a value).
2602 (let loop ((compiled-args `((quote ,(car args))))
2603 (args (cdr args)))
2604 (cond ((null? args)
2605 (reverse! compiled-args))
2606 ;; symbol in keyword position
2607 ((symbol? (car args))
2608 (loop compiled-args
2609 (cons (keyword-like-symbol->keyword (car args)) (cdr args))))
2610 ((memq (car args) '(#:no-backtrace #:pure))
2611 (loop (cons (car args) compiled-args)
2612 (cdr args)))
2613 ((null? (cdr args))
2614 (error "keyword without value:" (car args)))
2615 ((memq (car args) '(#:use-module #:use-syntax))
2616 (loop (cons* `(list ,@(compile-interface-spec (cadr args)))
2617 (car args)
2618 compiled-args)
2619 (cddr args)))
2620 ((eq? (car args) #:autoload)
2621 (loop (cons* `(quote ,(caddr args))
2622 `(quote ,(cadr args))
2623 (car args)
2624 compiled-args)
2625 (cdddr args)))
2626 (else
2627 (loop (cons* `(quote ,(cadr args))
2628 (car args)
2629 compiled-args)
2630 (cddr args))))))
2631
0f2d19dd 2632(defmacro define-module args
7b748b16 2633 `(eval-case
645e38d9 2634 ((load-toplevel)
bbf5a913 2635 (let ((m (process-define-module
532cf805 2636 (list ,@(compile-define-module-args args)))))
25afac98
MV
2637 (set-current-module m)
2638 m))
645e38d9
MV
2639 (else
2640 (error "define-module can only be used at the top level"))))
0f2d19dd 2641
532cf805
MV
2642;; The guts of the use-modules macro. Add the interfaces of the named
2643;; modules to the use-list of the current module, in order.
2644
482a28f9
MV
2645;; This function is called by "modules.c". If you change it, be sure
2646;; to change scm_c_use_module as well.
2647
532cf805 2648(define (process-use-modules module-interface-args)
d57da08b
MD
2649 (let ((interfaces (map (lambda (mif-args)
2650 (or (apply resolve-interface mif-args)
2651 (error "no such module" mif-args)))
2652 module-interface-args)))
2653 (call-with-deferred-observers
2654 (lambda ()
2655 (module-use-interfaces! (current-module) interfaces)))))
89da9036 2656
33cf699f 2657(defmacro use-modules modules
7b748b16 2658 `(eval-case
645e38d9 2659 ((load-toplevel)
532cf805
MV
2660 (process-use-modules
2661 (list ,@(map (lambda (m)
2662 `(list ,@(compile-interface-spec m)))
7b07e5ef
MD
2663 modules)))
2664 *unspecified*)
645e38d9
MV
2665 (else
2666 (error "use-modules can only be used at the top level"))))
33cf699f 2667
cf266109 2668(defmacro use-syntax (spec)
7b748b16 2669 `(eval-case
645e38d9 2670 ((load-toplevel)
7cbaee0c 2671 ,@(if (pair? spec)
532cf805
MV
2672 `((process-use-modules (list
2673 (list ,@(compile-interface-spec spec))))
7cbaee0c
MD
2674 (set-module-transformer! (current-module)
2675 ,(car (last-pair spec))))
cf743aea
MD
2676 `((set-module-transformer! (current-module) ,spec)))
2677 *unspecified*)
645e38d9 2678 (else
4879243c 2679 (error "use-syntax can only be used at the top level"))))
7a0ff2f8 2680
9123414e
DH
2681;; Dirk:FIXME:: This incorrect (according to R5RS) syntax needs to be changed
2682;; as soon as guile supports hygienic macros.
2683(define define-private define)
0f2d19dd
JB
2684
2685(defmacro define-public args
2686 (define (syntax)
2687 (error "bad syntax" (list 'define-public args)))
2688 (define (defined-name n)
2689 (cond
3c5af9ef
JB
2690 ((symbol? n) n)
2691 ((pair? n) (defined-name (car n)))
2692 (else (syntax))))
0f2d19dd 2693 (cond
645e38d9
MV
2694 ((null? args)
2695 (syntax))
2696 (#t
2697 (let ((name (defined-name (car args))))
2698 `(begin
a482f2cc
MV
2699 (define-private ,@args)
2700 (eval-case ((load-toplevel) (export ,name))))))))
0f2d19dd
JB
2701
2702(defmacro defmacro-public args
2703 (define (syntax)
2704 (error "bad syntax" (list 'defmacro-public args)))
2705 (define (defined-name n)
2706 (cond
645e38d9
MV
2707 ((symbol? n) n)
2708 (else (syntax))))
0f2d19dd 2709 (cond
645e38d9
MV
2710 ((null? args)
2711 (syntax))
2712 (#t
2713 (let ((name (defined-name (car args))))
2714 `(begin
d57da08b 2715 (eval-case ((load-toplevel) (export-syntax ,name)))
645e38d9 2716 (defmacro ,@args))))))
0f2d19dd 2717
89d06712 2718;; Export a local variable
482a28f9
MV
2719
2720;; This function is called from "modules.c". If you change it, be
2721;; sure to update "modules.c" as well.
2722
90847923
MD
2723(define (module-export! m names)
2724 (let ((public-i (module-public-interface m)))
2725 (for-each (lambda (name)
89d06712
MV
2726 (let ((var (module-ensure-local-variable! m name)))
2727 (module-add! public-i name var)))
2728 names)))
2729
f595ccfe
MD
2730(define (module-replace! m names)
2731 (let ((public-i (module-public-interface m)))
2732 (for-each (lambda (name)
2733 (let ((var (module-ensure-local-variable! m name)))
2734 (set-object-property! var 'replace #t)
2735 (module-add! public-i name var)))
2736 names)))
2737
89d06712
MV
2738;; Re-export a imported variable
2739;;
2740(define (module-re-export! m names)
2741 (let ((public-i (module-public-interface m)))
2742 (for-each (lambda (name)
2743 (let ((var (module-variable m name)))
2744 (cond ((not var)
2745 (error "Undefined variable:" name))
2746 ((eq? var (module-local-variable m name))
2747 (error "re-exporting local variable:" name))
2748 (else
2749 (module-add! public-i name var)))))
90847923
MD
2750 names)))
2751
a0cc0a01 2752(defmacro export names
7b748b16 2753 `(eval-case
645e38d9 2754 ((load-toplevel)
d57da08b
MD
2755 (call-with-deferred-observers
2756 (lambda ()
2757 (module-export! (current-module) ',names))))
645e38d9
MV
2758 (else
2759 (error "export can only be used at the top level"))))
a0cc0a01 2760
89d06712
MV
2761(defmacro re-export names
2762 `(eval-case
2763 ((load-toplevel)
d57da08b
MD
2764 (call-with-deferred-observers
2765 (lambda ()
2766 (module-re-export! (current-module) ',names))))
89d06712
MV
2767 (else
2768 (error "re-export can only be used at the top level"))))
2769
ab382f52 2770(defmacro export-syntax names
6aa9ea7c 2771 `(export ,@names))
a0cc0a01 2772
f2cbc0e5
DH
2773(defmacro re-export-syntax names
2774 `(re-export ,@names))
a0cc0a01 2775
0f2d19dd
JB
2776(define load load-module)
2777
7f24bc58 2778\f
f595ccfe
MD
2779;;; {Parameters}
2780;;;
2781
2782(define make-mutable-parameter
2783 (let ((make (lambda (fluid converter)
2784 (lambda args
2785 (if (null? args)
2786 (fluid-ref fluid)
2787 (fluid-set! fluid (converter (car args))))))))
2788 (lambda (init . converter)
2789 (let ((fluid (make-fluid))
2790 (converter (if (null? converter)
2791 identity
2792 (car converter))))
2793 (fluid-set! fluid (converter init))
2794 (make fluid converter)))))
2795
2796\f
7b07e5ef
MD
2797;;; {Handling of duplicate imported bindings}
2798;;;
2799
2800;; Duplicate handlers take the following arguments:
2801;;
2802;; module importing module
2803;; name conflicting name
2804;; int1 old interface where name occurs
2805;; val1 value of binding in old interface
2806;; int2 new interface where name occurs
2807;; val2 value of binding in new interface
2808;; var previous resolution or #f
2809;; val value of previous resolution
2810;;
2811;; A duplicate handler can take three alternative actions:
2812;;
2813;; 1. return #f => leave responsibility to next handler
2814;; 2. exit with an error
2815;; 3. return a variable resolving the conflict
2816;;
2817
2818(define duplicate-handlers
2819 (let ((m (make-module 7)))
f595ccfe
MD
2820
2821 (define (check module name int1 val1 int2 val2 var val)
2822 (scm-error 'misc-error
2823 #f
8dd18cea 2824 "~A: `~A' imported from both ~A and ~A"
f595ccfe
MD
2825 (list (module-name module)
2826 name
2827 (module-name int1)
2828 (module-name int2))
2829 #f))
2830
65bed4aa
MD
2831 (define (warn module name int1 val1 int2 val2 var val)
2832 (format #t
2833 "WARNING: ~A: `~A' imported from both ~A and ~A\n"
2834 (module-name module)
2835 name
2836 (module-name int1)
2837 (module-name int2))
2838 #f)
f595ccfe
MD
2839
2840 (define (replace module name int1 val1 int2 val2 var val)
2841 (let ((old (or (and var (object-property var 'replace) var)
2842 (module-variable int1 name)))
2843 (new (module-variable int2 name)))
2844 (if (object-property old 'replace)
2845 (and (or (eq? old new)
2846 (not (object-property new 'replace)))
2847 old)
2848 (and (object-property new 'replace)
2849 new))))
2850
65bed4aa
MD
2851 (define (warn-override-core module name int1 val1 int2 val2 var val)
2852 (and (eq? int1 the-scm-module)
2853 (begin
2854 (format #t
2855 "WARNING: ~A: imported module ~A overrides core binding `~A'\n"
2856 (module-name module)
2857 (module-name int2)
2858 name)
2859 (module-local-variable int2 name))))
f595ccfe 2860
65bed4aa
MD
2861 (define (first module name int1 val1 int2 val2 var val)
2862 (or var (module-local-variable int1 name)))
f595ccfe 2863
65bed4aa
MD
2864 (define (last module name int1 val1 int2 val2 var val)
2865 (module-local-variable int2 name))
f595ccfe 2866
65bed4aa
MD
2867 (define (noop module name int1 val1 int2 val2 var val)
2868 #f)
2869
7b07e5ef
MD
2870 (set-module-name! m 'duplicate-handlers)
2871 (set-module-kind! m 'interface)
f595ccfe
MD
2872 (module-define! m 'check check)
2873 (module-define! m 'warn warn)
2874 (module-define! m 'replace replace)
2875 (module-define! m 'warn-override-core warn-override-core)
2876 (module-define! m 'first first)
2877 (module-define! m 'last last)
65bed4aa
MD
2878 (module-define! m 'merge-generics noop)
2879 (module-define! m 'merge-accessors noop)
7b07e5ef
MD
2880 m))
2881
f595ccfe 2882(define (lookup-duplicates-handlers handler-names)
109c2c9f
MD
2883 (and handler-names
2884 (map (lambda (handler-name)
2885 (or (module-symbol-local-binding
2886 duplicate-handlers handler-name #f)
2887 (error "invalid duplicate handler name:"
2888 handler-name)))
2889 (if (list? handler-names)
2890 handler-names
2891 (list handler-names)))))
f595ccfe 2892
70a459e3
MD
2893(define default-duplicate-binding-procedures
2894 (make-mutable-parameter #f))
2895
2896(define default-duplicate-binding-handler
6496a663 2897 (make-mutable-parameter '(replace warn-override-core warn last)
70a459e3
MD
2898 (lambda (handler-names)
2899 (default-duplicate-binding-procedures
2900 (lookup-duplicates-handlers handler-names))
2901 handler-names)))
f595ccfe 2902
7b07e5ef
MD
2903(define (make-duplicates-interface)
2904 (let ((m (make-module)))
c614a00b 2905 (set-module-kind! m 'custom-interface)
7b07e5ef
MD
2906 (set-module-name! m 'duplicates)
2907 m))
2908
7b07e5ef 2909(define (process-duplicates module interface)
8d8dac1f 2910 (let* ((duplicates-handlers (or (module-duplicates-handlers module)
70a459e3 2911 (default-duplicate-binding-procedures)))
8d8dac1f 2912 (duplicates-interface (module-duplicates-interface module)))
7b07e5ef
MD
2913 (module-for-each
2914 (lambda (name var)
109c2c9f
MD
2915 (cond ((module-import-interface module name)
2916 =>
2917 (lambda (prev-interface)
2918 (let ((var1 (module-local-variable prev-interface name))
2919 (var2 (module-local-variable interface name)))
2920 (if (not (eq? var1 var2))
2921 (begin
2922 (if (not duplicates-interface)
2923 (begin
2924 (set! duplicates-interface
2925 (make-duplicates-interface))
8d8dac1f
MD
2926 (set-module-duplicates-interface!
2927 module
2928 duplicates-interface)))
109c2c9f
MD
2929 (let* ((var (module-local-variable duplicates-interface
2930 name))
2931 (val (and var
2932 (variable-bound? var)
2933 (variable-ref var))))
2934 (let loop ((duplicates-handlers duplicates-handlers))
2935 (cond ((null? duplicates-handlers))
2936 (((car duplicates-handlers)
2937 module
2938 name
2939 prev-interface
2940 (and (variable-bound? var1)
2941 (variable-ref var1))
2942 interface
2943 (and (variable-bound? var2)
2944 (variable-ref var2))
2945 var
2946 val)
2947 =>
2948 (lambda (var)
2949 (module-add! duplicates-interface name var)))
2950 (else
2951 (loop (cdr duplicates-handlers)))))))))))))
7b07e5ef
MD
2952 interface)))
2953
2954\f
7f24bc58
MG
2955
2956;;; {`cond-expand' for SRFI-0 support.}
2957;;;
2958;;; This syntactic form expands into different commands or
2959;;; definitions, depending on the features provided by the Scheme
2960;;; implementation.
2961;;;
2962;;; Syntax:
2963;;;
2964;;; <cond-expand>
2965;;; --> (cond-expand <cond-expand-clause>+)
2966;;; | (cond-expand <cond-expand-clause>* (else <command-or-definition>))
2967;;; <cond-expand-clause>
2968;;; --> (<feature-requirement> <command-or-definition>*)
2969;;; <feature-requirement>
2970;;; --> <feature-identifier>
2971;;; | (and <feature-requirement>*)
2972;;; | (or <feature-requirement>*)
2973;;; | (not <feature-requirement>)
2974;;; <feature-identifier>
2975;;; --> <a symbol which is the name or alias of a SRFI>
2976;;;
2977;;; Additionally, this implementation provides the
2978;;; <feature-identifier>s `guile' and `r5rs', so that programs can
2979;;; determine the implementation type and the supported standard.
2980;;;
2981;;; Currently, the following feature identifiers are supported:
2982;;;
f41be016 2983;;; guile r5rs srfi-0
7f24bc58
MG
2984;;;
2985;;; Remember to update the features list when adding more SRFIs.
2986
b9b8f9da 2987(define %cond-expand-features
f41be016
MG
2988 ;; Adjust the above comment when changing this.
2989 '(guile r5rs srfi-0))
1d00af09 2990
b9b8f9da
MG
2991;; This table maps module public interfaces to the list of features.
2992;;
2993(define %cond-expand-table (make-hash-table 31))
2994
2995;; Add one or more features to the `cond-expand' feature list of the
2996;; module `module'.
2997;;
2998(define (cond-expand-provide module features)
2999 (let ((mod (module-public-interface module)))
3000 (and mod
3001 (hashq-set! %cond-expand-table mod
3002 (append (hashq-ref %cond-expand-table mod '())
3003 features)))))
3004
9f79272a
MV
3005(define cond-expand
3006 (procedure->memoizing-macro
3007 (lambda (exp env)
3008 (let ((clauses (cdr exp))
3009 (syntax-error (lambda (cl)
3010 (error "invalid clause in `cond-expand'" cl))))
3011 (letrec
3012 ((test-clause
3013 (lambda (clause)
7f24bc58 3014 (cond
9f79272a
MV
3015 ((symbol? clause)
3016 (or (memq clause %cond-expand-features)
3017 (let lp ((uses (module-uses (env-module env))))
3018 (if (pair? uses)
3019 (or (memq clause
3020 (hashq-ref %cond-expand-table
3021 (car uses) '()))
3022 (lp (cdr uses)))
3023 #f))))
3024 ((pair? clause)
3025 (cond
3026 ((eq? 'and (car clause))
3027 (let lp ((l (cdr clause)))
3028 (cond ((null? l)
3029 #t)
3030 ((pair? l)
3031 (and (test-clause (car l)) (lp (cdr l))))
3032 (else
3033 (syntax-error clause)))))
3034 ((eq? 'or (car clause))
3035 (let lp ((l (cdr clause)))
3036 (cond ((null? l)
3037 #f)
3038 ((pair? l)
3039 (or (test-clause (car l)) (lp (cdr l))))
3040 (else
3041 (syntax-error clause)))))
3042 ((eq? 'not (car clause))
3043 (cond ((not (pair? (cdr clause)))
3044 (syntax-error clause))
3045 ((pair? (cddr clause))
3046 ((syntax-error clause))))
3047 (not (test-clause (cadr clause))))
3048 (else
3049 (syntax-error clause))))
3050 (else
3051 (syntax-error clause))))))
3052 (let lp ((c clauses))
3053 (cond
3054 ((null? c)
3055 (error "Unfulfilled `cond-expand'"))
3056 ((not (pair? c))
7f24bc58 3057 (syntax-error c))
9f79272a
MV
3058 ((not (pair? (car c)))
3059 (syntax-error (car c)))
3060 ((test-clause (caar c))
3061 `(begin ,@(cdar c)))
3062 ((eq? (caar c) 'else)
3063 (if (pair? (cdr c))
3064 (syntax-error c))
3065 `(begin ,@(cdar c)))
3066 (else
3067 (lp (cdr c))))))))))
0f2d19dd 3068
f41be016
MG
3069;; This procedure gets called from the startup code with a list of
3070;; numbers, which are the numbers of the SRFIs to be loaded on startup.
3071;;
3072(define (use-srfis srfis)
3073 (let lp ((s srfis))
3074 (if (pair? s)
f8a502cb
TTN
3075 (let* ((srfi (string->symbol
3076 (string-append "srfi-" (number->string (car s)))))
3077 (mod-i (resolve-interface (list 'srfi srfi))))
3078 (module-use! (current-module) mod-i)
f8a502cb
TTN
3079 (lp (cdr s))))))
3080
0f2d19dd 3081\f
9d774814 3082
9aca88c3
JB
3083;;; {Load emacs interface support if emacs option is given.}
3084
645e38d9 3085(define (named-module-use! user usee)
89d06712 3086 (module-use! (resolve-module user) (resolve-interface usee)))
645e38d9 3087
9aca88c3 3088(define (load-emacs-interface)
fb1b76f4
TTN
3089 (and (provided? 'debug-extensions)
3090 (debug-enable 'backtrace))
645e38d9 3091 (named-module-use! '(guile-user) '(ice-9 emacs)))
9aca88c3
JB
3092
3093\f
0f2d19dd 3094
755457ec
MD
3095(define using-readline?
3096 (let ((using-readline? (make-fluid)))
3097 (make-procedure-with-setter
3098 (lambda () (fluid-ref using-readline?))
3099 (lambda (v) (fluid-set! using-readline? v)))))
3100
20edfbbd 3101(define (top-repl)
615bfe72
MV
3102 (let ((guile-user-module (resolve-module '(guile-user))))
3103
3104 ;; Load emacs interface support if emacs option is given.
454b82f4
MD
3105 (if (and (module-defined? guile-user-module 'use-emacs-interface)
3106 (module-ref guile-user-module 'use-emacs-interface))
615bfe72
MV
3107 (load-emacs-interface))
3108
3109 ;; Use some convenient modules (in reverse order)
bbf5a913 3110
615bfe72 3111 (if (provided? 'regex)
89d06712 3112 (module-use! guile-user-module (resolve-interface '(ice-9 regex))))
615bfe72 3113 (if (provided? 'threads)
89d06712 3114 (module-use! guile-user-module (resolve-interface '(ice-9 threads))))
615bfe72 3115 ;; load debugger on demand
bbf5a913 3116 (module-use! guile-user-module
615bfe72
MV
3117 (make-autoload-interface guile-user-module
3118 '(ice-9 debugger) '(debug)))
89d06712
MV
3119 (module-use! guile-user-module (resolve-interface '(ice-9 session)))
3120 (module-use! guile-user-module (resolve-interface '(ice-9 debug)))
615bfe72 3121 ;; so that builtin bindings will be checked first
89d06712 3122 (module-use! guile-user-module (resolve-interface '(guile)))
615bfe72
MV
3123
3124 (set-current-module guile-user-module)
3125
3126 (let ((old-handlers #f)
3127 (signals (if (provided? 'posix)
3128 `((,SIGINT . "User interrupt")
3129 (,SIGFPE . "Arithmetic error")
3130 (,SIGBUS . "Bad memory access (bus error)")
3131 (,SIGSEGV
3132 . "Bad memory access (Segmentation violation)"))
3133 '())))
3134
3135 (dynamic-wind
3136
3137 ;; call at entry
3138 (lambda ()
3139 (let ((make-handler (lambda (msg)
3140 (lambda (sig)
3141 ;; Make a backup copy of the stack
3142 (fluid-set! before-signal-stack
3143 (fluid-ref the-last-stack))
bb00edfa 3144 (save-stack 2)
615bfe72
MV
3145 (scm-error 'signal
3146 #f
3147 msg
3148 #f
3149 (list sig))))))
3150 (set! old-handlers
3151 (map (lambda (sig-msg)
3152 (sigaction (car sig-msg)
3153 (make-handler (cdr sig-msg))))
3154 signals))))
bbf5a913 3155
615bfe72
MV
3156 ;; the protected thunk.
3157 (lambda ()
3158 (let ((status (scm-style-repl)))
3159 (run-hook exit-hook)
3160 status))
bbf5a913 3161
615bfe72
MV
3162 ;; call at exit.
3163 (lambda ()
3164 (map (lambda (sig-msg old-handler)
3165 (if (not (car old-handler))
3166 ;; restore original C handler.
3167 (sigaction (car sig-msg) #f)
3168 ;; restore Scheme handler, SIG_IGN or SIG_DFL.
3169 (sigaction (car sig-msg)
3170 (car old-handler)
3171 (cdr old-handler))))
3172 signals old-handlers))))))
0f2d19dd 3173
02b754d3
GH
3174(defmacro false-if-exception (expr)
3175 `(catch #t (lambda () ,expr)
3176 (lambda args #f)))
3177
2055a1bc
MD
3178;;; This hook is run at the very end of an interactive session.
3179;;;
3e3cec45 3180(define exit-hook (make-hook))
2055a1bc 3181
4d31f0da 3182\f
d866f445
MV
3183(append! %load-path (list "."))
3184
3185;; Place the user in the guile-user module.
3186;;
6eb396fe 3187
615bfe72 3188(define-module (guile-user))
6d36532c 3189
20edfbbd 3190;;; boot-9.scm ends here