📄 boot-9.scm
字号:
;; module-add! module symbol var;;;; ensure a particular variable for V in the local namespace of M.;;(define (module-add! m v var) (if (not (variable? var)) (error "Bad variable to module-add!" var)) (module-obarray-set! (module-obarray m) v var) (module-modified m));; module-remove!;;;; 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-modified m))(define (module-clear! m) (vector-fill! (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)))))(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))))));;; {Low Level Bootstrapping};;;;; make-root-module;; A root module uses the pre-modules-obarray as its obarray. This;; special obarray accumulates all bindings that have been established;; before the module system is fully booted.;;;; (The obarray continues to be used by code that has been closed over;; before the module system has been booted.)(define (make-root-module) (let ((m (make-module 0))) (set-module-obarray! m (%get-pre-modules-obarray)) m));; make-scm-module;; The root interface is a module that uses the same obarray as the;; root module. It does not allow new definitions, tho.(define (make-scm-module) (let ((m (make-module 0))) (set-module-obarray! m (%get-pre-modules-obarray)) (set-module-eval-closure! m (standard-interface-eval-closure m)) m));;; {Module-based Loading};;;(define (save-module-excursion thunk) (let ((inner-module (current-module)) (outer-module #f)) (dynamic-wind (lambda () (set! outer-module (current-module)) (set-current-module inner-module) (set! inner-module #f)) thunk (lambda () (set! inner-module (current-module)) (set-current-module outer-module) (set! outer-module #f)))))(define basic-load load)(define (load-module filename) (save-module-excursion (lambda () (let ((oldname (and (current-load-port) (port-filename (current-load-port))))) (basic-load (if (and oldname (> (string-length filename) 0) (not (char=? (string-ref filename 0) #\/)) (not (string=? (dirname oldname) "."))) (string-append (dirname oldname) "/" filename) filename))))));;; {MODULE-REF -- exported};;;; Returns the value of a variable called NAME in MODULE or any of its;; used modules. If there is no such variable, then if the optional third;; argument DEFAULT is present, it is returned; otherwise an error is signaled.;;(define (module-ref module name . rest) (let ((variable (module-variable module name))) (if (and variable (variable-bound? variable)) (variable-ref variable) (if (null? rest) (error "No variable named" name 'in module) (car rest) ; default value ))));; MODULE-SET! -- exported;;;; Sets the variable called NAME in MODULE (or in a module that MODULE uses);; to VALUE; if there is no such variable, an error is signaled.;;(define (module-set! module name value) (let ((variable (module-variable module name))) (if variable (variable-set! variable value) (error "No variable named" name 'in module))));; MODULE-DEFINE! -- exported;;;; Sets the variable called NAME in MODULE to VALUE; if there is no such;; variable, it is added first.;;(define (module-define! module name value) (let ((variable (module-local-variable module name))) (if variable (begin (variable-set! variable value) (module-modified module)) (let ((variable (make-variable value))) (variable-set-name-hint! variable name) (module-add! module name variable)))));; MODULE-DEFINED? -- exported;;;; Return #t iff NAME is defined in MODULE (or in a module that MODULE;; uses);;(define (module-defined? module name) (let ((variable (module-variable module name))) (and variable (variable-bound? variable))));; MODULE-USE! module interface;;;; Add INTERFACE to the list of interfaces used by MODULE.;;(define (module-use! module interface) (set-module-uses! module (cons interface (delq! interface (module-uses module)))) (module-modified module));;; {Recursive Namespaces};;;;;;;;; A hierarchical namespace emerges if we consider some module to be;;; root, and variables bound to modules as nested namespaces.;;;;;; The routines in this file manage variable names in hierarchical namespace.;;; Each variable name is a list of elements, looked up in successively nested;;; modules.;;;;;; (nested-ref some-root-module '(foo bar baz));;; => <value of a variable named baz in the module bound to bar in;;; the module bound to foo in some-root-module>;;;;;;;;; There are:;;;;;; ;; a-root is a module;;; ;; name is a list of symbols;;;;;; nested-ref a-root name;;; nested-set! a-root name val;;; nested-define! a-root name val;;; nested-remove! a-root name;;;;;;;;; (current-module) is a natural choice for a-root so for convenience there are;;; also:;;;;;; local-ref name == nested-ref (current-module) name;;; local-set! name val == nested-set! (current-module) name val;;; local-define! name val == nested-define! (current-module) name val;;; local-remove! name == nested-remove! (current-module) name;;;(define (nested-ref root names) (let loop ((cur root) (elts names)) (cond ((null? elts) cur) ((not (module? cur)) #f) (else (loop (module-ref cur (car elts) #f) (cdr elts))))))(define (nested-set! root names val) (let loop ((cur root) (elts names)) (if (null? (cdr elts)) (module-set! cur (car elts) val) (loop (module-ref cur (car elts)) (cdr elts)))))(define (nested-define! root names val) (let loop ((cur root) (elts names)) (if (null? (cdr elts)) (module-define! cur (car elts) val) (loop (module-ref cur (car elts)) (cdr elts)))))(define (nested-remove! root names) (let loop ((cur root) (elts names)) (if (null? (cdr elts)) (module-remove! cur (car elts)) (loop (module-ref cur (car elts)) (cdr elts)))))(define (local-ref names) (nested-ref (current-module) names))(define (local-set! names val) (nested-set! (current-module) names val))(define (local-define names val) (nested-define! (current-module) names val))(define (local-remove names) (nested-remove! (current-module) names));;; {The (app) module};;;;;; The root of conventionally named objects not directly in the top level.;;;;;; (app modules);;; (app modules guile);;;;;; The directory of all modules and the standard root module.;;;(define (module-public-interface m) (module-ref m '%module-public-interface #f))(define (set-module-public-interface! m i) (module-define! m '%module-public-interface 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-name! the-root-module '(guile))(set-module-name! the-scm-module '(guile))(set-module-kind! the-scm-module 'interface)(for-each set-system-module! (list the-root-module the-scm-module) '(#t #t));; NOTE: This binding is used in libguile/modules.c.;;(define (make-modules-in module name) (if (null? name) module (cond ((module-ref module (car name) #f) => (lambda (m) (make-modules-in m (cdr name)))) (else (let ((m (make-module 31))) (set-module-kind! m 'directory) (set-module-name! m (append (or (module-name module) '()) (list (car name)))) (module-define! module (car name) m) (make-modules-in m (cdr name)))))))(define (beautify-user-module! module) (let ((interface (module-public-interface module))) (if (or (not interface) (eq? interface module)) (let ((interface (make-module 31))) (set-module-name! interface (module-name module)) (set-module-kind! interface 'interface) (set-module-public-interface! module interface)))) (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)))));; NOTE: This binding is used in libguile/modules.c.;;(define (resolve-module name . maybe-autoload) (let ((full-name (append '(app modules) name))) (let ((already (local-ref full-name))) (if already ;; The module already exists... (if (and (or (null? maybe-autoload) (car maybe-autoload)) (not (module-public-interface already))) ;; ...but we are told to load and it doesn't contain source, so (begin (try-load-module name) already) ;; simply return it. already) (begin ;; Try to autoload it if we are told so (if (or (null? maybe-autoload) (car maybe-autoload)) (try-load-module name)) ;; Get/create it. (make-modules-in (current-module) full-name))))));; Cheat. These bindings are needed by modules.c, but we don't want;; to move their real definition here because that would be unnatural.;;(define try-module-autoload #f)(define process-define-module #f)(define process-use-modules #f)(define module-export! #f);; This boots the module system. All bindings needed by modules.c;; must have been defined by now.;;(set-current-module the-root-module)(define app (make-module 31))(local-define '(app modules) (make-module 31))(local-define '(app modules guile) the-root-module);; (define-special-value '(app modules new-ws) (lambda () (make-scm-module)))(define (try-load-module name) (or (begin-deprecated (try-module-linked name)) (try-module-autoload name) (begin-deprecated (try-module-dynamic-link name))))(define (purify-module! module) "Removes bindings in MODULE which are inherited from the (guile) module." (let ((use-list (module-uses module))) (if (and (pair? use-list) (eq? (car (last-pair use-list)) the-scm-module)) (set-module-uses! module (reverse (cdr (reverse use-list)))))));; Return a module that is an interface to the module designated by;; NAME.;;;; `resolve-interface' takes two keyword arguments:;;;; #:select SELECTION;;;; SELECTION is a list of binding-specs to be imported; A binding-spec;; is either a symbol or a pair of symbols (ORIG . SEEN), where ORIG;; is the name in the used module and SEEN is the name in the using;; module. Note that SEEN is also passed through RENAMER, below. The;; default is to select all bindings. If you specify no selection but;; a renamer, only the bindings that already exist in the used module;; are made available in the interface. Bindings that are added later;; are not picked up.;;;; #:renamer RENAMER;;;; RENAMER is a procedure that takes a symbol and returns its new;; name. The default is to not perform any renaming.;;;; Signal "no code for module" error if module name is not resolvable;; or its public interface is not available. Signal "no binding";; error if selected binding does not exist in the used module.;;(define (resolve-interface name . args) (define (get-keyword-arg args kw def) (cond ((memq kw args) => (lambda (kw-arg) (if (null? (cdr kw-arg)) (error "keyword without value: " kw)) (cadr kw-arg))) (else def))) (let* ((select (get-keyword-arg args #:select #f)) (renamer (get-keyword-arg args #:renamer identity)) (module (resolve-module name)) (public-i (and module (module-public-interface module)))) (and (or (not module) (not public-i)) (error "no code for module" name)) (if (and (not select) (eq? renamer identity)) public-i (let ((selection (or select (module-map (lambda (sym var) sym) public-i))) (custom-i (make-module 31))) (set-module-kind! custom-i 'interface) ;; XXX - should use a lazy binder so that changes to the ;; used module are picked up automatically. (for-each (lambda (bspec) (let* ((direct? (symbol? bspec)) (orig (if direct? bspec (car bspec))) (seen (if direct? bspec (cdr bspec)))) (module-add! custom-i (renamer seen) (or (module-local-variable public-i orig) (module-local-variable module orig) (error ;; fixme: format manually for now (simple-format #f "no binding `~A' in module ~A" orig name)))))) selection) custom-i))))(define (symbol-prefix-proc prefix) (lambda (symbol) (symbol-append prefix symbol)));; This function is called from "modules.c". If you change it, be;; sure to update "modules.c" as well.(define (process-define-module args) (let* ((module-id (car args)) (module (resolve-module module-id #f)) (kws (cdr args)) (unrecognized (lambda (arg) (error "unrecognized define-module argument" arg)))) (beautify-user-module! module) (let loop ((kws kws) (reversed-interfaces '()) (exports '()) (re-exports '()))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -