X-Git-Url: http://git.hcoop.net/bpt/guile.git/blobdiff_plain/d7c0c26d886c35dc168cf07cf16b51c0594b21be..107139eaadab946e9713748cdeacd07b22a181db:/ice-9/boot-9.scm diff --git a/ice-9/boot-9.scm b/ice-9/boot-9.scm index 6ada33c68..bde0b852a 100644 --- a/ice-9/boot-9.scm +++ b/ice-9/boot-9.scm @@ -92,9 +92,11 @@ ;; (eval-case ((situation*) forms)* (else forms)?) ;; ;; Evaluate certain code based on the situation that eval-case is used -;; in. The only defined situation right now is `load-toplevel' which -;; triggers for code evaluated at the top-level, for example from the -;; REPL or when loading a file. +;; in. There are three situations defined. `load-toplevel' triggers for +;; code evaluated at the top-level, for example from the REPL or when +;; loading a file. `compile-toplevel' triggers for code compiled at the +;; toplevel. `execute' triggers during execution of code not at the top +;; level. (define eval-case (procedure->memoizing-macro @@ -123,6 +125,14 @@ +;; Before compiling, make sure any symbols are resolved in the (guile) +;; module, the primary location of those symbols, rather than in +;; (guile-user), the default module that we compile in. + +(eval-case + ((compile-toplevel) + (set-current-module (resolve-module '(guile))))) + ;;; {Defmacros} ;;; ;;; Depends on: features, eval-case @@ -151,18 +161,12 @@ (lambda (name parms . body) (let ((transformer `(lambda ,parms ,@body))) `(eval-case - ((load-toplevel) - (define ,name (defmacro:transformer ,transformer))) + ((load-toplevel compile-toplevel) + (define ,name (defmacro:transformer ,transformer))) (else (error "defmacro can only be used at the top level"))))))) (defmacro:transformer defmacro-transformer))) -(define defmacro:syntax-transformer - (lambda (f) - (procedure->syntax - (lambda (exp env) - (copy-tree (apply f (cdr exp))))))) - ;; XXX - should the definition of the car really be looked up in the ;; current module? @@ -196,15 +200,15 @@ (defmacro begin-deprecated forms (if (include-deprecated-features) - (cons begin forms) - #f)) + `(begin ,@forms) + (begin))) ;;; {R4RS compliance} ;;; -(primitive-load-path "ice-9/r4rs.scm") +(primitive-load-path "ice-9/r4rs") @@ -327,22 +331,6 @@ -;;; {Environments} -;;; - -(define the-environment - (procedure->syntax - (lambda (x e) - e))) - -(define the-root-environment (the-environment)) - -(define (environment-module env) - (let ((closure (and (pair? env) (car (last-pair env))))) - (and closure (procedure-property closure 'module)))) - - - ;;; {Records} ;;; @@ -418,14 +406,14 @@ (define (record-constructor rtd . opt) (let ((field-names (if (pair? opt) (car opt) (record-type-fields rtd)))) - (local-eval `(lambda ,field-names - (make-struct ',rtd 0 ,@(map (lambda (f) - (if (memq f field-names) - f - #f)) - (record-type-fields rtd)))) - the-root-environment))) - + (primitive-eval + `(lambda ,field-names + (make-struct ',rtd 0 ,@(map (lambda (f) + (if (memq f field-names) + f + #f)) + (record-type-fields rtd))))))) + (define (record-predicate rtd) (lambda (obj) (and (struct? obj) (eq? rtd (struct-vtable obj))))) @@ -437,25 +425,22 @@ #f))) (define (record-accessor rtd field-name) - (let* ((pos (list-index (record-type-fields rtd) field-name))) + (let ((pos (list-index (record-type-fields rtd) field-name))) (if (not pos) (error 'no-such-field field-name)) - (local-eval `(lambda (obj) - (if (eq? (struct-vtable obj) ,rtd) - (struct-ref obj ,pos) - (%record-type-error ,rtd obj))) - the-root-environment))) + (lambda (obj) + (if (eq? (struct-vtable obj) rtd) + (struct-ref obj pos) + (%record-type-error rtd obj))))) (define (record-modifier rtd field-name) - (let* ((pos (list-index (record-type-fields rtd) field-name))) + (let ((pos (list-index (record-type-fields rtd) field-name))) (if (not pos) (error 'no-such-field field-name)) - (local-eval `(lambda (obj val) - (if (eq? (struct-vtable obj) ,rtd) - (struct-set! obj ,pos val) - (%record-type-error ,rtd obj))) - the-root-environment))) - + (lambda (obj val) + (if (eq? (struct-vtable obj) rtd) + (struct-set! obj pos val) + (%record-type-error rtd obj))))) (define (record? obj) (and (struct? obj) (record-type? (struct-vtable obj)))) @@ -538,10 +523,10 @@ (if (provided? 'posix) - (primitive-load-path "ice-9/posix.scm")) + (primitive-load-path "ice-9/posix")) (if (provided? 'socket) - (primitive-load-path "ice-9/networking.scm")) + (primitive-load-path "ice-9/networking")) ;; For reference, Emacs file-exists-p uses stat in this same way. ;; ENHANCE-ME: Catching an exception from stat is a bit wasteful, do this in @@ -569,10 +554,7 @@ #f))))) (define (has-suffix? str suffix) - (let ((sufl (string-length suffix)) - (sl (string-length str))) - (and (> sl sufl) - (string=? (substring str (- sl sufl) sl) suffix)))) + (string-suffix? suffix str)) (define (system-error-errno args) (if (eq? (car args) 'system-error) @@ -768,6 +750,14 @@ +;;; {The interpreter stack} +;;; + +(defmacro start-stack (tag exp) + `(%start-stack ,tag (lambda () ,exp))) + + + ;;; {Loading by paths} ;;; @@ -1838,25 +1828,29 @@ ;; NOTE: This binding is used in libguile/modules.c. ;; -(define (resolve-module name . maybe-autoload) - (let ((full-name (append '(%app modules) name))) - (let ((already (nested-ref the-root-module 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)))))) +(define resolve-module + (let ((the-root-module the-root-module)) + (lambda (name . maybe-autoload) + (if (equal? name '(guile)) + the-root-module + (let ((full-name (append '(%app modules) name))) + (let ((already (nested-ref the-root-module 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. @@ -1867,16 +1861,17 @@ (define module-export! #f) (define default-duplicate-binding-procedures #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)) (define app %app) ;; for backwards compatability + (local-define '(%app modules) (make-module 31)) (local-define '(%app modules guile) the-root-module) +;; This boots the module system. All bindings needed by modules.c +;; must have been defined by now. +;; +(set-current-module the-root-module) + ;; (define-special-value '(%app modules new-ws) (lambda () (make-scm-module))) (define (try-load-module name) @@ -1997,98 +1992,98 @@ (error "unrecognized define-module argument" arg)))) (beautify-user-module! module) (let loop ((kws kws) - (reversed-interfaces '()) - (exports '()) - (re-exports '()) - (replacements '()) + (reversed-interfaces '()) + (exports '()) + (re-exports '()) + (replacements '()) (autoloads '())) (if (null? kws) - (call-with-deferred-observers - (lambda () - (module-use-interfaces! module (reverse reversed-interfaces)) - (module-export! module exports) - (module-replace! module replacements) - (module-re-export! module re-exports) + (call-with-deferred-observers + (lambda () + (module-use-interfaces! module (reverse reversed-interfaces)) + (module-export! module exports) + (module-replace! module replacements) + (module-re-export! module re-exports) (if (not (null? autoloads)) (apply module-autoload! module autoloads)))) - (case (car kws) - ((#:use-module #:use-syntax) - (or (pair? (cdr kws)) - (unrecognized kws)) - (let* ((interface-args (cadr kws)) - (interface (apply resolve-interface interface-args))) - (and (eq? (car kws) #:use-syntax) - (or (symbol? (caar interface-args)) - (error "invalid module name for use-syntax" - (car interface-args))) - (set-module-transformer! - module - (module-ref interface - (car (last-pair (car interface-args))) - #f))) - (loop (cddr kws) - (cons interface reversed-interfaces) - exports - re-exports - replacements + (case (car kws) + ((#:use-module #:use-syntax) + (or (pair? (cdr kws)) + (unrecognized kws)) + (let* ((interface-args (cadr kws)) + (interface (apply resolve-interface interface-args))) + (and (eq? (car kws) #:use-syntax) + (or (symbol? (caar interface-args)) + (error "invalid module name for use-syntax" + (car interface-args))) + (set-module-transformer! + module + (module-ref interface + (car (last-pair (car interface-args))) + #f))) + (loop (cddr kws) + (cons interface reversed-interfaces) + exports + re-exports + replacements autoloads))) - ((#:autoload) - (or (and (pair? (cdr kws)) (pair? (cddr kws))) - (unrecognized kws)) - (loop (cdddr kws) + ((#:autoload) + (or (and (pair? (cdr kws)) (pair? (cddr kws))) + (unrecognized kws)) + (loop (cdddr kws) reversed-interfaces - exports - re-exports - replacements + exports + re-exports + replacements (let ((name (cadr kws)) (bindings (caddr kws))) (cons* name bindings autoloads)))) - ((#:no-backtrace) - (set-system-module! module #t) - (loop (cdr kws) reversed-interfaces exports re-exports + ((#:no-backtrace) + (set-system-module! module #t) + (loop (cdr kws) reversed-interfaces exports re-exports replacements autoloads)) - ((#:pure) - (purify-module! module) - (loop (cdr kws) reversed-interfaces exports re-exports + ((#:pure) + (purify-module! module) + (loop (cdr kws) reversed-interfaces exports re-exports replacements autoloads)) - ((#:duplicates) - (if (not (pair? (cdr kws))) - (unrecognized kws)) - (set-module-duplicates-handlers! - module - (lookup-duplicates-handlers (cadr kws))) - (loop (cddr kws) reversed-interfaces exports re-exports + ((#:duplicates) + (if (not (pair? (cdr kws))) + (unrecognized kws)) + (set-module-duplicates-handlers! + module + (lookup-duplicates-handlers (cadr kws))) + (loop (cddr kws) reversed-interfaces exports re-exports replacements autoloads)) - ((#:export #:export-syntax) - (or (pair? (cdr kws)) - (unrecognized kws)) - (loop (cddr kws) - reversed-interfaces - (append (cadr kws) exports) - re-exports - replacements + ((#:export #:export-syntax) + (or (pair? (cdr kws)) + (unrecognized kws)) + (loop (cddr kws) + reversed-interfaces + (append (cadr kws) exports) + re-exports + replacements autoloads)) - ((#:re-export #:re-export-syntax) - (or (pair? (cdr kws)) - (unrecognized kws)) - (loop (cddr kws) - reversed-interfaces - exports - (append (cadr kws) re-exports) - replacements + ((#:re-export #:re-export-syntax) + (or (pair? (cdr kws)) + (unrecognized kws)) + (loop (cddr kws) + reversed-interfaces + exports + (append (cadr kws) re-exports) + replacements autoloads)) - ((#:replace #:replace-syntax) - (or (pair? (cdr kws)) - (unrecognized kws)) - (loop (cddr kws) - reversed-interfaces - exports - re-exports - (append (cadr kws) replacements) + ((#:replace #:replace-syntax) + (or (pair? (cdr kws)) + (unrecognized kws)) + (loop (cddr kws) + reversed-interfaces + exports + re-exports + (append (cadr kws) replacements) autoloads)) - (else - (unrecognized kws))))) + (else + (unrecognized kws))))) (run-hook module-defined-hook module) module)) @@ -2137,7 +2132,8 @@ module '(ice-9 q) '(make-q q-length))}." ;;; {Compiled module} -(define load-compiled #f) +(if (not (defined? 'load-compiled)) + (define load-compiled #f)) @@ -2167,14 +2163,20 @@ module '(ice-9 q) '(make-q q-length))}." (lambda () (autoload-in-progress! dir-hint name)) (lambda () (let ((file (in-vicinity dir-hint name))) - (cond ((and load-compiled - (%search-load-path (string-append file ".go"))) - => (lambda (full) - (load-file load-compiled full))) - ((%search-load-path file) - => (lambda (full) - (with-fluids ((current-reader #f)) - (load-file primitive-load full))))))) + (let ((compiled (and load-compiled + (%search-load-path + (string-append file ".go")))) + (source (%search-load-path file))) + (cond ((and source + (or (not compiled) + (< (stat:mtime (stat compiled)) + (stat:mtime (stat source))))) + (if compiled + (warn "source file" source "newer than" compiled)) + (with-fluids ((current-reader #f)) + (load-file primitive-load source))) + (compiled + (load-file load-compiled compiled)))))) (lambda () (set-autoloaded! dir-hint name didit))) didit)))) @@ -2215,23 +2217,11 @@ module '(ice-9 q) '(make-q q-length))}." ;;; {Run-time options} ;;; -(define define-option-interface +(defmacro define-option-interface (option-group) (let* ((option-name car) (option-value cadr) (option-documentation caddr) - (print-option (lambda (option) - (display (option-name option)) - (if (< (string-length - (symbol->string (option-name option))) - 8) - (display #\tab)) - (display #\tab) - (display (option-value option)) - (display #\tab) - (display (option-documentation option)) - (newline))) - ;; Below follow the macros defining the run-time option interfaces. (make-options (lambda (interface) @@ -2239,8 +2229,19 @@ module '(ice-9 q) '(make-q q-length))}." (cond ((null? args) (,interface)) ((list? (car args)) (,interface (car args)) (,interface)) - (else (for-each ,print-option - (,interface #t))))))) + (else (for-each + (lambda (option) + (display (option-name option)) + (if (< (string-length + (symbol->string (option-name option))) + 8) + (display #\tab)) + (display #\tab) + (display (option-value option)) + (display #\tab) + (display (option-documentation option)) + (newline)) + (,interface #t))))))) (make-enable (lambda (interface) `(lambda flags @@ -2255,22 +2256,19 @@ module '(ice-9 q) '(make-q q-length))}." flags) (,interface options) (,interface)))))) - (procedure->memoizing-macro - (lambda (exp env) - (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)))))))))) + (let* ((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 @@ -2526,7 +2524,7 @@ module '(ice-9 q) '(make-q q-length))}." ;;; the readline library. (define repl-reader (lambda (prompt) - (display prompt) + (display (if (string? prompt) prompt (prompt))) (force-output) (run-hook before-read-hook) ((or (fluid-ref current-reader) read) (current-input-port)))) @@ -2710,24 +2708,12 @@ module '(ice-9 q) '(make-q q-length))}." (car rest) `(lambda ,(cdr first) ,@rest)))) `(eval-case - ((load-toplevel) + ((load-toplevel compile-toplevel) (define ,name (defmacro:transformer ,transformer))) (else (error "define-macro can only be used at the top level"))))) -(defmacro define-syntax-macro (first . rest) - (let ((name (if (symbol? first) first (car first))) - (transformer - (if (symbol? first) - (car rest) - `(lambda ,(cdr first) ,@rest)))) - `(eval-case - ((load-toplevel) - (define ,name (defmacro:syntax-transformer ,transformer))) - (else - (error "define-syntax-macro can only be used at the top level"))))) - ;;; {While} @@ -2752,18 +2738,18 @@ module '(ice-9 q) '(make-q q-length))}." ;; This is probably a bug in syncase. ;; (define-macro (while cond . body) - (define (while-helper proc) - (do ((key (make-symbol "while-key"))) - ((catch key - (lambda () - (proc (lambda () (throw key #t)) - (lambda () (throw key #f)))) - (lambda (key arg) arg))))) - `(,while-helper (,lambda (break continue) - (do () - ((,not ,cond)) - ,@body) - #t))) + (let ((key (make-symbol "while-key"))) + `(do () + ((catch ',key + (lambda () + (let ((break (lambda () (throw ',key #t))) + (continue (lambda () (throw ',key #f)))) + (do () + ((not ,cond)) + ,@body) + #t)) + (lambda (key arg) + arg)))))) @@ -2774,6 +2760,11 @@ module '(ice-9 q) '(make-q q-length))}." ;; Return a list of expressions that evaluate to the appropriate ;; arguments for resolve-interface according to SPEC. +(eval-case + ((compile-toplevel) + (if (memq 'prefix (read-options)) + (error "boot-9 must be compiled with #:kw, not :kw")))) + (define (compile-interface-spec spec) (define (make-keyarg sym key quote?) (cond ((or (memq sym spec) @@ -2838,7 +2829,7 @@ module '(ice-9 q) '(make-q q-length))}." (defmacro define-module args `(eval-case - ((load-toplevel) + ((load-toplevel compile-toplevel) (let ((m (process-define-module (list ,@(compile-define-module-args args))))) (set-current-module m) @@ -2863,7 +2854,7 @@ module '(ice-9 q) '(make-q q-length))}." (defmacro use-modules modules `(eval-case - ((load-toplevel) + ((load-toplevel compile-toplevel) (process-use-modules (list ,@(map (lambda (m) `(list ,@(compile-interface-spec m))) @@ -2874,7 +2865,7 @@ module '(ice-9 q) '(make-q q-length))}." (defmacro use-syntax (spec) `(eval-case - ((load-toplevel) + ((load-toplevel compile-toplevel) ,@(if (pair? spec) `((process-use-modules (list (list ,@(compile-interface-spec spec)))) @@ -2904,7 +2895,7 @@ module '(ice-9 q) '(make-q q-length))}." (let ((name (defined-name (car args)))) `(begin (define-private ,@args) - (eval-case ((load-toplevel) (export ,name)))))))) + (eval-case ((load-toplevel compile-toplevel) (export ,name)))))))) (defmacro defmacro-public args (define (syntax) @@ -2919,7 +2910,7 @@ module '(ice-9 q) '(make-q q-length))}." (#t (let ((name (defined-name (car args)))) `(begin - (eval-case ((load-toplevel) (export-syntax ,name))) + (eval-case ((load-toplevel compile-toplevel) (export-syntax ,name))) (defmacro ,@args)))))) ;; Export a local variable @@ -2958,7 +2949,7 @@ module '(ice-9 q) '(make-q q-length))}." (defmacro export names `(eval-case - ((load-toplevel) + ((load-toplevel compile-toplevel) (call-with-deferred-observers (lambda () (module-export! (current-module) ',names)))) @@ -2967,7 +2958,7 @@ module '(ice-9 q) '(make-q q-length))}." (defmacro re-export names `(eval-case - ((load-toplevel) + ((load-toplevel compile-toplevel) (call-with-deferred-observers (lambda () (module-re-export! (current-module) ',names)))) @@ -2992,6 +2983,7 @@ module '(ice-9 q) '(make-q q-length))}." ;; Indeed, all references to global variables are memoized into such ;; variable objects. +;; FIXME: these don't work with the compiler (define-macro (@ mod-name var-name) (let ((var (module-variable (resolve-interface mod-name) var-name))) (if (not var) @@ -3354,6 +3346,8 @@ module '(ice-9 q) '(make-q q-length))}." ;; scmsigs.c scm_sigaction_for_thread), so the handlers setup here have ;; no effect. (let ((old-handlers #f) + (start-repl (module-ref (resolve-interface '(system repl repl)) + 'start-repl)) (signals (if (provided? 'posix) `((,SIGINT . "User interrupt") (,SIGFPE . "Arithmetic error") @@ -3388,7 +3382,7 @@ module '(ice-9 q) '(make-q q-length))}." ;; the protected thunk. (lambda () - (let ((status (scm-style-repl))) + (let ((status (start-repl 'scheme))) (run-hook exit-hook) status)) @@ -3420,7 +3414,7 @@ module '(ice-9 q) '(make-q q-length))}." (provided? sym))) (begin-deprecated - (primitive-load-path "ice-9/deprecated.scm")) + (primitive-load-path "ice-9/deprecated"))