[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 09/12: psyntax: Avoid lambda in procedure definitions
From: |
Andy Wingo |
Subject: |
[Guile-commits] 09/12: psyntax: Avoid lambda in procedure definitions |
Date: |
Fri, 15 Nov 2024 10:25:32 -0500 (EST) |
wingo pushed a commit to branch main
in repository guile.
commit d30b39e4eab02ee9cdf1eecb2896282b244ad1ad
Author: Andy Wingo <wingo@pobox.com>
AuthorDate: Fri Nov 15 14:06:32 2024 +0100
psyntax: Avoid lambda in procedure definitions
* module/ice-9/psyntax.scm: Instead of e.g. (define foo (lambda (x)
...)), do (define (foo x) ...). No functional change.
---
module/ice-9/psyntax.scm | 3192 ++++++++++++++++++++++------------------------
1 file changed, 1552 insertions(+), 1640 deletions(-)
diff --git a/module/ice-9/psyntax.scm b/module/ice-9/psyntax.scm
index 97e4d8524..c772c4aca 100644
--- a/module/ice-9/psyntax.scm
+++ b/module/ice-9/psyntax.scm
@@ -153,25 +153,20 @@
val))
;; output constructors
- (define build-void
- (lambda (sourcev)
- (make-void sourcev)))
+ (define (build-void sourcev)
+ (make-void sourcev))
- (define build-call
- (lambda (sourcev fun-exp arg-exps)
- (make-call sourcev fun-exp arg-exps)))
+ (define (build-call sourcev fun-exp arg-exps)
+ (make-call sourcev fun-exp arg-exps))
- (define build-conditional
- (lambda (sourcev test-exp then-exp else-exp)
- (make-conditional sourcev test-exp then-exp else-exp)))
+ (define (build-conditional sourcev test-exp then-exp else-exp)
+ (make-conditional sourcev test-exp then-exp else-exp))
- (define build-lexical-reference
- (lambda (type sourcev name var)
- (make-lexical-ref sourcev name var)))
+ (define (build-lexical-reference type sourcev name var)
+ (make-lexical-ref sourcev name var))
- (define build-lexical-assignment
- (lambda (sourcev name var exp)
- (make-lexical-set sourcev name var (maybe-name-value name exp))))
+ (define (build-lexical-assignment sourcev name var exp)
+ (make-lexical-set sourcev name var (maybe-name-value name exp)))
(define (analyze-variable mod var modref-cont bare-cont)
(if (not mod)
@@ -188,44 +183,39 @@
(syntax-violation #f "primitive not in operator position" var))
(else (syntax-violation #f "bad module kind" var mod))))))
- (define build-global-reference
- (lambda (sourcev var mod)
+ (define (build-global-reference sourcev var mod)
+ (analyze-variable
+ mod var
+ (lambda (mod var public?)
+ (make-module-ref sourcev mod var public?))
+ (lambda (mod var)
+ (make-toplevel-ref sourcev mod var))))
+
+ (define (build-global-assignment sourcev var exp mod)
+ (let ((exp (maybe-name-value var exp)))
(analyze-variable
mod var
(lambda (mod var public?)
- (make-module-ref sourcev mod var public?))
+ (make-module-set sourcev mod var public? exp))
(lambda (mod var)
- (make-toplevel-ref sourcev mod var)))))
-
- (define build-global-assignment
- (lambda (sourcev var exp mod)
- (let ((exp (maybe-name-value var exp)))
- (analyze-variable
- mod var
- (lambda (mod var public?)
- (make-module-set sourcev mod var public? exp))
- (lambda (mod var)
- (make-toplevel-set sourcev mod var exp))))))
-
- (define build-global-definition
- (lambda (sourcev mod var exp)
- (make-toplevel-define sourcev (and mod (cdr mod)) var
- (maybe-name-value var exp))))
-
- (define build-simple-lambda
- (lambda (src req rest vars meta exp)
- (make-lambda src
- meta
- ;; hah, a case in which kwargs would be nice.
- (make-lambda-case
- ;; src req opt rest kw inits vars body else
- src req #f rest #f '() vars exp #f))))
-
- (define build-case-lambda
- (lambda (src meta body)
- (make-lambda src meta body)))
-
- (define build-lambda-case
+ (make-toplevel-set sourcev mod var exp)))))
+
+ (define (build-global-definition sourcev mod var exp)
+ (make-toplevel-define sourcev (and mod (cdr mod)) var
+ (maybe-name-value var exp)))
+
+ (define (build-simple-lambda src req rest vars meta exp)
+ (make-lambda src
+ meta
+ ;; hah, a case in which kwargs would be nice.
+ (make-lambda-case
+ ;; src req opt rest kw inits vars body else
+ src req #f rest #f '() vars exp #f)))
+
+ (define (build-case-lambda src meta body)
+ (make-lambda src meta body))
+
+ (define (build-lambda-case src req opt rest kw inits vars body else-case)
;; req := (name ...)
;; opt := (name ...) | #f
;; rest := name | #f
@@ -236,53 +226,46 @@
;; required, optional (positional), rest, keyword.
;; the body of a lambda: anything, already expanded
;; else: lambda-case | #f
- (lambda (src req opt rest kw inits vars body else-case)
- (make-lambda-case src req opt rest kw inits vars body else-case)))
+ (make-lambda-case src req opt rest kw inits vars body else-case))
- (define build-primcall
- (lambda (src name args)
- (make-primcall src name args)))
+ (define (build-primcall src name args)
+ (make-primcall src name args))
- (define build-primref
- (lambda (src name)
- (make-primitive-ref src name)))
+ (define (build-primref src name)
+ (make-primitive-ref src name))
(define (build-data src exp)
(make-const src exp))
- (define build-sequence
- (lambda (src exps)
- (if (null? (cdr exps))
- (car exps)
- (make-seq src (car exps) (build-sequence #f (cdr exps))))))
-
- (define build-let
- (lambda (src ids vars val-exps body-exp)
- (let ((val-exps (map maybe-name-value ids val-exps)))
- (if (null? vars)
- body-exp
- (make-let src ids vars val-exps body-exp)))))
-
- (define build-named-let
- (lambda (src ids vars val-exps body-exp)
- (let ((f (car vars))
- (f-name (car ids))
- (vars (cdr vars))
- (ids (cdr ids)))
- (let ((proc (build-simple-lambda src ids #f vars '() body-exp)))
- (make-letrec
- src #f
- (list f-name) (list f) (list (maybe-name-value f-name proc))
- (build-call src (build-lexical-reference 'fun src f-name f)
- (map maybe-name-value ids val-exps)))))))
-
- (define build-letrec
- (lambda (src in-order? ids vars val-exps body-exp)
+ (define (build-sequence src exps)
+ (if (null? (cdr exps))
+ (car exps)
+ (make-seq src (car exps) (build-sequence #f (cdr exps)))))
+
+ (define (build-let src ids vars val-exps body-exp)
+ (let ((val-exps (map maybe-name-value ids val-exps)))
(if (null? vars)
body-exp
- (make-letrec src in-order? ids vars
- (map maybe-name-value ids val-exps)
- body-exp))))
+ (make-let src ids vars val-exps body-exp))))
+
+ (define (build-named-let src ids vars val-exps body-exp)
+ (let ((f (car vars))
+ (f-name (car ids))
+ (vars (cdr vars))
+ (ids (cdr ids)))
+ (let ((proc (build-simple-lambda src ids #f vars '() body-exp)))
+ (make-letrec
+ src #f
+ (list f-name) (list f) (list (maybe-name-value f-name proc))
+ (build-call src (build-lexical-reference 'fun src f-name f)
+ (map maybe-name-value ids val-exps))))))
+
+ (define (build-letrec src in-order? ids vars val-exps body-exp)
+ (if (null? vars)
+ body-exp
+ (make-letrec src in-order? ids vars
+ (map maybe-name-value ids val-exps)
+ body-exp)))
(define (gen-lexical id)
@@ -307,14 +290,10 @@
(assq-ref props 'line)
(assq-ref props 'column)))))
- (define source-annotation
- (lambda (x)
- ;; Normally X is a syntax object. However, if it comes from a
- ;; read hash extension, X might be a plain sexp with source
- ;; properties.
- (if (syntax? x)
- (syntax-sourcev x)
- (datum-sourcev x))))
+ (define (source-annotation x)
+ (if (syntax? x)
+ (syntax-sourcev x)
+ (datum-sourcev x)))
(define-syntax-rule (arg-check pred? e who)
(let ((x e))
@@ -393,38 +372,34 @@
(define-syntax null-env (identifier-syntax '()))
- (define extend-env
- (lambda (labels bindings r)
- (if (null? labels)
- r
- (extend-env (cdr labels) (cdr bindings)
- (cons (cons (car labels) (car bindings)) r)))))
+ (define (extend-env labels bindings r)
+ (if (null? labels)
+ r
+ (extend-env (cdr labels) (cdr bindings)
+ (cons (cons (car labels) (car bindings)) r))))
- (define extend-var-env
+ (define (extend-var-env labels vars r)
;; variant of extend-env that forms "lexical" binding
- (lambda (labels vars r)
- (if (null? labels)
- r
- (extend-var-env (cdr labels) (cdr vars)
- (cons (cons (car labels) (make-binding 'lexical (car
vars))) r)))))
+ (if (null? labels)
+ r
+ (extend-var-env (cdr labels) (cdr vars)
+ (cons (cons (car labels) (make-binding 'lexical (car
vars))) r))))
;; we use a "macros only" environment in expansion of local macro
;; definitions so that their definitions can use local macros without
;; attempting to use other lexical identifiers.
- (define macros-only-env
- (lambda (r)
- (if (null? r)
- '()
- (let ((a (car r)))
- (if (memq (cadr a) '(macro syntax-parameter ellipsis))
- (cons a (macros-only-env (cdr r)))
- (macros-only-env (cdr r)))))))
-
- (define global-extend
- (lambda (type sym val)
- (module-define! (current-module)
- sym
- (make-syntax-transformer sym type val))))
+ (define (macros-only-env r)
+ (if (null? r)
+ '()
+ (let ((a (car r)))
+ (if (memq (cadr a) '(macro syntax-parameter ellipsis))
+ (cons a (macros-only-env (cdr r)))
+ (macros-only-env (cdr r))))))
+
+ (define (global-extend type sym val)
+ (module-define! (current-module)
+ sym
+ (make-syntax-transformer sym type val)))
;; Conceptually, identifiers are always syntax objects. Internally,
@@ -432,17 +407,15 @@
;; efficiency and confusion), so that symbols are also considered
;; identifiers by id?. Externally, they are always wrapped.
- (define nonsymbol-id?
- (lambda (x)
- (and (syntax? x)
- (symbol? (syntax-expression x)))))
+ (define (nonsymbol-id? x)
+ (and (syntax? x)
+ (symbol? (syntax-expression x))))
- (define id?
- (lambda (x)
- (cond
- ((symbol? x) #t)
- ((syntax? x) (symbol? (syntax-expression x)))
- (else #f))))
+ (define (id? x)
+ (cond
+ ((symbol? x) #t)
+ ((syntax? x) (symbol? (syntax-expression x)))
+ (else #f)))
(define-syntax-rule (id-sym-name e)
(let ((x e))
@@ -450,13 +423,12 @@
(syntax-expression x)
x)))
- (define id-sym-name&marks
- (lambda (x w)
- (if (syntax? x)
- (values
- (syntax-expression x)
- (join-marks (wrap-marks w) (wrap-marks (syntax-wrap x))))
- (values x (wrap-marks w)))))
+ (define (id-sym-name&marks x w)
+ (if (syntax? x)
+ (values
+ (syntax-expression x)
+ (join-marks (wrap-marks w) (wrap-marks (syntax-wrap x))))
+ (values x (wrap-marks w))))
;; syntax object wraps
@@ -516,10 +488,9 @@
(define-syntax the-anti-mark (identifier-syntax #f))
- (define anti-mark
- (lambda (w)
- (make-wrap (cons the-anti-mark (wrap-marks w))
- (cons 'shift (wrap-subst w)))))
+ (define (anti-mark w)
+ (make-wrap (cons the-anti-mark (wrap-marks w))
+ (cons 'shift (wrap-subst w))))
(define (new-mark)
(gen-unique))
@@ -529,72 +500,66 @@
(define-syntax-rule (make-empty-ribcage)
(make-ribcage '() '() '()))
- (define extend-ribcage!
+ (define (extend-ribcage! ribcage id label)
;; must receive ids with complete wraps
- (lambda (ribcage id label)
- (set-ribcage-symnames! ribcage
- (cons (syntax-expression id)
- (ribcage-symnames ribcage)))
- (set-ribcage-marks! ribcage
- (cons (wrap-marks (syntax-wrap id))
- (ribcage-marks ribcage)))
- (set-ribcage-labels! ribcage
- (cons label (ribcage-labels ribcage)))))
+ (set-ribcage-symnames! ribcage
+ (cons (syntax-expression id)
+ (ribcage-symnames ribcage)))
+ (set-ribcage-marks! ribcage
+ (cons (wrap-marks (syntax-wrap id))
+ (ribcage-marks ribcage)))
+ (set-ribcage-labels! ribcage
+ (cons label (ribcage-labels ribcage))))
;; make-binding-wrap creates vector-based ribcages
- (define make-binding-wrap
- (lambda (ids labels w)
- (if (null? ids)
- w
+ (define (make-binding-wrap ids labels w)
+ (if (null? ids)
+ w
+ (make-wrap
+ (wrap-marks w)
+ (cons
+ (let ((labelvec (list->vector labels)))
+ (let ((n (vector-length labelvec)))
+ (let ((symnamevec (make-vector n)) (marksvec (make-vector n)))
+ (let f ((ids ids) (i 0))
+ (if (not (null? ids))
+ (call-with-values
+ (lambda () (id-sym-name&marks (car ids) w))
+ (lambda (symname marks)
+ (vector-set! symnamevec i symname)
+ (vector-set! marksvec i marks)
+ (f (cdr ids) (1+ i))))))
+ (make-ribcage symnamevec marksvec labelvec))))
+ (wrap-subst w)))))
+
+ (define (smart-append m1 m2)
+ (if (null? m2)
+ m1
+ (append m1 m2)))
+
+ (define (join-wraps w1 w2)
+ (let ((m1 (wrap-marks w1)) (s1 (wrap-subst w1)))
+ (if (null? m1)
+ (if (null? s1)
+ w2
+ (make-wrap
+ (wrap-marks w2)
+ (smart-append s1 (wrap-subst w2))))
(make-wrap
- (wrap-marks w)
- (cons
- (let ((labelvec (list->vector labels)))
- (let ((n (vector-length labelvec)))
- (let ((symnamevec (make-vector n)) (marksvec (make-vector n)))
- (let f ((ids ids) (i 0))
- (if (not (null? ids))
- (call-with-values
- (lambda () (id-sym-name&marks (car ids) w))
- (lambda (symname marks)
- (vector-set! symnamevec i symname)
- (vector-set! marksvec i marks)
- (f (cdr ids) (1+ i))))))
- (make-ribcage symnamevec marksvec labelvec))))
- (wrap-subst w))))))
-
- (define smart-append
- (lambda (m1 m2)
- (if (null? m2)
- m1
- (append m1 m2))))
-
- (define join-wraps
- (lambda (w1 w2)
- (let ((m1 (wrap-marks w1)) (s1 (wrap-subst w1)))
- (if (null? m1)
- (if (null? s1)
- w2
- (make-wrap
- (wrap-marks w2)
- (smart-append s1 (wrap-subst w2))))
- (make-wrap
- (smart-append m1 (wrap-marks w2))
- (smart-append s1 (wrap-subst w2)))))))
-
- (define join-marks
- (lambda (m1 m2)
- (smart-append m1 m2)))
-
- (define same-marks?
- (lambda (x y)
- (or (eq? x y)
- (and (not (null? x))
- (not (null? y))
- (eq? (car x) (car y))
- (same-marks? (cdr x) (cdr y))))))
-
- (define id-var-name
+ (smart-append m1 (wrap-marks w2))
+ (smart-append s1 (wrap-subst w2))))))
+
+ (define (join-marks m1 m2)
+ (smart-append m1 m2))
+
+ (define (same-marks? x y)
+ (or (eq? x y)
+ (and (not (null? x))
+ (not (null? y))
+ (eq? (car x) (car y))
+ (same-marks? (cdr x) (cdr y)))))
+
+ (define (id-var-name id w mod)
;; Syntax objects use wraps to associate names with marked
;; identifiers. This function returns the name corresponding to
;; the given identifier and wrap, or the original identifier if no
@@ -619,65 +584,64 @@
;; case, this routine returns either a symbol, a syntax object, or
;; a string label.
;;
- (lambda (id w mod)
- (define-syntax-rule (first e)
- ;; Rely on Guile's multiple-values truncation.
- e)
- (define search
- (lambda (sym subst marks mod)
- (if (null? subst)
- (values #f marks)
- (let ((fst (car subst)))
- (if (eq? fst 'shift)
- (search sym (cdr subst) (cdr marks) mod)
- (let ((symnames (ribcage-symnames fst)))
- (if (vector? symnames)
- (search-vector-rib sym subst marks symnames fst mod)
- (search-list-rib sym subst marks symnames fst
mod))))))))
- (define search-list-rib
- (lambda (sym subst marks symnames ribcage mod)
- (let f ((symnames symnames)
- (rlabels (ribcage-labels ribcage))
- (rmarks (ribcage-marks ribcage)))
+ (define-syntax-rule (first e)
+ ;; Rely on Guile's multiple-values truncation.
+ e)
+ (define search
+ (lambda (sym subst marks mod)
+ (if (null? subst)
+ (values #f marks)
+ (let ((fst (car subst)))
+ (if (eq? fst 'shift)
+ (search sym (cdr subst) (cdr marks) mod)
+ (let ((symnames (ribcage-symnames fst)))
+ (if (vector? symnames)
+ (search-vector-rib sym subst marks symnames fst mod)
+ (search-list-rib sym subst marks symnames fst
mod))))))))
+ (define search-list-rib
+ (lambda (sym subst marks symnames ribcage mod)
+ (let f ((symnames symnames)
+ (rlabels (ribcage-labels ribcage))
+ (rmarks (ribcage-marks ribcage)))
+ (cond
+ ((null? symnames) (search sym (cdr subst) marks mod))
+ ((and (eq? (car symnames) sym) (same-marks? marks (car rmarks)))
+ (let ((n (car rlabels)))
+ (if (pair? n)
+ (if (equal? mod (car n))
+ (values (cdr n) marks)
+ (f (cdr symnames) (cdr rlabels) (cdr rmarks)))
+ (values n marks))))
+ (else (f (cdr symnames) (cdr rlabels) (cdr rmarks)))))))
+ (define search-vector-rib
+ (lambda (sym subst marks symnames ribcage mod)
+ (let ((n (vector-length symnames)))
+ (let f ((i 0))
(cond
- ((null? symnames) (search sym (cdr subst) marks mod))
- ((and (eq? (car symnames) sym) (same-marks? marks (car rmarks)))
- (let ((n (car rlabels)))
+ ((= i n) (search sym (cdr subst) marks mod))
+ ((and (eq? (vector-ref symnames i) sym)
+ (same-marks? marks (vector-ref (ribcage-marks ribcage) i)))
+ (let ((n (vector-ref (ribcage-labels ribcage) i)))
(if (pair? n)
(if (equal? mod (car n))
(values (cdr n) marks)
- (f (cdr symnames) (cdr rlabels) (cdr rmarks)))
+ (f (1+ i)))
(values n marks))))
- (else (f (cdr symnames) (cdr rlabels) (cdr rmarks)))))))
- (define search-vector-rib
- (lambda (sym subst marks symnames ribcage mod)
- (let ((n (vector-length symnames)))
- (let f ((i 0))
- (cond
- ((= i n) (search sym (cdr subst) marks mod))
- ((and (eq? (vector-ref symnames i) sym)
- (same-marks? marks (vector-ref (ribcage-marks ribcage)
i)))
- (let ((n (vector-ref (ribcage-labels ribcage) i)))
- (if (pair? n)
- (if (equal? mod (car n))
- (values (cdr n) marks)
- (f (1+ i)))
- (values n marks))))
- (else (f (1+ i))))))))
- (cond
- ((symbol? id)
- (or (first (search id (wrap-subst w) (wrap-marks w) mod)) id))
- ((syntax? id)
- (let ((id (syntax-expression id))
- (w1 (syntax-wrap id))
- (mod (or (syntax-module id) mod)))
- (let ((marks (join-marks (wrap-marks w) (wrap-marks w1))))
- (call-with-values (lambda () (search id (wrap-subst w) marks mod))
- (lambda (new-id marks)
- (or new-id
- (first (search id (wrap-subst w1) marks mod))
- id))))))
- (else (syntax-violation 'id-var-name "invalid id" id)))))
+ (else (f (1+ i))))))))
+ (cond
+ ((symbol? id)
+ (or (first (search id (wrap-subst w) (wrap-marks w) mod)) id))
+ ((syntax? id)
+ (let ((id (syntax-expression id))
+ (w1 (syntax-wrap id))
+ (mod (or (syntax-module id) mod)))
+ (let ((marks (join-marks (wrap-marks w) (wrap-marks w1))))
+ (call-with-values (lambda () (search id (wrap-subst w) marks mod))
+ (lambda (new-id marks)
+ (or new-id
+ (first (search id (wrap-subst w1) marks mod))
+ id))))))
+ (else (syntax-violation 'id-var-name "invalid id" id))))
;; A helper procedure for syntax-locally-bound-identifiers, which
;; itself is a helper for transformer procedures.
@@ -691,42 +655,41 @@
;; are anti-marked, so that rebuild-macro-output doesn't apply new
;; marks to them.
;;
- (define locally-bound-identifiers
- (lambda (w mod)
- (define scan
- (lambda (subst results)
- (if (null? subst)
- results
- (let ((fst (car subst)))
- (if (eq? fst 'shift)
- (scan (cdr subst) results)
- (let ((symnames (ribcage-symnames fst))
- (marks (ribcage-marks fst)))
- (if (vector? symnames)
- (scan-vector-rib subst symnames marks results)
- (scan-list-rib subst symnames marks results))))))))
- (define scan-list-rib
- (lambda (subst symnames marks results)
- (let f ((symnames symnames) (marks marks) (results results))
- (if (null? symnames)
+ (define (locally-bound-identifiers w mod)
+ (define scan
+ (lambda (subst results)
+ (if (null? subst)
+ results
+ (let ((fst (car subst)))
+ (if (eq? fst 'shift)
+ (scan (cdr subst) results)
+ (let ((symnames (ribcage-symnames fst))
+ (marks (ribcage-marks fst)))
+ (if (vector? symnames)
+ (scan-vector-rib subst symnames marks results)
+ (scan-list-rib subst symnames marks results))))))))
+ (define scan-list-rib
+ (lambda (subst symnames marks results)
+ (let f ((symnames symnames) (marks marks) (results results))
+ (if (null? symnames)
+ (scan (cdr subst) results)
+ (f (cdr symnames) (cdr marks)
+ (cons (wrap (car symnames)
+ (anti-mark (make-wrap (car marks) subst))
+ mod)
+ results))))))
+ (define scan-vector-rib
+ (lambda (subst symnames marks results)
+ (let ((n (vector-length symnames)))
+ (let f ((i 0) (results results))
+ (if (= i n)
(scan (cdr subst) results)
- (f (cdr symnames) (cdr marks)
- (cons (wrap (car symnames)
- (anti-mark (make-wrap (car marks) subst))
+ (f (1+ i)
+ (cons (wrap (vector-ref symnames i)
+ (anti-mark (make-wrap (vector-ref marks i)
subst))
mod)
- results))))))
- (define scan-vector-rib
- (lambda (subst symnames marks results)
- (let ((n (vector-length symnames)))
- (let f ((i 0) (results results))
- (if (= i n)
- (scan (cdr subst) results)
- (f (1+ i)
- (cons (wrap (vector-ref symnames i)
- (anti-mark (make-wrap (vector-ref marks i)
subst))
- mod)
- results)))))))
- (scan (wrap-subst w) '())))
+ results)))))))
+ (scan (wrap-subst w) '()))
;; Returns three values: binding type, binding value, and the module
;; (for resolving toplevel vars).
@@ -834,66 +797,63 @@
;; free-id=? must be passed fully wrapped ids since (free-id=? x y)
;; may be true even if (free-id=? (wrap x w) (wrap y w)) is not.
- (define free-id=?
- (lambda (i j)
- (let* ((mi (and (syntax? i) (syntax-module i)))
- (mj (and (syntax? j) (syntax-module j)))
- (ni (id-var-name i empty-wrap mi))
- (nj (id-var-name j empty-wrap mj)))
- (define (id-module-binding id mod)
- (module-variable
- (if mod
- ;; The normal case.
- (resolve-module (cdr mod))
- ;; Either modules have not been booted, or we have a
- ;; raw symbol coming in, which is possible.
- (current-module))
- (id-sym-name id)))
- (cond
- ((syntax? ni) (free-id=? ni j))
- ((syntax? nj) (free-id=? i nj))
- ((symbol? ni)
- ;; `i' is not lexically bound. Assert that `j' is free,
- ;; and if so, compare their bindings, that they are either
- ;; bound to the same variable, or both unbound and have
- ;; the same name.
- (and (eq? nj (id-sym-name j))
- (let ((bi (id-module-binding i mi)))
- (if bi
- (eq? bi (id-module-binding j mj))
- (and (not (id-module-binding j mj))
- (eq? ni nj))))
- (eq? (id-module-binding i mi) (id-module-binding j mj))))
- (else
- ;; Otherwise `i' is bound, so check that `j' is bound, and
- ;; bound to the same thing.
- (equal? ni nj))))))
+ (define (free-id=? i j)
+ (let* ((mi (and (syntax? i) (syntax-module i)))
+ (mj (and (syntax? j) (syntax-module j)))
+ (ni (id-var-name i empty-wrap mi))
+ (nj (id-var-name j empty-wrap mj)))
+ (define (id-module-binding id mod)
+ (module-variable
+ (if mod
+ ;; The normal case.
+ (resolve-module (cdr mod))
+ ;; Either modules have not been booted, or we have a
+ ;; raw symbol coming in, which is possible.
+ (current-module))
+ (id-sym-name id)))
+ (cond
+ ((syntax? ni) (free-id=? ni j))
+ ((syntax? nj) (free-id=? i nj))
+ ((symbol? ni)
+ ;; `i' is not lexically bound. Assert that `j' is free,
+ ;; and if so, compare their bindings, that they are either
+ ;; bound to the same variable, or both unbound and have
+ ;; the same name.
+ (and (eq? nj (id-sym-name j))
+ (let ((bi (id-module-binding i mi)))
+ (if bi
+ (eq? bi (id-module-binding j mj))
+ (and (not (id-module-binding j mj))
+ (eq? ni nj))))
+ (eq? (id-module-binding i mi) (id-module-binding j mj))))
+ (else
+ ;; Otherwise `i' is bound, so check that `j' is bound, and
+ ;; bound to the same thing.
+ (equal? ni nj)))))
;; bound-id=? may be passed unwrapped (or partially wrapped) ids as
;; long as the missing portion of the wrap is common to both of the ids
;; since (bound-id=? x y) iff (bound-id=? (wrap x w) (wrap y w))
- (define bound-id=?
- (lambda (i j)
- (if (and (syntax? i) (syntax? j))
- (and (eq? (syntax-expression i)
- (syntax-expression j))
- (same-marks? (wrap-marks (syntax-wrap i))
- (wrap-marks (syntax-wrap j))))
- (eq? i j))))
+ (define (bound-id=? i j)
+ (if (and (syntax? i) (syntax? j))
+ (and (eq? (syntax-expression i)
+ (syntax-expression j))
+ (same-marks? (wrap-marks (syntax-wrap i))
+ (wrap-marks (syntax-wrap j))))
+ (eq? i j)))
;; "valid-bound-ids?" returns #t if it receives a list of distinct ids.
;; valid-bound-ids? may be passed unwrapped (or partially wrapped) ids
;; as long as the missing portion of the wrap is common to all of the
;; ids.
- (define valid-bound-ids?
- (lambda (ids)
- (and (let all-ids? ((ids ids))
- (or (null? ids)
- (and (id? (car ids))
- (all-ids? (cdr ids)))))
- (distinct-bound-ids? ids))))
+ (define (valid-bound-ids? ids)
+ (and (let all-ids? ((ids ids))
+ (or (null? ids)
+ (and (id? (car ids))
+ (all-ids? (cdr ids)))))
+ (distinct-bound-ids? ids)))
;; distinct-bound-ids? expects a list of ids and returns #t if there are
;; no duplicates. It is quadratic on the length of the id list; long
@@ -901,24 +861,21 @@
;; may be passed unwrapped (or partially wrapped) ids as long as the
;; missing portion of the wrap is common to all of the ids.
- (define distinct-bound-ids?
- (lambda (ids)
- (let distinct? ((ids ids))
- (or (null? ids)
- (and (not (bound-id-member? (car ids) (cdr ids)))
- (distinct? (cdr ids)))))))
+ (define (distinct-bound-ids? ids)
+ (let distinct? ((ids ids))
+ (or (null? ids)
+ (and (not (bound-id-member? (car ids) (cdr ids)))
+ (distinct? (cdr ids))))))
- (define bound-id-member?
- (lambda (x list)
- (and (not (null? list))
- (or (bound-id=? x (car list))
- (bound-id-member? x (cdr list))))))
+ (define (bound-id-member? x list)
+ (and (not (null? list))
+ (or (bound-id=? x (car list))
+ (bound-id-member? x (cdr list)))))
;; wrapping expressions and identifiers
- (define wrap
- (lambda (x w defmod)
- (source-wrap x w #f defmod)))
+ (define (wrap x w defmod)
+ (source-wrap x w #f defmod))
(define (wrap-syntax x w defmod)
(make-syntax (syntax-expression x)
@@ -938,14 +895,13 @@
;; expanding
- (define expand-sequence
- (lambda (body r w s mod)
- (build-sequence s
- (let dobody ((body body) (r r) (w w) (mod mod))
- (if (null? body)
- '()
- (let ((first (expand (car body) r w mod)))
- (cons first (dobody (cdr body) r w mod))))))))
+ (define (expand-sequence body r w s mod)
+ (build-sequence s
+ (let dobody ((body body) (r r) (w w) (mod mod))
+ (if (null? body)
+ '()
+ (let ((first (expand (car body) r w mod)))
+ (cons first (dobody (cdr body) r w mod)))))))
;; At top-level, we allow mixed definitions and expressions. Like
;; expand-body we expand in two passes.
@@ -961,215 +917,207 @@
;; expansions of all normal definitions and expressions in the
;; sequence.
;;
- (define expand-top-sequence
- (lambda (body r w s m esew mod)
- (let* ((r (cons '("placeholder" . (placeholder)) r))
- (ribcage (make-empty-ribcage))
- (w (make-wrap (wrap-marks w) (cons ribcage (wrap-subst w)))))
- (define (record-definition! id var)
- (let ((mod (cons 'hygiene (module-name (current-module)))))
- ;; Ribcages map symbol+marks to names, mostly for
- ;; resolving lexicals. Here to add a mapping for toplevel
- ;; definitions we also need to match the module. So, we
- ;; put it in the name instead, and make id-var-name handle
- ;; the special case of names that are pairs. See the
- ;; comments in id-var-name for more.
- (extend-ribcage! ribcage id
- (cons (or (syntax-module id) mod)
- (wrap var top-wrap mod)))))
- (define (macro-introduced-identifier? id)
- (not (equal? (wrap-marks (syntax-wrap id)) '(top))))
- (define (ensure-fresh-name var)
- ;; If a macro introduces a top-level identifier, we attempt
- ;; to give it a fresh name by appending the hash of the
- ;; expression in which it appears. However, this can fail
- ;; for hash collisions, which is more common that one might
- ;; think: Guile's hash function stops descending into cdr's
- ;; at some point. So, within an expansion unit, fall back
- ;; to appending a uniquifying integer.
- (define (ribcage-has-var? var)
- (let lp ((labels (ribcage-labels ribcage)))
- (and (pair? labels)
- (let ((wrapped (cdar labels)))
- (or (eq? (syntax-expression wrapped) var)
- (lp (cdr labels)))))))
- (let lp ((unique var) (n 1))
- (if (ribcage-has-var? unique)
- (let ((tail (string->symbol (number->string n))))
- (lp (symbol-append var '- tail) (1+ n)))
- unique)))
- (define (fresh-derived-name id orig-form)
- (ensure-fresh-name
- (symbol-append
- (syntax-expression id)
- '-
- (string->symbol
- ;; FIXME: This encodes hash values into the ABI of
- ;; compiled modules; a problem?
- (number->string
- (hash (syntax->datum orig-form) most-positive-fixnum)
- 16)))))
- (define (parse body r w s m esew mod)
- (let lp ((body body) (exps '()))
- (if (null? body)
- exps
- (lp (cdr body)
- (append (parse1 (car body) r w s m esew mod)
- exps)))))
- (define (parse1 x r w s m esew mod)
- (define (current-module-for-expansion mod)
- (case (car mod)
- ;; If the module was just put in place for hygiene, in a
- ;; top-level `begin' always recapture the current
- ;; module. If a user wants to override, then we need to
- ;; use @@ or similar.
- ((hygiene) (cons 'hygiene (module-name (current-module))))
- (else mod)))
- (call-with-values
- (lambda ()
- (let ((mod (current-module-for-expansion mod)))
- (syntax-type x r w (source-annotation x) ribcage mod #f)))
- (lambda (type value form e w s mod)
- (case type
- ((define-form)
- (let* ((id (wrap value w mod))
- (var (if (macro-introduced-identifier? id)
- (fresh-derived-name id x)
- (syntax-expression id))))
- (record-definition! id var)
- (list
- (if (eq? m 'c&e)
- (let ((x (build-global-definition s mod var (expand e
r w mod))))
- (top-level-eval x mod)
- (lambda () x))
- (call-with-values
- (lambda () (resolve-identifier id empty-wrap r mod
#t))
- (lambda (type* value* mod*)
- ;; If the identifier to be bound is currently
bound to a
- ;; macro, then immediately discard that binding.
- (if (eq? type* 'macro)
- (top-level-eval (build-global-definition
- s mod var (build-void s))
- mod))
- (lambda ()
- (build-global-definition s mod var (expand e r w
mod)))))))))
- ((define-syntax-form define-syntax-parameter-form)
- (let* ((id (wrap value w mod))
- (var (if (macro-introduced-identifier? id)
- (fresh-derived-name id x)
- (syntax-expression id))))
- (record-definition! id var)
- (case m
- ((c)
- (cond
- ((memq 'compile esew)
- (let ((e (expand-install-global mod var type (expand e
r w mod))))
- (top-level-eval e mod)
- (if (memq 'load esew)
- (list (lambda () e))
- '())))
- ((memq 'load esew)
- (list (lambda ()
- (expand-install-global mod var type (expand e
r w mod)))))
- (else '())))
- ((c&e)
- (let ((e (expand-install-global mod var type (expand e r
w mod))))
- (top-level-eval e mod)
- (list (lambda () e))))
- (else
- (if (memq 'eval esew)
- (top-level-eval
- (expand-install-global mod var type (expand e r w
mod))
- mod))
- '()))))
- ((begin-form)
- (syntax-case e ()
- ((_ e1 ...)
- (parse #'(e1 ...) r w s m esew mod))))
- ((local-syntax-form)
- (expand-local-syntax value e r w s mod
- (lambda (forms r w s mod)
- (parse forms r w s m esew mod))))
- ((eval-when-form)
- (syntax-case e ()
- ((_ (x ...) e1 e2 ...)
- (let ((when-list (parse-when-list e #'(x ...)))
- (body #'(e1 e2 ...)))
- (define (recurse m esew)
- (parse body r w s m esew mod))
- (cond
- ((eq? m 'e)
- (if (memq 'eval when-list)
- (recurse (if (memq 'expand when-list) 'c&e 'e)
- '(eval))
- (begin
- (if (memq 'expand when-list)
- (top-level-eval
- (expand-top-sequence body r w s 'e '(eval)
mod)
- mod))
- '())))
- ((memq 'load when-list)
- (if (or (memq 'compile when-list)
- (memq 'expand when-list)
- (and (eq? m 'c&e) (memq 'eval when-list)))
- (recurse 'c&e '(compile load))
- (if (memq m '(c c&e))
- (recurse 'c '(load))
- '())))
- ((or (memq 'compile when-list)
- (memq 'expand when-list)
- (and (eq? m 'c&e) (memq 'eval when-list)))
- (top-level-eval
- (expand-top-sequence body r w s 'e '(eval) mod)
- mod)
- '())
- (else
- '()))))))
- (else
+ (define (expand-top-sequence body r w s m esew mod)
+ (let* ((r (cons '("placeholder" . (placeholder)) r))
+ (ribcage (make-empty-ribcage))
+ (w (make-wrap (wrap-marks w) (cons ribcage (wrap-subst w)))))
+ (define (record-definition! id var)
+ (let ((mod (cons 'hygiene (module-name (current-module)))))
+ ;; Ribcages map symbol+marks to names, mostly for
+ ;; resolving lexicals. Here to add a mapping for toplevel
+ ;; definitions we also need to match the module. So, we
+ ;; put it in the name instead, and make id-var-name handle
+ ;; the special case of names that are pairs. See the
+ ;; comments in id-var-name for more.
+ (extend-ribcage! ribcage id
+ (cons (or (syntax-module id) mod)
+ (wrap var top-wrap mod)))))
+ (define (macro-introduced-identifier? id)
+ (not (equal? (wrap-marks (syntax-wrap id)) '(top))))
+ (define (ensure-fresh-name var)
+ ;; If a macro introduces a top-level identifier, we attempt
+ ;; to give it a fresh name by appending the hash of the
+ ;; expression in which it appears. However, this can fail
+ ;; for hash collisions, which is more common that one might
+ ;; think: Guile's hash function stops descending into cdr's
+ ;; at some point. So, within an expansion unit, fall back
+ ;; to appending a uniquifying integer.
+ (define (ribcage-has-var? var)
+ (let lp ((labels (ribcage-labels ribcage)))
+ (and (pair? labels)
+ (let ((wrapped (cdar labels)))
+ (or (eq? (syntax-expression wrapped) var)
+ (lp (cdr labels)))))))
+ (let lp ((unique var) (n 1))
+ (if (ribcage-has-var? unique)
+ (let ((tail (string->symbol (number->string n))))
+ (lp (symbol-append var '- tail) (1+ n)))
+ unique)))
+ (define (fresh-derived-name id orig-form)
+ (ensure-fresh-name
+ (symbol-append
+ (syntax-expression id)
+ '-
+ (string->symbol
+ ;; FIXME: This encodes hash values into the ABI of
+ ;; compiled modules; a problem?
+ (number->string
+ (hash (syntax->datum orig-form) most-positive-fixnum)
+ 16)))))
+ (define (parse body r w s m esew mod)
+ (let lp ((body body) (exps '()))
+ (if (null? body)
+ exps
+ (lp (cdr body)
+ (append (parse1 (car body) r w s m esew mod)
+ exps)))))
+ (define (parse1 x r w s m esew mod)
+ (define (current-module-for-expansion mod)
+ (case (car mod)
+ ;; If the module was just put in place for hygiene, in a
+ ;; top-level `begin' always recapture the current
+ ;; module. If a user wants to override, then we need to
+ ;; use @@ or similar.
+ ((hygiene) (cons 'hygiene (module-name (current-module))))
+ (else mod)))
+ (call-with-values
+ (lambda ()
+ (let ((mod (current-module-for-expansion mod)))
+ (syntax-type x r w (source-annotation x) ribcage mod #f)))
+ (lambda (type value form e w s mod)
+ (case type
+ ((define-form)
+ (let* ((id (wrap value w mod))
+ (var (if (macro-introduced-identifier? id)
+ (fresh-derived-name id x)
+ (syntax-expression id))))
+ (record-definition! id var)
(list
(if (eq? m 'c&e)
- (let ((x (expand-expr type value form e r w s mod)))
+ (let ((x (build-global-definition s mod var (expand e r
w mod))))
(top-level-eval x mod)
(lambda () x))
- (lambda ()
- (expand-expr type value form e r w s mod)))))))))
- (let ((exps (map (lambda (x) (x))
- (reverse (parse body r w s m esew mod)))))
- (if (null? exps)
- (build-void s)
- (build-sequence s exps))))))
+ (call-with-values
+ (lambda () (resolve-identifier id empty-wrap r mod
#t))
+ (lambda (type* value* mod*)
+ ;; If the identifier to be bound is currently bound
to a
+ ;; macro, then immediately discard that binding.
+ (if (eq? type* 'macro)
+ (top-level-eval (build-global-definition
+ s mod var (build-void s))
+ mod))
+ (lambda ()
+ (build-global-definition s mod var (expand e r w
mod)))))))))
+ ((define-syntax-form define-syntax-parameter-form)
+ (let* ((id (wrap value w mod))
+ (var (if (macro-introduced-identifier? id)
+ (fresh-derived-name id x)
+ (syntax-expression id))))
+ (record-definition! id var)
+ (case m
+ ((c)
+ (cond
+ ((memq 'compile esew)
+ (let ((e (expand-install-global mod var type (expand e r
w mod))))
+ (top-level-eval e mod)
+ (if (memq 'load esew)
+ (list (lambda () e))
+ '())))
+ ((memq 'load esew)
+ (list (lambda ()
+ (expand-install-global mod var type (expand e r
w mod)))))
+ (else '())))
+ ((c&e)
+ (let ((e (expand-install-global mod var type (expand e r w
mod))))
+ (top-level-eval e mod)
+ (list (lambda () e))))
+ (else
+ (if (memq 'eval esew)
+ (top-level-eval
+ (expand-install-global mod var type (expand e r w
mod))
+ mod))
+ '()))))
+ ((begin-form)
+ (syntax-case e ()
+ ((_ e1 ...)
+ (parse #'(e1 ...) r w s m esew mod))))
+ ((local-syntax-form)
+ (expand-local-syntax value e r w s mod
+ (lambda (forms r w s mod)
+ (parse forms r w s m esew mod))))
+ ((eval-when-form)
+ (syntax-case e ()
+ ((_ (x ...) e1 e2 ...)
+ (let ((when-list (parse-when-list e #'(x ...)))
+ (body #'(e1 e2 ...)))
+ (define (recurse m esew)
+ (parse body r w s m esew mod))
+ (cond
+ ((eq? m 'e)
+ (if (memq 'eval when-list)
+ (recurse (if (memq 'expand when-list) 'c&e 'e)
+ '(eval))
+ (begin
+ (if (memq 'expand when-list)
+ (top-level-eval
+ (expand-top-sequence body r w s 'e '(eval)
mod)
+ mod))
+ '())))
+ ((memq 'load when-list)
+ (if (or (memq 'compile when-list)
+ (memq 'expand when-list)
+ (and (eq? m 'c&e) (memq 'eval when-list)))
+ (recurse 'c&e '(compile load))
+ (if (memq m '(c c&e))
+ (recurse 'c '(load))
+ '())))
+ ((or (memq 'compile when-list)
+ (memq 'expand when-list)
+ (and (eq? m 'c&e) (memq 'eval when-list)))
+ (top-level-eval
+ (expand-top-sequence body r w s 'e '(eval) mod)
+ mod)
+ '())
+ (else
+ '()))))))
+ (else
+ (list
+ (if (eq? m 'c&e)
+ (let ((x (expand-expr type value form e r w s mod)))
+ (top-level-eval x mod)
+ (lambda () x))
+ (lambda ()
+ (expand-expr type value form e r w s mod)))))))))
+ (let ((exps (map (lambda (x) (x))
+ (reverse (parse body r w s m esew mod)))))
+ (if (null? exps)
+ (build-void s)
+ (build-sequence s exps)))))
- (define expand-install-global
- (lambda (mod name type e)
- (build-global-definition
- no-source
- mod
- name
- (build-primcall
- no-source
- 'make-syntax-transformer
- (list (build-data no-source name)
- (build-data no-source
- (if (eq? type 'define-syntax-parameter-form)
- 'syntax-parameter
- 'macro))
- e)))))
+ (define (expand-install-global mod name type e)
+ (build-global-definition
+ no-source
+ mod
+ name
+ (build-primcall
+ no-source
+ 'make-syntax-transformer
+ (list (build-data no-source name)
+ (build-data no-source
+ (if (eq? type 'define-syntax-parameter-form)
+ 'syntax-parameter
+ 'macro))
+ e))))
- (define parse-when-list
- (lambda (e when-list)
- ;; `when-list' is syntax'd version of list of situations. We
- ;; could match these keywords lexically, via free-id=?, but then
- ;; we twingle the definition of eval-when to the bindings of
- ;; eval, load, expand, and compile, which is totally unintended.
- ;; So do a symbolic match instead.
- (let ((result (strip when-list)))
- (let lp ((l result))
- (if (null? l)
- result
- (if (memq (car l) '(compile load eval expand))
- (lp (cdr l))
- (syntax-violation 'eval-when "invalid situation" e
- (car l))))))))
+ (define (parse-when-list e when-list)
+ (let ((result (strip when-list)))
+ (let lp ((l result))
+ (if (null? l)
+ result
+ (if (memq (car l) '(compile load eval expand))
+ (lp (cdr l))
+ (syntax-violation 'eval-when "invalid situation" e
+ (car l)))))))
;; syntax-type returns seven values: type, value, form, e, w, s, and
;; mod. The first two are described in the table below.
@@ -1212,178 +1160,174 @@
;; of the forms above. It also parses definition forms, although
;; perhaps this should be done by the consumer.
- (define syntax-type
- (lambda (e r w s rib mod for-car?)
- (cond
- ((symbol? e)
- (call-with-values (lambda () (resolve-identifier e w r mod #t))
- (lambda (type value mod*)
- (case type
- ((macro)
- (if for-car?
- (values type value e e w s mod)
- (syntax-type (expand-macro value e r w s rib mod)
- r empty-wrap s rib mod #f)))
+ (define (syntax-type e r w s rib mod for-car?)
+ (cond
+ ((symbol? e)
+ (call-with-values (lambda () (resolve-identifier e w r mod #t))
+ (lambda (type value mod*)
+ (case type
+ ((macro)
+ (if for-car?
+ (values type value e e w s mod)
+ (syntax-type (expand-macro value e r w s rib mod)
+ r empty-wrap s rib mod #f)))
+ ((global)
+ ;; Toplevel definitions may resolve to bindings with
+ ;; different names or in different modules.
+ (values type value e value w s mod*))
+ (else (values type value e e w s mod))))))
+ ((pair? e)
+ (let ((first (car e)))
+ (call-with-values
+ (lambda () (syntax-type first r w s rib mod #t))
+ (lambda (ftype fval fform fe fw fs fmod)
+ (case ftype
+ ((lexical)
+ (values 'lexical-call fval e e w s mod))
((global)
- ;; Toplevel definitions may resolve to bindings with
- ;; different names or in different modules.
- (values type value e value w s mod*))
- (else (values type value e e w s mod))))))
- ((pair? e)
- (let ((first (car e)))
- (call-with-values
- (lambda () (syntax-type first r w s rib mod #t))
- (lambda (ftype fval fform fe fw fs fmod)
- (case ftype
- ((lexical)
- (values 'lexical-call fval e e w s mod))
- ((global)
- (if (equal? fmod '(primitive))
- (values 'primitive-call fval e e w s mod)
- ;; If we got here via an (@@ ...) expansion, we
- ;; need to make sure the fmod information is
- ;; propagated back correctly -- hence this
- ;; consing.
- (values 'global-call (make-syntax fval w fmod fs)
- e e w s mod)))
- ((macro)
- (syntax-type (expand-macro fval e r w s rib mod)
- r empty-wrap s rib mod for-car?))
- ((module-ref)
- (call-with-values (lambda () (fval e r w mod))
- (lambda (e r w s mod)
- (syntax-type e r w s rib mod for-car?))))
- ((core)
- (values 'core-form fval e e w s mod))
- ((local-syntax)
- (values 'local-syntax-form fval e e w s mod))
- ((begin)
- (values 'begin-form #f e e w s mod))
- ((eval-when)
- (values 'eval-when-form #f e e w s mod))
- ((define)
- (syntax-case e ()
- ((_ name val)
- (id? #'name)
- (values 'define-form #'name e #'val w s mod))
- ((_ (name . args) e1 e2 ...)
- (and (id? #'name)
- (valid-bound-ids? (lambda-var-list #'args)))
- ;; need lambda here...
- (values 'define-form (wrap #'name w mod)
- (wrap e w mod)
- (source-wrap
- (cons #'lambda (wrap #'(args e1 e2 ...) w mod))
- empty-wrap s #f)
- empty-wrap s mod))
- ((_ name)
- (id? #'name)
- (values 'define-form (wrap #'name w mod)
- (wrap e w mod)
- #'(if #f #f)
- empty-wrap s mod))))
- ((define-syntax)
- (syntax-case e ()
- ((_ name val)
- (id? #'name)
- (values 'define-syntax-form #'name e #'val w s mod))))
- ((define-syntax-parameter)
- (syntax-case e ()
- ((_ name val)
- (id? #'name)
- (values 'define-syntax-parameter-form #'name e #'val w s
mod))))
- (else
- (values 'call #f e e w s mod)))))))
- ((syntax? e)
- (syntax-type (syntax-expression e)
- r
- (join-wraps w (syntax-wrap e))
- (or (source-annotation e) s) rib
- (or (syntax-module e) mod) for-car?))
- ((self-evaluating? e) (values 'constant #f e e w s mod))
- (else (values 'other #f e e w s mod)))))
-
- (define expand
- (lambda (e r w mod)
- (call-with-values
- (lambda () (syntax-type e r w (source-annotation e) #f mod #f))
- (lambda (type value form e w s mod)
- (expand-expr type value form e r w s mod)))))
-
- (define expand-expr
- (lambda (type value form e r w s mod)
- (case type
- ((lexical)
- (build-lexical-reference 'value s e value))
- ((core core-form)
- ;; apply transformer
- (value e r w s mod))
- ((module-ref)
- (call-with-values (lambda () (value e r w mod))
- (lambda (e r w s mod)
- (expand e r w mod))))
- ((lexical-call)
- (expand-call
- (let ((id (car e)))
- (build-lexical-reference 'fun (source-annotation id)
- (if (syntax? id)
- (syntax->datum id)
- id)
- value))
- e r w s mod))
- ((global-call)
- (expand-call
- (build-global-reference (or (source-annotation (car e)) s)
- (if (syntax? value)
- (syntax-expression value)
- value)
- (or (and (syntax? value)
- (syntax-module value))
- mod))
- e r w s mod))
- ((primitive-call)
- (syntax-case e ()
- ((_ e ...)
- (build-primcall s
- value
- (map (lambda (e) (expand e r w mod))
- #'(e ...))))))
- ((constant) (build-data s (strip e)))
- ((global) (build-global-reference s value mod))
- ((call) (expand-call (expand (car e) r w mod) e r w s mod))
- ((begin-form)
- (syntax-case e ()
- ((_ e1 e2 ...) (expand-sequence #'(e1 e2 ...) r w s mod))
- ((_)
- (syntax-violation #f "sequence of zero expressions"
+ (if (equal? fmod '(primitive))
+ (values 'primitive-call fval e e w s mod)
+ ;; If we got here via an (@@ ...) expansion, we
+ ;; need to make sure the fmod information is
+ ;; propagated back correctly -- hence this
+ ;; consing.
+ (values 'global-call (make-syntax fval w fmod fs)
+ e e w s mod)))
+ ((macro)
+ (syntax-type (expand-macro fval e r w s rib mod)
+ r empty-wrap s rib mod for-car?))
+ ((module-ref)
+ (call-with-values (lambda () (fval e r w mod))
+ (lambda (e r w s mod)
+ (syntax-type e r w s rib mod for-car?))))
+ ((core)
+ (values 'core-form fval e e w s mod))
+ ((local-syntax)
+ (values 'local-syntax-form fval e e w s mod))
+ ((begin)
+ (values 'begin-form #f e e w s mod))
+ ((eval-when)
+ (values 'eval-when-form #f e e w s mod))
+ ((define)
+ (syntax-case e ()
+ ((_ name val)
+ (id? #'name)
+ (values 'define-form #'name e #'val w s mod))
+ ((_ (name . args) e1 e2 ...)
+ (and (id? #'name)
+ (valid-bound-ids? (lambda-var-list #'args)))
+ ;; need lambda here...
+ (values 'define-form (wrap #'name w mod)
+ (wrap e w mod)
+ (source-wrap
+ (cons #'lambda (wrap #'(args e1 e2 ...) w mod))
+ empty-wrap s #f)
+ empty-wrap s mod))
+ ((_ name)
+ (id? #'name)
+ (values 'define-form (wrap #'name w mod)
+ (wrap e w mod)
+ #'(if #f #f)
+ empty-wrap s mod))))
+ ((define-syntax)
+ (syntax-case e ()
+ ((_ name val)
+ (id? #'name)
+ (values 'define-syntax-form #'name e #'val w s mod))))
+ ((define-syntax-parameter)
+ (syntax-case e ()
+ ((_ name val)
+ (id? #'name)
+ (values 'define-syntax-parameter-form #'name e #'val w s
mod))))
+ (else
+ (values 'call #f e e w s mod)))))))
+ ((syntax? e)
+ (syntax-type (syntax-expression e)
+ r
+ (join-wraps w (syntax-wrap e))
+ (or (source-annotation e) s) rib
+ (or (syntax-module e) mod) for-car?))
+ ((self-evaluating? e) (values 'constant #f e e w s mod))
+ (else (values 'other #f e e w s mod))))
+
+ (define (expand e r w mod)
+ (call-with-values
+ (lambda () (syntax-type e r w (source-annotation e) #f mod #f))
+ (lambda (type value form e w s mod)
+ (expand-expr type value form e r w s mod))))
+
+ (define (expand-expr type value form e r w s mod)
+ (case type
+ ((lexical)
+ (build-lexical-reference 'value s e value))
+ ((core core-form)
+ ;; apply transformer
+ (value e r w s mod))
+ ((module-ref)
+ (call-with-values (lambda () (value e r w mod))
+ (lambda (e r w s mod)
+ (expand e r w mod))))
+ ((lexical-call)
+ (expand-call
+ (let ((id (car e)))
+ (build-lexical-reference 'fun (source-annotation id)
+ (if (syntax? id)
+ (syntax->datum id)
+ id)
+ value))
+ e r w s mod))
+ ((global-call)
+ (expand-call
+ (build-global-reference (or (source-annotation (car e)) s)
+ (if (syntax? value)
+ (syntax-expression value)
+ value)
+ (or (and (syntax? value)
+ (syntax-module value))
+ mod))
+ e r w s mod))
+ ((primitive-call)
+ (syntax-case e ()
+ ((_ e ...)
+ (build-primcall s
+ value
+ (map (lambda (e) (expand e r w mod))
+ #'(e ...))))))
+ ((constant) (build-data s (strip e)))
+ ((global) (build-global-reference s value mod))
+ ((call) (expand-call (expand (car e) r w mod) e r w s mod))
+ ((begin-form)
+ (syntax-case e ()
+ ((_ e1 e2 ...) (expand-sequence #'(e1 e2 ...) r w s mod))
+ ((_)
+ (syntax-violation #f "sequence of zero expressions"
+ (source-wrap e w s mod)))))
+ ((local-syntax-form)
+ (expand-local-syntax value e r w s mod expand-sequence))
+ ((eval-when-form)
+ (syntax-case e ()
+ ((_ (x ...) e1 e2 ...)
+ (let ((when-list (parse-when-list e #'(x ...))))
+ (if (memq 'eval when-list)
+ (expand-sequence #'(e1 e2 ...) r w s mod)
+ (expand-void))))))
+ ((define-form define-syntax-form define-syntax-parameter-form)
+ (syntax-violation #f "definition in expression context, where
definitions are not allowed,"
+ (source-wrap form w s mod)))
+ ((syntax)
+ (syntax-violation #f "reference to pattern variable outside syntax form"
+ (source-wrap e w s mod)))
+ ((displaced-lexical)
+ (syntax-violation #f "reference to identifier outside its scope"
+ (source-wrap e w s mod)))
+ (else (syntax-violation #f "unexpected syntax"
(source-wrap e w s mod)))))
- ((local-syntax-form)
- (expand-local-syntax value e r w s mod expand-sequence))
- ((eval-when-form)
- (syntax-case e ()
- ((_ (x ...) e1 e2 ...)
- (let ((when-list (parse-when-list e #'(x ...))))
- (if (memq 'eval when-list)
- (expand-sequence #'(e1 e2 ...) r w s mod)
- (expand-void))))))
- ((define-form define-syntax-form define-syntax-parameter-form)
- (syntax-violation #f "definition in expression context, where
definitions are not allowed,"
- (source-wrap form w s mod)))
- ((syntax)
- (syntax-violation #f "reference to pattern variable outside syntax
form"
- (source-wrap e w s mod)))
- ((displaced-lexical)
- (syntax-violation #f "reference to identifier outside its scope"
- (source-wrap e w s mod)))
- (else (syntax-violation #f "unexpected syntax"
- (source-wrap e w s mod))))))
-
- (define expand-call
- (lambda (x e r w s mod)
- (syntax-case e ()
- ((e0 e1 ...)
- (build-call s x
- (map (lambda (e) (expand e r w mod)) #'(e1 ...)))))))
+
+ (define (expand-call x e r w s mod)
+ (syntax-case e ()
+ ((e0 e1 ...)
+ (build-call s x
+ (map (lambda (e) (expand e r w mod)) #'(e1 ...))))))
;; (What follows is my interpretation of what's going on here -- Andy)
;;
@@ -1418,59 +1362,58 @@
;; really nice if we could also annotate introduced expressions with the
;; locations corresponding to the macro definition, but that is not yet
;; possible.
- (define expand-macro
- (lambda (p e r w s rib mod)
- (define (decorate-source x)
- (source-wrap x empty-wrap s #f))
- (define (map* f x)
- (cond
- ((null? x) x)
- ((pair? x) (cons (f (car x)) (map* f (cdr x))))
- (else (f x))))
- (define rebuild-macro-output
- (lambda (x m)
- (cond ((pair? x)
- (decorate-source
- (map* (lambda (x) (rebuild-macro-output x m)) x)))
- ((syntax? x)
- (let ((w (syntax-wrap x)))
- (let ((ms (wrap-marks w)) (ss (wrap-subst w)))
- (if (and (pair? ms) (eq? (car ms) the-anti-mark))
- ;; output is from original text
- (wrap-syntax
- x
- (make-wrap (cdr ms)
- (if rib
- (cons rib (cdr ss))
- (cdr ss)))
- mod)
- ;; output introduced by macro
- (wrap-syntax
- x
- (make-wrap (cons m ms)
- (if rib
- (cons rib (cons 'shift ss))
- (cons 'shift ss)))
- mod)))))
-
- ((vector? x)
- (let* ((n (vector-length x))
- (v (make-vector n)))
- (do ((i 0 (1+ i)))
- ((= i n) v)
- (vector-set! v i
- (rebuild-macro-output (vector-ref x i) m)))
- (decorate-source v)))
- ((symbol? x)
- (syntax-violation #f "encountered raw symbol in macro output"
- (source-wrap e w (wrap-subst w) mod) x))
- (else (decorate-source x)))))
- (with-fluids ((transformer-environment
- (lambda (k) (k e r w s rib mod))))
- (rebuild-macro-output (p (source-wrap e (anti-mark w) s mod))
- (new-mark)))))
-
- (define expand-body
+ (define (expand-macro p e r w s rib mod)
+ (define (decorate-source x)
+ (source-wrap x empty-wrap s #f))
+ (define (map* f x)
+ (cond
+ ((null? x) x)
+ ((pair? x) (cons (f (car x)) (map* f (cdr x))))
+ (else (f x))))
+ (define rebuild-macro-output
+ (lambda (x m)
+ (cond ((pair? x)
+ (decorate-source
+ (map* (lambda (x) (rebuild-macro-output x m)) x)))
+ ((syntax? x)
+ (let ((w (syntax-wrap x)))
+ (let ((ms (wrap-marks w)) (ss (wrap-subst w)))
+ (if (and (pair? ms) (eq? (car ms) the-anti-mark))
+ ;; output is from original text
+ (wrap-syntax
+ x
+ (make-wrap (cdr ms)
+ (if rib
+ (cons rib (cdr ss))
+ (cdr ss)))
+ mod)
+ ;; output introduced by macro
+ (wrap-syntax
+ x
+ (make-wrap (cons m ms)
+ (if rib
+ (cons rib (cons 'shift ss))
+ (cons 'shift ss)))
+ mod)))))
+
+ ((vector? x)
+ (let* ((n (vector-length x))
+ (v (make-vector n)))
+ (do ((i 0 (1+ i)))
+ ((= i n) v)
+ (vector-set! v i
+ (rebuild-macro-output (vector-ref x i) m)))
+ (decorate-source v)))
+ ((symbol? x)
+ (syntax-violation #f "encountered raw symbol in macro output"
+ (source-wrap e w (wrap-subst w) mod) x))
+ (else (decorate-source x)))))
+ (with-fluids ((transformer-environment
+ (lambda (k) (k e r w s rib mod))))
+ (rebuild-macro-output (p (source-wrap e (anti-mark w) s mod))
+ (new-mark))))
+
+ (define (expand-body body outer-form r w mod)
;; In processing the forms of the body, we create a new, empty wrap.
;; This wrap is augmented (destructively) each time we discover that
;; the next form is a definition. This is done:
@@ -1509,399 +1452,390 @@
;; into the body.
;;
;; outer-form is fully wrapped w/source
- (lambda (body outer-form r w mod)
- (let* ((r (cons '("placeholder" . (placeholder)) r))
- (ribcage (make-empty-ribcage))
- (w (make-wrap (wrap-marks w) (cons ribcage (wrap-subst w)))))
- (let parse ((body (map (lambda (x) (cons r (wrap x w mod))) body))
- (ids '()) (labels '())
- (var-ids '()) (vars '()) (vals '()) (bindings '())
- (expand-tail-expr #f))
- (cond
- ((null? body)
- (unless expand-tail-expr
- (when (null? ids)
- (syntax-violation #f "empty body" outer-form))
- (syntax-violation #f "body should end with an expression"
outer-form))
- (unless (valid-bound-ids? ids)
- (syntax-violation
- #f "invalid or duplicate identifier in definition"
- outer-form))
- (set-cdr! r (extend-env labels bindings (cdr r)))
- (let ((src (source-annotation outer-form)))
- (let lp ((var-ids var-ids) (vars vars) (vals vals)
- (tail (expand-tail-expr)))
- (cond
- ((null? var-ids) tail)
- ((not (car var-ids))
- (lp (cdr var-ids) (cdr vars) (cdr vals)
- (make-seq src ((car vals)) tail)))
- (else
- (let ((var-ids (map (lambda (id)
- (if id (syntax->datum id) '_))
- (reverse var-ids)))
- (vars (map (lambda (var) (or var (gen-lexical '_)))
- (reverse vars)))
- (vals (map (lambda (expand-expr id)
- (if id
- (expand-expr)
- (make-seq src
- (expand-expr)
- (build-void src))))
- (reverse vals) (reverse var-ids))))
- (build-letrec src #t var-ids vars vals tail)))))))
- (expand-tail-expr
- (parse body ids labels
- (cons #f var-ids)
- (cons #f vars)
- (cons expand-tail-expr vals)
- bindings #f))
- (else
- (let ((e (cdar body)) (er (caar body)) (body (cdr body)))
- (call-with-values
- (lambda () (syntax-type e er empty-wrap (source-annotation
e) ribcage mod #f))
- (lambda (type value form e w s mod)
- (case type
- ((define-form)
- (let ((id (wrap value w mod)) (label (gen-label)))
- (let ((var (gen-var id)))
- (extend-ribcage! ribcage id label)
- (parse body
- (cons id ids) (cons label labels)
- (cons id var-ids)
- (cons var vars)
- (cons (let ((wrapped (source-wrap e w s mod)))
- (lambda ()
- (expand wrapped er empty-wrap mod)))
- vals)
- (cons (make-binding 'lexical var) bindings)
- #f))))
- ((define-syntax-form)
- (let ((id (wrap value w mod))
- (label (gen-label))
- (trans-r (macros-only-env er)))
- (extend-ribcage! ribcage id label)
- ;; As required by R6RS, evaluate the right-hand-sides
of internal
- ;; syntax definition forms and add their transformers
to the
- ;; compile-time environment immediately, so that the
newly-defined
- ;; keywords may be used in definition context within
the same
- ;; lexical contour.
- (set-cdr! r (extend-env
- (list label)
- (list (make-binding
- 'macro
- (eval-local-transformer
- (expand e trans-r w mod)
- mod)))
- (cdr r)))
- (parse body (cons id ids)
- labels var-ids vars vals bindings #f)))
- ((define-syntax-parameter-form)
- ;; Same as define-syntax-form, different binding type
though.
- (let ((id (wrap value w mod))
- (label (gen-label))
- (trans-r (macros-only-env er)))
- (extend-ribcage! ribcage id label)
- (set-cdr! r (extend-env
- (list label)
- (list (make-binding
- 'syntax-parameter
- (eval-local-transformer
- (expand e trans-r w mod)
- mod)))
- (cdr r)))
- (parse body (cons id ids)
- labels var-ids vars vals bindings #f)))
- ((begin-form)
- (syntax-case e ()
- ((_ e1 ...)
- (parse (let f ((forms #'(e1 ...)))
- (if (null? forms)
- body
- (cons (cons er (wrap (car forms) w mod))
- (f (cdr forms)))))
- ids labels var-ids vars vals bindings #f))))
- ((local-syntax-form)
- (expand-local-syntax
- value e er w s mod
- (lambda (forms er w s mod)
- (parse (let f ((forms forms))
- (if (null? forms)
- body
- (cons (cons er (wrap (car forms) w mod))
- (f (cdr forms)))))
- ids labels var-ids vars vals bindings #f))))
- (else ; An expression, not a definition.
- (let ((wrapped (source-wrap e w s mod)))
- (parse body ids labels var-ids vars vals bindings
- (lambda ()
- (expand wrapped er empty-wrap
mod)))))))))))))))
-
- (define expand-local-syntax
- (lambda (rec? e r w s mod k)
- (syntax-case e ()
- ((_ ((id val) ...) e1 e2 ...)
- (let ((ids #'(id ...)))
- (if (not (valid-bound-ids? ids))
- (syntax-violation #f "duplicate bound keyword" e)
- (let ((labels (gen-labels ids)))
- (let ((new-w (make-binding-wrap ids labels w)))
- (k #'(e1 e2 ...)
- (extend-env
- labels
- (let ((w (if rec? new-w w))
- (trans-r (macros-only-env r)))
- (map (lambda (x)
- (make-binding 'macro
- (eval-local-transformer
- (expand x trans-r w mod)
- mod)))
- #'(val ...)))
- r)
- new-w
- s
- mod))))))
- (_ (syntax-violation #f "bad local syntax definition"
- (source-wrap e w s mod))))))
-
- (define eval-local-transformer
- (lambda (expanded mod)
- (let ((p (local-eval expanded mod)))
- (if (procedure? p)
- p
- (syntax-violation #f "nonprocedure transformer" p)))))
-
- (define expand-void
- (lambda ()
- (build-void no-source)))
-
- (define ellipsis?
- (lambda (e r mod)
- (and (nonsymbol-id? e)
- ;; If there is a binding for the special identifier
- ;; #{ $sc-ellipsis }# in the lexical environment of E,
- ;; and if the associated binding type is 'ellipsis',
- ;; then the binding's value specifies the custom ellipsis
- ;; identifier within that lexical environment, and the
- ;; comparison is done using 'bound-id=?'.
- (call-with-values
- (lambda () (resolve-identifier
- (make-syntax '#{ $sc-ellipsis }#
- (syntax-wrap e)
- (or (syntax-module e) mod)
- #f)
- empty-wrap r mod #f))
- (lambda (type value mod)
- (if (eq? type 'ellipsis)
- (bound-id=? e value)
- (free-id=? e #'(... ...))))))))
-
- (define lambda-formals
- (lambda (orig-args)
- (define (req args rreq)
- (syntax-case args ()
- (()
- (check (reverse rreq) #f))
- ((a . b) (id? #'a)
- (req #'b (cons #'a rreq)))
- (r (id? #'r)
- (check (reverse rreq) #'r))
- (else
- (syntax-violation 'lambda "invalid argument list" orig-args args))))
- (define (check req rest)
- (cond
- ((distinct-bound-ids? (if rest (cons rest req) req))
- (values req #f rest #f))
- (else
- (syntax-violation 'lambda "duplicate identifier in argument list"
- orig-args))))
- (req orig-args '())))
-
- (define expand-simple-lambda
- (lambda (e r w s mod req rest meta body)
- (let* ((ids (if rest (append req (list rest)) req))
- (vars (map gen-var ids))
- (labels (gen-labels ids)))
- (build-simple-lambda
- s
- (map syntax->datum req) (and rest (syntax->datum rest)) vars
- meta
- (expand-body body (source-wrap e w s mod)
- (extend-var-env labels vars r)
- (make-binding-wrap ids labels w)
- mod)))))
-
- (define lambda*-formals
- (lambda (orig-args)
- (define (req args rreq)
- (syntax-case args ()
- (()
- (check (reverse rreq) '() #f '()))
- ((a . b) (id? #'a)
- (req #'b (cons #'a rreq)))
- ((a . b) (eq? (syntax->datum #'a) #:optional)
- (opt #'b (reverse rreq) '()))
- ((a . b) (eq? (syntax->datum #'a) #:key)
- (key #'b (reverse rreq) '() '()))
- ((a b) (eq? (syntax->datum #'a) #:rest)
- (rest #'b (reverse rreq) '() '()))
- (r (id? #'r)
- (rest #'r (reverse rreq) '() '()))
- (else
- (syntax-violation 'lambda* "invalid argument list" orig-args
args))))
- (define (opt args req ropt)
- (syntax-case args ()
- (()
- (check req (reverse ropt) #f '()))
- ((a . b) (id? #'a)
- (opt #'b req (cons #'(a #f) ropt)))
- (((a init) . b) (id? #'a)
- (opt #'b req (cons #'(a init) ropt)))
- ((a . b) (eq? (syntax->datum #'a) #:key)
- (key #'b req (reverse ropt) '()))
- ((a b) (eq? (syntax->datum #'a) #:rest)
- (rest #'b req (reverse ropt) '()))
- (r (id? #'r)
- (rest #'r req (reverse ropt) '()))
- (else
- (syntax-violation 'lambda* "invalid optional argument list"
- orig-args args))))
- (define (key args req opt rkey)
- (syntax-case args ()
- (()
- (check req opt #f (cons #f (reverse rkey))))
- ((a . b) (id? #'a)
- (with-syntax ((k (symbol->keyword (syntax->datum #'a))))
- (key #'b req opt (cons #'(k a #f) rkey))))
- (((a init) . b) (id? #'a)
- (with-syntax ((k (symbol->keyword (syntax->datum #'a))))
- (key #'b req opt (cons #'(k a init) rkey))))
- (((a init k) . b) (and (id? #'a)
- (keyword? (syntax->datum #'k)))
- (key #'b req opt (cons #'(k a init) rkey)))
- ((aok) (eq? (syntax->datum #'aok) #:allow-other-keys)
- (check req opt #f (cons #t (reverse rkey))))
- ((aok a b) (and (eq? (syntax->datum #'aok) #:allow-other-keys)
- (eq? (syntax->datum #'a) #:rest))
- (rest #'b req opt (cons #t (reverse rkey))))
- ((aok . r) (and (eq? (syntax->datum #'aok) #:allow-other-keys)
- (id? #'r))
- (rest #'r req opt (cons #t (reverse rkey))))
- ((a b) (eq? (syntax->datum #'a) #:rest)
- (rest #'b req opt (cons #f (reverse rkey))))
- (r (id? #'r)
- (rest #'r req opt (cons #f (reverse rkey))))
- (else
- (syntax-violation 'lambda* "invalid keyword argument list"
- orig-args args))))
- (define (rest args req opt kw)
- (syntax-case args ()
- (r (id? #'r)
- (check req opt #'r kw))
- (else
- (syntax-violation 'lambda* "invalid rest argument"
- orig-args args))))
- (define (check req opt rest kw)
- (cond
- ((distinct-bound-ids?
- (append req (map car opt) (if rest (list rest) '())
- (if (pair? kw) (map cadr (cdr kw)) '())))
- (values req opt rest kw))
- (else
- (syntax-violation 'lambda* "duplicate identifier in argument list"
- orig-args))))
- (req orig-args '())))
-
- (define expand-lambda-case
- (lambda (e r w s mod get-formals clauses)
- (define (parse-req req opt rest kw body)
- (let ((vars (map gen-var req))
- (labels (gen-labels req)))
- (let ((r* (extend-var-env labels vars r))
- (w* (make-binding-wrap req labels w)))
- (parse-opt (map syntax->datum req)
- opt rest kw body (reverse vars) r* w* '() '()))))
- (define (parse-opt req opt rest kw body vars r* w* out inits)
+ (let* ((r (cons '("placeholder" . (placeholder)) r))
+ (ribcage (make-empty-ribcage))
+ (w (make-wrap (wrap-marks w) (cons ribcage (wrap-subst w)))))
+ (let parse ((body (map (lambda (x) (cons r (wrap x w mod))) body))
+ (ids '()) (labels '())
+ (var-ids '()) (vars '()) (vals '()) (bindings '())
+ (expand-tail-expr #f))
(cond
- ((pair? opt)
- (syntax-case (car opt) ()
- ((id i)
- (let* ((v (gen-var #'id))
- (l (gen-labels (list v)))
- (r** (extend-var-env l (list v) r*))
- (w** (make-binding-wrap (list #'id) l w*)))
- (parse-opt req (cdr opt) rest kw body (cons v vars)
- r** w** (cons (syntax->datum #'id) out)
- (cons (expand #'i r* w* mod) inits))))))
- (rest
- (let* ((v (gen-var rest))
- (l (gen-labels (list v)))
- (r* (extend-var-env l (list v) r*))
- (w* (make-binding-wrap (list rest) l w*)))
- (parse-kw req (if (pair? out) (reverse out) #f)
- (syntax->datum rest)
- (if (pair? kw) (cdr kw) kw)
- body (cons v vars) r* w*
- (if (pair? kw) (car kw) #f)
- '() inits)))
+ ((null? body)
+ (unless expand-tail-expr
+ (when (null? ids)
+ (syntax-violation #f "empty body" outer-form))
+ (syntax-violation #f "body should end with an expression"
outer-form))
+ (unless (valid-bound-ids? ids)
+ (syntax-violation
+ #f "invalid or duplicate identifier in definition"
+ outer-form))
+ (set-cdr! r (extend-env labels bindings (cdr r)))
+ (let ((src (source-annotation outer-form)))
+ (let lp ((var-ids var-ids) (vars vars) (vals vals)
+ (tail (expand-tail-expr)))
+ (cond
+ ((null? var-ids) tail)
+ ((not (car var-ids))
+ (lp (cdr var-ids) (cdr vars) (cdr vals)
+ (make-seq src ((car vals)) tail)))
+ (else
+ (let ((var-ids (map (lambda (id)
+ (if id (syntax->datum id) '_))
+ (reverse var-ids)))
+ (vars (map (lambda (var) (or var (gen-lexical '_)))
+ (reverse vars)))
+ (vals (map (lambda (expand-expr id)
+ (if id
+ (expand-expr)
+ (make-seq src
+ (expand-expr)
+ (build-void src))))
+ (reverse vals) (reverse var-ids))))
+ (build-letrec src #t var-ids vars vals tail)))))))
+ (expand-tail-expr
+ (parse body ids labels
+ (cons #f var-ids)
+ (cons #f vars)
+ (cons expand-tail-expr vals)
+ bindings #f))
(else
- (parse-kw req (if (pair? out) (reverse out) #f) #f
+ (let ((e (cdar body)) (er (caar body)) (body (cdr body)))
+ (call-with-values
+ (lambda () (syntax-type e er empty-wrap (source-annotation e)
ribcage mod #f))
+ (lambda (type value form e w s mod)
+ (case type
+ ((define-form)
+ (let ((id (wrap value w mod)) (label (gen-label)))
+ (let ((var (gen-var id)))
+ (extend-ribcage! ribcage id label)
+ (parse body
+ (cons id ids) (cons label labels)
+ (cons id var-ids)
+ (cons var vars)
+ (cons (let ((wrapped (source-wrap e w s mod)))
+ (lambda ()
+ (expand wrapped er empty-wrap mod)))
+ vals)
+ (cons (make-binding 'lexical var) bindings)
+ #f))))
+ ((define-syntax-form)
+ (let ((id (wrap value w mod))
+ (label (gen-label))
+ (trans-r (macros-only-env er)))
+ (extend-ribcage! ribcage id label)
+ ;; As required by R6RS, evaluate the right-hand-sides of
internal
+ ;; syntax definition forms and add their transformers to
the
+ ;; compile-time environment immediately, so that the
newly-defined
+ ;; keywords may be used in definition context within the
same
+ ;; lexical contour.
+ (set-cdr! r (extend-env
+ (list label)
+ (list (make-binding
+ 'macro
+ (eval-local-transformer
+ (expand e trans-r w mod)
+ mod)))
+ (cdr r)))
+ (parse body (cons id ids)
+ labels var-ids vars vals bindings #f)))
+ ((define-syntax-parameter-form)
+ ;; Same as define-syntax-form, different binding type
though.
+ (let ((id (wrap value w mod))
+ (label (gen-label))
+ (trans-r (macros-only-env er)))
+ (extend-ribcage! ribcage id label)
+ (set-cdr! r (extend-env
+ (list label)
+ (list (make-binding
+ 'syntax-parameter
+ (eval-local-transformer
+ (expand e trans-r w mod)
+ mod)))
+ (cdr r)))
+ (parse body (cons id ids)
+ labels var-ids vars vals bindings #f)))
+ ((begin-form)
+ (syntax-case e ()
+ ((_ e1 ...)
+ (parse (let f ((forms #'(e1 ...)))
+ (if (null? forms)
+ body
+ (cons (cons er (wrap (car forms) w mod))
+ (f (cdr forms)))))
+ ids labels var-ids vars vals bindings #f))))
+ ((local-syntax-form)
+ (expand-local-syntax
+ value e er w s mod
+ (lambda (forms er w s mod)
+ (parse (let f ((forms forms))
+ (if (null? forms)
+ body
+ (cons (cons er (wrap (car forms) w mod))
+ (f (cdr forms)))))
+ ids labels var-ids vars vals bindings #f))))
+ (else ; An expression, not a definition.
+ (let ((wrapped (source-wrap e w s mod)))
+ (parse body ids labels var-ids vars vals bindings
+ (lambda ()
+ (expand wrapped er empty-wrap mod))))))))))))))
+
+ (define (expand-local-syntax rec? e r w s mod k)
+ (syntax-case e ()
+ ((_ ((id val) ...) e1 e2 ...)
+ (let ((ids #'(id ...)))
+ (if (not (valid-bound-ids? ids))
+ (syntax-violation #f "duplicate bound keyword" e)
+ (let ((labels (gen-labels ids)))
+ (let ((new-w (make-binding-wrap ids labels w)))
+ (k #'(e1 e2 ...)
+ (extend-env
+ labels
+ (let ((w (if rec? new-w w))
+ (trans-r (macros-only-env r)))
+ (map (lambda (x)
+ (make-binding 'macro
+ (eval-local-transformer
+ (expand x trans-r w mod)
+ mod)))
+ #'(val ...)))
+ r)
+ new-w
+ s
+ mod))))))
+ (_ (syntax-violation #f "bad local syntax definition"
+ (source-wrap e w s mod)))))
+
+ (define (eval-local-transformer expanded mod)
+ (let ((p (local-eval expanded mod)))
+ (if (procedure? p)
+ p
+ (syntax-violation #f "nonprocedure transformer" p))))
+
+ (define (expand-void)
+ (build-void no-source))
+
+ (define (ellipsis? e r mod)
+ (and (nonsymbol-id? e)
+ ;; If there is a binding for the special identifier
+ ;; #{ $sc-ellipsis }# in the lexical environment of E,
+ ;; and if the associated binding type is 'ellipsis',
+ ;; then the binding's value specifies the custom ellipsis
+ ;; identifier within that lexical environment, and the
+ ;; comparison is done using 'bound-id=?'.
+ (call-with-values
+ (lambda () (resolve-identifier
+ (make-syntax '#{ $sc-ellipsis }#
+ (syntax-wrap e)
+ (or (syntax-module e) mod)
+ #f)
+ empty-wrap r mod #f))
+ (lambda (type value mod)
+ (if (eq? type 'ellipsis)
+ (bound-id=? e value)
+ (free-id=? e #'(... ...)))))))
+
+ (define (lambda-formals orig-args)
+ (define (req args rreq)
+ (syntax-case args ()
+ (()
+ (check (reverse rreq) #f))
+ ((a . b) (id? #'a)
+ (req #'b (cons #'a rreq)))
+ (r (id? #'r)
+ (check (reverse rreq) #'r))
+ (else
+ (syntax-violation 'lambda "invalid argument list" orig-args args))))
+ (define (check req rest)
+ (cond
+ ((distinct-bound-ids? (if rest (cons rest req) req))
+ (values req #f rest #f))
+ (else
+ (syntax-violation 'lambda "duplicate identifier in argument list"
+ orig-args))))
+ (req orig-args '()))
+
+ (define (expand-simple-lambda e r w s mod req rest meta body)
+ (let* ((ids (if rest (append req (list rest)) req))
+ (vars (map gen-var ids))
+ (labels (gen-labels ids)))
+ (build-simple-lambda
+ s
+ (map syntax->datum req) (and rest (syntax->datum rest)) vars
+ meta
+ (expand-body body (source-wrap e w s mod)
+ (extend-var-env labels vars r)
+ (make-binding-wrap ids labels w)
+ mod))))
+
+ (define (lambda*-formals orig-args)
+ (define (req args rreq)
+ (syntax-case args ()
+ (()
+ (check (reverse rreq) '() #f '()))
+ ((a . b) (id? #'a)
+ (req #'b (cons #'a rreq)))
+ ((a . b) (eq? (syntax->datum #'a) #:optional)
+ (opt #'b (reverse rreq) '()))
+ ((a . b) (eq? (syntax->datum #'a) #:key)
+ (key #'b (reverse rreq) '() '()))
+ ((a b) (eq? (syntax->datum #'a) #:rest)
+ (rest #'b (reverse rreq) '() '()))
+ (r (id? #'r)
+ (rest #'r (reverse rreq) '() '()))
+ (else
+ (syntax-violation 'lambda* "invalid argument list" orig-args args))))
+ (define (opt args req ropt)
+ (syntax-case args ()
+ (()
+ (check req (reverse ropt) #f '()))
+ ((a . b) (id? #'a)
+ (opt #'b req (cons #'(a #f) ropt)))
+ (((a init) . b) (id? #'a)
+ (opt #'b req (cons #'(a init) ropt)))
+ ((a . b) (eq? (syntax->datum #'a) #:key)
+ (key #'b req (reverse ropt) '()))
+ ((a b) (eq? (syntax->datum #'a) #:rest)
+ (rest #'b req (reverse ropt) '()))
+ (r (id? #'r)
+ (rest #'r req (reverse ropt) '()))
+ (else
+ (syntax-violation 'lambda* "invalid optional argument list"
+ orig-args args))))
+ (define (key args req opt rkey)
+ (syntax-case args ()
+ (()
+ (check req opt #f (cons #f (reverse rkey))))
+ ((a . b) (id? #'a)
+ (with-syntax ((k (symbol->keyword (syntax->datum #'a))))
+ (key #'b req opt (cons #'(k a #f) rkey))))
+ (((a init) . b) (id? #'a)
+ (with-syntax ((k (symbol->keyword (syntax->datum #'a))))
+ (key #'b req opt (cons #'(k a init) rkey))))
+ (((a init k) . b) (and (id? #'a)
+ (keyword? (syntax->datum #'k)))
+ (key #'b req opt (cons #'(k a init) rkey)))
+ ((aok) (eq? (syntax->datum #'aok) #:allow-other-keys)
+ (check req opt #f (cons #t (reverse rkey))))
+ ((aok a b) (and (eq? (syntax->datum #'aok) #:allow-other-keys)
+ (eq? (syntax->datum #'a) #:rest))
+ (rest #'b req opt (cons #t (reverse rkey))))
+ ((aok . r) (and (eq? (syntax->datum #'aok) #:allow-other-keys)
+ (id? #'r))
+ (rest #'r req opt (cons #t (reverse rkey))))
+ ((a b) (eq? (syntax->datum #'a) #:rest)
+ (rest #'b req opt (cons #f (reverse rkey))))
+ (r (id? #'r)
+ (rest #'r req opt (cons #f (reverse rkey))))
+ (else
+ (syntax-violation 'lambda* "invalid keyword argument list"
+ orig-args args))))
+ (define (rest args req opt kw)
+ (syntax-case args ()
+ (r (id? #'r)
+ (check req opt #'r kw))
+ (else
+ (syntax-violation 'lambda* "invalid rest argument"
+ orig-args args))))
+ (define (check req opt rest kw)
+ (cond
+ ((distinct-bound-ids?
+ (append req (map car opt) (if rest (list rest) '())
+ (if (pair? kw) (map cadr (cdr kw)) '())))
+ (values req opt rest kw))
+ (else
+ (syntax-violation 'lambda* "duplicate identifier in argument list"
+ orig-args))))
+ (req orig-args '()))
+
+ (define (expand-lambda-case e r w s mod get-formals clauses)
+ (define (parse-req req opt rest kw body)
+ (let ((vars (map gen-var req))
+ (labels (gen-labels req)))
+ (let ((r* (extend-var-env labels vars r))
+ (w* (make-binding-wrap req labels w)))
+ (parse-opt (map syntax->datum req)
+ opt rest kw body (reverse vars) r* w* '() '()))))
+ (define (parse-opt req opt rest kw body vars r* w* out inits)
+ (cond
+ ((pair? opt)
+ (syntax-case (car opt) ()
+ ((id i)
+ (let* ((v (gen-var #'id))
+ (l (gen-labels (list v)))
+ (r** (extend-var-env l (list v) r*))
+ (w** (make-binding-wrap (list #'id) l w*)))
+ (parse-opt req (cdr opt) rest kw body (cons v vars)
+ r** w** (cons (syntax->datum #'id) out)
+ (cons (expand #'i r* w* mod) inits))))))
+ (rest
+ (let* ((v (gen-var rest))
+ (l (gen-labels (list v)))
+ (r* (extend-var-env l (list v) r*))
+ (w* (make-binding-wrap (list rest) l w*)))
+ (parse-kw req (if (pair? out) (reverse out) #f)
+ (syntax->datum rest)
(if (pair? kw) (cdr kw) kw)
- body vars r* w*
+ body (cons v vars) r* w*
(if (pair? kw) (car kw) #f)
- '() inits))))
- (define (parse-kw req opt rest kw body vars r* w* aok out inits)
- (cond
- ((pair? kw)
- (syntax-case (car kw) ()
- ((k id i)
- (let* ((v (gen-var #'id))
- (l (gen-labels (list v)))
- (r** (extend-var-env l (list v) r*))
- (w** (make-binding-wrap (list #'id) l w*)))
- (parse-kw req opt rest (cdr kw) body (cons v vars)
- r** w** aok
- (cons (list (syntax->datum #'k)
- (syntax->datum #'id)
- v)
- out)
- (cons (expand #'i r* w* mod) inits))))))
- (else
- (parse-body req opt rest
- (if (or aok (pair? out)) (cons aok (reverse out)) #f)
- body (reverse vars) r* w* (reverse inits) '()))))
- (define (parse-body req opt rest kw body vars r* w* inits meta)
- (syntax-case body ()
- ((docstring e1 e2 ...) (string? (syntax->datum #'docstring))
- (parse-body req opt rest kw #'(e1 e2 ...) vars r* w* inits
- (append meta
- `((documentation
- . ,(syntax->datum #'docstring))))))
- ((#((k . v) ...) e1 e2 ...)
- (parse-body req opt rest kw #'(e1 e2 ...) vars r* w* inits
- (append meta (syntax->datum #'((k . v) ...)))))
- ((e1 e2 ...)
- (values meta req opt rest kw inits vars
- (expand-body #'(e1 e2 ...) (source-wrap e w s mod)
- r* w* mod)))))
-
- (syntax-case clauses ()
- (() (values '() #f))
- (((args e1 e2 ...) (args* e1* e2* ...) ...)
- (call-with-values (lambda () (get-formals #'args))
- (lambda (req opt rest kw)
- (call-with-values (lambda ()
- (parse-req req opt rest kw #'(e1 e2 ...)))
- (lambda (meta req opt rest kw inits vars body)
- (call-with-values
- (lambda ()
- (expand-lambda-case e r w s mod get-formals
- #'((args* e1* e2* ...) ...)))
- (lambda (meta* else*)
- (values
- (append meta meta*)
- (build-lambda-case s req opt rest kw inits vars
- body else*))))))))))))
+ '() inits)))
+ (else
+ (parse-kw req (if (pair? out) (reverse out) #f) #f
+ (if (pair? kw) (cdr kw) kw)
+ body vars r* w*
+ (if (pair? kw) (car kw) #f)
+ '() inits))))
+ (define (parse-kw req opt rest kw body vars r* w* aok out inits)
+ (cond
+ ((pair? kw)
+ (syntax-case (car kw) ()
+ ((k id i)
+ (let* ((v (gen-var #'id))
+ (l (gen-labels (list v)))
+ (r** (extend-var-env l (list v) r*))
+ (w** (make-binding-wrap (list #'id) l w*)))
+ (parse-kw req opt rest (cdr kw) body (cons v vars)
+ r** w** aok
+ (cons (list (syntax->datum #'k)
+ (syntax->datum #'id)
+ v)
+ out)
+ (cons (expand #'i r* w* mod) inits))))))
+ (else
+ (parse-body req opt rest
+ (if (or aok (pair? out)) (cons aok (reverse out)) #f)
+ body (reverse vars) r* w* (reverse inits) '()))))
+ (define (parse-body req opt rest kw body vars r* w* inits meta)
+ (syntax-case body ()
+ ((docstring e1 e2 ...) (string? (syntax->datum #'docstring))
+ (parse-body req opt rest kw #'(e1 e2 ...) vars r* w* inits
+ (append meta
+ `((documentation
+ . ,(syntax->datum #'docstring))))))
+ ((#((k . v) ...) e1 e2 ...)
+ (parse-body req opt rest kw #'(e1 e2 ...) vars r* w* inits
+ (append meta (syntax->datum #'((k . v) ...)))))
+ ((e1 e2 ...)
+ (values meta req opt rest kw inits vars
+ (expand-body #'(e1 e2 ...) (source-wrap e w s mod)
+ r* w* mod)))))
+
+ (syntax-case clauses ()
+ (() (values '() #f))
+ (((args e1 e2 ...) (args* e1* e2* ...) ...)
+ (call-with-values (lambda () (get-formals #'args))
+ (lambda (req opt rest kw)
+ (call-with-values (lambda ()
+ (parse-req req opt rest kw #'(e1 e2 ...)))
+ (lambda (meta req opt rest kw inits vars body)
+ (call-with-values
+ (lambda ()
+ (expand-lambda-case e r w s mod get-formals
+ #'((args* e1* e2* ...) ...)))
+ (lambda (meta* else*)
+ (values
+ (append meta meta*)
+ (build-lambda-case s req opt rest kw inits vars
+ body else*)))))))))))
;; data
@@ -1924,26 +1858,24 @@
;; lexical variables
- (define gen-var
- (lambda (id)
- (let ((id (if (syntax? id) (syntax-expression id) id)))
- (gen-lexical id))))
+ (define (gen-var id)
+ (let ((id (if (syntax? id) (syntax-expression id) id)))
+ (gen-lexical id)))
;; appears to return a reversed list
- (define lambda-var-list
- (lambda (vars)
- (let lvl ((vars vars) (ls '()) (w empty-wrap))
- (cond
- ((pair? vars) (lvl (cdr vars) (cons (wrap (car vars) w #f) ls) w))
- ((id? vars) (cons (wrap vars w #f) ls))
- ((null? vars) ls)
- ((syntax? vars)
- (lvl (syntax-expression vars)
- ls
- (join-wraps w (syntax-wrap vars))))
- ;; include anything else to be caught by subsequent error
- ;; checking
- (else (cons vars ls))))))
+ (define (lambda-var-list vars)
+ (let lvl ((vars vars) (ls '()) (w empty-wrap))
+ (cond
+ ((pair? vars) (lvl (cdr vars) (cons (wrap (car vars) w #f) ls) w))
+ ((id? vars) (cons (wrap vars w #f) ls))
+ ((null? vars) ls)
+ ((syntax? vars)
+ (lvl (syntax-expression vars)
+ ls
+ (join-wraps w (syntax-wrap vars))))
+ ;; include anything else to be caught by subsequent error
+ ;; checking
+ (else (cons vars ls)))))
;; core transformers
@@ -2006,156 +1938,148 @@
(global-extend
'core 'syntax
(let ()
- (define gen-syntax
- (lambda (src e r maps ellipsis? mod)
- (if (id? e)
- (call-with-values (lambda ()
- (resolve-identifier e empty-wrap r mod #f))
- (lambda (type value mod)
- (case type
- ((syntax)
- (call-with-values
- (lambda () (gen-ref src (car value) (cdr value) maps))
- (lambda (var maps)
- (values `(ref ,var) maps))))
- (else
- (if (ellipsis? e r mod)
- (syntax-violation 'syntax "misplaced ellipsis" src)
- (values `(quote ,e) maps))))))
- (syntax-case e ()
- ((dots e)
- (ellipsis? #'dots r mod)
- (gen-syntax src #'e r maps (lambda (e r mod) #f) mod))
- ((x dots . y)
- ;; this could be about a dozen lines of code, except that we
- ;; choose to handle #'(x ... ...) forms
- (ellipsis? #'dots r mod)
- (let f ((y #'y)
- (k (lambda (maps)
- (call-with-values
- (lambda ()
- (gen-syntax src #'x r
- (cons '() maps) ellipsis? mod))
- (lambda (x maps)
- (if (null? (car maps))
- (syntax-violation 'syntax "extra ellipsis"
- src)
- (values (gen-map x (car maps))
- (cdr maps))))))))
- (syntax-case y ()
- ((dots . y)
- (ellipsis? #'dots r mod)
- (f #'y
- (lambda (maps)
- (call-with-values
- (lambda () (k (cons '() maps)))
- (lambda (x maps)
- (if (null? (car maps))
- (syntax-violation 'syntax "extra ellipsis"
src)
- (values (gen-mappend x (car maps))
- (cdr maps))))))))
- (_ (call-with-values
- (lambda () (gen-syntax src y r maps ellipsis? mod))
- (lambda (y maps)
+ (define (gen-syntax src e r maps ellipsis? mod)
+ (if (id? e)
+ (call-with-values (lambda ()
+ (resolve-identifier e empty-wrap r mod #f))
+ (lambda (type value mod)
+ (case type
+ ((syntax)
+ (call-with-values
+ (lambda () (gen-ref src (car value) (cdr value) maps))
+ (lambda (var maps)
+ (values `(ref ,var) maps))))
+ (else
+ (if (ellipsis? e r mod)
+ (syntax-violation 'syntax "misplaced ellipsis" src)
+ (values `(quote ,e) maps))))))
+ (syntax-case e ()
+ ((dots e)
+ (ellipsis? #'dots r mod)
+ (gen-syntax src #'e r maps (lambda (e r mod) #f) mod))
+ ((x dots . y)
+ ;; this could be about a dozen lines of code, except that we
+ ;; choose to handle #'(x ... ...) forms
+ (ellipsis? #'dots r mod)
+ (let f ((y #'y)
+ (k (lambda (maps)
(call-with-values
- (lambda () (k maps))
+ (lambda ()
+ (gen-syntax src #'x r
+ (cons '() maps) ellipsis? mod))
(lambda (x maps)
- (values (gen-append x y) maps)))))))))
- ((x . y)
- (call-with-values
- (lambda () (gen-syntax src #'x r maps ellipsis? mod))
- (lambda (x maps)
- (call-with-values
- (lambda () (gen-syntax src #'y r maps ellipsis? mod))
- (lambda (y maps) (values (gen-cons x y) maps))))))
- (#(e1 e2 ...)
- (call-with-values
- (lambda ()
- (gen-syntax src #'(e1 e2 ...) r maps ellipsis? mod))
- (lambda (e maps) (values (gen-vector e) maps))))
- (x (eq? (syntax->datum #'x) #nil) (values '(quote #nil) maps))
- (() (values '(quote ()) maps))
- (_ (values `(quote ,e) maps))))))
-
- (define gen-ref
- (lambda (src var level maps)
- (if (= level 0)
- (values var maps)
- (if (null? maps)
- (syntax-violation 'syntax "missing ellipsis" src)
- (call-with-values
- (lambda () (gen-ref src var (1- level) (cdr maps)))
- (lambda (outer-var outer-maps)
- (let ((b (assq outer-var (car maps))))
- (if b
- (values (cdr b) maps)
- (let ((inner-var (gen-var 'tmp)))
- (values inner-var
- (cons (cons (cons outer-var inner-var)
- (car maps))
- outer-maps)))))))))))
-
- (define gen-mappend
- (lambda (e map-env)
- `(apply (primitive append) ,(gen-map e map-env))))
-
- (define gen-map
- (lambda (e map-env)
- (let ((formals (map cdr map-env))
- (actuals (map (lambda (x) `(ref ,(car x))) map-env)))
- (cond
- ((eq? (car e) 'ref)
- ;; identity map equivalence:
- ;; (map (lambda (x) x) y) == y
- (car actuals))
- ((and-map
- (lambda (x) (and (eq? (car x) 'ref) (memq (cadr x) formals)))
- (cdr e))
- ;; eta map equivalence:
- ;; (map (lambda (x ...) (f x ...)) y ...) == (map f y ...)
- `(map (primitive ,(car e))
- ,@(map (let ((r (map cons formals actuals)))
- (lambda (x) (cdr (assq (cadr x) r))))
- (cdr e))))
- (else `(map (lambda ,formals ,e) ,@actuals))))))
-
- (define gen-cons
- (lambda (x y)
- (case (car y)
- ((quote)
- (if (eq? (car x) 'quote)
- `(quote (,(cadr x) . ,(cadr y)))
- (if (eq? (cadr y) '())
- `(list ,x)
- `(cons ,x ,y))))
- ((list) `(list ,x ,@(cdr y)))
- (else `(cons ,x ,y)))))
-
- (define gen-append
- (lambda (x y)
- (if (equal? y '(quote ()))
- x
- `(append ,x ,y))))
-
- (define gen-vector
- (lambda (x)
+ (if (null? (car maps))
+ (syntax-violation 'syntax "extra ellipsis"
+ src)
+ (values (gen-map x (car maps))
+ (cdr maps))))))))
+ (syntax-case y ()
+ ((dots . y)
+ (ellipsis? #'dots r mod)
+ (f #'y
+ (lambda (maps)
+ (call-with-values
+ (lambda () (k (cons '() maps)))
+ (lambda (x maps)
+ (if (null? (car maps))
+ (syntax-violation 'syntax "extra ellipsis" src)
+ (values (gen-mappend x (car maps))
+ (cdr maps))))))))
+ (_ (call-with-values
+ (lambda () (gen-syntax src y r maps ellipsis? mod))
+ (lambda (y maps)
+ (call-with-values
+ (lambda () (k maps))
+ (lambda (x maps)
+ (values (gen-append x y) maps)))))))))
+ ((x . y)
+ (call-with-values
+ (lambda () (gen-syntax src #'x r maps ellipsis? mod))
+ (lambda (x maps)
+ (call-with-values
+ (lambda () (gen-syntax src #'y r maps ellipsis? mod))
+ (lambda (y maps) (values (gen-cons x y) maps))))))
+ (#(e1 e2 ...)
+ (call-with-values
+ (lambda ()
+ (gen-syntax src #'(e1 e2 ...) r maps ellipsis? mod))
+ (lambda (e maps) (values (gen-vector e) maps))))
+ (x (eq? (syntax->datum #'x) #nil) (values '(quote #nil) maps))
+ (() (values '(quote ()) maps))
+ (_ (values `(quote ,e) maps)))))
+
+ (define (gen-ref src var level maps)
+ (if (= level 0)
+ (values var maps)
+ (if (null? maps)
+ (syntax-violation 'syntax "missing ellipsis" src)
+ (call-with-values
+ (lambda () (gen-ref src var (1- level) (cdr maps)))
+ (lambda (outer-var outer-maps)
+ (let ((b (assq outer-var (car maps))))
+ (if b
+ (values (cdr b) maps)
+ (let ((inner-var (gen-var 'tmp)))
+ (values inner-var
+ (cons (cons (cons outer-var inner-var)
+ (car maps))
+ outer-maps))))))))))
+
+ (define (gen-mappend e map-env)
+ `(apply (primitive append) ,(gen-map e map-env)))
+
+ (define (gen-map e map-env)
+ (let ((formals (map cdr map-env))
+ (actuals (map (lambda (x) `(ref ,(car x))) map-env)))
(cond
- ((eq? (car x) 'list) `(vector ,@(cdr x)))
- ((eq? (car x) 'quote) `(quote #(,@(cadr x))))
- (else `(list->vector ,x)))))
-
-
- (define regen
- (lambda (x)
- (case (car x)
- ((ref) (build-lexical-reference 'value no-source (cadr x) (cadr x)))
- ((primitive) (build-primref no-source (cadr x)))
- ((quote) (build-data no-source (cadr x)))
- ((lambda)
- (if (list? (cadr x))
- (build-simple-lambda no-source (cadr x) #f (cadr x) '() (regen
(caddr x)))
- (error "how did we get here" x)))
- (else (build-primcall no-source (car x) (map regen (cdr x)))))))
+ ((eq? (car e) 'ref)
+ ;; identity map equivalence:
+ ;; (map (lambda (x) x) y) == y
+ (car actuals))
+ ((and-map
+ (lambda (x) (and (eq? (car x) 'ref) (memq (cadr x) formals)))
+ (cdr e))
+ ;; eta map equivalence:
+ ;; (map (lambda (x ...) (f x ...)) y ...) == (map f y ...)
+ `(map (primitive ,(car e))
+ ,@(map (let ((r (map cons formals actuals)))
+ (lambda (x) (cdr (assq (cadr x) r))))
+ (cdr e))))
+ (else `(map (lambda ,formals ,e) ,@actuals)))))
+
+ (define (gen-cons x y)
+ (case (car y)
+ ((quote)
+ (if (eq? (car x) 'quote)
+ `(quote (,(cadr x) . ,(cadr y)))
+ (if (eq? (cadr y) '())
+ `(list ,x)
+ `(cons ,x ,y))))
+ ((list) `(list ,x ,@(cdr y)))
+ (else `(cons ,x ,y))))
+
+ (define (gen-append x y)
+ (if (equal? y '(quote ()))
+ x
+ `(append ,x ,y)))
+
+ (define (gen-vector x)
+ (cond
+ ((eq? (car x) 'list) `(vector ,@(cdr x)))
+ ((eq? (car x) 'quote) `(quote #(,@(cadr x))))
+ (else `(list->vector ,x))))
+
+
+ (define (regen x)
+ (case (car x)
+ ((ref) (build-lexical-reference 'value no-source (cadr x) (cadr x)))
+ ((primitive) (build-primref no-source (cadr x)))
+ ((quote) (build-data no-source (cadr x)))
+ ((lambda)
+ (if (list? (cadr x))
+ (build-simple-lambda no-source (cadr x) #f (cadr x) '() (regen
(caddr x)))
+ (error "how did we get here" x)))
+ (else (build-primcall no-source (car x) (map regen (cdr x))))))
(lambda (e r w s mod)
(let ((e (source-wrap e w s mod)))
@@ -2394,24 +2318,23 @@
(global-extend 'module-ref '@@
(lambda (e r w mod)
- (define remodulate
- (lambda (x mod)
- (cond ((pair? x)
- (cons (remodulate (car x) mod)
- (remodulate (cdr x) mod)))
- ((syntax? x)
- (make-syntax
- (remodulate (syntax-expression x) mod)
- (syntax-wrap x)
- ;; hither the remodulation
- mod
- (syntax-sourcev x)))
- ((vector? x)
- (let* ((n (vector-length x)) (v (make-vector n)))
- (do ((i 0 (1+ i)))
- ((= i n) v)
- (vector-set! v i (remodulate (vector-ref x
i) mod)))))
- (else x))))
+ (define (remodulate x mod)
+ (cond ((pair? x)
+ (cons (remodulate (car x) mod)
+ (remodulate (cdr x) mod)))
+ ((syntax? x)
+ (make-syntax
+ (remodulate (syntax-expression x) mod)
+ (syntax-wrap x)
+ ;; hither the remodulation
+ mod
+ (syntax-sourcev x)))
+ ((vector? x)
+ (let* ((n (vector-length x)) (v (make-vector n)))
+ (do ((i 0 (1+ i)))
+ ((= i n) v)
+ (vector-set! v i (remodulate (vector-ref x i)
mod)))))
+ (else x)))
(syntax-case e (@@ primitive)
((_ primitive id)
(and (id? #'id)
@@ -2467,163 +2390,159 @@
(global-extend 'core 'syntax-case
(let ()
- (define convert-pattern
+ (define (convert-pattern pattern keys ellipsis?)
;; accepts pattern & keys
;; returns $sc-dispatch pattern & ids
- (lambda (pattern keys ellipsis?)
- (define cvt*
- (lambda (p* n ids)
- (syntax-case p* ()
- ((x . y)
- (call-with-values
- (lambda () (cvt* #'y n ids))
- (lambda (y ids)
- (call-with-values
- (lambda () (cvt #'x n ids))
- (lambda (x ids)
- (values (cons x y) ids))))))
- (_ (cvt p* n ids)))))
-
- (define (v-reverse x)
- (let loop ((r '()) (x x))
- (if (not (pair? x))
- (values r x)
- (loop (cons (car x) r) (cdr x)))))
-
- (define cvt
- (lambda (p n ids)
- (if (id? p)
- (cond
- ((bound-id-member? p keys)
- (values (vector 'free-id p) ids))
- ((free-id=? p #'_)
- (values '_ ids))
- (else
- (values 'any (cons (cons p n) ids))))
- (syntax-case p ()
- ((x dots)
- (ellipsis? (syntax dots))
- (call-with-values
- (lambda () (cvt (syntax x) (1+ n) ids))
- (lambda (p ids)
- (values (if (eq? p 'any) 'each-any
(vector 'each p))
- ids))))
- ((x dots . ys)
- (ellipsis? (syntax dots))
- (call-with-values
- (lambda () (cvt* (syntax ys) n ids))
- (lambda (ys ids)
- (call-with-values
- (lambda () (cvt (syntax x) (+ n 1)
ids))
- (lambda (x ids)
- (call-with-values
- (lambda () (v-reverse ys))
- (lambda (ys e)
- (values `#(each+ ,x ,ys ,e)
- ids))))))))
- ((x . y)
- (call-with-values
- (lambda () (cvt (syntax y) n ids))
- (lambda (y ids)
- (call-with-values
- (lambda () (cvt (syntax x) n ids))
- (lambda (x ids)
- (values (cons x y) ids))))))
- (() (values '() ids))
- (#(x ...)
- (call-with-values
- (lambda () (cvt (syntax (x ...)) n ids))
- (lambda (p ids) (values (vector 'vector p)
ids))))
- (x (values (vector 'atom (strip p)) ids))))))
- (cvt pattern 0 '())))
-
- (define build-dispatch-call
- (lambda (pvars exp y r mod)
- (let ((ids (map car pvars)) (levels (map cdr pvars)))
- (let ((labels (gen-labels ids)) (new-vars (map
gen-var ids)))
- (build-primcall
- no-source
- 'apply
- (list (build-simple-lambda no-source (map
syntax->datum ids) #f new-vars '()
- (expand exp
- (extend-env
- labels
- (map (lambda
(var level)
-
(make-binding 'syntax `(,var . ,level)))
- new-vars
- (map cdr
pvars))
- r)
-
(make-binding-wrap ids labels empty-wrap)
- mod))
- y))))))
-
- (define gen-clause
- (lambda (x keys clauses r pat fender exp mod)
- (call-with-values
- (lambda () (convert-pattern pat keys (lambda (e)
(ellipsis? e r mod))))
- (lambda (p pvars)
- (cond
- ((not (and-map (lambda (x) (not (ellipsis? (car x)
r mod))) pvars))
- (syntax-violation 'syntax-case "misplaced
ellipsis" pat))
- ((not (distinct-bound-ids? (map car pvars)))
- (syntax-violation 'syntax-case "duplicate pattern
variable" pat))
- (else
- (let ((y (gen-var 'tmp)))
- ;; fat finger binding and references to temp
variable y
- (build-call no-source
- (build-simple-lambda no-source
(list 'tmp) #f (list y) '()
- (let ((y
(build-lexical-reference 'value no-source
-
'tmp y)))
-
(build-conditional no-source
-
(syntax-case fender ()
-
(#t y)
-
(_ (build-conditional no-source
-
y
-
(build-dispatch-call pvars fender y r mod)
-
(build-data no-source #f))))
-
(build-dispatch-call pvars exp y r mod)
-
(gen-syntax-case x keys clauses r mod))))
- (list (if (eq? p 'any)
- (build-primcall no-source
'list (list x))
- (build-primcall no-source
'$sc-dispatch
- (list x
(build-data no-source p)))))))))))))
-
- (define gen-syntax-case
- (lambda (x keys clauses r mod)
- (if (null? clauses)
- (build-primcall no-source 'syntax-violation
- (list (build-data no-source #f)
- (build-data no-source
- "source
expression failed to match any pattern")
- x))
- (syntax-case (car clauses) ()
- ((pat exp)
- (if (and (id? #'pat)
- (and-map (lambda (x) (not (free-id=?
#'pat x)))
- (cons #'(... ...) keys)))
- (if (free-id=? #'pat #'_)
- (expand #'exp r empty-wrap mod)
- (let ((labels (list (gen-label)))
- (var (gen-var #'pat)))
- (build-call no-source
- (build-simple-lambda
- no-source (list
(syntax->datum #'pat)) #f (list var)
- '()
- (expand #'exp
- (extend-env labels
- (list
(make-binding 'syntax `(,var . 0)))
- r)
-
(make-binding-wrap #'(pat)
-
labels empty-wrap)
+ (define cvt*
+ (lambda (p* n ids)
+ (syntax-case p* ()
+ ((x . y)
+ (call-with-values
+ (lambda () (cvt* #'y n ids))
+ (lambda (y ids)
+ (call-with-values
+ (lambda () (cvt #'x n ids))
+ (lambda (x ids)
+ (values (cons x y) ids))))))
+ (_ (cvt p* n ids)))))
+
+ (define (v-reverse x)
+ (let loop ((r '()) (x x))
+ (if (not (pair? x))
+ (values r x)
+ (loop (cons (car x) r) (cdr x)))))
+
+ (define cvt
+ (lambda (p n ids)
+ (if (id? p)
+ (cond
+ ((bound-id-member? p keys)
+ (values (vector 'free-id p) ids))
+ ((free-id=? p #'_)
+ (values '_ ids))
+ (else
+ (values 'any (cons (cons p n) ids))))
+ (syntax-case p ()
+ ((x dots)
+ (ellipsis? (syntax dots))
+ (call-with-values
+ (lambda () (cvt (syntax x) (1+ n) ids))
+ (lambda (p ids)
+ (values (if (eq? p 'any) 'each-any (vector
'each p))
+ ids))))
+ ((x dots . ys)
+ (ellipsis? (syntax dots))
+ (call-with-values
+ (lambda () (cvt* (syntax ys) n ids))
+ (lambda (ys ids)
+ (call-with-values
+ (lambda () (cvt (syntax x) (+ n 1)
ids))
+ (lambda (x ids)
+ (call-with-values
+ (lambda () (v-reverse ys))
+ (lambda (ys e)
+ (values `#(each+ ,x ,ys ,e)
+ ids))))))))
+ ((x . y)
+ (call-with-values
+ (lambda () (cvt (syntax y) n ids))
+ (lambda (y ids)
+ (call-with-values
+ (lambda () (cvt (syntax x) n ids))
+ (lambda (x ids)
+ (values (cons x y) ids))))))
+ (() (values '() ids))
+ (#(x ...)
+ (call-with-values
+ (lambda () (cvt (syntax (x ...)) n ids))
+ (lambda (p ids) (values (vector 'vector p)
ids))))
+ (x (values (vector 'atom (strip p)) ids))))))
+ (cvt pattern 0 '()))
+
+ (define (build-dispatch-call pvars exp y r mod)
+ (let ((ids (map car pvars)) (levels (map cdr pvars)))
+ (let ((labels (gen-labels ids)) (new-vars (map gen-var
ids)))
+ (build-primcall
+ no-source
+ 'apply
+ (list (build-simple-lambda no-source (map
syntax->datum ids) #f new-vars '()
+ (expand exp
+ (extend-env
+ labels
+ (map (lambda
(var level)
+
(make-binding 'syntax `(,var . ,level)))
+ new-vars
+ (map cdr
pvars))
+ r)
+
(make-binding-wrap ids labels empty-wrap)
mod))
- (list x))))
- (gen-clause x keys (cdr clauses) r
- #'pat #t #'exp mod)))
- ((pat fender exp)
- (gen-clause x keys (cdr clauses) r
- #'pat #'fender #'exp mod))
- (_ (syntax-violation 'syntax-case "invalid clause"
- (car clauses)))))))
+ y)))))
+
+ (define (gen-clause x keys clauses r pat fender exp mod)
+ (call-with-values
+ (lambda () (convert-pattern pat keys (lambda (e)
(ellipsis? e r mod))))
+ (lambda (p pvars)
+ (cond
+ ((not (and-map (lambda (x) (not (ellipsis? (car x) r
mod))) pvars))
+ (syntax-violation 'syntax-case "misplaced ellipsis"
pat))
+ ((not (distinct-bound-ids? (map car pvars)))
+ (syntax-violation 'syntax-case "duplicate pattern
variable" pat))
+ (else
+ (let ((y (gen-var 'tmp)))
+ ;; fat finger binding and references to temp
variable y
+ (build-call no-source
+ (build-simple-lambda no-source (list
'tmp) #f (list y) '()
+ (let ((y
(build-lexical-reference 'value no-source
+
'tmp y)))
+
(build-conditional no-source
+
(syntax-case fender ()
+
(#t y)
+
(_ (build-conditional no-source
+
y
+
(build-dispatch-call pvars fender y r mod)
+
(build-data no-source #f))))
+
(build-dispatch-call pvars exp y r mod)
+
(gen-syntax-case x keys clauses r mod))))
+ (list (if (eq? p 'any)
+ (build-primcall no-source
'list (list x))
+ (build-primcall no-source
'$sc-dispatch
+ (list x
(build-data no-source p))))))))))))
+
+ (define (gen-syntax-case x keys clauses r mod)
+ (if (null? clauses)
+ (build-primcall no-source 'syntax-violation
+ (list (build-data no-source #f)
+ (build-data no-source
+ "source expression
failed to match any pattern")
+ x))
+ (syntax-case (car clauses) ()
+ ((pat exp)
+ (if (and (id? #'pat)
+ (and-map (lambda (x) (not (free-id=?
#'pat x)))
+ (cons #'(... ...) keys)))
+ (if (free-id=? #'pat #'_)
+ (expand #'exp r empty-wrap mod)
+ (let ((labels (list (gen-label)))
+ (var (gen-var #'pat)))
+ (build-call no-source
+ (build-simple-lambda
+ no-source (list
(syntax->datum #'pat)) #f (list var)
+ '()
+ (expand #'exp
+ (extend-env labels
+ (list
(make-binding 'syntax `(,var . 0)))
+ r)
+ (make-binding-wrap
#'(pat)
+
labels empty-wrap)
+ mod))
+ (list x))))
+ (gen-clause x keys (cdr clauses) r
+ #'pat #t #'exp mod)))
+ ((pat fender exp)
+ (gen-clause x keys (cdr clauses) r
+ #'pat #'fender #'exp mod))
+ (_ (syntax-violation 'syntax-case "invalid clause"
+ (car clauses))))))
(lambda (e r w s mod)
(let ((e (source-wrap e w s mod)))
@@ -2817,134 +2736,127 @@
(let ()
- (define match-each
- (lambda (e p w mod)
- (cond
- ((pair? e)
- (let ((first (match (car e) p w '() mod)))
- (and first
- (let ((rest (match-each (cdr e) p w mod)))
- (and rest (cons first rest))))))
- ((null? e) '())
- ((syntax? e)
- (match-each (syntax-expression e)
- p
- (join-wraps w (syntax-wrap e))
- (or (syntax-module e) mod)))
- (else #f))))
-
- (define match-each+
- (lambda (e x-pat y-pat z-pat w r mod)
- (let f ((e e) (w w))
- (cond
- ((pair? e)
- (call-with-values (lambda () (f (cdr e) w))
- (lambda (xr* y-pat r)
- (if r
- (if (null? y-pat)
- (let ((xr (match (car e) x-pat w '() mod)))
- (if xr
- (values (cons xr xr*) y-pat r)
- (values #f #f #f)))
- (values
- '()
- (cdr y-pat)
- (match (car e) (car y-pat) w r mod)))
- (values #f #f #f)))))
- ((syntax? e)
- (f (syntax-expression e)
- (join-wraps w (syntax-wrap e))))
- (else
- (values '() y-pat (match e z-pat w r mod)))))))
-
- (define match-each-any
- (lambda (e w mod)
+ (define (match-each e p w mod)
+ (cond
+ ((pair? e)
+ (let ((first (match (car e) p w '() mod)))
+ (and first
+ (let ((rest (match-each (cdr e) p w mod)))
+ (and rest (cons first rest))))))
+ ((null? e) '())
+ ((syntax? e)
+ (match-each (syntax-expression e)
+ p
+ (join-wraps w (syntax-wrap e))
+ (or (syntax-module e) mod)))
+ (else #f)))
+
+ (define (match-each+ e x-pat y-pat z-pat w r mod)
+ (let f ((e e) (w w))
(cond
((pair? e)
- (let ((l (match-each-any (cdr e) w mod)))
- (and l (cons (wrap (car e) w mod) l))))
- ((null? e) '())
+ (call-with-values (lambda () (f (cdr e) w))
+ (lambda (xr* y-pat r)
+ (if r
+ (if (null? y-pat)
+ (let ((xr (match (car e) x-pat w '() mod)))
+ (if xr
+ (values (cons xr xr*) y-pat r)
+ (values #f #f #f)))
+ (values
+ '()
+ (cdr y-pat)
+ (match (car e) (car y-pat) w r mod)))
+ (values #f #f #f)))))
((syntax? e)
- (match-each-any (syntax-expression e)
- (join-wraps w (syntax-wrap e))
- mod))
- (else #f))))
-
- (define match-empty
- (lambda (p r)
- (cond
- ((null? p) r)
- ((eq? p '_) r)
- ((eq? p 'any) (cons '() r))
- ((pair? p) (match-empty (car p) (match-empty (cdr p) r)))
- ((eq? p 'each-any) (cons '() r))
- (else
- (case (vector-ref p 0)
- ((each) (match-empty (vector-ref p 1) r))
- ((each+) (match-empty (vector-ref p 1)
- (match-empty
- (reverse (vector-ref p 2))
- (match-empty (vector-ref p 3) r))))
- ((free-id atom) r)
- ((vector) (match-empty (vector-ref p 1) r)))))))
-
- (define combine
- (lambda (r* r)
- (if (null? (car r*))
- r
- (cons (map car r*) (combine (map cdr r*) r)))))
-
- (define match*
- (lambda (e p w r mod)
- (cond
- ((null? p) (and (null? e) r))
- ((pair? p)
- (and (pair? e) (match (car e) (car p) w
- (match (cdr e) (cdr p) w r mod)
- mod)))
- ((eq? p 'each-any)
- (let ((l (match-each-any e w mod))) (and l (cons l r))))
+ (f (syntax-expression e)
+ (join-wraps w (syntax-wrap e))))
(else
- (case (vector-ref p 0)
- ((each)
- (if (null? e)
- (match-empty (vector-ref p 1) r)
- (let ((l (match-each e (vector-ref p 1) w mod)))
- (and l
- (let collect ((l l))
- (if (null? (car l))
- r
- (cons (map car l) (collect (map cdr l)))))))))
- ((each+)
- (call-with-values
- (lambda ()
- (match-each+ e (vector-ref p 1) (vector-ref p 2)
(vector-ref p 3) w r mod))
- (lambda (xr* y-pat r)
- (and r
- (null? y-pat)
- (if (null? xr*)
- (match-empty (vector-ref p 1) r)
- (combine xr* r))))))
- ((free-id) (and (id? e) (free-id=? (wrap e w mod) (vector-ref p
1)) r))
- ((atom) (and (equal? (vector-ref p 1) (strip e)) r))
- ((vector)
- (and (vector? e)
- (match (vector->list e) (vector-ref p 1) w r mod))))))))
-
- (define match
- (lambda (e p w r mod)
- (cond
- ((not r) #f)
- ((eq? p '_) r)
- ((eq? p 'any) (cons (wrap e w mod) r))
- ((syntax? e)
- (match*
- (syntax-expression e)
- p
- (join-wraps w (syntax-wrap e))
- r
- (or (syntax-module e) mod)))
- (else (match* e p w r mod)))))
+ (values '() y-pat (match e z-pat w r mod))))))
+
+ (define (match-each-any e w mod)
+ (cond
+ ((pair? e)
+ (let ((l (match-each-any (cdr e) w mod)))
+ (and l (cons (wrap (car e) w mod) l))))
+ ((null? e) '())
+ ((syntax? e)
+ (match-each-any (syntax-expression e)
+ (join-wraps w (syntax-wrap e))
+ mod))
+ (else #f)))
+
+ (define (match-empty p r)
+ (cond
+ ((null? p) r)
+ ((eq? p '_) r)
+ ((eq? p 'any) (cons '() r))
+ ((pair? p) (match-empty (car p) (match-empty (cdr p) r)))
+ ((eq? p 'each-any) (cons '() r))
+ (else
+ (case (vector-ref p 0)
+ ((each) (match-empty (vector-ref p 1) r))
+ ((each+) (match-empty (vector-ref p 1)
+ (match-empty
+ (reverse (vector-ref p 2))
+ (match-empty (vector-ref p 3) r))))
+ ((free-id atom) r)
+ ((vector) (match-empty (vector-ref p 1) r))))))
+
+ (define (combine r* r)
+ (if (null? (car r*))
+ r
+ (cons (map car r*) (combine (map cdr r*) r))))
+
+ (define (match* e p w r mod)
+ (cond
+ ((null? p) (and (null? e) r))
+ ((pair? p)
+ (and (pair? e) (match (car e) (car p) w
+ (match (cdr e) (cdr p) w r mod)
+ mod)))
+ ((eq? p 'each-any)
+ (let ((l (match-each-any e w mod))) (and l (cons l r))))
+ (else
+ (case (vector-ref p 0)
+ ((each)
+ (if (null? e)
+ (match-empty (vector-ref p 1) r)
+ (let ((l (match-each e (vector-ref p 1) w mod)))
+ (and l
+ (let collect ((l l))
+ (if (null? (car l))
+ r
+ (cons (map car l) (collect (map cdr l)))))))))
+ ((each+)
+ (call-with-values
+ (lambda ()
+ (match-each+ e (vector-ref p 1) (vector-ref p 2) (vector-ref
p 3) w r mod))
+ (lambda (xr* y-pat r)
+ (and r
+ (null? y-pat)
+ (if (null? xr*)
+ (match-empty (vector-ref p 1) r)
+ (combine xr* r))))))
+ ((free-id) (and (id? e) (free-id=? (wrap e w mod) (vector-ref p 1))
r))
+ ((atom) (and (equal? (vector-ref p 1) (strip e)) r))
+ ((vector)
+ (and (vector? e)
+ (match (vector->list e) (vector-ref p 1) w r mod)))))))
+
+ (define (match e p w r mod)
+ (cond
+ ((not r) #f)
+ ((eq? p '_) r)
+ ((eq? p 'any) (cons (wrap e w mod) r))
+ ((syntax? e)
+ (match*
+ (syntax-expression e)
+ p
+ (join-wraps w (syntax-wrap e))
+ r
+ (or (syntax-module e) mod)))
+ (else (match* e p w r mod))))
(set! $sc-dispatch
(lambda (e p)
- [Guile-commits] branch main updated (bb7154fb8 -> 2daea4020), Andy Wingo, 2024/11/15
- [Guile-commits] 05/12: psyntax: Clean up use of fx+, etc, Andy Wingo, 2024/11/15
- [Guile-commits] 06/12: psyntax: Functional annotation of function names, Andy Wingo, 2024/11/15
- [Guile-commits] 10/12: psyntax: Add simple pattern matcher, Andy Wingo, 2024/11/15
- [Guile-commits] 04/12: psyntax: Rename top-level-eval, local-eval, Andy Wingo, 2024/11/15
- [Guile-commits] 07/12: psyntax: Inline the single use of define-structure, Andy Wingo, 2024/11/15
- [Guile-commits] 08/12: psyntax: Remove a useless level of let, Andy Wingo, 2024/11/15
- [Guile-commits] 12/12: psyntax: Use new `match' instead of cdadring, Andy Wingo, 2024/11/15
- [Guile-commits] 11/12: psyntax: Use new `match' instead of cdadring, Andy Wingo, 2024/11/15
- [Guile-commits] 09/12: psyntax: Avoid lambda in procedure definitions,
Andy Wingo <=
- [Guile-commits] 01/12: psyntax: Clean up lexical gensym creation, Andy Wingo, 2024/11/15
- [Guile-commits] 03/12: psyntax: Use vectors instead of gensyms for labels, marks, Andy Wingo, 2024/11/15
- [Guile-commits] 02/12: psyntax: Remove useless gen-label invocations, Andy Wingo, 2024/11/15