1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-12 06:41:13 +02:00

Fix race when expanding syntax-parameterize and define-syntax-parameter

* module/ice-9/psyntax.scm (put-global-definition-hook)
  (get-global-definition-hook): Inline into uses.
  (make-binding): Change format of lexically defined or rebound syntax
  parameters to just be the transformer, not a list of the transformer.
  (resolve-identifier, expand-install-global, expand-body)
  (syntax-parameterize): Adapt to use the variable object (box) holding
  the top-level syntax parameter as the "key" for lookups into the
  lexical environment, instead of a fresh object associated with the
  syntax transformer.
* module/ice-9/psyntax-pp.scm: Regenerate.

Fixes #27476, a horrible race when one thread is expanding a
syntax-parameterize form including uses, and another thread is expanding
the corresponding define-syntax-parameter.  See
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27476#102.
This commit is contained in:
Andy Wingo 2019-02-22 15:25:21 +01:00
parent 27ffbfb023
commit 2dccec9f55
2 changed files with 196 additions and 172 deletions

View file

@ -120,26 +120,6 @@
(session-id (session-id
(let ((v (module-variable (current-module) 'syntax-session-id))) (let ((v (module-variable (current-module) 'syntax-session-id)))
(lambda () ((variable-ref v))))) (lambda () ((variable-ref v)))))
(put-global-definition-hook
(lambda (symbol type val)
(module-define!
(current-module)
symbol
(make-syntax-transformer symbol type val))))
(get-global-definition-hook
(lambda (symbol module)
(if (and (not module) (current-module))
(warn "module system is booted, we should have a module" symbol))
(and (not (equal? module '(primitive)))
(let ((v (module-variable
(if module (resolve-module (cdr module)) (current-module))
symbol)))
(and v
(variable-bound? v)
(let ((val (variable-ref v)))
(and (macro? val)
(macro-type val)
(cons (macro-type val) (macro-binding val)))))))))
(decorate-source (decorate-source
(lambda (e s) (lambda (e s)
(if (and s (supports-source-properties? e)) (if (and s (supports-source-properties? e))
@ -297,7 +277,11 @@
(cons a (macros-only-env (cdr r))) (cons a (macros-only-env (cdr r)))
(macros-only-env (cdr r))))))) (macros-only-env (cdr r)))))))
(global-extend (global-extend
(lambda (type sym val) (put-global-definition-hook sym type val))) (lambda (type sym val)
(module-define!
(current-module)
sym
(make-syntax-transformer sym type val))))
(nonsymbol-id? (nonsymbol-id?
(lambda (x) (lambda (x)
(and (syntax-object? x) (symbol? (syntax-object-expression x))))) (and (syntax-object? x) (symbol? (syntax-object-expression x)))))
@ -459,23 +443,37 @@
(resolve-identifier (resolve-identifier
(lambda (id w r mod resolve-syntax-parameters?) (lambda (id w r mod resolve-syntax-parameters?)
(letrec* (letrec*
((resolve-syntax-parameters ((resolve-global
(lambda (b)
(if (and resolve-syntax-parameters? (eq? (car b) 'syntax-parameter))
(or (assq-ref r (cdr b)) (cons 'macro (car (cdr b))))
b)))
(resolve-global
(lambda (var mod) (lambda (var mod)
(let ((b (resolve-syntax-parameters (if (and (not mod) (current-module))
(or (get-global-definition-hook var mod) '(global))))) (warn "module system is booted, we should have a module" var))
(if (eq? (car b) 'global) (let ((v (and (not (equal? mod '(primitive)))
(values 'global var mod) (module-variable
(values (car b) (cdr b) mod))))) (if mod (resolve-module (cdr mod)) (current-module))
var))))
(if (and v (variable-bound? v) (macro? (variable-ref v)))
(let* ((m (variable-ref v))
(type (macro-type m))
(trans (macro-binding m))
(trans (if (pair? trans) (car trans) trans)))
(if (eq? type 'syntax-parameter)
(if resolve-syntax-parameters?
(let ((lexical (assq-ref r v)))
(values 'macro (if lexical (cdr lexical) trans) mod))
(values type v mod))
(values type trans mod)))
(values 'global var mod)))))
(resolve-lexical (resolve-lexical
(lambda (label mod) (lambda (label mod)
(let ((b (resolve-syntax-parameters (let ((b (assq-ref r label)))
(or (assq-ref r label) '(displaced-lexical))))) (if b
(values (car b) (cdr b) mod))))) (let ((type (car b)) (value (cdr b)))
(if (eq? type 'syntax-parameter)
(if resolve-syntax-parameters?
(values 'macro value mod)
(values type label mod))
(values type value mod)))
(values 'displaced-lexical #f #f))))))
(let ((n (id-var-name id w mod))) (let ((n (id-var-name id w mod)))
(cond ((syntax-object? n) (cond ((syntax-object? n)
(if (not (eq? n id)) (if (not (eq? n id))
@ -726,11 +724,13 @@
(build-primcall (build-primcall
#f #f
'make-syntax-transformer 'make-syntax-transformer
(if (eq? type 'define-syntax-parameter-form) (list (build-data #f name)
(list (build-data #f name) (build-data
(build-data #f 'syntax-parameter) #f
(build-primcall #f 'list (list e))) (if (eq? type 'define-syntax-parameter-form)
(list (build-data #f name) (build-data #f 'macro) e)))))) 'syntax-parameter
'macro))
e)))))
(parse-when-list (parse-when-list
(lambda (e when-list) (lambda (e when-list)
(let ((result (strip when-list '(())))) (let ((result (strip when-list '(()))))
@ -1010,11 +1010,11 @@
(source-wrap e w (cdr w) mod) (source-wrap e w (cdr w) mod)
x)) x))
(else (decorate-source x s)))))) (else (decorate-source x s))))))
(let* ((t-680b775fb37a463-7fa transformer-environment) (let* ((t-680b775fb37a463-7d8 transformer-environment)
(t-680b775fb37a463-7fb (lambda (k) (k e r w s rib mod)))) (t-680b775fb37a463-7d9 (lambda (k) (k e r w s rib mod))))
(with-fluid* (with-fluid*
t-680b775fb37a463-7fa t-680b775fb37a463-7d8
t-680b775fb37a463-7fb t-680b775fb37a463-7d9
(lambda () (lambda ()
(rebuild-macro-output (rebuild-macro-output
(p (source-wrap e (anti-mark w) s mod)) (p (source-wrap e (anti-mark w) s mod))
@ -1072,7 +1072,7 @@
(extend-env (extend-env
(list label) (list label)
(list (cons 'syntax-parameter (list (cons 'syntax-parameter
(list (eval-local-transformer (expand e trans-r w mod) mod)))) (eval-local-transformer (expand e trans-r w mod) mod)))
(cdr r))) (cdr r)))
(parse (cdr body) (cons id ids) labels var-ids vars vals bindings))) (parse (cdr body) (cons id ids) labels var-ids vars vals bindings)))
((memv key '(begin-form)) ((memv key '(begin-form))
@ -1550,11 +1550,11 @@
s s
mod mod
get-formals get-formals
(map (lambda (tmp-680b775fb37a463-aeb (map (lambda (tmp-680b775fb37a463-ac9
tmp-680b775fb37a463-aea tmp-680b775fb37a463-ac8
tmp-680b775fb37a463-ae9) tmp-680b775fb37a463-ac7)
(cons tmp-680b775fb37a463-ae9 (cons tmp-680b775fb37a463-ac7
(cons tmp-680b775fb37a463-aea tmp-680b775fb37a463-aeb))) (cons tmp-680b775fb37a463-ac8 tmp-680b775fb37a463-ac9)))
e2* e2*
e1* e1*
args*))) args*)))
@ -1630,7 +1630,8 @@
(bindings (bindings
(let ((trans-r (macros-only-env r))) (let ((trans-r (macros-only-env r)))
(map (lambda (x) (map (lambda (x)
(cons 'macro (eval-local-transformer (expand x trans-r w mod) mod))) (cons 'syntax-parameter
(eval-local-transformer (expand x trans-r w mod) mod)))
val)))) val))))
(expand-body (expand-body
(cons e1 e2) (cons e1 e2)
@ -1854,11 +1855,11 @@
(apply (lambda (args e1 e2) (apply (lambda (args e1 e2)
(build-it (build-it
'() '()
(map (lambda (tmp-680b775fb37a463-cb8 (map (lambda (tmp-680b775fb37a463-c96
tmp-680b775fb37a463-cb7 tmp-680b775fb37a463-c95
tmp-680b775fb37a463-cb6) tmp-680b775fb37a463-c94)
(cons tmp-680b775fb37a463-cb6 (cons tmp-680b775fb37a463-c94
(cons tmp-680b775fb37a463-cb7 tmp-680b775fb37a463-cb8))) (cons tmp-680b775fb37a463-c95 tmp-680b775fb37a463-c96)))
e2 e2
e1 e1
args))) args)))
@ -1870,11 +1871,11 @@
(apply (lambda (docstring args e1 e2) (apply (lambda (docstring args e1 e2)
(build-it (build-it
(list (cons 'documentation (syntax->datum docstring))) (list (cons 'documentation (syntax->datum docstring)))
(map (lambda (tmp-680b775fb37a463-cce (map (lambda (tmp-680b775fb37a463-cac
tmp-680b775fb37a463-ccd tmp-680b775fb37a463-cab
tmp-680b775fb37a463-ccc) tmp-680b775fb37a463-caa)
(cons tmp-680b775fb37a463-ccc (cons tmp-680b775fb37a463-caa
(cons tmp-680b775fb37a463-ccd tmp-680b775fb37a463-cce))) (cons tmp-680b775fb37a463-cab tmp-680b775fb37a463-cac)))
e2 e2
e1 e1
args))) args)))
@ -1897,11 +1898,11 @@
(apply (lambda (args e1 e2) (apply (lambda (args e1 e2)
(build-it (build-it
'() '()
(map (lambda (tmp-680b775fb37a463-cee (map (lambda (tmp-680b775fb37a463-ccc
tmp-680b775fb37a463-ced tmp-680b775fb37a463-ccb
tmp-680b775fb37a463-cec) tmp-680b775fb37a463-cca)
(cons tmp-680b775fb37a463-cec (cons tmp-680b775fb37a463-cca
(cons tmp-680b775fb37a463-ced tmp-680b775fb37a463-cee))) (cons tmp-680b775fb37a463-ccb tmp-680b775fb37a463-ccc)))
e2 e2
e1 e1
args))) args)))
@ -1913,11 +1914,11 @@
(apply (lambda (docstring args e1 e2) (apply (lambda (docstring args e1 e2)
(build-it (build-it
(list (cons 'documentation (syntax->datum docstring))) (list (cons 'documentation (syntax->datum docstring)))
(map (lambda (tmp-680b775fb37a463-d04 (map (lambda (tmp-680b775fb37a463-ce2
tmp-680b775fb37a463-d03 tmp-680b775fb37a463-ce1
tmp-680b775fb37a463-d02) tmp-680b775fb37a463-ce0)
(cons tmp-680b775fb37a463-d02 (cons tmp-680b775fb37a463-ce0
(cons tmp-680b775fb37a463-d03 tmp-680b775fb37a463-d04))) (cons tmp-680b775fb37a463-ce1 tmp-680b775fb37a463-ce2)))
e2 e2
e1 e1
args))) args)))
@ -2497,8 +2498,7 @@
(let ((key type)) (let ((key type))
(cond ((memv key '(lexical)) (values 'lexical value)) (cond ((memv key '(lexical)) (values 'lexical value))
((memv key '(macro)) (values 'macro value)) ((memv key '(macro)) (values 'macro value))
((memv key '(syntax-parameter)) ((memv key '(syntax-parameter)) (values 'syntax-parameter value))
(values 'syntax-parameter (car value)))
((memv key '(syntax)) (values 'pattern-variable value)) ((memv key '(syntax)) (values 'pattern-variable value))
((memv key '(displaced-lexical)) (values 'displaced-lexical #f)) ((memv key '(displaced-lexical)) (values 'displaced-lexical #f))
((memv key '(global)) ((memv key '(global))
@ -2850,9 +2850,11 @@
#f #f
k k
(list docstring) (list docstring)
(map (lambda (tmp-680b775fb37a463-2 tmp-680b775fb37a463-1 tmp-680b775fb37a463) (map (lambda (tmp-680b775fb37a463
(list (cons tmp-680b775fb37a463 tmp-680b775fb37a463-1) tmp-680b775fb37a463-114f
tmp-680b775fb37a463-2)) tmp-680b775fb37a463-114e)
(list (cons tmp-680b775fb37a463-114e tmp-680b775fb37a463-114f)
tmp-680b775fb37a463))
template template
pattern pattern
keyword))) keyword)))
@ -2867,11 +2869,9 @@
dots dots
k k
'() '()
(map (lambda (tmp-680b775fb37a463-118b (map (lambda (tmp-680b775fb37a463-2 tmp-680b775fb37a463-1 tmp-680b775fb37a463)
tmp-680b775fb37a463-118a (list (cons tmp-680b775fb37a463 tmp-680b775fb37a463-1)
tmp-680b775fb37a463) tmp-680b775fb37a463-2))
(list (cons tmp-680b775fb37a463 tmp-680b775fb37a463-118a)
tmp-680b775fb37a463-118b))
template template
pattern pattern
keyword))) keyword)))
@ -2887,11 +2887,9 @@
dots dots
k k
(list docstring) (list docstring)
(map (lambda (tmp-680b775fb37a463-11aa (map (lambda (tmp-680b775fb37a463-2 tmp-680b775fb37a463-1 tmp-680b775fb37a463)
tmp-680b775fb37a463-11a9 (list (cons tmp-680b775fb37a463 tmp-680b775fb37a463-1)
tmp-680b775fb37a463-11a8) tmp-680b775fb37a463-2))
(list (cons tmp-680b775fb37a463-11a8 tmp-680b775fb37a463-11a9)
tmp-680b775fb37a463-11aa))
template template
pattern pattern
keyword))) keyword)))
@ -3039,8 +3037,8 @@
(apply (lambda (p) (apply (lambda (p)
(if (= lev 0) (if (= lev 0)
(quasilist* (quasilist*
(map (lambda (tmp-680b775fb37a463) (map (lambda (tmp-680b775fb37a463-11f3)
(list "value" tmp-680b775fb37a463)) (list "value" tmp-680b775fb37a463-11f3))
p) p)
(quasi q lev)) (quasi q lev))
(quasicons (quasicons
@ -3063,8 +3061,8 @@
(apply (lambda (p) (apply (lambda (p)
(if (= lev 0) (if (= lev 0)
(quasiappend (quasiappend
(map (lambda (tmp-680b775fb37a463-121a) (map (lambda (tmp-680b775fb37a463-11f8)
(list "value" tmp-680b775fb37a463-121a)) (list "value" tmp-680b775fb37a463-11f8))
p) p)
(quasi q lev)) (quasi q lev))
(quasicons (quasicons
@ -3098,7 +3096,8 @@
(apply (lambda (p) (apply (lambda (p)
(if (= lev 0) (if (= lev 0)
(quasilist* (quasilist*
(map (lambda (tmp-680b775fb37a463) (list "value" tmp-680b775fb37a463)) (map (lambda (tmp-680b775fb37a463-120e)
(list "value" tmp-680b775fb37a463-120e))
p) p)
(vquasi q lev)) (vquasi q lev))
(quasicons (quasicons
@ -3208,8 +3207,8 @@
(let ((tmp-1 ls)) (let ((tmp-1 ls))
(let ((tmp ($sc-dispatch tmp-1 'each-any))) (let ((tmp ($sc-dispatch tmp-1 'each-any)))
(if tmp (if tmp
(apply (lambda (t-680b775fb37a463-127e) (apply (lambda (t-680b775fb37a463-125c)
(cons "vector" t-680b775fb37a463-127e)) (cons "vector" t-680b775fb37a463-125c))
tmp) tmp)
(syntax-violation (syntax-violation
#f #f
@ -3219,8 +3218,7 @@
(let ((tmp-1 ($sc-dispatch tmp '(#(atom "quote") each-any)))) (let ((tmp-1 ($sc-dispatch tmp '(#(atom "quote") each-any))))
(if tmp-1 (if tmp-1
(apply (lambda (y) (apply (lambda (y)
(k (map (lambda (tmp-680b775fb37a463-128a) (k (map (lambda (tmp-680b775fb37a463) (list "quote" tmp-680b775fb37a463))
(list "quote" tmp-680b775fb37a463-128a))
y))) y)))
tmp-1) tmp-1)
(let ((tmp-1 ($sc-dispatch tmp '(#(atom "list") . each-any)))) (let ((tmp-1 ($sc-dispatch tmp '(#(atom "list") . each-any))))
@ -3245,9 +3243,9 @@
(let ((tmp-1 (map emit x))) (let ((tmp-1 (map emit x)))
(let ((tmp ($sc-dispatch tmp-1 'each-any))) (let ((tmp ($sc-dispatch tmp-1 'each-any)))
(if tmp (if tmp
(apply (lambda (t-680b775fb37a463-12a8) (apply (lambda (t-680b775fb37a463)
(cons (make-syntax 'list '((top)) '(hygiene guile)) (cons (make-syntax 'list '((top)) '(hygiene guile))
t-680b775fb37a463-12a8)) t-680b775fb37a463))
tmp) tmp)
(syntax-violation (syntax-violation
#f #f
@ -3263,10 +3261,10 @@
(let ((tmp-1 (list (emit (car x*)) (f (cdr x*))))) (let ((tmp-1 (list (emit (car x*)) (f (cdr x*)))))
(let ((tmp ($sc-dispatch tmp-1 '(any any)))) (let ((tmp ($sc-dispatch tmp-1 '(any any))))
(if tmp (if tmp
(apply (lambda (t-680b775fb37a463-12bc t-680b775fb37a463-12bb) (apply (lambda (t-680b775fb37a463-129a t-680b775fb37a463)
(list (make-syntax 'cons '((top)) '(hygiene guile)) (list (make-syntax 'cons '((top)) '(hygiene guile))
t-680b775fb37a463-12bc t-680b775fb37a463-129a
t-680b775fb37a463-12bb)) t-680b775fb37a463))
tmp) tmp)
(syntax-violation (syntax-violation
#f #f
@ -3279,9 +3277,9 @@
(let ((tmp-1 (map emit x))) (let ((tmp-1 (map emit x)))
(let ((tmp ($sc-dispatch tmp-1 'each-any))) (let ((tmp ($sc-dispatch tmp-1 'each-any)))
(if tmp (if tmp
(apply (lambda (t-680b775fb37a463-12c8) (apply (lambda (t-680b775fb37a463-12a6)
(cons (make-syntax 'append '((top)) '(hygiene guile)) (cons (make-syntax 'append '((top)) '(hygiene guile))
t-680b775fb37a463-12c8)) t-680b775fb37a463-12a6))
tmp) tmp)
(syntax-violation (syntax-violation
#f #f
@ -3294,9 +3292,9 @@
(let ((tmp-1 (map emit x))) (let ((tmp-1 (map emit x)))
(let ((tmp ($sc-dispatch tmp-1 'each-any))) (let ((tmp ($sc-dispatch tmp-1 'each-any)))
(if tmp (if tmp
(apply (lambda (t-680b775fb37a463-12d4) (apply (lambda (t-680b775fb37a463-12b2)
(cons (make-syntax 'vector '((top)) '(hygiene guile)) (cons (make-syntax 'vector '((top)) '(hygiene guile))
t-680b775fb37a463-12d4)) t-680b775fb37a463-12b2))
tmp) tmp)
(syntax-violation (syntax-violation
#f #f
@ -3307,9 +3305,9 @@
(if tmp-1 (if tmp-1
(apply (lambda (x) (apply (lambda (x)
(let ((tmp (emit x))) (let ((tmp (emit x)))
(let ((t-680b775fb37a463-12e0 tmp)) (let ((t-680b775fb37a463-12be tmp))
(list (make-syntax 'list->vector '((top)) '(hygiene guile)) (list (make-syntax 'list->vector '((top)) '(hygiene guile))
t-680b775fb37a463-12e0)))) t-680b775fb37a463-12be))))
tmp-1) tmp-1)
(let ((tmp-1 ($sc-dispatch tmp '(#(atom "value") any)))) (let ((tmp-1 ($sc-dispatch tmp '(#(atom "value") any))))
(if tmp-1 (if tmp-1

View file

@ -1,7 +1,7 @@
;;;; -*-scheme-*- ;;;; -*-scheme-*-
;;;; ;;;;
;;;; Copyright (C) 2001, 2003, 2006, 2009, 2010, 2011, ;;;; Copyright (C) 2001, 2003, 2006, 2009, 2010, 2011,
;;;; 2012, 2013, 2015, 2016 Free Software Foundation, Inc. ;;;; 2012, 2013, 2015, 2016, 2019 Free Software Foundation, Inc.
;;;; ;;;;
;;;; This library is free software; you can redistribute it and/or ;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public ;;;; modify it under the terms of the GNU Lesser General Public
@ -292,29 +292,7 @@
(define session-id (define session-id
(let ((v (module-variable (current-module) 'syntax-session-id))) (let ((v (module-variable (current-module) 'syntax-session-id)))
(lambda () (lambda ()
((variable-ref v))))) ((variable-ref v))))))
(define put-global-definition-hook
(lambda (symbol type val)
(module-define! (current-module)
symbol
(make-syntax-transformer symbol type val))))
(define get-global-definition-hook
(lambda (symbol module)
(if (and (not module) (current-module))
(warn "module system is booted, we should have a module" symbol))
(and (not (equal? module '(primitive)))
(let ((v (module-variable (if module
(resolve-module (cdr module))
(current-module))
symbol)))
(and v (variable-bound? v)
(let ((val (variable-ref v)))
(and (macro? val) (macro-type val)
(cons (macro-type val)
(macro-binding val))))))))))
(define (decorate-source e s) (define (decorate-source e s)
(if (and s (supports-source-properties? e)) (if (and s (supports-source-properties? e))
@ -513,11 +491,10 @@
;; wrap : id --> label ;; wrap : id --> label
;; env : label --> <element> ;; env : label --> <element>
;; environments are represented in two parts: a lexical part and a global ;; environments are represented in two parts: a lexical part and a
;; part. The lexical part is a simple list of associations from labels ;; global part. The lexical part is a simple list of associations
;; to bindings. The global part is implemented by ;; from labels to bindings. The global part is implemented by
;; {put,get}-global-definition-hook and associates symbols with ;; Guile's module system and associates symbols with bindings.
;; bindings.
;; global (assumed global variable) and displaced-lexical (see below) ;; global (assumed global variable) and displaced-lexical (see below)
;; do not show up in any environment; instead, they are fabricated by ;; do not show up in any environment; instead, they are fabricated by
@ -528,7 +505,7 @@
;; identifier bindings include a type and a value ;; identifier bindings include a type and a value
;; <binding> ::= (macro . <procedure>) macros ;; <binding> ::= (macro . <procedure>) macros
;; (syntax-parameter . (<procedure>)) syntax parameters ;; (syntax-parameter . <procedure>) syntax parameters
;; (core . <procedure>) core forms ;; (core . <procedure>) core forms
;; (module-ref . <procedure>) @ or @@ ;; (module-ref . <procedure>) @ or @@
;; (begin) begin ;; (begin) begin
@ -610,7 +587,9 @@
(define global-extend (define global-extend
(lambda (type sym val) (lambda (type sym val)
(put-global-definition-hook sym type val))) (module-define! (current-module)
sym
(make-syntax-transformer sym type val))))
;; Conceptually, identifiers are always syntax objects. Internally, ;; Conceptually, identifiers are always syntax objects. Internally,
@ -892,27 +871,75 @@
results))))))) results)))))))
(scan (wrap-subst w) '()))) (scan (wrap-subst w) '())))
;; Returns three values: binding type, binding value, the module (for ;; Returns three values: binding type, binding value, and the module
;; resolving toplevel vars). ;; (for resolving toplevel vars).
(define (resolve-identifier id w r mod resolve-syntax-parameters?) (define (resolve-identifier id w r mod resolve-syntax-parameters?)
(define (resolve-syntax-parameters b)
(if (and resolve-syntax-parameters?
(eq? (binding-type b) 'syntax-parameter))
(or (assq-ref r (binding-value b))
(make-binding 'macro (car (binding-value b))))
b))
(define (resolve-global var mod) (define (resolve-global var mod)
(let ((b (resolve-syntax-parameters (when (and (not mod) (current-module))
(or (get-global-definition-hook var mod) (warn "module system is booted, we should have a module" var))
(make-binding 'global))))) (let ((v (and (not (equal? mod '(primitive)))
(if (eq? (binding-type b) 'global) (module-variable (if mod
(values 'global var mod) (resolve-module (cdr mod))
(values (binding-type b) (binding-value b) mod)))) (current-module))
var))))
;; The expander needs to know when a top-level definition from
;; outside the compilation unit is a macro.
;;
;; Additionally if a macro is actually a syntax-parameter, we
;; might need to resolve its current binding. If the syntax
;; parameter is locally bound (via syntax-parameterize), then
;; its variable will be present in `r', the expand-time
;; environment. It's a kind of double lookup: first we see
;; that a name is bound to a syntax parameter, then we look
;; for the current binding of the syntax parameter.
;;
;; We use the variable (box) holding the syntax parameter
;; definition as the key for the second lookup. We use the
;; variable for two reasons:
;;
;; 1. If the syntax parameter is redefined in parallel
;; (perhaps via a parallel module compilation), the
;; redefinition keeps the same variable. We don't want to
;; use a "key" that could change during a redefinition. See
;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27476.
;;
;; 2. Using the variable instead of its (symname, modname)
;; pair allows for syntax parameters to be renamed or
;; aliased while preserving the syntax parameter's identity.
;;
(if (and v (variable-bound? v) (macro? (variable-ref v)))
(let* ((m (variable-ref v))
(type (macro-type m))
(trans (macro-binding m))
(trans (if (pair? trans) (car trans) trans)))
(if (eq? type 'syntax-parameter)
(if resolve-syntax-parameters?
(let ((lexical (assq-ref r v)))
;; A resolved syntax parameter is
;; indistinguishable from a macro.
(values 'macro
(if lexical
(binding-value lexical)
trans)
mod))
;; Return box as value for use in second lookup.
(values type v mod))
(values type trans mod)))
(values 'global var mod))))
(define (resolve-lexical label mod) (define (resolve-lexical label mod)
(let ((b (resolve-syntax-parameters (let ((b (assq-ref r label)))
(or (assq-ref r label) (if b
(make-binding 'displaced-lexical))))) (let ((type (binding-type b))
(values (binding-type b) (binding-value b) mod))) (value (binding-value b)))
(if (eq? type 'syntax-parameter)
(if resolve-syntax-parameters?
(values 'macro value mod)
;; If the syntax parameter was defined within
;; this compilation unit, use its label as its
;; lookup key.
(values type label mod))
(values type value mod)))
(values 'displaced-lexical #f #f))))
(let ((n (id-var-name id w mod))) (let ((n (id-var-name id w mod)))
(cond (cond
((syntax-object? n) ((syntax-object? n)
@ -1245,13 +1272,12 @@
(build-primcall (build-primcall
no-source no-source
'make-syntax-transformer 'make-syntax-transformer
(if (eq? type 'define-syntax-parameter-form) (list (build-data no-source name)
(list (build-data no-source name) (build-data no-source
(build-data no-source 'syntax-parameter) (if (eq? type 'define-syntax-parameter-form)
(build-primcall no-source 'list (list e))) 'syntax-parameter
(list (build-data no-source name) 'macro))
(build-data no-source 'macro) e)))))
e))))))
(define parse-when-list (define parse-when-list
(lambda (e when-list) (lambda (e when-list)
@ -1641,7 +1667,7 @@
(cdr r))) (cdr r)))
(parse (cdr body) (cons id ids) labels var-ids vars vals bindings))) (parse (cdr body) (cons id ids) labels var-ids vars vals bindings)))
((define-syntax-parameter-form) ((define-syntax-parameter-form)
;; Same as define-syntax-form, but different format of the binding. ;; Same as define-syntax-form, different binding type though.
(let ((id (wrap value w mod)) (let ((id (wrap value w mod))
(label (gen-label)) (label (gen-label))
(trans-r (macros-only-env er))) (trans-r (macros-only-env er)))
@ -1650,9 +1676,9 @@
(list label) (list label)
(list (make-binding (list (make-binding
'syntax-parameter 'syntax-parameter
(list (eval-local-transformer (eval-local-transformer
(expand e trans-r w mod) (expand e trans-r w mod)
mod)))) mod)))
(cdr r))) (cdr r)))
(parse (cdr body) (cons id ids) labels var-ids vars vals bindings))) (parse (cdr body) (cons id ids) labels var-ids vars vals bindings)))
((begin-form) ((begin-form)
@ -2053,14 +2079,14 @@
(let ((trans-r (macros-only-env r))) (let ((trans-r (macros-only-env r)))
(map (lambda (x) (map (lambda (x)
(make-binding (make-binding
'macro 'syntax-parameter
(eval-local-transformer (expand x trans-r w mod) mod))) (eval-local-transformer (expand x trans-r w mod) mod)))
#'(val ...))))) #'(val ...)))))
(expand-body #'(e1 e2 ...) (expand-body #'(e1 e2 ...)
(source-wrap e w s mod) (source-wrap e w s mod)
(extend-env names bindings r) (extend-env names bindings r)
w w
mod))) mod)))
(_ (syntax-violation 'syntax-parameterize "bad syntax" (_ (syntax-violation 'syntax-parameterize "bad syntax"
(source-wrap e w s mod)))))) (source-wrap e w s mod))))))
@ -2799,7 +2825,7 @@
(case type (case type
((lexical) (values 'lexical value)) ((lexical) (values 'lexical value))
((macro) (values 'macro value)) ((macro) (values 'macro value))
((syntax-parameter) (values 'syntax-parameter (car value))) ((syntax-parameter) (values 'syntax-parameter value))
((syntax) (values 'pattern-variable value)) ((syntax) (values 'pattern-variable value))
((displaced-lexical) (values 'displaced-lexical #f)) ((displaced-lexical) (values 'displaced-lexical #f))
((global) ((global)