mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
Psyntax generates new syntax objects
* module/ice-9/psyntax.scm (make-syntax-object): Change to make new-style syntax objects. * module/ice-9/psyntax-pp.scm: Regenerate. * module/ice-9/compile-psyntax.scm (squeeze-syntax-object): Change to be functional. (squeeze-constant): Likewise. (squeeze-tree-il): Likewise. (translate-literal-syntax-objects): New pass. The compiler can embed literal syntax objects into compiled objects, but syntax can no longer be read/written; otherwise users could forge syntax objects. So for the bootstrap phase, rewrite literal constants to calls to make-syntax.
This commit is contained in:
parent
eb84c2f2da
commit
a42bfae65f
3 changed files with 950 additions and 857 deletions
|
@ -20,67 +20,132 @@
|
||||||
(language tree-il primitives)
|
(language tree-il primitives)
|
||||||
(language tree-il canonicalize)
|
(language tree-il canonicalize)
|
||||||
(srfi srfi-1)
|
(srfi srfi-1)
|
||||||
|
(ice-9 control)
|
||||||
(ice-9 pretty-print)
|
(ice-9 pretty-print)
|
||||||
(system syntax))
|
(system syntax internal))
|
||||||
|
|
||||||
;; Minimize a syntax-object such that it can no longer be used as the
|
;; Minimize a syntax-object such that it can no longer be used as the
|
||||||
;; first argument to 'datum->syntax', but is otherwise equivalent.
|
;; first argument to 'datum->syntax', but is otherwise equivalent.
|
||||||
(define (squeeze-syntax-object! syn)
|
(define (squeeze-syntax-object syn)
|
||||||
(define (ensure-list x) (if (vector? x) (vector->list x) x))
|
(define (ensure-list x) (if (vector? x) (vector->list x) x))
|
||||||
(let ((x (vector-ref syn 1))
|
(let ((x (syntax-expression syn))
|
||||||
(wrap (vector-ref syn 2))
|
(wrap (syntax-wrap syn))
|
||||||
(mod (vector-ref syn 3)))
|
(mod (syntax-module syn)))
|
||||||
(let ((marks (car wrap))
|
(let ((marks (car wrap))
|
||||||
(subst (cdr wrap)))
|
(subst (cdr wrap)))
|
||||||
(define (set-wrap! marks subst)
|
(define (squeeze-wrap marks subst)
|
||||||
(vector-set! syn 2 (cons marks subst)))
|
(make-syntax x (cons marks subst) mod))
|
||||||
(cond
|
(cond
|
||||||
((symbol? x)
|
((symbol? x)
|
||||||
(let loop ((marks marks) (subst subst))
|
(let loop ((marks marks) (subst subst))
|
||||||
(cond
|
(cond
|
||||||
((null? subst) (set-wrap! marks subst) syn)
|
((null? subst) (squeeze-wrap marks subst))
|
||||||
((eq? 'shift (car subst)) (loop (cdr marks) (cdr subst)))
|
((eq? 'shift (car subst)) (loop (cdr marks) (cdr subst)))
|
||||||
((find (lambda (entry) (and (eq? x (car entry))
|
((find (lambda (entry) (and (eq? x (car entry))
|
||||||
(equal? marks (cadr entry))))
|
(equal? marks (cadr entry))))
|
||||||
(apply map list (map ensure-list
|
(apply map list (map ensure-list
|
||||||
(cdr (vector->list (car subst))))))
|
(cdr (vector->list (car subst))))))
|
||||||
=> (lambda (entry)
|
=> (lambda (entry)
|
||||||
(set-wrap! marks
|
(squeeze-wrap marks
|
||||||
(list (list->vector
|
(list (list->vector
|
||||||
(cons 'ribcage
|
(cons 'ribcage
|
||||||
(map vector entry)))))
|
(map vector entry)))))))
|
||||||
syn))
|
|
||||||
(else (loop marks (cdr subst))))))
|
(else (loop marks (cdr subst))))))
|
||||||
((or (pair? x) (vector? x))
|
((or (pair? x) (vector? x)) syn)
|
||||||
syn)
|
|
||||||
(else x)))))
|
(else x)))))
|
||||||
|
|
||||||
(define (squeeze-constant! x)
|
(define (squeeze-constant x)
|
||||||
(define (syntax-object? x)
|
(cond ((syntax? x) (squeeze-syntax-object x))
|
||||||
(and (vector? x)
|
|
||||||
(= 4 (vector-length x))
|
|
||||||
(eq? 'syntax-object (vector-ref x 0))))
|
|
||||||
(cond ((syntax-object? x)
|
|
||||||
(squeeze-syntax-object! x))
|
|
||||||
((pair? x)
|
((pair? x)
|
||||||
(set-car! x (squeeze-constant! (car x)))
|
(cons (squeeze-constant (car x))
|
||||||
(set-cdr! x (squeeze-constant! (cdr x)))
|
(squeeze-constant (cdr x))))
|
||||||
x)
|
|
||||||
((vector? x)
|
((vector? x)
|
||||||
(for-each (lambda (i)
|
(list->vector (squeeze-constant (vector->list x))))
|
||||||
(vector-set! x i (squeeze-constant! (vector-ref x i))))
|
|
||||||
(iota (vector-length x)))
|
|
||||||
x)
|
|
||||||
(else x)))
|
(else x)))
|
||||||
|
|
||||||
(define (squeeze-tree-il x)
|
(define (squeeze-tree-il x)
|
||||||
(post-order (lambda (x)
|
(post-order (lambda (x)
|
||||||
(if (const? x)
|
(if (const? x)
|
||||||
(make-const (const-src x)
|
(make-const (const-src x)
|
||||||
(squeeze-constant! (const-exp x)))
|
(squeeze-constant (const-exp x)))
|
||||||
x))
|
x))
|
||||||
x))
|
x))
|
||||||
|
|
||||||
|
(define (translate-literal-syntax-objects x)
|
||||||
|
(define (find-make-syntax-lexical-binding x)
|
||||||
|
(let/ec return
|
||||||
|
(pre-order (lambda (x)
|
||||||
|
(when (let? x)
|
||||||
|
(for-each (lambda (name sym)
|
||||||
|
(when (eq? name 'make-syntax)
|
||||||
|
(return sym)))
|
||||||
|
(let-names x) (let-gensyms x)))
|
||||||
|
x)
|
||||||
|
x)
|
||||||
|
#f))
|
||||||
|
(let ((make-syntax-gensym (find-make-syntax-lexical-binding x))
|
||||||
|
(retry-tag (make-prompt-tag)))
|
||||||
|
(define (translate-constant x)
|
||||||
|
(let ((src (const-src x))
|
||||||
|
(exp (const-exp x)))
|
||||||
|
(cond
|
||||||
|
((list? exp)
|
||||||
|
(let ((exp (map (lambda (x)
|
||||||
|
(translate-constant (make-const src x)))
|
||||||
|
exp)))
|
||||||
|
(if (and-map const? exp)
|
||||||
|
x
|
||||||
|
(make-primcall src 'list exp))))
|
||||||
|
((pair? exp)
|
||||||
|
(let ((car (translate-constant (make-const src (car exp))))
|
||||||
|
(cdr (translate-constant (make-const src (cdr exp)))))
|
||||||
|
(if (and (const? car) (const? cdr))
|
||||||
|
x
|
||||||
|
(make-primcall src 'cons (list car cdr)))))
|
||||||
|
((vector? exp)
|
||||||
|
(let ((exp (map (lambda (x)
|
||||||
|
(translate-constant (make-const src x)))
|
||||||
|
(vector->list exp))))
|
||||||
|
(if (and-map const? exp)
|
||||||
|
x
|
||||||
|
(make-primcall src 'vector exp))))
|
||||||
|
((syntax? exp)
|
||||||
|
(make-call src
|
||||||
|
(if make-syntax-gensym
|
||||||
|
(make-lexical-ref src 'make-syntax
|
||||||
|
make-syntax-gensym)
|
||||||
|
(abort-to-prompt retry-tag))
|
||||||
|
(list
|
||||||
|
(translate-constant
|
||||||
|
(make-const src (syntax-expression exp)))
|
||||||
|
(translate-constant
|
||||||
|
(make-const src (syntax-wrap exp)))
|
||||||
|
(translate-constant
|
||||||
|
(make-const src (syntax-module exp))))))
|
||||||
|
(else x))))
|
||||||
|
(call-with-prompt retry-tag
|
||||||
|
(lambda ()
|
||||||
|
(post-order (lambda (x)
|
||||||
|
(if (const? x)
|
||||||
|
(translate-constant x)
|
||||||
|
x))
|
||||||
|
x))
|
||||||
|
(lambda (k)
|
||||||
|
;; OK, we have a syntax object embedded in this code, but
|
||||||
|
;; make-syntax isn't lexically bound. This is the case for the
|
||||||
|
;; top-level macro definitions in psyntax that follow the main
|
||||||
|
;; let blob. Attach a lexical binding and retry.
|
||||||
|
(unless (toplevel-define? x) (error "unexpected"))
|
||||||
|
(translate-literal-syntax-objects
|
||||||
|
(make-toplevel-define
|
||||||
|
(toplevel-define-src x)
|
||||||
|
(toplevel-define-name x)
|
||||||
|
(make-let (toplevel-define-src x)
|
||||||
|
(list 'make-syntax)
|
||||||
|
(list (module-gensym))
|
||||||
|
(list (make-toplevel-ref #f 'make-syntax))
|
||||||
|
(toplevel-define-exp x))))))))
|
||||||
|
|
||||||
;; Avoid gratuitous churn in psyntax-pp.scm due to the marks and labels
|
;; Avoid gratuitous churn in psyntax-pp.scm due to the marks and labels
|
||||||
;; changing session identifiers.
|
;; changing session identifiers.
|
||||||
(set! syntax-session-id (lambda () "*"))
|
(set! syntax-session-id (lambda () "*"))
|
||||||
|
@ -99,11 +164,12 @@
|
||||||
(close-port in))
|
(close-port in))
|
||||||
(begin
|
(begin
|
||||||
(pretty-print (tree-il->scheme
|
(pretty-print (tree-il->scheme
|
||||||
(squeeze-tree-il
|
(translate-literal-syntax-objects
|
||||||
(canonicalize
|
(squeeze-tree-il
|
||||||
(resolve-primitives
|
(canonicalize
|
||||||
(macroexpand x 'c '(compile load eval))
|
(resolve-primitives
|
||||||
(current-module))))
|
(macroexpand x 'c '(compile load eval))
|
||||||
|
(current-module)))))
|
||||||
(current-module)
|
(current-module)
|
||||||
(list #:avoid-lambda? #f
|
(list #:avoid-lambda? #f
|
||||||
#:use-case? #f
|
#:use-case? #f
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -477,7 +477,7 @@
|
||||||
(= (vector-length x) 4)
|
(= (vector-length x) 4)
|
||||||
(eqv? (vector-ref x 0) 'syntax-object))))
|
(eqv? (vector-ref x 0) 'syntax-object))))
|
||||||
(define (make-syntax-object expression wrap module)
|
(define (make-syntax-object expression wrap module)
|
||||||
(vector 'syntax-object expression wrap module))
|
(make-syntax expression wrap module))
|
||||||
(define (syntax-object-expression obj)
|
(define (syntax-object-expression obj)
|
||||||
(if (syntax? obj)
|
(if (syntax? obj)
|
||||||
(syntax-expression obj)
|
(syntax-expression obj)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue