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