|  | #lang racket | 
        
          |  |  | 
        
          |  | (require racket/stxparam | 
        
          |  | rebellion/base/result | 
        
          |  | syntax/parse/define) | 
        
          |  |  | 
        
          |  | (define permission-check-tag (make-continuation-prompt-tag 'permission-check)) | 
        
          |  |  | 
        
          |  | (define (check-permission-dynamically permission) | 
        
          |  | (call-with-current-continuation | 
        
          |  | (λ (jump-back) (abort-current-continuation permission-check-tag permission jump-back)) | 
        
          |  | permission-check-tag)) | 
        
          |  |  | 
        
          |  | (define (make-permission-check-handler granted-permissions) | 
        
          |  | (define (handler permission jump-back) | 
        
          |  | (if (set-member? granted-permissions permission) | 
        
          |  | (call-with-continuation-prompt jump-back permission-check-tag handler) | 
        
          |  | (failure permission))) | 
        
          |  | handler) | 
        
          |  |  | 
        
          |  | (define (grant-permissions-dynamically permissions thunk) | 
        
          |  | (define handler (make-permission-check-handler permissions)) | 
        
          |  | (call-with-continuation-prompt (λ () (success (thunk))) permission-check-tag handler)) | 
        
          |  |  | 
        
          |  | (define-syntax-parameter in-grant-permissions-block? #false) | 
        
          |  |  | 
        
          |  | (define-syntax-parse-rule (check-permission! id:id) | 
        
          |  | #:fail-unless (syntax-parameter-value #'in-grant-permissions-block?) | 
        
          |  | "cannot be used outside a grant-permissions block" | 
        
          |  | (check-permission-dynamically 'id)) | 
        
          |  |  | 
        
          |  | (define-syntax-parse-rule (grant-permissions (~seq #:allow sym:id) ... body ...) | 
        
          |  | (grant-permissions-dynamically | 
        
          |  | (set 'sym ...) | 
        
          |  | (λ () | 
        
          |  | (syntax-parameterize ([in-grant-permissions-block? #true]) | 
        
          |  | body ...)))) | 
        
          |  |  | 
        
          |  | ;; evaluates to (failure 'system-clock) | 
        
          |  | (grant-permissions | 
        
          |  | #:allow filesystem | 
        
          |  | #:allow network | 
        
          |  |  | 
        
          |  | (displayln "Stealing secret files...") | 
        
          |  | (check-permission! filesystem) | 
        
          |  | (displayln "Secret files stolen!") | 
        
          |  |  | 
        
          |  | (newline) | 
        
          |  |  | 
        
          |  | (displayln "Contacting the NSA...") | 
        
          |  | (check-permission! network) | 
        
          |  | (displayln "NSA contacted!") | 
        
          |  |  | 
        
          |  | (newline) | 
        
          |  |  | 
        
          |  | (displayln "Changing the system clock...") | 
        
          |  | (check-permission! system-clock) | 
        
          |  | ;; this part is never printed | 
        
          |  | (displayln "System clock changed!")) | 
  
(side note) Regarding the first case, one can also use a simple escape continuation ("ec"):