progress on submodule docs; bug fixes

This commit is contained in:
Matthew Flatt 2012-03-08 07:50:44 -07:00
parent 3d69dfab86
commit 566759a5fa
10 changed files with 237 additions and 38 deletions

View File

@ -174,7 +174,8 @@ structures that are produced by @racket[zo-parse] and consumed by
[dummy toplevel?]
[lang-info (or/c #f (vector/c module-path? symbol? any/c))]
[internal-context (or/c #f #t stx?)]
[submodules (listof mod?)])]{
[pre-submodules (listof mod?)]
[post-submodules (listof mod?)])]{
Represents a @racket[module] declaration.
The @racket[provides] and @racket[requires] lists are each an

View File

@ -76,18 +76,37 @@ and its lexical context is not enriched before it is passed to the
@tech{evaluation handler}.}
@defparam[current-load proc (path? (or/c symbol? #f) . -> . any)]{
@defparam[current-load proc (path? (or/c #f
symbol?
(cons/c (or/c #f symbol?)
(non-empty-listof symbol?)))
. -> .
any)]{
A parameter that determines the current @deftech{load handler} to load
top-level forms from a file. The @tech{load handler} is called by
@racket[load], @racket[load-relative], @racket[load/cd], and the
default @tech{compiled-load handler}.
A load handler takes two arguments: a path (see
@secref["pathutils"]) and an expected module name. The expected
module name is a symbol when the call is to load a module declaration
in response to a @racket[require] (in which case the file should
contain a module declaration), or @racket[#f] for any other load.
A load handler takes two arguments: a path (see @secref["pathutils"])
and an expected module name. The expected module name is a symbol or a
list when the call is to load a module declaration in response to a
@racket[require] (in which case the file should contain a module
declaration), or @racket[#f] for any other load.
When loading a module from a stream that starts with a compiled module
that contains submodules, the load handler should load only the
requested module, where a symbol as the load handler's indicates the
root module and a list indicates a submodule whose path relative to
the root module is given by the @racket[cdr] of the list. The list
starts with @racket[#f] when a submodule should be loaded @emph{only}
if it can be loaded independently (i.e., from compiled form---never
from source); if the submodule cannot be loaded independently, the
load handler should return without loading from a file. When the
expected module name is a list that starts with a symbol, the root
module and any other submodules can be loaded from the given file,
which might be from source, and the load handler still should not
complain if the expected submodule is not found.
The default load handler reads forms from the file in
@racket[read-syntax] mode with line-counting enabled for the file
@ -211,7 +230,11 @@ Like @racket[load-extension], but resolves @racket[file] using
@racket[current-load-relative-directory] like @racket[load-relative].}
@defparam[current-load/use-compiled proc (path? (or/c symbol? #f) . -> . any)]{
@defparam[current-load/use-compiled proc (path? (or/c #f
symbol?
(cons/c (or/c #f symbol?)
(non-empty-listof symbol?)))
. -> . any)]{
A parameter that determines the current @deftech{compiled-load
handler} to load from a file that may have a compiled form. The

View File

@ -135,7 +135,12 @@ A parameter that determines a module name that is used when evaluating
a @racket[module] declaration (when the parameter value is not
@racket[#f]). In that case, the @racket[_id] from the @racket[module]
declaration is ignored, and the parameter's value is used as the name
of the declared module.}
of the declared module.
When declaring @tech{submodules}, @racket[current-module-declare-name]
determines the name used for the submodule's root module, while its
submodule path relative to the root module is unaffected.}
@defparam[current-module-declare-source src (or/c symbol? (and/c path? complete-path?) #f)]{
@ -215,7 +220,7 @@ resolved name can depend on the value of
@defproc[(module-path-index-split [mpi module-path-index?])
(values (or/c module-path? #f)
(values (or/c module-path? path? #f)
(or/c module-path-index? resolved-module-path? #f))]{
Returns two values: a module path, and a base @tech{module path index}
@ -230,7 +235,7 @@ A @racket[#f] for the first result implies a @racket[#f] for the
second result, and means that @racket[mpi] represents ``self'' (see
above).}
@defproc[(module-path-index-join [path (or/c module-path? #f)]
@defproc[(module-path-index-join [path (or/c module-path? path? #f)]
[mpi (or/c module-path-index? resolved-module-path? #f)])
module-path-index?]{
@ -245,11 +250,36 @@ declaration, @racket[#f] otherwise. See also
@racket[current-compile].}
@defproc[(module-compiled-name [compiled-module-code compiled-module-expression?])
symbol?]{
@defproc*[([(module-compiled-name [compiled-module-code compiled-module-expression?])
(or/c symbol? (cons/c symbol? (listof symbol?)))]
[(module-compiled-name [compiled-module-code compiled-module-expression?]
[name (or/c symbol? (cons/c symbol? (listof symbol?)))])
compiled-module-expression?])]{
Takes a module declaration in compiled form and returns a symbol for
the module's declared name.}
Takes a module declaration in compiled form and either gets the
module's declared name (when @racket[name] is not provided) or returns
a revised module declaration with the given @racket[name].
The name is a symbol for a top-level module, and it list of symbols
for a @tech{submodule}, where a list reflects the submodule path to
the module starting with the top-level module's declared name.}
@defproc*[([(module-compiled-submodules [compiled-module-code compiled-module-expression?]
[non-star? any/c])
symbol?]
[(module-compiled-submodules [compiled-module-code compiled-module-expression?]
[non-star? any/c]
[submodules (listof compiled-module-expression?)])
compiled-module-expression?])]{
Takes a module declaration in compiled form and either gets the
module's @tech{submodules} (when @racket[submodules] is not provided) or
returns a revised module declaration with the given
@racket[submodules]. The @racket[pre-module?] argument determines
whether the result or new submodule list corresponds to
@racket[module] declarations (when @racket[non-star?] is true)
or @racket[module*] declarations (when @racket[non-star?] is @racket[#f]).}
@defproc[(module-compiled-imports [compiled-module-code compiled-module-expression?])
@ -385,7 +415,8 @@ more than the namespace's @tech{base phase}.}
@defproc[(module-declared?
[mod (or/c module-path? path? resolved-module-path?)]
[mod (or/c module-path? path? module-path-index?
resolved-module-path?)]
[load? any/c #f])
boolean?]{
@ -395,12 +426,16 @@ in the current namespace, @racket[#f] otherwise.
If @racket[load?] is @racket[#t] and @racket[mod] is not a
@tech{resolved module path}, the module is loaded in the process of
resolving @racket[mod] (as for @racket[dynamic-require]
and other functions).}
resolving @racket[mod] (as for @racket[dynamic-require] and other
functions). Checking for the declaration of a @tech{submodule} does
not trigger an exception if the submodule cannot be loaded because
it does not exist, either within a root module that does exist or
because the root module does not exist.}
@defproc[(module->language-info
[mod (or/c module-path? path? resolved-module-path?)]
[mod (or/c module-path? path? module-path-index?
resolved-module-path?)]
[load? any/c #f])
(or/c #f (vector/c module-path? symbol? any/c))]{
@ -417,7 +452,8 @@ implementation as compiled code.}
@defproc[(module->imports
[mod (or/c module-path? path? resolved-module-path?)])
[mod (or/c module-path? path? module-path-index?
resolved-module-path?)])
(listof (cons/c (or/c exact-integer? #f)
(listof module-path-index?)))]{

View File

@ -837,8 +837,13 @@ of alphanumeric ASCII, @litchar{+}, @litchar{-}, @litchar{_}, and/or
@litchar{/} characters terminated by
@racketlink[char-whitespace?]{whitespace} or an end-of-file. The
sequence must not start or end with @litchar{/}. A sequence
@litchar{#lang }@nonterm{name} is equivalent to
@litchar{#reader }@nonterm{name}@litchar{/lang/reader}. Note
@litchar{#lang }@nonterm{name} is equivalent to either
@litchar{#reader (submod }@nonterm{name}@litchar{ reader)} or
@litchar{#reader }@nonterm{name}@litchar{/lang/reader}, where the
former is tried first guarded by a @racket[module-declared?]
check (but after filtering by
@racket[current-reader-guard], so both are passed to the
value of @racket[current-reader-guard] if the latter is used). Note
that the terminating whitespace (if any) is not consumed before the
external reading procedure is called.

View File

@ -81,12 +81,12 @@ opposed to @tech{syntax object}s inserted by macros.}
@defproc[(syntax-source-module [stx syntax?] [source? any/c #f])
(or/c module-path-index? symbol? path? #f)]{
(or/c module-path-index? symbol? path? resolved-module-path? #f)]{
Returns an indication of the module whose source contains
@racket[stx], or @racket[#f] if @racket[stx] has no source module. If
@racket[source?] is @racket[#f], then result is a module path index or
symbol (see @secref["modpathidx"]); if @racket[source?] is true, the
symbol (see @secref["modpathidx"]) or a @tech{resolved module path}; if @racket[source?] is true, the
result is a path or symbol corresponding to the loaded module's
source in the sense of @racket[current-module-declare-source].}

View File

@ -1039,13 +1039,16 @@ multiple symbolic names.}
(#,(racketidfont "prefix-all-except") prefix-id
raw-module-path id ...)
(#,(racketidfont "rename") raw-module-path local-id exported-id)]
[raw-module-path (#,(racketidfont "quote") id)
rel-string
(#,(racketidfont "lib") rel-string ...)
id
(#,(racketidfont "file") string)
(#,(racketidfont "planet") rel-string
(user-string pkg-string vers ...))])]{
[raw-module-path (#,(racketidfont "submod") raw-root-module-path id ...+)
(#,(racketidfont "submod") "." id ...+)]
[raw-root-module-path (#,(racketidfont "quote") id)
rel-string
(#,(racketidfont "lib") rel-string ...)
id
(#,(racketidfont "file") string)
(#,(racketidfont "planet") rel-string
(user-string pkg-string vers ...))
literal-path])]{
The primitive import form, to which @racket[require] expands. A
@racket[raw-require-spec] is similar to a @racket[_require-spec] in a
@ -1063,7 +1066,14 @@ identifiers in reverse order compared to @racket[rename-in].
For most @racket[raw-require-spec]s, the lexical context of the
@racket[raw-require-spec] determines the context of introduced
identifiers. The exception is the @racketidfont{rename} sub-form,
where the lexical context of the @racket[local-id] is preserved.}
where the lexical context of the @racket[local-id] is preserved.
A @racket[literal-path] as a @racket[raw-root-module-path] corresponds
to a path in the sense of @racket[path?]. Since path values are never
produced by @racket[read-syntax], they appear only in programmatically
constructed expressions. They also appear naturally as arguments to
functions such as @racket[namespace-require], with otherwise take a
quoted @racket[raw-module-spec].}
@defform/subs[(#%provide raw-provide-spec ...)

View File

@ -639,6 +639,24 @@
(require (for-meta -1 (only-in racket cons) (only-in r5rs cons)))))
(lambda (exn) (regexp-match? #rx"phase -1" (exn-message exn))))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Check renames and lifts:
(module post-ex-rename-example-1 racket/base
(require (for-syntax racket/base))
(provide go)
(define-syntax (go stx)
(syntax-local-lift-module-end-declaration
#'(define-stuff))
#'(define-syntax (define-stuff stx)
#'(define x #f))))
(module post-ex-rename-example-2 racket/base
(require 'post-ex-rename-example-1)
(go))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(report-errs)

View File

@ -45,6 +45,27 @@
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(module subm-example-9 racket/base
(define x '(1))
(provide x)
(module* a #f
(require racket/list)
(define z (last x))
(provide z)
(define-syntax-rule (as-last) last)
(provide as-last)))
(test '(1) dynamic-require ''subm-example-9 'x)
(test 1 dynamic-require '(submod 'subm-example-9 a) 'z)
(module subm-example-use-9 racket/base
(require (submod 'subm-example-9 a))
(define x ((as-last) '(1 2 3)))
(provide x))
(test 3 dynamic-require ''subm-example-use-9 'x)
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(let ([o (open-output-bytes)])
(write (compile '(module subm-example-0 racket/base
(define x 1)
@ -262,4 +283,35 @@
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(module subm-example-11 racket/base
(require (for-syntax racket/base))
(define (listify x) (list x))
(define-syntax (add-submodule stx)
(with-syntax (#;[(define-b-module) (generate-temporaries '(define-b))])
(syntax-local-lift-module-end-declaration
#'(module* a #f
(provide a)
(define a (listify 'a))))
(syntax-local-lift-module-end-declaration
#'(define-b-module))
#'(define-syntax (define-b-module stx)
#'(module* b #f
(define b 'b)
(provide b)))))
(add-submodule)
(provide add-submodule))
(test '(a) dynamic-require '(submod 'subm-example-11 a) 'a)
(test 'b dynamic-require '(submod 'subm-example-11 b) 'b)
(module subm-example-12 racket/base
(require 'subm-example-11)
(add-submodule))
(test '(a) dynamic-require '(submod 'subm-example-12 a) 'a)
(test 'b dynamic-require '(submod 'subm-example-12 b) 'b)
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(report-errs)

View File

@ -1,5 +1,5 @@
Version 5.2.900.1
Add submodules, including `module*'
Add submodules, including module*, module-compiled-submodules
Change resolver protocol so that declaration notify is always issued
Change load/use-compiled handler to work with submodules
compiler/zo-struct: added pre-submodules and post-submodules field to

View File

@ -5989,8 +5989,8 @@ static Scheme_Object *jit_vector(Scheme_Object *orig_l, int in_vec, int jit)
static Scheme_Object *do_module_clone(Scheme_Object *data, int jit)
{
Scheme_Module *m = (Scheme_Module *)data;
Scheme_Object *l1, **naya = NULL;
int j, i;
Scheme_Object *l1, *l2, *pre_submods, *post_submods, *sm, **naya = NULL;
int j, i, submod_changed;
Resolve_Prefix *rp;
rp = scheme_prefix_eval_clone(m->prefix);
@ -6013,8 +6013,33 @@ static Scheme_Object *do_module_clone(Scheme_Object *data, int jit)
}
}
pre_submods = m->pre_submodules;
post_submods = m->post_submodules;
submod_changed = 0;
for (j = 0; j < 2; j++) {
l1 = (j ? post_submods : pre_submods);
if (l1 && !SCHEME_NULLP(l1)) {
l2 = scheme_null;
while (!SCHEME_NULLP(l1)) {
sm = do_module_clone(SCHEME_CAR(l1), jit);
if (!SAME_OBJ(sm, SCHEME_CAR(l1)))
submod_changed = 1;
l2 = scheme_make_pair(sm, l2);
l1 = SCHEME_CDR(l1);
}
if (submod_changed) {
l2 = scheme_reverse(l2);
if (j)
post_submods = l2;
else
pre_submods = l2;
}
}
}
if (!naya) {
if (SAME_OBJ(rp, m->prefix))
if (SAME_OBJ(rp, m->prefix) && !submod_changed)
return data;
naya = m->bodies;
}
@ -6024,6 +6049,9 @@ static Scheme_Object *do_module_clone(Scheme_Object *data, int jit)
m->bodies = naya;
m->prefix = rp;
m->pre_submodules = pre_submods;
m->post_submodules = post_submods;
return (Scheme_Object *)m;
}
@ -6837,6 +6865,18 @@ static void propagate_imports(Module_Begin_Expand_State *bxs,
}
}
Scheme_Object *reverse_and_add_rename(Scheme_Object *fm, Scheme_Object *post_ex_rn)
{
Scheme_Object *l2 = scheme_null;
while (!SCHEME_NULLP(fm)) {
l2 = scheme_make_pair(scheme_add_rename(SCHEME_CAR(fm), post_ex_rn),
l2);
fm = SCHEME_CDR(fm);
}
return l2;
}
static Scheme_Object *stx_sym(Scheme_Object *name, Scheme_Object *_genv)
{
return scheme_tl_id_sym((Scheme_Env *)_genv, name, NULL, 2, NULL, NULL);
@ -7302,12 +7342,16 @@ static Scheme_Object *do_module_begin(Scheme_Object *orig_form, Scheme_Comp_Env
Resolve_Info *ri;
Scheme_Object *o;
int max_let_depth;
int use_jit;
/* Since we optimize & resolve the module here, it won't need to
be optimized and resolved later. The resolve pass
sets m->comp_prefix to NULL, which is how optimize & resolve
know to avoid re-optimizing and re-resolving. */
o = scheme_get_param(scheme_current_config(), MZCONFIG_USE_JIT);
use_jit = SCHEME_TRUEP(o);
oi = scheme_optimize_info_create(env->prefix);
scheme_optimize_info_enforce_const(oi, rec[drec].comp_flags & COMP_ENFORCE_CONSTS);
if (!(rec[drec].comp_flags & COMP_CAN_INLINE))
@ -7322,6 +7366,11 @@ static Scheme_Object *do_module_begin(Scheme_Object *orig_form, Scheme_Comp_Env
max_let_depth = scheme_resolve_info_max_let_depth(ri);
o = scheme_sfs(o, NULL, max_let_depth);
if (use_jit)
o = scheme_jit_expr(o);
else
o = scheme_eval_clone(o);
(void)do_module_execute(o, env->genv, 0, 1, root_module_name);
}
@ -7663,7 +7712,7 @@ static Scheme_Object *do_module_begin_at_phase(Scheme_Object *form, Scheme_Comp_
e = scheme_reverse(e);
if (expand_ends) {
fm = scheme_frame_get_end_statement_lifts(xenv);
fm = scheme_reverse(fm);
fm = reverse_and_add_rename(fm, post_ex_rn);
if (!SCHEME_NULLP(e))
fm = scheme_append(fm, e);
maybe_has_lifts = 0;
@ -8057,7 +8106,7 @@ static Scheme_Object *do_module_begin_at_phase(Scheme_Object *form, Scheme_Comp_
e = scheme_reverse(e);
if (expand_ends) {
fm = scheme_frame_get_end_statement_lifts(xenv);
fm = scheme_reverse(fm);
fm = reverse_and_add_rename(fm, post_ex_rn);
if (!SCHEME_NULLP(e))
fm = scheme_append(fm, e);
maybe_has_lifts = 0;
@ -10216,6 +10265,11 @@ void add_single_require(Scheme_Module_Exports *me, /* from module */
leads to generated local names). */
context_marks = scheme_stx_extract_marks(mark_src);
has_context = !SCHEME_NULLP(context_marks);
if (!has_context) {
if (SCHEME_TRUEP(scheme_stx_moduleless_env(mark_src))) {
has_context = 1;
}
}
if (has_context) {
if (all_simple)
*all_simple = 0;