add tracking of require
and provide
subforms
Use `syntax-track-origin` and 'disappeared-use properties to communicate `require` and `provide` form bindings to tools such as Check Syntax. Relevant to PR 13186
This commit is contained in:
parent
59777ca17a
commit
5749d4080c
|
@ -1353,6 +1353,42 @@
|
||||||
|
|
||||||
(test #t syntax? (expand-syntax (expand lifted-require-of-submodule)))
|
(test #t syntax? (expand-syntax (expand lifted-require-of-submodule)))
|
||||||
|
|
||||||
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Check addition of 'disappeared-use by `provide`
|
||||||
|
|
||||||
|
(require (rename-in racket/base [lib racket-base:lib]))
|
||||||
|
|
||||||
|
(let ()
|
||||||
|
(define (find-disappeared stx id)
|
||||||
|
(let loop ([s stx])
|
||||||
|
(cond
|
||||||
|
[(syntax? s)
|
||||||
|
(define p (cons (syntax-property s 'disappeared-use)
|
||||||
|
(syntax-property s 'origin)))
|
||||||
|
(or (let loop ([p p])
|
||||||
|
(cond
|
||||||
|
[(identifier? p) (and (free-identifier=? p id)
|
||||||
|
(eq? (syntax-e p) (syntax-e id)))]
|
||||||
|
[(pair? p) (or (loop (car p))
|
||||||
|
(loop (cdr p)))]
|
||||||
|
[else #f]))
|
||||||
|
(loop (syntax-e s)))]
|
||||||
|
[(pair? s)
|
||||||
|
(or (loop (car s))
|
||||||
|
(loop (cdr s)))]
|
||||||
|
[else #f])))
|
||||||
|
(let ([form (expand `(module m racket/base
|
||||||
|
(provide (struct-out s))
|
||||||
|
(struct s ())))])
|
||||||
|
(test #t find-disappeared form #'struct-out))
|
||||||
|
(let ([form (expand `(module m racket/base
|
||||||
|
(require (only-in racket/base car))))])
|
||||||
|
(test #t find-disappeared form #'only-in))
|
||||||
|
(let ([form (expand `(module m racket/base
|
||||||
|
(require (rename-in racket/base [lib racket-base:lib])
|
||||||
|
(racket-base:lib "racket/base"))))])
|
||||||
|
(test #t find-disappeared form #'racket-base:lib)))
|
||||||
|
|
||||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(report-errs)
|
(report-errs)
|
||||||
|
|
|
@ -55,16 +55,16 @@
|
||||||
(if (and (eq? new-mp #'mp)
|
(if (and (eq? new-mp #'mp)
|
||||||
(eq? (car d) 'submod))
|
(eq? (car d) 'submod))
|
||||||
stx
|
stx
|
||||||
(datum->syntax
|
(syntax-track/form (datum->syntax
|
||||||
stx
|
stx
|
||||||
(list* kw new-mp #'rest)
|
(list* kw new-mp #'rest)
|
||||||
stx
|
stx)
|
||||||
stx)))])]
|
stx)))])]
|
||||||
[(eq? (car d) kw) stx]
|
[(eq? (car d) kw) stx]
|
||||||
[else (datum->syntax
|
[else (syntax-track/form (datum->syntax
|
||||||
stx
|
stx
|
||||||
(cons kw (cdr d))
|
(cons kw (cdr d))
|
||||||
stx
|
stx)
|
||||||
stx)]))
|
stx)]))
|
||||||
stx)))
|
stx)))
|
||||||
|
|
||||||
|
@ -298,12 +298,13 @@
|
||||||
(simple-path? #'path)
|
(simple-path? #'path)
|
||||||
(list (mode-wrap
|
(list (mode-wrap
|
||||||
base-mode
|
base-mode
|
||||||
|
(syntax-track/form
|
||||||
(datum->syntax
|
(datum->syntax
|
||||||
#'path
|
#'path
|
||||||
(syntax-e
|
(syntax-e
|
||||||
(quasisyntax
|
(quasisyntax
|
||||||
(prefix pfx #,(xlate-path #'path))))
|
(prefix pfx #,(xlate-path #'path))))
|
||||||
in
|
in)
|
||||||
in)))]
|
in)))]
|
||||||
[(except-in path id ...)
|
[(except-in path id ...)
|
||||||
(and (simple-path? #'path)
|
(and (simple-path? #'path)
|
||||||
|
@ -312,14 +313,19 @@
|
||||||
(lambda (a b) #t)))
|
(lambda (a b) #t)))
|
||||||
(list (mode-wrap
|
(list (mode-wrap
|
||||||
base-mode
|
base-mode
|
||||||
|
(syntax-track/form
|
||||||
(datum->syntax
|
(datum->syntax
|
||||||
#'path
|
#'path
|
||||||
(syntax-e
|
(syntax-e
|
||||||
(quasisyntax/loc in
|
(quasisyntax/loc in
|
||||||
(all-except #,(xlate-path #'path) id ...))))))]
|
(all-except #,(xlate-path #'path) id ...))))
|
||||||
|
in)))]
|
||||||
;; General case:
|
;; General case:
|
||||||
[_ (let-values ([(imports sources) (expand-import in)])
|
[_ (let-values ([(imports sources) (expand-import in)])
|
||||||
;; TODO: collapse back to simple cases when possible
|
;; TODO: collapse back to simple cases when possible
|
||||||
|
(cons/syntax-track/form
|
||||||
|
#'(just-meta 0)
|
||||||
|
in
|
||||||
(append
|
(append
|
||||||
(map (lambda (import)
|
(map (lambda (import)
|
||||||
#`(just-meta
|
#`(just-meta
|
||||||
|
@ -332,7 +338,7 @@
|
||||||
(map (lambda (src)
|
(map (lambda (src)
|
||||||
(mode-wrap (phase+ base-mode (import-source-mode src))
|
(mode-wrap (phase+ base-mode (import-source-mode src))
|
||||||
#`(only #,(import-source-mod-path-stx src))))
|
#`(only #,(import-source-mod-path-stx src))))
|
||||||
sources)))]))]
|
sources))))]))]
|
||||||
[transform-one
|
[transform-one
|
||||||
(lambda (in)
|
(lambda (in)
|
||||||
;; Recognize `for-syntax', etc. for simple cases:
|
;; Recognize `for-syntax', etc. for simple cases:
|
||||||
|
@ -340,14 +346,20 @@
|
||||||
[(for-meta n elem ...)
|
[(for-meta n elem ...)
|
||||||
(or (exact-integer? (syntax-e #'n))
|
(or (exact-integer? (syntax-e #'n))
|
||||||
(not (syntax-e #'n)))
|
(not (syntax-e #'n)))
|
||||||
|
(cons/syntax-track/form
|
||||||
|
#'(for-meta n)
|
||||||
|
in
|
||||||
(apply append
|
(apply append
|
||||||
(map (lambda (in)
|
(map (lambda (in)
|
||||||
(transform-simple in (syntax-e #'n)))
|
(transform-simple in (syntax-e #'n)))
|
||||||
(syntax->list #'(elem ...))))]
|
(syntax->list #'(elem ...)))))]
|
||||||
[(for-something elem ...)
|
[(for-something elem ...)
|
||||||
(and (identifier? #'for-something)
|
(and (identifier? #'for-something)
|
||||||
(ormap (lambda (i) (free-identifier=? i #'for-something))
|
(ormap (lambda (i) (free-identifier=? i #'for-something))
|
||||||
(list #'for-syntax #'for-template #'for-label)))
|
(list #'for-syntax #'for-template #'for-label)))
|
||||||
|
(cons/syntax-track/form
|
||||||
|
#'(for-something)
|
||||||
|
in
|
||||||
(apply append
|
(apply append
|
||||||
(map (lambda (in)
|
(map (lambda (in)
|
||||||
(transform-simple in
|
(transform-simple in
|
||||||
|
@ -358,7 +370,7 @@
|
||||||
-1]
|
-1]
|
||||||
[(free-identifier=? #'for-something #'for-label)
|
[(free-identifier=? #'for-something #'for-label)
|
||||||
#f])))
|
#f])))
|
||||||
(syntax->list #'(elem ...))))]
|
(syntax->list #'(elem ...)))))]
|
||||||
[_ (transform-simple in 0 #| run phase |#)]))])
|
[_ (transform-simple in 0 #| run phase |#)]))])
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ in)
|
[(_ in)
|
||||||
|
@ -401,6 +413,15 @@
|
||||||
"not at module level or top level"
|
"not at module level or top level"
|
||||||
stx)]))
|
stx)]))
|
||||||
|
|
||||||
|
(define-for-syntax (syntax-track/form stx orig)
|
||||||
|
(syntax-track-origin stx orig (syntax-local-introduce (car (syntax-e orig)))))
|
||||||
|
|
||||||
|
(define-for-syntax (cons/syntax-track/form stx orig l)
|
||||||
|
;; Add `stx` as a dummy require if needed to track `orig`
|
||||||
|
(if (pair? l)
|
||||||
|
(cons (syntax-track/form (car l) orig)
|
||||||
|
(cdr l))
|
||||||
|
(cons (syntax-track/form stx orig) l)))
|
||||||
|
|
||||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; require transformers
|
;; require transformers
|
||||||
|
@ -721,11 +742,32 @@
|
||||||
exports)))])
|
exports)))])
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_ out ...)
|
[(_ out ...)
|
||||||
(with-syntax ([(new-out ...)
|
(let ([outs (syntax->list #'(out ...))])
|
||||||
(apply append
|
(with-syntax ([(new-out ...) (apply append (map transform-simple outs))])
|
||||||
(map transform-simple (syntax->list #'(out ...))))])
|
(copy-disappeared-uses
|
||||||
|
outs
|
||||||
(syntax/loc stx
|
(syntax/loc stx
|
||||||
(begin new-out ...)))]))]))
|
(begin new-out ...)))))]))]))
|
||||||
|
|
||||||
|
(define-for-syntax (copy-disappeared-uses outs r)
|
||||||
|
(cond
|
||||||
|
[(null? outs) r]
|
||||||
|
[else
|
||||||
|
(let ([p (syntax-property (car outs) 'disappeared-use)]
|
||||||
|
[name (if (identifier? (car outs))
|
||||||
|
#f
|
||||||
|
(syntax-local-introduce (car (syntax-e (car outs)))))]
|
||||||
|
[combine (lambda (b a)
|
||||||
|
(if a
|
||||||
|
(if b
|
||||||
|
(cons a b)
|
||||||
|
a)
|
||||||
|
b))])
|
||||||
|
(syntax-property r 'disappeared-use
|
||||||
|
(combine p
|
||||||
|
(combine
|
||||||
|
name
|
||||||
|
(syntax-property r 'disappeared-use)))))]))
|
||||||
|
|
||||||
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; provide transformers
|
;; provide transformers
|
||||||
|
|
|
@ -75,7 +75,9 @@
|
||||||
#f
|
#f
|
||||||
"result from provide pre-transformer is not a syntax object"
|
"result from provide pre-transformer is not a syntax object"
|
||||||
stx))
|
stx))
|
||||||
v)
|
(syntax-property v
|
||||||
|
'disappeared-use
|
||||||
|
(syntax-local-introduce #'id)))
|
||||||
stx))]
|
stx))]
|
||||||
[_ stx]))))
|
[_ stx]))))
|
||||||
|
|
||||||
|
|
|
@ -11016,7 +11016,7 @@ void parse_provides(Scheme_Object *form, Scheme_Object *fst, Scheme_Object *e,
|
||||||
Scheme_Comp_Env *cenv, Scheme_Compile_Info *rec, int drec,
|
Scheme_Comp_Env *cenv, Scheme_Compile_Info *rec, int drec,
|
||||||
Scheme_Object **_expanded)
|
Scheme_Object **_expanded)
|
||||||
{
|
{
|
||||||
Scheme_Object *l, *rebuilt = scheme_null, *protect_stx = NULL;
|
Scheme_Object *l, *rebuilt = scheme_null, *protect_stx = NULL, *rebuild_from = scheme_null;
|
||||||
int protect_cnt = 0, mode_cnt = 0, expanded = 0;
|
int protect_cnt = 0, mode_cnt = 0, expanded = 0;
|
||||||
Scheme_Object *mode = scheme_make_integer(0), *mode_stx = NULL;
|
Scheme_Object *mode = scheme_make_integer(0), *mode_stx = NULL;
|
||||||
Scheme_Object *all_x_defs_out, *all_x_defs;
|
Scheme_Object *all_x_defs_out, *all_x_defs;
|
||||||
|
@ -11041,6 +11041,8 @@ void parse_provides(Scheme_Object *form, Scheme_Object *fst, Scheme_Object *e,
|
||||||
if (SAME_OBJ(protect_symbol, av)) {
|
if (SAME_OBJ(protect_symbol, av)) {
|
||||||
if (protect_cnt)
|
if (protect_cnt)
|
||||||
scheme_wrong_syntax(NULL, a, e, "nested `protect' not allowed");
|
scheme_wrong_syntax(NULL, a, e, "nested `protect' not allowed");
|
||||||
|
if (_expanded)
|
||||||
|
rebuild_from = scheme_make_pair(a, rebuild_from);
|
||||||
protect_stx = a;
|
protect_stx = a;
|
||||||
a = SCHEME_STX_CDR(a);
|
a = SCHEME_STX_CDR(a);
|
||||||
a = scheme_flatten_syntax_list(a, NULL);
|
a = scheme_flatten_syntax_list(a, NULL);
|
||||||
|
@ -11142,6 +11144,9 @@ void parse_provides(Scheme_Object *form, Scheme_Object *fst, Scheme_Object *e,
|
||||||
if (!all_x_defs) all_x_defs = scheme_null;
|
if (!all_x_defs) all_x_defs = scheme_null;
|
||||||
p = expand_provide(p, at_phase, tables, all_defs, cenv, rec, drec);
|
p = expand_provide(p, at_phase, tables, all_defs, cenv, rec, drec);
|
||||||
|
|
||||||
|
if (_expanded)
|
||||||
|
rebuild_from = scheme_make_pair(p, rebuild_from);
|
||||||
|
|
||||||
/* Check for '(begin datum ...) result: */
|
/* Check for '(begin datum ...) result: */
|
||||||
p = scheme_flatten_syntax_list(p, &islist);
|
p = scheme_flatten_syntax_list(p, &islist);
|
||||||
if (!islist)
|
if (!islist)
|
||||||
|
@ -11440,6 +11445,12 @@ void parse_provides(Scheme_Object *form, Scheme_Object *fst, Scheme_Object *e,
|
||||||
a = SCHEME_STX_CAR(e);
|
a = SCHEME_STX_CAR(e);
|
||||||
rebuilt = scheme_make_pair(a, scheme_reverse(rebuilt));
|
rebuilt = scheme_make_pair(a, scheme_reverse(rebuilt));
|
||||||
rebuilt = scheme_datum_to_syntax(rebuilt, e, e, 0, 2);
|
rebuilt = scheme_datum_to_syntax(rebuilt, e, e, 0, 2);
|
||||||
|
|
||||||
|
while (SCHEME_PAIRP(rebuild_from)) {
|
||||||
|
rebuilt = scheme_stx_track(rebuilt, SCHEME_CAR(rebuild_from), NULL);
|
||||||
|
rebuild_from = SCHEME_CDR(rebuild_from);
|
||||||
|
}
|
||||||
|
|
||||||
*_expanded = rebuilt;
|
*_expanded = rebuilt;
|
||||||
} else {
|
} else {
|
||||||
*_expanded = e;
|
*_expanded = e;
|
||||||
|
|
|
@ -656,7 +656,7 @@ Scheme_Object *scheme_stx_track(Scheme_Object *naya,
|
||||||
for (; SCHEME_PAIRP(oe); oe = SCHEME_CDR(oe)) {
|
for (; SCHEME_PAIRP(oe); oe = SCHEME_CDR(oe)) {
|
||||||
a = SCHEME_CAR(SCHEME_CAR(oe));
|
a = SCHEME_CAR(SCHEME_CAR(oe));
|
||||||
if (!SAME_OBJ(a, source_symbol) && !SAME_OBJ(a, share_symbol)) {
|
if (!SAME_OBJ(a, source_symbol) && !SAME_OBJ(a, share_symbol)) {
|
||||||
if (!SAME_OBJ(a, origin_symbol)) {
|
if (!origin || !SAME_OBJ(a, origin_symbol)) {
|
||||||
p = ICONS(SCHEME_CAR(oe), scheme_null);
|
p = ICONS(SCHEME_CAR(oe), scheme_null);
|
||||||
} else {
|
} else {
|
||||||
p = ICONS(ICONS(a, ICONS(origin,
|
p = ICONS(ICONS(a, ICONS(origin,
|
||||||
|
@ -675,7 +675,7 @@ Scheme_Object *scheme_stx_track(Scheme_Object *naya,
|
||||||
|
|
||||||
oe = first;
|
oe = first;
|
||||||
}
|
}
|
||||||
if (add) {
|
if (add && origin) {
|
||||||
oe = ICONS(ICONS(origin_symbol,
|
oe = ICONS(ICONS(origin_symbol,
|
||||||
ICONS(origin, scheme_null)),
|
ICONS(origin, scheme_null)),
|
||||||
oe);
|
oe);
|
||||||
|
@ -686,10 +686,14 @@ Scheme_Object *scheme_stx_track(Scheme_Object *naya,
|
||||||
oe = NULL;
|
oe = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!oe)
|
if (!oe) {
|
||||||
|
if (origin)
|
||||||
oe = ICONS(ICONS(origin_symbol,
|
oe = ICONS(ICONS(origin_symbol,
|
||||||
ICONS(origin, scheme_null)),
|
ICONS(origin, scheme_null)),
|
||||||
scheme_null);
|
scheme_null);
|
||||||
|
else
|
||||||
|
oe = scheme_null;
|
||||||
|
}
|
||||||
|
|
||||||
/* Merge ne and oe (ne takes precedence). */
|
/* Merge ne and oe (ne takes precedence). */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user