(spar-subform)
(spar-push spar-arg:ctx)
(spar-push-subform-if mit-lambda-list? spar-arg:form)
- (spar-push-body)))))
+ (spar-push-body make-internal-senv)))))
(define $named-lambda
(spar-classifier->runtime
(spar-subform
(spar-push-subform-if identifier? spar-arg:form)
(spar-push-form-if mit-lambda-list? spar-arg:form))
- (spar-push-body)))))
+ (spar-push-body make-internal-senv)))))
-(define (spar-push-body)
+(define (spar-push-body make-senv)
(spar-and
(spar-push spar-arg:ctx)
(spar-encapsulate-values
(lambda (elts)
(lambda (frame-senv)
- (let ((body-senv (make-internal-senv frame-senv)))
+ (let ((body-senv (make-senv frame-senv)))
(map-in-order (lambda (elt) (elt body-senv))
elts))))
(spar+ (spar-subform spar-push-open-classified))
(delay
(spar-call-with-values
(lambda (ctx bindings body-ctx body)
- (let ((frame-senv (make-internal-senv (serror-ctx-senv ctx))))
+ (let ((frame-senv
+ (make-keyword-internal-senv (serror-ctx-senv ctx))))
(for-each (lambda (binding)
(bind-keyword (car binding) frame-senv (cdr binding)))
bindings)
(spar-subform spar-push-classified)
(spar-match-null)))))
(spar-match-null))
- (spar-push-body))))
+ (spar-push-body make-keyword-internal-senv))))
(define $let-syntax
(spar-classifier->runtime spar-promise:let-syntax))
(delay
(spar-call-with-values
(lambda (ctx bindings body-ctx body)
- (let ((frame-senv (make-internal-senv (serror-ctx-senv ctx)))
+ (let ((frame-senv
+ (make-keyword-internal-senv (serror-ctx-senv ctx)))
(ids (map car bindings)))
(for-each (lambda (id)
- (reserve-identifier id frame-senv))
+ (reserve-keyword id frame-senv))
ids)
(for-each (lambda (id item)
(bind-keyword id frame-senv item))
(spar-subform spar-push-open-classified)
(spar-match-null)))))
(spar-match-null))
- (spar-push-body)))))
+ (spar-push-body make-keyword-internal-senv)))))
\f
;;;; Pseudo keywords
(var-item identifier)))
'lookup-identifier))
-(define reserve-identifier
+(define reserve-keyword
(id-dispatcher (lambda (identifier senv)
- ((senv-store senv) identifier (reserved-name-item)))
- 'reserve-identifier))
+ ((senv-store senv) identifier #t (reserved-name-item)))
+ 'reserve-keyword))
(define (bind-keyword identifier senv item)
(guarantee keyword-item? item 'bind-keyword)
((id-dispatcher (lambda (identifier senv)
- ((senv-store senv) identifier item))
+ ((senv-store senv) identifier #t item))
'bind-keyword)
identifier
senv))
(define bind-variable
(id-dispatcher (lambda (identifier senv)
(let ((rename ((senv-rename senv) identifier)))
- ((senv-store senv) identifier (var-item rename))
+ ((senv-store senv) identifier #f (var-item rename))
rename))
'bind-variable))
(cdr binding)
(environment-lookup-macro env identifier))))
- (define (store identifier item)
+ (define (store identifier keyword? item)
+ (declare (ignore keyword?))
(let ((binding (assq identifier bound)))
(if binding
(set-cdr! binding item)
(define (lookup identifier)
(environment-lookup-macro env identifier))
- (define (store identifier item)
+ (define (store identifier keyword? item)
+ (declare (ignore keyword?))
(error "Can't bind in non-top-level runtime environment:" identifier item))
(define (rename identifier)
(and (eq? name identifier)
item))
- (define (store identifier item)
+ (define (store identifier keyword? item)
+ (declare (ignore keyword?))
(error "Can't bind in keyword environment:" identifier item))
(define (rename identifier)
(set! free (cons (cons identifier item) free))
item))))
- (define (store identifier item)
+ (define (store identifier keyword? item)
+ (declare (ignore keyword?))
(cond ((assq identifier bound)
=> (lambda (binding)
(set-cdr! binding item)))
(make-senv get-type get-runtime lookup store rename describe)))
\f
+;;; Internal keyword syntactic environments represent environments created by
+;;; syntactic scopes, such as let-syntax.
+
+(define (make-keyword-internal-senv parent)
+ (guarantee syntactic-environment? parent 'make-keyword-internal-senv)
+ (let ((bound '())
+ (free '())
+ (get-runtime (senv-get-runtime parent))
+ (rename (senv-rename parent)))
+
+ (define (get-type)
+ 'keyword-internal)
+
+ (define (lookup identifier)
+ (let ((binding
+ (or (assq identifier bound)
+ (assq identifier free))))
+ (if binding
+ (cdr binding)
+ (let ((item ((senv-lookup parent) identifier)))
+ (set! free (cons (cons identifier item) free))
+ item))))
+
+ (define (store identifier keyword? item)
+ (if keyword?
+ (cond ((assq identifier bound)
+ => (lambda (binding)
+ (set-cdr! binding item)))
+ ((assq identifier free)
+ (error "Can't define name; already free:" identifier))
+ (else
+ (set! bound (cons (cons identifier item) bound))
+ unspecific))
+ ((senv-store parent) identifier keyword? item)))
+
+ (define (describe)
+ `((bound ,bound)
+ (free ,free)
+ (parent ,parent)))
+
+ (make-senv get-type get-runtime lookup store rename describe)))
+\f
;;; Partial syntactic environments are used to implement syntactic
;;; closures that have free names.
(define (lookup identifier)
((senv-lookup (select-env identifier)) identifier))
- (define (store identifier item)
+ (define (store identifier keyword? item)
+ (declare (ignore keyword?))
;; **** Shouldn't this be a syntax error? It can happen as the
;; result of a misplaced definition. ****
(error "Can't bind identifier in partial syntactic environment:"
(set! free (cons (cons identifier item) free))
item))))
- (define (store identifier item)
+ (define (store identifier keyword? item)
+ (declare (ignore keyword?))
(cond ((assq identifier bound)
=> (lambda (binding)
(set-cdr! binding item)))