;;; installed-scm-file
-;;;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+;;;; Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002, 2003 Free Software Foundation, Inc.
;;;;
;;;; This program is free software; you can redistribute it and/or modify
;;;; it under the terms of the GNU General Public License as published by
(and (memq feature *features*) #t))
(begin-deprecated
- (define feature? provided?))
+ (define (feature? sym)
+ (issue-deprecation-warning
+ "`feature?' is deprecated. Use `provided?' instead.")
+ (provided? sym)))
;;; let format alias simple-format until the more complete version is loaded
(define format simple-format)
(define (1+ n) (+ n 1))
(define (1- n) (+ n -1))
(define (and=> value procedure) (and value (procedure value)))
-(define (make-hash-table k) (make-vector k '()))
;;; apply-to-args is functionally redundant with apply and, worse,
;;; is less general than apply since it only takes two arguments.
(define (tms:cutime obj) (vector-ref obj 3))
(define (tms:cstime obj) (vector-ref obj 4))
-(define (file-position . args) (apply ftell args))
-(define (file-set-position . args) (apply fseek args))
+(define file-position ftell)
+(define (file-set-position port offset . whence)
+ (let ((whence (if (eq? whence '()) SEEK_SET (car whence))))
+ (seek port offset whence)))
(define (move->fdes fd/port fd)
(cond ((integer? fd/port)
(define (sqrt z)
(if (real? z)
(if (negative? z) (make-rectangular 0 ($sqrt (- z)))
- ($sqrt z))
+ ($sqrt z))
(make-polar ($sqrt (magnitude z)) (/ (angle z) 2))))
(define expt
(let ((integer-expt integer-expt))
(lambda (z1 z2)
(cond ((integer? z2)
- (if (>= z2 0)
- (integer-expt z1 z2)
- (/ 1 (integer-expt z1 (- z2)))))
+ (if (negative? z2)
+ (/ 1 (integer-expt z1 (- z2)))
+ (integer-expt z1 z2)))
((and (real? z2) (real? z1) (>= z1 0))
($expt z1 z2))
(else
(if (> (length args) 3)
(error "Too many args to make-module." args))
- (let ((size (parse-arg 0 1021))
+ (let ((size (parse-arg 0 31))
(uses (parse-arg 1 '()))
(binder (parse-arg 2 #f)))
(error
"Lazy-binder expected to be a procedure or #f." binder))
- (let ((module (module-constructor (make-vector size '())
+ (let ((module (module-constructor (and (not (zero? size))
+ (make-hash-table size))
uses binder #f #f #f #f
'()
(make-weak-value-hash-table 31)
;;
(define (module-symbol-local-binding m v . opt-val)
(let ((var (module-local-variable m v)))
- (if var
+ (if (and var (variable-bound? var))
(variable-ref var)
(if (not (null? opt-val))
(car opt-val)
;;
(define (module-symbol-binding m v . opt-val)
(let ((var (module-variable m v)))
- (if var
+ (if (and var (variable-bound? var))
(variable-ref var)
(if (not (null? opt-val))
(car opt-val)
;; make sure that a symbol is undefined in the local namespace of M.
;;
(define (module-remove! m v)
- (module-obarray-remove! (module-obarray m) v)
+ (module-obarray-remove! (module-obarray m) v)
(module-modified m))
(define (module-clear! m)
- (vector-fill! (module-obarray m) '())
+ (hash-clear! (module-obarray m))
(module-modified m))
;; MODULE-FOR-EACH -- exported
;; Call PROC on each symbol in MODULE, with arguments of (SYMBOL VARIABLE).
;;
(define (module-for-each proc module)
- (let ((obarray (module-obarray module)))
- (do ((index 0 (+ index 1))
- (end (vector-length obarray)))
- ((= index end))
- (for-each
- (lambda (bucket)
- (proc (car bucket) (cdr bucket)))
- (vector-ref obarray index)))))
-
+ (hash-for-each proc (module-obarray module)))
(define (module-map proc module)
- (let* ((obarray (module-obarray module))
- (end (vector-length obarray)))
-
- (let loop ((i 0)
- (answer '()))
- (if (= i end)
- answer
- (loop (+ 1 i)
- (append!
- (map (lambda (bucket)
- (proc (car bucket) (cdr bucket)))
- (vector-ref obarray i))
- answer))))))
+ (hash-map proc (module-obarray module)))
+
\f
;;; {Low Level Bootstrapping}
(cons interface (delq! interface (module-uses module))))
(module-modified module))
+;; MODULE-USE-INTERFACES! module interfaces
+;;
+;; Same as MODULE-USE! but add multiple interfaces and check for duplicates
+;;
+(define (module-use-interfaces! module interfaces)
+ (let* ((duplicates-info (module-duplicates-info module))
+ (duplicates-handlers? (car duplicates-info))
+ (uses (module-uses module)))
+ ;; remove duplicates-interface
+ (set! uses (delq! (cdr duplicates-info) uses))
+ ;; remove interfaces to be added
+ (for-each (lambda (interface)
+ (set! uses (delq! interface uses)))
+ interfaces)
+ ;; add interfaces to use list
+ (set-module-uses! module uses)
+ (for-each (lambda (interface)
+ (and duplicates-handlers?
+ ;; perform duplicate checking
+ (process-duplicates module interface))
+ (set! uses (cons interface uses))
+ (set-module-uses! module uses))
+ interfaces)
+ ;; add duplicates interface
+ (if (cdr duplicates-info)
+ (set-module-uses! module (cons (cdr duplicates-info) uses)))
+ (module-modified module)))
+
\f
;;; {Recursive Namespaces}
;;;
(module-ref m '%module-public-interface #f))
(define (set-module-public-interface! m i)
(module-define! m '%module-public-interface i))
+(define (module-duplicates-info m)
+ (or (module-ref m '%module-duplicates-info #f) (cons #f #f)))
+(define (set-module-duplicates-info! m i)
+ (module-define! m '%module-duplicates-info i))
(define (set-system-module! m s)
(set-procedure-property! (module-eval-closure m) 'system-module s))
(define the-root-module (make-root-module))
(define the-scm-module (make-scm-module))
(set-module-public-interface! the-root-module the-scm-module)
+(set-module-duplicates-info! the-root-module (cons #f #f))
(set-module-name! the-root-module '(guile))
(set-module-name! the-scm-module '(guile))
(set-module-kind! the-scm-module 'interface)
(let ((interface (make-module 31)))
(set-module-name! interface (module-name module))
(set-module-kind! interface 'interface)
- (set-module-public-interface! module interface))))
+ (set-module-public-interface! module interface)
+ (set-module-duplicates-info! module (cons #f #f)))))
(if (and (not (memq the-scm-module (module-uses module)))
(not (eq? module the-root-module)))
- (set-module-uses! module (append (module-uses module) (list the-scm-module)))))
+ (set-module-uses! module
+ (append (module-uses module) (list the-scm-module)))))
;; NOTE: This binding is used in libguile/modules.c.
;;
(re-exports '()))
(if (null? kws)
(begin
- (for-each (lambda (interface)
- (module-use! module interface))
- (reverse reversed-interfaces))
+ (module-use-interfaces! module (reverse reversed-interfaces))
(module-export! module exports)
(module-re-export! module re-exports))
(case (car kws)
((#:pure)
(purify-module! module)
(loop (cdr kws) reversed-interfaces exports re-exports))
+ ((#:duplicates)
+ (if (not (pair? (cdr kws)))
+ (unrecognized kws))
+ (set-car! (module-duplicates-info module)
+ (map (lambda (handler-name)
+ (or (module-symbol-local-binding
+ duplicate-handlers handler-name #f)
+ (error "invalid duplicate handler name:"
+ handler-name)))
+ (if (list? (cadr kws))
+ (cadr kws)
+ (list (cadr kws)))))
+ (loop (cddr kws) reversed-interfaces exports re-exports))
((#:export #:export-syntax)
(or (pair? (cdr kws))
(unrecognized kws))
(append (cadr kws) re-exports)))
(else
(unrecognized kws)))))
+ (run-hook module-defined-hook module)
module))
+;; `module-defined-hook' is a hook that is run whenever a new module
+;; is defined. Its members are called with one argument, the new
+;; module.
+(define module-defined-hook (make-hook 1))
+
;;; {Autoload}
(define (make-autoload-interface module name bindings)
;;; {Defmacros}
;;;
-(define macro-table (make-weak-key-hash-table 523))
-(define xformer-table (make-weak-key-hash-table 523))
+(define macro-table (make-weak-key-hash-table 61))
+(define xformer-table (make-weak-key-hash-table 61))
(define (defmacro? m) (hashq-ref macro-table m))
(define (assert-defmacro?! m) (hashq-set! macro-table m #t))
(set! options (delq! flag options)))
flags)
(,interface options)
- (,interface)))))
-
- (make-set! (lambda (interface)
- `((name exp)
- (,'quasiquote
- (begin (,interface (append (,interface)
- (list '(,'unquote name)
- (,'unquote exp))))
- (,interface)))))))
- (procedure->macro
+ (,interface))))))
+ (procedure->memoizing-macro
(lambda (exp env)
- (cons 'begin
- (let* ((option-group (cadr exp))
- (interface (car option-group)))
- (append (map (lambda (name constructor)
- `(define ,name
- ,(constructor interface)))
- (cadr option-group)
- (list make-options
- make-enable
- make-disable))
- (map (lambda (name constructor)
- `(defmacro ,name
- ,@(constructor interface)))
- (caddr option-group)
- (list make-set!)))))))))
+ (let* ((option-group (cadr exp))
+ (interface (car option-group))
+ (options/enable/disable (cadr option-group)))
+ `(begin
+ (define ,(car options/enable/disable)
+ ,(make-options interface))
+ (define ,(cadr options/enable/disable)
+ ,(make-enable interface))
+ (define ,(caddr options/enable/disable)
+ ,(make-disable interface))
+ (defmacro ,(caaddr option-group) (opt val)
+ `(,,(car options/enable/disable)
+ (append (,,(car options/enable/disable))
+ (list ',opt ,val))))))))))
(define-option-interface
(eval-options-interface
(lambda ()
(lazy-catch #t
(lambda ()
- (dynamic-wind
- (lambda () (unmask-signals))
+ (call-with-unblocked-asyncs
(lambda ()
(with-traps
(lambda ()
(set! first #f)
(let loop ((v (thunk)))
(loop (thunk)))
- #f)))
- (lambda () (mask-signals))))
+ #f)))))
lazy-handler-dispatch))
(#t
(error "sorry, not implemented")))))
(set! batch-mode? (lambda () (not interactive)))
- (loop (lambda () #t))))
+ (call-with-blocked-asyncs
+ (lambda () (loop (lambda () #t))))))
;;(define the-last-stack (make-fluid)) Defined by scm_init_backtrace ()
(define before-signal-stack (make-fluid))
;; to change scm_c_use_module as well.
(define (process-use-modules module-interface-args)
- (for-each (lambda (mif-args)
- (let ((mod-iface (apply resolve-interface mif-args)))
- (or mod-iface
- (error "no such module" mif-args))
- (module-use! (current-module) mod-iface)))
- module-interface-args))
+ (module-use-interfaces! (current-module)
+ (map (lambda (mif-args)
+ (or (apply resolve-interface mif-args)
+ (error "no such module" mif-args)))
+ module-interface-args)))
(defmacro use-modules modules
`(eval-case
(process-use-modules
(list ,@(map (lambda (m)
`(list ,@(compile-interface-spec m)))
- modules))))
+ modules)))
+ *unspecified*)
(else
(error "use-modules can only be used at the top level"))))
(list ,@(compile-interface-spec spec))))
(set-module-transformer! (current-module)
,(car (last-pair spec))))
- `((set-module-transformer! (current-module) ,spec))))
+ `((set-module-transformer! (current-module) ,spec)))
+ *unspecified*)
(else
(error "use-syntax can only be used at the top level"))))
+;; Dirk:FIXME:: This incorrect (according to R5RS) syntax needs to be changed
+;; as soon as guile supports hygienic macros.
(define define-private define)
(defmacro define-public args
(else
(error "re-export can only be used at the top level"))))
-(define export-syntax export)
-(define re-export-syntax re-export)
+(defmacro export-syntax names
+ `(export ,@names))
+(defmacro re-export-syntax names
+ `(re-export ,@names))
(define load load-module)
\f
+;;; {Handling of duplicate imported bindings}
+;;;
+
+;; Duplicate handlers take the following arguments:
+;;
+;; module importing module
+;; name conflicting name
+;; int1 old interface where name occurs
+;; val1 value of binding in old interface
+;; int2 new interface where name occurs
+;; val2 value of binding in new interface
+;; var previous resolution or #f
+;; val value of previous resolution
+;;
+;; A duplicate handler can take three alternative actions:
+;;
+;; 1. return #f => leave responsibility to next handler
+;; 2. exit with an error
+;; 3. return a variable resolving the conflict
+;;
+
+(define duplicate-handlers
+ (let ((m (make-module 7)))
+ (set-module-name! m 'duplicate-handlers)
+ (set-module-kind! m 'interface)
+ (module-define! m 'check
+ (lambda (module name int1 val1 int2 val2 var val)
+ (scm-error 'misc-error
+ #f
+ "module ~A: duplicate binding ~A imported from ~A and ~A"
+ (list (module-name module)
+ name
+ (module-name int1)
+ (module-name int2))
+ #f)))
+ (module-define! m 'first
+ (lambda (module name int1 val1 int2 val2 var val)
+ (or var (module-local-variable int1 name))))
+ (module-define! m 'last
+ (lambda (module name int1 val1 int2 val2 var val)
+ (module-local-variable int2 name)))
+ m))
+
+(define (make-duplicates-interface)
+ (let ((m (make-module)))
+ (set-module-kind! m 'interface)
+ (set-module-name! m 'duplicates)
+ m))
+
+(define (module-symbol-interface module sym)
+ (or-map (lambda (interface)
+ (module-search (lambda (interface sym)
+ (and (module-local-variable interface sym)
+ interface))
+ interface
+ sym))
+ (module-uses module)))
+
+(define (process-duplicates module interface)
+ (let* ((duplicates-info (module-duplicates-info module))
+ (handlers (car duplicates-info))
+ (d-interface (cdr duplicates-info)))
+ (module-for-each
+ (lambda (name var)
+ (let ((prev-interface (module-symbol-interface module name)))
+ (if prev-interface
+ (begin
+ (if (not d-interface)
+ (begin
+ (set! d-interface (make-duplicates-interface))
+ (set-cdr! duplicates-info d-interface)))
+ (let* ((var (module-local-variable d-interface name))
+ (val (and var (variable-bound? var) (variable-ref var))))
+ (let loop ((handlers handlers))
+ (cond ((null? handlers))
+ (((car handlers)
+ module
+ name
+ prev-interface
+ (module-symbol-local-binding prev-interface name #f)
+ interface
+ (module-symbol-local-binding interface name #f)
+ var
+ val)
+ =>
+ (lambda (var)
+ (module-add! d-interface name var)))
+ (else
+ (loop (cdr handlers))))))))))
+ interface)))
+
+\f
;;; {`cond-expand' for SRFI-0 support.}
;;;
(let ((guile-user-module (resolve-module '(guile-user))))
;; Load emacs interface support if emacs option is given.
- (if (and (module-defined? the-root-module 'use-emacs-interface)
- (module-ref the-root-module 'use-emacs-interface))
+ (if (and (module-defined? guile-user-module 'use-emacs-interface)
+ (module-ref guile-user-module 'use-emacs-interface))
(load-emacs-interface))
;; Use some convenient modules (in reverse order)
;; Make a backup copy of the stack
(fluid-set! before-signal-stack
(fluid-ref the-last-stack))
- (save-stack %deliver-signals)
+ (save-stack 2)
(scm-error 'signal
#f
msg