expander: add 'protected property to protected references

As documented and as implemented by the old expander.
This commit is contained in:
Matthew Flatt 2018-02-28 17:14:06 -07:00
parent 24a4882e5d
commit b4f0499256
9 changed files with 7977 additions and 7934 deletions

View File

@ -238,6 +238,21 @@
(define-define-stx stx-with-property) (define-define-stx stx-with-property)
(test 'y syntax-property stx-with-property 'x) (test 'y syntax-property stx-with-property 'x)
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Check that protected references are annotated with a 'protected property
(module exports-macros-that-expand-to-protected-references racket/base
(provide emtetpr-m1 emtetpr-m2 (protect-out x1))
(define x1 1)
(define x2 2)
(define-syntax-rule (emtetpr-m1) x1)
(define-syntax-rule (emtetpr-m2) x2))
(require 'exports-macros-that-expand-to-protected-references)
(test #t syntax-property (expand #'(emtetpr-m1)) 'protected)
(test #t syntax-property (expand #'(emtetpr-m2)) 'protected)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Check immutability ;; Check immutability

View File

@ -25,5 +25,6 @@
[else [else
;; Use `binding-lookup` to both check for taints and determine whether the ;; Use `binding-lookup` to both check for taints and determine whether the
;; binding is a transformer or variable binding ;; binding is a transformer or variable binding
(define-values (val primitive? insp) (binding-lookup b empty-env null ns at-phase id)) (define-values (val primitive? insp protected?)
(binding-lookup b empty-env null ns at-phase id))
(not (variable? val))])) (not (variable? val))]))

View File

@ -107,6 +107,7 @@
;; Returns: `variable` or a compile-time value ;; Returns: `variable` or a compile-time value
;; #f or #t indicating whether the binding is to a primitive ;; #f or #t indicating whether the binding is to a primitive
;; #f or (for a transformer) an inspector for the defining module ;; #f or (for a transformer) an inspector for the defining module
;; #f or #t for a protected binding
;; A binding provided to `binding-lookup` should be obtained either by ;; A binding provided to `binding-lookup` should be obtained either by
;; passing `#:immediate? #t` to `resolve+shift` or by using `resolve+shift/extra-inspector`, ;; passing `#:immediate? #t` to `resolve+shift` or by using `resolve+shift/extra-inspector`,
;; where the latter checks protected access for `free-identifier=?` equivalence ;; where the latter checks protected access for `free-identifier=?` equivalence
@ -125,9 +126,10 @@
(check-taint id) (check-taint id)
(define t (namespace-get-transformer m-ns (module-binding-phase b) (module-binding-sym b) (define t (namespace-get-transformer m-ns (module-binding-phase b) (module-binding-sym b)
variable)) variable))
(when mi (check-access b mi id in-s (if (variable? t) "variable" "transformer"))) (define protected?
(and mi (check-access b mi id in-s (if (variable? t) "variable" "transformer"))))
(define insp (and mi (module-instance-module mi) (module-inspector (module-instance-module mi)))) (define insp (and mi (module-instance-module mi) (module-inspector (module-instance-module mi))))
(values t primitive? insp)] (values t primitive? insp protected?)]
[(local-binding? b) [(local-binding? b)
(define t (hash-ref env (local-binding-key b) missing)) (define t (hash-ref env (local-binding-key b) missing))
(cond (cond
@ -140,10 +142,11 @@
variable variable
(error "identifier used out of context:" id))) (error "identifier used out of context:" id)))
#f #f
#f
#f)] #f)]
[else [else
(check-taint id) (check-taint id)
(values t #f #f)])] (values t #f #f #f)])]
[else (error "internal error: unknown binding for lookup:" b)])) [else (error "internal error: unknown binding for lookup:" b)]))
;; Check for taints on a variable reference ;; Check for taints on a variable reference

View File

@ -627,9 +627,9 @@
#:immediate? #t)) #:immediate? #t))
(when (eq? binding 'ambiguous) (when (eq? binding 'ambiguous)
(raise-ambiguous-error id ctx)) (raise-ambiguous-error id ctx))
(define-values (t primitive? insp) (if binding (define-values (t primitive? insp protected?) (if binding
(lookup binding ctx s) (lookup binding ctx s)
(values #f #f #f))) (values #f #f #f #f)))
(log-expand ctx 'resolve id) (log-expand ctx 'resolve id)
(cond (cond
[(or (variable? t) [(or (variable? t)
@ -703,12 +703,12 @@
(expand-context-allow-unbound? ctx)) (expand-context-allow-unbound? ctx))
(raise-unbound-syntax-error #f "unbound identifier" s var-id null (raise-unbound-syntax-error #f "unbound identifier" s var-id null
(syntax-debug-info-string var-id ctx))) (syntax-debug-info-string var-id ctx)))
(define-values (t primitive? insp-of-t) (define-values (t primitive? insp-of-t protected?)
(if binding (if binding
(lookup binding ctx var-id (lookup binding ctx var-id
#:in s #:in s
#:out-of-context-as-variable? (expand-context-in-local-expand? ctx)) #:out-of-context-as-variable? (expand-context-in-local-expand? ctx))
(values #f #f #f))) (values #f #f #f #f)))
(when (and t (not (variable? t))) (when (and t (not (variable? t)))
(raise-syntax-error #f "identifier does not refer to a variable" var-id s)) (raise-syntax-error #f "identifier does not refer to a variable" var-id s))
(if (expand-context-to-parsed? ctx) (if (expand-context-to-parsed? ctx)

View File

@ -105,10 +105,11 @@
(expand-implicit '#%top (substitute-alternate-id s alternate-id) ctx s)] (expand-implicit '#%top (substitute-alternate-id s alternate-id) ctx s)]
[else [else
;; Variable or form as identifier macro ;; Variable or form as identifier macro
(define-values (t primitive? insp-of-t) (lookup binding ctx id (define-values (t primitive? insp-of-t protected?)
(lookup binding ctx id
#:in (and alternate-id s) #:in (and alternate-id s)
#:out-of-context-as-variable? (expand-context-in-local-expand? ctx))) #:out-of-context-as-variable? (expand-context-in-local-expand? ctx)))
(dispatch t insp-of-t s id ctx binding primitive?)]))) (dispatch t insp-of-t s id ctx binding primitive? protected?)])))
;; An "application" form that starts with an identifier ;; An "application" form that starts with an identifier
(define (expand-id-application-form s ctx alternate-id) (define (expand-id-application-form s ctx alternate-id)
@ -127,7 +128,8 @@
(expand-implicit '#%app (substitute-alternate-id s alternate-id) ctx id)] (expand-implicit '#%app (substitute-alternate-id s alternate-id) ctx id)]
[else [else
;; Find out whether it's bound as a variable, syntax, or core form ;; Find out whether it's bound as a variable, syntax, or core form
(define-values (t primitive? insp-of-t) (lookup binding ctx id (define-values (t primitive? insp-of-t protected?)
(lookup binding ctx id
#:in (and alternate-id (car (syntax-e/no-taint s))) #:in (and alternate-id (car (syntax-e/no-taint s)))
#:out-of-context-as-variable? (expand-context-in-local-expand? ctx))) #:out-of-context-as-variable? (expand-context-in-local-expand? ctx)))
(cond (cond
@ -136,7 +138,7 @@
(expand-implicit '#%app (substitute-alternate-id s alternate-id) ctx id)] (expand-implicit '#%app (substitute-alternate-id s alternate-id) ctx id)]
[else [else
;; Syntax or core form as "application" ;; Syntax or core form as "application"
(dispatch t insp-of-t s id ctx binding primitive?)])]))) (dispatch t insp-of-t s id ctx binding primitive? protected?)])])))
;; Handle an implicit: `#%app`, `#%top`, or `#%datum`; this is similar ;; Handle an implicit: `#%app`, `#%top`, or `#%datum`; this is similar
;; to handling an id-application form, but there are several little ;; to handling an id-application form, but there are several little
@ -160,7 +162,8 @@
[(eq? b 'ambiguous) [(eq? b 'ambiguous)
(raise-ambiguous-error id ctx)] (raise-ambiguous-error id ctx)]
[else [else
(define-values (t primitive? insp-of-t) (if b (lookup b ctx id) (values #f #f #f))) (define-values (t primitive? insp-of-t protected?)
(if b (lookup b ctx id) (values #f #f #f #f)))
(cond (cond
[(transformer? t) [(transformer? t)
(dispatch-transformer t insp-of-t (make-explicit ctx sym s disarmed-s) id ctx b)] (dispatch-transformer t insp-of-t (make-explicit ctx sym s disarmed-s) id ctx b)]
@ -226,14 +229,14 @@
;; other compile-time value (which is an error), or a token ;; other compile-time value (which is an error), or a token
;; indicating that the binding is a run-time variable; note that ;; indicating that the binding is a run-time variable; note that
;; `s` is not disarmed ;; `s` is not disarmed
(define (dispatch t insp-of-t s id ctx binding primitive?) (define (dispatch t insp-of-t s id ctx binding primitive? protected?)
(cond (cond
[(core-form? t) [(core-form? t)
(dispatch-core-form t s ctx)] (dispatch-core-form t s ctx)]
[(transformer? t) [(transformer? t)
(dispatch-transformer t insp-of-t s id ctx binding)] (dispatch-transformer t insp-of-t s id ctx binding)]
[(variable? t) [(variable? t)
(dispatch-variable t s id ctx binding primitive?)] (dispatch-variable t s id ctx binding primitive? protected?)]
[else [else
;; Some other compile-time value: ;; Some other compile-time value:
(raise-syntax-error #f "illegal use of syntax" s)])) (raise-syntax-error #f "illegal use of syntax" s)]))
@ -301,7 +304,7 @@
(rename-transformer? t)))])])) (rename-transformer? t)))])]))
;; Handle the expansion of a variable to itself ;; Handle the expansion of a variable to itself
(define (dispatch-variable t s id ctx binding primitive?) (define (dispatch-variable t s id ctx binding primitive? protected?)
(cond (cond
[(expand-context-only-immediate? ctx) [(expand-context-only-immediate? ctx)
(log-expand* ctx ['exit-check s]) (log-expand* ctx ['exit-check s])
@ -321,8 +324,11 @@
(parsed-primitive-id prop-s binding insp) (parsed-primitive-id prop-s binding insp)
(parsed-id prop-s binding insp))] (parsed-id prop-s binding insp))]
[else [else
(log-expand ctx 'return result-s) (define protected-result-s (if protected?
result-s])])) (syntax-property result-s 'protected #t)
result-s))
(log-expand ctx 'return protected-result-s)
protected-result-s])]))
;; ---------------------------------------- ;; ----------------------------------------

View File

@ -13,15 +13,18 @@
;; Check inspector-based access to a module's definitions; a suitable inspector ;; Check inspector-based access to a module's definitions; a suitable inspector
;; might be provided by `id`, or the binding might carry an extra inspector ;; might be provided by `id`, or the binding might carry an extra inspector
;; (put there via a provide of a rename transformer, where the extra inspector ;; (put there via a provide of a rename transformer, where the extra inspector
;; was attached to the identifier in the rename transformer) ;; was attached to the identifier in the rename transformer). Return #t if
;; the binding is protected.
(define (check-access b mi id in-s what) (define (check-access b mi id in-s what)
(define m (module-instance-module mi)) (define m (module-instance-module mi))
(when (and m (not (module-no-protected? m))) (cond
[(and m (not (module-no-protected? m)))
(define access (or (module-access m) (module-compute-access! m))) (define access (or (module-access m) (module-compute-access! m)))
(define a (hash-ref (hash-ref access (module-binding-phase b) #hasheq()) (define a (hash-ref (hash-ref access (module-binding-phase b) #hasheq())
(module-binding-sym b) (module-binding-sym b)
'unexported)) 'unexported))
(when (or (eq? a 'unexported) ; not provided => implicitly protected (cond
[(or (eq? a 'unexported) ; not provided => implicitly protected
(eq? a 'protected)) (eq? a 'protected))
(unless (or (inspector-superior? (or (syntax-inspector id) (current-code-inspector)) (unless (or (inspector-superior? (or (syntax-inspector id) (current-code-inspector))
(namespace-inspector (module-instance-namespace mi))) (namespace-inspector (module-instance-namespace mi)))
@ -41,7 +44,10 @@
a a
what what
(module-path-index-resolve (namespace-mpi (module-instance-namespace mi)))) (module-path-index-resolve (namespace-mpi (module-instance-namespace mi))))
complain-id id null))))) complain-id id null))
#t]
[else #f])]
[else #f]))
;; Like `resolve+shift`, but follow `free-identifier=?` chains to ;; Like `resolve+shift`, but follow `free-identifier=?` chains to
;; attach an inspector at the last step in the chain to the ;; attach an inspector at the last step in the chain to the

View File

@ -188,7 +188,8 @@
(failure-thunk) (failure-thunk)
(error 'syntax-local-value "unbound identifier: ~v" id))] (error 'syntax-local-value "unbound identifier: ~v" id))]
[else [else
(define-values (v primitive? insp) (lookup b ctx id #:out-of-context-as-variable? #t)) (define-values (v primitive? insp protected?)
(lookup b ctx id #:out-of-context-as-variable? #t))
(cond (cond
[(or (variable? v) (core-form? v)) [(or (variable? v) (core-form? v))
(log-expand ctx 'local-value-result #f) (log-expand ctx 'local-value-result #f)

View File

@ -180,7 +180,7 @@
(namespace-phase ns) (namespace-phase ns)
ns)) ns))
(when b (namespace-visit-available-modules! ns)) (when b (namespace-visit-available-modules! ns))
(define-values (v primitive? extra-inspector) (define-values (v primitive? extra-inspector protected?)
(if b (if b
(binding-lookup b empty-env null ns (namespace-phase ns) id) (binding-lookup b empty-env null ns (namespace-phase ns) id)
(values variable #f #f))) (values variable #f #f)))

File diff suppressed because it is too large Load Diff