~ chicken-core (chicken-5) c7417d3e9112ff5fd2e18e171a755e73118b2301
commit c7417d3e9112ff5fd2e18e171a755e73118b2301 Author: felix <felix@call-with-current-continuation.org> AuthorDate: Fri Jul 29 14:40:07 2011 +0200 Commit: felix <felix@call-with-current-continuation.org> CommitDate: Fri Jul 29 14:40:07 2011 +0200 added module-environment; refactored lookup of import lib; module saved-envs include val+syntax exports; added env tests; fixed overly general result-type decls for r5rs env procs diff --git a/chicken.import.scm b/chicken.import.scm index 722094df..35860dd1 100644 --- a/chicken.import.scm +++ b/chicken.import.scm @@ -174,6 +174,7 @@ maximum-flonum memory-statistics minimum-flonum + module-environment most-negative-fixnum most-positive-fixnum on-exit diff --git a/eval.scm b/eval.scm index 2b76a14d..6260409b 100644 --- a/eval.scm +++ b/eval.scm @@ -1333,8 +1333,8 @@ (##sys#write-char-0 #\> p)) (define scheme-report-environment - (let ((r4 (##sys#module-environment 'r4rs 'scheme-report-environment/4)) - (r5 (##sys#module-environment 'scheme 'scheme-report-environment/5))) + (let ((r4 (module-environment 'r4rs 'scheme-report-environment/4)) + (r5 (module-environment 'scheme 'scheme-report-environment/5))) (lambda (n) (##sys#check-exact n 'scheme-report-environment) (case n @@ -1346,8 +1346,8 @@ "unsupported scheme report environment version" n)) ) ) ) ) (define null-environment - (let ((r4 (##sys#module-environment 'r4rs-null 'null-environment/4)) - (r5 (##sys#module-environment 'r5rs-null 'null-environment/5))) + (let ((r4 (module-environment 'r4rs-null 'null-environment/4)) + (r5 (module-environment 'r5rs-null 'null-environment/5))) (lambda (n) (##sys#check-exact n 'null-environment) (case n diff --git a/manual/Modules b/manual/Modules index 37ef8713..4583e40d 100644 --- a/manual/Modules +++ b/manual/Modules @@ -236,6 +236,23 @@ macros. Note that these definitions will ruthlessly pollute the toplevel namespace and so they should be used sparingly. +=== Using modules as evaluation environments + +==== module-environment + +<procedure>(module-environment MODULENAME)</procedure> + +Locates the module with the name {{MODULENAME}} and returns an +environment that can be passed as the second argument to {{eval}}. The +evaluated expressions have only access to the bindings that are +visible inside the module. Note that the environment is not mutable. + +If the module is not registered in the current process, {{module-environment}} +will try to locate meta-information about the module by loading any +existing import library with the name {{MODULENAME.import.[scm|so]}}, +if possible. + + === Predefined modules Import libraries for the following modules are initially diff --git a/modules.scm b/modules.scm index 55e8e0a2..b4dbc423 100644 --- a/modules.scm +++ b/modules.scm @@ -396,7 +396,9 @@ sexports)))) (set-module-saved-environments! mod - (cons (##sys#current-environment) + (cons (merge-se (##sys#current-environment) + (module-vexports mod) + (module-sexports mod)) (##sys#macro-environment))) (set! ##sys#module-table (cons (cons name mod) ##sys#module-table)) mod)) @@ -522,7 +524,7 @@ (set-module-sexports! mod sexports) (set-module-saved-environments! mod - (cons (##sys#current-environment) + (cons (merge-se (##sys#current-environment) vexports sexports) (##sys#macro-environment)))))))) (define ##sys#module-table '()) @@ -530,6 +532,28 @@ ;;; Import-expansion +(define (##sys#find-module/import-library mname loc) + (let* ((mname (##sys#resolve-module-name mname loc)) + (mod (##sys#find-module mname #f loc))) + (unless mod + (let* ((il (##sys#find-extension + (string-append (symbol->string mname) ".import") + #t))) + (cond (il (parameterize ((##sys#current-module #f) + (##sys#current-environment '()) + (##sys#current-meta-environment + (##sys#current-meta-environment)) + (##sys#macro-environment + (##sys#meta-macro-environment))) + (fluid-let ((##sys#notices-enabled #f)) ; to avoid re-import warnings + (##sys#load il #f #f))) + (set! mod (##sys#find-module mname 'import))) + (else + (##sys#syntax-error-hook + loc "cannot import from undefined module" + mname))))) + mod)) + (define (##sys#expand-import x r c import-env macro-env meta? reexp? loc) (let ((%only (r 'only)) (%rename (r 'rename)) @@ -545,28 +569,10 @@ ((number? x) (number->string x)) (else (##sys#syntax-error-hook loc "invalid prefix" )))) (define (import-name spec) - (let* ((mname (##sys#resolve-module-name (##sys#strip-syntax spec) 'import)) - (mod (##sys#find-module mname #f 'import))) - (unless mod - (let* ((il (##sys#find-extension - (string-append (symbol->string mname) ".import") - #t))) - (cond (il (parameterize ((##sys#current-module #f) - (##sys#current-environment '()) - (##sys#current-meta-environment - (##sys#current-meta-environment)) - (##sys#macro-environment - (##sys#meta-macro-environment))) - (fluid-let ((##sys#notices-enabled #f)) ; to avoid re-import warnings - (##sys#load il #f #f))) - (set! mod (##sys#find-module mname 'import))) - (else - (##sys#syntax-error-hook - loc "cannot import from undefined module" - mname))))) - (let ((vexp (module-vexports mod)) - (sexp (module-sexports mod))) - (cons vexp sexp)))) + (let* ((mod (##sys#find-module/import-library (##sys#strip-syntax spec) 'import)) + (vexp (module-vexports mod)) + (sexp (module-sexports mod))) + (cons vexp sexp))) (define (import-spec spec) (cond ((symbol? spec) (import-name spec)) ((or (not (list? spec)) (< (length spec) 2)) @@ -851,26 +857,32 @@ with-output-to-file eval char-ready? imag-part real-part magnitude numerator denominator scheme-report-environment null-environment interaction-environment - else))) - (##sys#register-primitive-module - 'r4rs - r4rs-values - ##sys#default-macro-environment) + else)) + (r4rs-syntax + ;;XXX currently disabled - better would be to move these into the "chicken" + ;; module. "import[-for-syntax]" and "reexport" are in + ;; ##sys#initial-macro-environment and thus always available inside modules. + #;(foldr + (lambda (s r) + (if (memq (car s) + '(import require-extension require-library begin-for-syntax + export module cond-expand syntax reexport import-for-syntax)) + r + (cons s r))) + '() + ##sys#default-macro-environment) + ##sys#default-macro-environment)) + (##sys#register-primitive-module 'r4rs r4rs-values r4rs-syntax) (##sys#register-primitive-module 'scheme (append '(dynamic-wind values call-with-values) r4rs-values) - ##sys#default-macro-environment)) - -(##sys#register-primitive-module 'r4rs-null '() ##sys#default-macro-environment) -(##sys#register-primitive-module 'r5rs-null '() ##sys#default-macro-environment) + r4rs-syntax) + (##sys#register-primitive-module 'r4rs-null '() r4rs-syntax) + (##sys#register-primitive-module 'r5rs-null '() r4rs-syntax)) (##sys#register-module-alias 'r5rs 'scheme) -(define (##sys#module-environment mname #!optional (ename mname)) - (let ((mod (##sys#find-module mname))) - (##sys#make-structure - 'environment - ename - (append - (module-vexports mod) - (module-sexports mod))))) +(define (module-environment mname #!optional (ename mname)) + (let* ((mod (##sys#find-module/import-library mname 'module-environment)) + (saved (module-saved-environments mod))) + (##sys#make-structure 'environment ename (car saved)))) diff --git a/tests/environment-tests.scm b/tests/environment-tests.scm index 3735d6f2..517254b2 100644 --- a/tests/environment-tests.scm +++ b/tests/environment-tests.scm @@ -26,4 +26,20 @@ (test-error (eval 'car (null-environment 5))) (test-equal (eval '((lambda (x) x) 123) (null-environment 5)) 123) +(define baz 100) + +(module foo (bar) + (import r5rs) + (define (bar) 99)) + +(define foo-env (module-environment 'foo)) +(define srfi-1-env (module-environment 'srfi-1)) + +(require-library srfi-1) + +(test-equal (eval '(bar) foo-env) 99) +(test-error (eval 'baz foo-env)) +(test-equal (eval '(xcons 1 2) srfi-1-env) '(2 . 1)) +(test-error (eval 'baz srf-1-env)) + (test-end) diff --git a/types.db b/types.db index 1603fda7..f0b6bb64 100644 --- a/types.db +++ b/types.db @@ -212,16 +212,19 @@ (dynamic-wind (procedure dynamic-wind (procedure procedure procedure) . *)) (values (procedure values (#!rest values) . *)) (call-with-values (procedure call-with-values (procedure procedure) . *)) -(eval (procedure eval (* #!optional *) *)) +(eval (procedure eval (* #!optional (struct environment)) *)) (char-ready? (procedure char-ready? (#!optional port) boolean)) (imag-part (procedure imag-part (number) number)) (real-part (procedure real-part (number) number)) (magnitude (procedure magnitude (number) number)) (numerator (procedure numerator (number) number)) (denominator (procedure denominator (number) number)) -(scheme-report-environment (procedure scheme-report-environment (#!optional fixnum) *)) -(null-environment (procedure null-environment (#!optional fixnum) *)) -(interaction-environment (procedure interaction-environment () *)) +(scheme-report-environment (procedure scheme-report-environment (#!optional fixnum) + (struct environment))) +(null-environment (procedure null-environment (#!optional fixnum) + (struct environment))) +(interaction-environment (procedure interaction-environment () + (struct environment))) (port-closed? (procedure port-closed? (port) boolean)) ;; chicken @@ -375,6 +378,7 @@ (maximum-flonum float) (memory-statistics (procedure memory-statistics () vector)) (minimum-flonum float) +(module-environment (procedure module-environment (symbol #!optional symbol) (struct environment))) (most-negative-fixnum fixnum) (most-positive-fixnum fixnum) (on-exit (procedure on-exit ((procedure () . *)) undefined))Trap