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