From 9270936a282a059c24703461e0ee34ee76447331 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Wed, 16 May 2012 07:10:49 -0600 Subject: [PATCH] instantiate `require'd modules in the order that they are `require'd This order is now specified, whereas the order was previously unspecified, and the previous reverse order was an artifact of the implementation. --- collects/scribblings/reference/syntax.scrbl | 6 +++++- collects/tests/racket/module.rktl | 14 +++++++++++++- doc/release-notes/racket/HISTORY.txt | 1 + src/racket/src/module.c | 15 +++++++++++---- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/collects/scribblings/reference/syntax.scrbl b/collects/scribblings/reference/syntax.scrbl index 0658d29b20..35be58c5f1 100644 --- a/collects/scribblings/reference/syntax.scrbl +++ b/collects/scribblings/reference/syntax.scrbl @@ -232,7 +232,11 @@ module, whose full name depends both on @racket[id] or A module body is executed only when the module is explicitly @techlink{instantiate}d via @racket[require] or -@racket[dynamic-require]. On invocation, expressions and definitions +@racket[dynamic-require]. On invocation, imported modules are +instantiated in the order in which they are @racket[require]d +into the module (although earlier instantiations or transitive +@racket[require]s can trigger the instantiation of a module before +its order within a given module). Then, expressions and definitions are evaluated in order as they appear within the module. Each evaluation of an expression or definition is wrapped with a continuation prompt (see @racket[call-with-continuation-prompt]) for diff --git a/collects/tests/racket/module.rktl b/collects/tests/racket/module.rktl index 464e713889..0d1ef2c8b7 100644 --- a/collects/tests/racket/module.rktl +++ b/collects/tests/racket/module.rktl @@ -182,7 +182,7 @@ (test '(d b c) values l) (eval `(module f mzscheme (,here 'f) - (require 'b 'e))) + (require 'e 'b))) (test '(d b d b c) values l) (eval `(require 'f)) (let ([finished '(f b e a d b d b d b c)]) @@ -764,6 +764,18 @@ (err/rt-test (eval '(define-syntax m (syntax-local-module-defined-identifiers)))) +;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Check that invocation order matches `require' order: + +(module order-check-module-a racket/base 'a) +(module order-check-module-b racket/base 'b) +(module order-check-module racket/base (require 'order-check-module-a + 'order-check-module-b)) +(let ([o (open-output-string)]) + (parameterize ([current-output-port o]) + (dynamic-require ''order-check-module #f)) + (test "'a\n'b\n" get-output-string o)) + ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (report-errs) diff --git a/doc/release-notes/racket/HISTORY.txt b/doc/release-notes/racket/HISTORY.txt index 32b859455d..d3326b9546 100644 --- a/doc/release-notes/racket/HISTORY.txt +++ b/doc/release-notes/racket/HISTORY.txt @@ -1,4 +1,5 @@ Version 5.3.0.8 +Required modules are instantiated in the order that they are required Added variable-reference->module-path-index Added syntax-local-submodules Added relative-in diff --git a/src/racket/src/module.c b/src/racket/src/module.c index 1af160acb0..dcfaac74d2 100644 --- a/src/racket/src/module.c +++ b/src/racket/src/module.c @@ -2766,7 +2766,6 @@ void scheme_prep_namespace_rename(Scheme_Env *menv) if (l) { /* Do initial import first to get shadowing right: */ - l = scheme_reverse(l); for (; SCHEME_PAIRP(l); l = SCHEME_CDR(l)) { idx = SCHEME_CAR(l); name = scheme_module_resolve(idx, 0); @@ -4497,7 +4496,7 @@ static void show_done(const char *what, Scheme_Env *menv, int v1, int v2, int i, static void compute_require_names(Scheme_Env *menv, Scheme_Object *phase, Scheme_Env *load_env, Scheme_Object *syntax_idx) { - Scheme_Object *np, *midx, *l, *reqs, *req_names; + Scheme_Object *np, *np_first, *np_last, *midx, *l, *reqs, *req_names; if (SAME_OBJ(phase, scheme_make_integer(0))) { req_names = menv->require_names; @@ -4532,7 +4531,8 @@ static void compute_require_names(Scheme_Env *menv, Scheme_Object *phase, if (req_names && !SCHEME_NULLP(req_names)) return; - np = scheme_null; + np_first = scheme_null; + np_last = NULL; for (l = reqs; !SCHEME_NULLP(l); l = SCHEME_CDR(l)) { midx = do_modidx_shift(SCHEME_CAR(l), @@ -4543,9 +4543,16 @@ static void compute_require_names(Scheme_Env *menv, Scheme_Object *phase, if (load_env) module_load(scheme_module_resolve(midx, 1), load_env, NULL); - np = cons(midx, np); + np = cons(midx, scheme_null); + if (np_last) + SCHEME_CDR(np_last) = np; + else + np_first = np; + np_last = np; } + np = np_first; + if (!SAME_OBJ(np, req_names)) { if (SAME_OBJ(phase, scheme_make_integer(0))) { menv->require_names = np;