guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 01/02: Allow mixed local definitions and expressions


From: Andy Wingo
Subject: [Guile-commits] 01/02: Allow mixed local definitions and expressions
Date: Sun, 25 Aug 2019 11:07:24 -0400 (EDT)

wingo pushed a commit to branch master
in repository guile.

commit 20535922147cd5992330962aaa5c4986563fc905
Author: Andy Wingo <address@hidden>
Date:   Sun Aug 25 16:44:07 2019 +0200

    Allow mixed local definitions and expressions
    
    This change to the expander allows mixed local definitions and
    expressions.  The expansion turns:
    
      (let () (a) (define (b) 42) (b) (b))
    
    into:
    
      (let ()
        (letrec* ((t0 (begin (a) (if #f #f)))
                  (b (lambda () 42)))
          (b)))
    
    Which is to say, expressions that precede definitions are expanded as
    definitions of a temporary via (begin EXP (if #f #f)).
    
    * module/ice-9/psyntax.scm (expand-body): Allow mixed definitions and
      expressions.
    * module/ice-9/psyntax-pp.scm: Regenerate.
    * test-suite/tests/syntax.test: Add a couple tests and update for new
      error messages.
---
 module/ice-9/psyntax-pp.scm  | 363 +++++++++++++++++++++++--------------------
 module/ice-9/psyntax.scm     | 211 ++++++++++++++-----------
 test-suite/tests/syntax.test |  31 +++-
 3 files changed, 341 insertions(+), 264 deletions(-)

diff --git a/module/ice-9/psyntax-pp.scm b/module/ice-9/psyntax-pp.scm
index 6cd7676..167e15c 100644
--- a/module/ice-9/psyntax-pp.scm
+++ b/module/ice-9/psyntax-pp.scm
@@ -987,11 +987,11 @@
                          (source-wrap e w (cdr w) mod)
                          x))
                       (else (decorate-source x s))))))
-           (let* ((t-680b775fb37a463-7c8 transformer-environment)
-                  (t-680b775fb37a463-7c9 (lambda (k) (k e r w s rib mod))))
+           (let* ((t-680b775fb37a463-d6b transformer-environment)
+                  (t-680b775fb37a463-d6c (lambda (k) (k e r w s rib mod))))
              (with-fluid*
-               t-680b775fb37a463-7c8
-               t-680b775fb37a463-7c9
+               t-680b775fb37a463-d6b
+               t-680b775fb37a463-d6c
                (lambda ()
                  (rebuild-macro-output
                    (p (source-wrap e (anti-mark w) s mod))
@@ -1007,111 +1007,141 @@
                        (var-ids '())
                        (vars '())
                        (vals '())
-                       (bindings '()))
-             (if (null? body)
-               (syntax-violation #f "no expressions in body" outer-form)
-               (let ((e (cdar body)) (er (caar body)))
-                 (call-with-values
-                   (lambda ()
-                     (syntax-type e er '(()) (source-annotation e) ribcage mod 
#f))
-                   (lambda (type value form e w s mod)
-                     (let ((key type))
-                       (cond ((memv key '(define-form))
-                              (let ((id (wrap value w mod)) (label 
(gen-label)))
-                                (let ((var (gen-var id)))
-                                  (extend-ribcage! ribcage id label)
-                                  (parse (cdr body)
-                                         (cons id ids)
-                                         (cons label labels)
-                                         (cons id var-ids)
-                                         (cons var vars)
-                                         (cons (cons er (wrap e w mod)) vals)
-                                         (cons (cons 'lexical var) 
bindings)))))
-                             ((memv key '(define-syntax-form))
-                              (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 (cons 'macro (eval-local-transformer 
(expand e trans-r w mod) mod)))
-                                    (cdr r)))
-                                (parse (cdr body) (cons id ids) labels var-ids 
vars vals bindings)))
-                             ((memv key '(define-syntax-parameter-form))
-                              (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 (cons 'syntax-parameter
-                                                (eval-local-transformer 
(expand e trans-r w mod) mod)))
-                                    (cdr r)))
-                                (parse (cdr body) (cons id ids) labels var-ids 
vars vals bindings)))
-                             ((memv key '(begin-form))
-                              (let* ((tmp-1 e) (tmp ($sc-dispatch tmp-1 '(_ . 
each-any))))
-                                (if tmp
-                                  (apply (lambda (e1)
-                                           (parse (let f ((forms e1))
-                                                    (if (null? forms)
-                                                      (cdr body)
-                                                      (cons (cons er (wrap 
(car forms) w mod)) (f (cdr forms)))))
-                                                  ids
-                                                  labels
-                                                  var-ids
-                                                  vars
-                                                  vals
-                                                  bindings))
-                                         tmp)
-                                  (syntax-violation
-                                    #f
-                                    "source expression failed to match any 
pattern"
-                                    tmp-1))))
-                             ((memv key '(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)
-                                             (cdr body)
-                                             (cons (cons er (wrap (car forms) 
w mod)) (f (cdr forms)))))
-                                         ids
-                                         labels
-                                         var-ids
-                                         vars
-                                         vals
-                                         bindings))))
-                             ((null? ids)
-                              (build-sequence
-                                #f
-                                (map (lambda (x) (expand (cdr x) (car x) '(()) 
mod))
-                                     (cons (cons er (source-wrap e w s mod)) 
(cdr body)))))
-                             (else
-                              (if (not (valid-bound-ids? ids))
-                                (syntax-violation
-                                  #f
-                                  "invalid or duplicate identifier in 
definition"
-                                  outer-form))
-                              (set-cdr! r (extend-env labels bindings (cdr r)))
-                              (build-letrec
-                                #f
-                                #t
-                                (reverse (map syntax->datum var-ids))
-                                (reverse vars)
-                                (map (lambda (x) (expand (cdr x) (car x) '(()) 
mod)) (reverse vals))
-                                (build-sequence
-                                  #f
-                                  (map (lambda (x) (expand (cdr x) (car x) 
'(()) mod))
-                                       (cons (cons er (source-wrap e w s mod)) 
(cdr body))))))))))))))))
+                       (bindings '())
+                       (expand-tail-expr #f))
+             (cond ((null? body)
+                    (if (not expand-tail-expr)
+                      (begin
+                        (if (null? ids) (syntax-violation #f "empty body" 
outer-form))
+                        (syntax-violation #f "body should end with an 
expression" outer-form)))
+                    (if (not (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-label))) (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 '(()) (source-annotation e) 
ribcage mod #f))
+                        (lambda (type value form e w s mod)
+                          (let ((key type))
+                            (cond ((memv key '(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 '(()) mod)))
+                                                    vals)
+                                              (cons (cons 'lexical var) 
bindings)
+                                              #f))))
+                                  ((memv key '(define-syntax-form))
+                                   (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 (cons '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)))
+                                  ((memv key '(define-syntax-parameter-form))
+                                   (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 (cons '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)))
+                                  ((memv key '(begin-form))
+                                   (let* ((tmp-1 e) (tmp ($sc-dispatch tmp-1 
'(_ . each-any))))
+                                     (if tmp
+                                       (apply (lambda (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))
+                                              tmp)
+                                       (syntax-violation
+                                         #f
+                                         "source expression failed to match 
any pattern"
+                                         tmp-1))))
+                                  ((memv key '(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
+                                   (let ((wrapped (source-wrap e w s mod)))
+                                     (parse body
+                                            ids
+                                            labels
+                                            var-ids
+                                            vars
+                                            vals
+                                            bindings
+                                            (lambda () (expand wrapped er 
'(()) mod))))))))))))))))
      (expand-local-syntax
        (lambda (rec? e r w s mod k)
          (let* ((tmp e)
@@ -1524,11 +1554,11 @@
                                           s
                                           mod
                                           get-formals
-                                          (map (lambda (tmp-680b775fb37a463-ab9
-                                                        tmp-680b775fb37a463-ab8
-                                                        
tmp-680b775fb37a463-ab7)
-                                                 (cons tmp-680b775fb37a463-ab7
-                                                       (cons 
tmp-680b775fb37a463-ab8 tmp-680b775fb37a463-ab9)))
+                                          (map (lambda (tmp-680b775fb37a463-fdc
+                                                        tmp-680b775fb37a463-fdb
+                                                        
tmp-680b775fb37a463-fda)
+                                                 (cons tmp-680b775fb37a463-fda
+                                                       (cons 
tmp-680b775fb37a463-fdb tmp-680b775fb37a463-fdc)))
                                                e2*
                                                e1*
                                                args*)))
@@ -1826,11 +1856,11 @@
               (apply (lambda (args e1 e2)
                        (build-it
                          '()
-                         (map (lambda (tmp-680b775fb37a463-c86
-                                       tmp-680b775fb37a463-c85
-                                       tmp-680b775fb37a463-c84)
-                                (cons tmp-680b775fb37a463-c84
-                                      (cons tmp-680b775fb37a463-c85 
tmp-680b775fb37a463-c86)))
+                         (map (lambda (tmp-680b775fb37a463-69c
+                                       tmp-680b775fb37a463-69b
+                                       tmp-680b775fb37a463-69a)
+                                (cons tmp-680b775fb37a463-69a
+                                      (cons tmp-680b775fb37a463-69b 
tmp-680b775fb37a463-69c)))
                               e2
                               e1
                               args)))
@@ -1842,11 +1872,11 @@
                   (apply (lambda (docstring args e1 e2)
                            (build-it
                              (list (cons 'documentation (syntax->datum 
docstring)))
-                             (map (lambda (tmp-680b775fb37a463-c9c
-                                           tmp-680b775fb37a463-c9b
-                                           tmp-680b775fb37a463-c9a)
-                                    (cons tmp-680b775fb37a463-c9a
-                                          (cons tmp-680b775fb37a463-c9b 
tmp-680b775fb37a463-c9c)))
+                             (map (lambda (tmp-680b775fb37a463-6b2
+                                           tmp-680b775fb37a463-6b1
+                                           tmp-680b775fb37a463-6b0)
+                                    (cons tmp-680b775fb37a463-6b0
+                                          (cons tmp-680b775fb37a463-6b1 
tmp-680b775fb37a463-6b2)))
                                   e2
                                   e1
                                   args)))
@@ -1869,11 +1899,9 @@
               (apply (lambda (args e1 e2)
                        (build-it
                          '()
-                         (map (lambda (tmp-680b775fb37a463-cbc
-                                       tmp-680b775fb37a463-cbb
-                                       tmp-680b775fb37a463-cba)
-                                (cons tmp-680b775fb37a463-cba
-                                      (cons tmp-680b775fb37a463-cbb 
tmp-680b775fb37a463-cbc)))
+                         (map (lambda (tmp-680b775fb37a463-2 
tmp-680b775fb37a463-1 tmp-680b775fb37a463)
+                                (cons tmp-680b775fb37a463
+                                      (cons tmp-680b775fb37a463-1 
tmp-680b775fb37a463-2)))
                               e2
                               e1
                               args)))
@@ -1885,11 +1913,11 @@
                   (apply (lambda (docstring args e1 e2)
                            (build-it
                              (list (cons 'documentation (syntax->datum 
docstring)))
-                             (map (lambda (tmp-680b775fb37a463-cd2
-                                           tmp-680b775fb37a463-cd1
-                                           tmp-680b775fb37a463-cd0)
-                                    (cons tmp-680b775fb37a463-cd0
-                                          (cons tmp-680b775fb37a463-cd1 
tmp-680b775fb37a463-cd2)))
+                             (map (lambda (tmp-680b775fb37a463-67c
+                                           tmp-680b775fb37a463-67b
+                                           tmp-680b775fb37a463-67a)
+                                    (cons tmp-680b775fb37a463-67a
+                                          (cons tmp-680b775fb37a463-67b 
tmp-680b775fb37a463-67c)))
                                   e2
                                   e1
                                   args)))
@@ -2813,11 +2841,9 @@
                                #f
                                k
                                (list docstring)
-                               (map (lambda (tmp-680b775fb37a463
-                                             tmp-680b775fb37a463-113f
-                                             tmp-680b775fb37a463-113e)
-                                      (list (cons tmp-680b775fb37a463-113e 
tmp-680b775fb37a463-113f)
-                                            tmp-680b775fb37a463))
+                               (map (lambda (tmp-680b775fb37a463-2 
tmp-680b775fb37a463-1 tmp-680b775fb37a463)
+                                      (list (cons tmp-680b775fb37a463 
tmp-680b775fb37a463-1)
+                                            tmp-680b775fb37a463-2))
                                     template
                                     pattern
                                     keyword)))
@@ -2832,9 +2858,11 @@
                                    dots
                                    k
                                    '()
-                                   (map (lambda (tmp-680b775fb37a463-2 
tmp-680b775fb37a463-1 tmp-680b775fb37a463)
-                                          (list (cons tmp-680b775fb37a463 
tmp-680b775fb37a463-1)
-                                                tmp-680b775fb37a463-2))
+                                   (map (lambda (tmp-680b775fb37a463-113b
+                                                 tmp-680b775fb37a463-113a
+                                                 tmp-680b775fb37a463)
+                                          (list (cons tmp-680b775fb37a463 
tmp-680b775fb37a463-113a)
+                                                tmp-680b775fb37a463-113b))
                                         template
                                         pattern
                                         keyword)))
@@ -2850,9 +2878,9 @@
                                        dots
                                        k
                                        (list docstring)
-                                       (map (lambda (tmp-680b775fb37a463-2 
tmp-680b775fb37a463-1 tmp-680b775fb37a463)
+                                       (map (lambda (tmp-680b775fb37a463-115a 
tmp-680b775fb37a463-1 tmp-680b775fb37a463)
                                               (list (cons tmp-680b775fb37a463 
tmp-680b775fb37a463-1)
-                                                    tmp-680b775fb37a463-2))
+                                                    tmp-680b775fb37a463-115a))
                                             template
                                             pattern
                                             keyword)))
@@ -3000,8 +3028,8 @@
                                                (apply (lambda (p)
                                                         (if (= lev 0)
                                                           (quasilist*
-                                                            (map (lambda 
(tmp-680b775fb37a463-11e3)
-                                                                   (list 
"value" tmp-680b775fb37a463-11e3))
+                                                            (map (lambda 
(tmp-680b775fb37a463-120a)
+                                                                   (list 
"value" tmp-680b775fb37a463-120a))
                                                                  p)
                                                             (quasi q lev))
                                                           (quasicons
@@ -3024,8 +3052,8 @@
                                                    (apply (lambda (p)
                                                             (if (= lev 0)
                                                               (quasiappend
-                                                                (map (lambda 
(tmp-680b775fb37a463-11e8)
-                                                                       (list 
"value" tmp-680b775fb37a463-11e8))
+                                                                (map (lambda 
(tmp-680b775fb37a463-120f)
+                                                                       (list 
"value" tmp-680b775fb37a463-120f))
                                                                      p)
                                                                 (quasi q lev))
                                                               (quasicons
@@ -3059,8 +3087,7 @@
                                   (apply (lambda (p)
                                            (if (= lev 0)
                                              (quasilist*
-                                               (map (lambda 
(tmp-680b775fb37a463-11fe)
-                                                      (list "value" 
tmp-680b775fb37a463-11fe))
+                                               (map (lambda 
(tmp-680b775fb37a463) (list "value" tmp-680b775fb37a463))
                                                     p)
                                                (vquasi q lev))
                                              (quasicons
@@ -3079,8 +3106,8 @@
                                       (apply (lambda (p)
                                                (if (= lev 0)
                                                  (quasiappend
-                                                   (map (lambda 
(tmp-680b775fb37a463)
-                                                          (list "value" 
tmp-680b775fb37a463))
+                                                   (map (lambda 
(tmp-680b775fb37a463-122a)
+                                                          (list "value" 
tmp-680b775fb37a463-122a))
                                                         p)
                                                    (vquasi q lev))
                                                  (quasicons
@@ -3170,8 +3197,7 @@
                                 (let ((tmp-1 ls))
                                   (let ((tmp ($sc-dispatch tmp-1 'each-any)))
                                     (if tmp
-                                      (apply (lambda (t-680b775fb37a463-124c)
-                                               (cons "vector" 
t-680b775fb37a463-124c))
+                                      (apply (lambda (t-680b775fb37a463) (cons 
"vector" t-680b775fb37a463))
                                              tmp)
                                       (syntax-violation
                                         #f
@@ -3181,7 +3207,8 @@
                        (let ((tmp-1 ($sc-dispatch tmp '(#(atom "quote") 
each-any))))
                          (if tmp-1
                            (apply (lambda (y)
-                                    (k (map (lambda (tmp-680b775fb37a463) 
(list "quote" tmp-680b775fb37a463))
+                                    (k (map (lambda (tmp-680b775fb37a463-127f)
+                                              (list "quote" 
tmp-680b775fb37a463-127f))
                                             y)))
                                   tmp-1)
                            (let ((tmp-1 ($sc-dispatch tmp '(#(atom "list") . 
each-any))))
@@ -3192,8 +3219,8 @@
                                    (apply (lambda (y z) (f z (lambda (ls) (k 
(append y ls))))) tmp-1)
                                    (let ((else tmp))
                                      (let ((tmp x))
-                                       (let ((t-680b775fb37a463 tmp))
-                                         (list "list->vector" 
t-680b775fb37a463)))))))))))))))))
+                                       (let ((t-680b775fb37a463-128e tmp))
+                                         (list "list->vector" 
t-680b775fb37a463-128e)))))))))))))))))
          (emit (lambda (x)
                  (let ((tmp x))
                    (let ((tmp-1 ($sc-dispatch tmp '(#(atom "quote") any))))
@@ -3206,9 +3233,9 @@
                                     (let ((tmp-1 (map emit x)))
                                       (let ((tmp ($sc-dispatch tmp-1 
'each-any)))
                                         (if tmp
-                                          (apply (lambda (t-680b775fb37a463)
+                                          (apply (lambda 
(t-680b775fb37a463-129d)
                                                    (cons (make-syntax 'list 
'((top)) '(hygiene guile))
-                                                         t-680b775fb37a463))
+                                                         
t-680b775fb37a463-129d))
                                                  tmp)
                                           (syntax-violation
                                             #f
@@ -3224,10 +3251,10 @@
                                             (let ((tmp-1 (list (emit (car x*)) 
(f (cdr x*)))))
                                               (let ((tmp ($sc-dispatch tmp-1 
'(any any))))
                                                 (if tmp
-                                                  (apply (lambda 
(t-680b775fb37a463-128a t-680b775fb37a463)
+                                                  (apply (lambda 
(t-680b775fb37a463-12b1 t-680b775fb37a463-12b0)
                                                            (list (make-syntax 
'cons '((top)) '(hygiene guile))
-                                                                 
t-680b775fb37a463-128a
-                                                                 
t-680b775fb37a463))
+                                                                 
t-680b775fb37a463-12b1
+                                                                 
t-680b775fb37a463-12b0))
                                                          tmp)
                                                   (syntax-violation
                                                     #f
@@ -3240,9 +3267,9 @@
                                             (let ((tmp-1 (map emit x)))
                                               (let ((tmp ($sc-dispatch tmp-1 
'each-any)))
                                                 (if tmp
-                                                  (apply (lambda 
(t-680b775fb37a463)
+                                                  (apply (lambda 
(t-680b775fb37a463-12bd)
                                                            (cons (make-syntax 
'append '((top)) '(hygiene guile))
-                                                                 
t-680b775fb37a463))
+                                                                 
t-680b775fb37a463-12bd))
                                                          tmp)
                                                   (syntax-violation
                                                     #f
@@ -3255,9 +3282,9 @@
                                                 (let ((tmp-1 (map emit x)))
                                                   (let ((tmp ($sc-dispatch 
tmp-1 'each-any)))
                                                     (if tmp
-                                                      (apply (lambda 
(t-680b775fb37a463-12a2)
+                                                      (apply (lambda 
(t-680b775fb37a463-12c9)
                                                                (cons 
(make-syntax 'vector '((top)) '(hygiene guile))
-                                                                     
t-680b775fb37a463-12a2))
+                                                                     
t-680b775fb37a463-12c9))
                                                              tmp)
                                                       (syntax-violation
                                                         #f
@@ -3268,9 +3295,9 @@
                                          (if tmp-1
                                            (apply (lambda (x)
                                                     (let ((tmp (emit x)))
-                                                      (let 
((t-680b775fb37a463-12ae tmp))
+                                                      (let 
((t-680b775fb37a463-12d5 tmp))
                                                         (list (make-syntax 
'list->vector '((top)) '(hygiene guile))
-                                                              
t-680b775fb37a463-12ae))))
+                                                              
t-680b775fb37a463-12d5))))
                                                   tmp-1)
                                            (let ((tmp-1 ($sc-dispatch tmp 
'(#(atom "value") any))))
                                              (if tmp-1
diff --git a/module/ice-9/psyntax.scm b/module/ice-9/psyntax.scm
index 3cd87c8..902ecea 100644
--- a/module/ice-9/psyntax.scm
+++ b/module/ice-9/psyntax.scm
@@ -1610,99 +1610,126 @@
                (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 '()))
-            (if (null? body)
-                (syntax-violation #f "no expressions in body" outer-form)
-                (let ((e (cdar body)) (er (caar 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 (cdr body)
-                                    (cons id ids) (cons label labels)
-                                    (cons id var-ids)
-                                    (cons var vars) (cons (cons er (wrap e w 
mod)) vals)
-                                    (cons (make-binding 'lexical var) 
bindings)))))
-                        ((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 (cdr body) (cons id ids) labels var-ids vars 
vals bindings)))
-                        ((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)))
+                      (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-label)))
+                                     (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)
-                           (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 (cdr body) (cons id ids) labels var-ids vars 
vals bindings)))
-                        ((begin-form)
-                         (syntax-case e ()
-                           ((_ e1 ...)
-                            (parse (let f ((forms #'(e1 ...)))
-                                     (if (null? forms)
-                                         (cdr body)
-                                         (cons (cons er (wrap (car forms) w 
mod))
-                                               (f (cdr forms)))))
-                                   ids labels var-ids vars vals bindings))))
-                        ((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)
-                                                             (cdr body)
-                                                             (cons (cons er 
(wrap (car forms) w mod))
-                                                                   (f (cdr 
forms)))))
-                                                       ids labels var-ids vars 
vals bindings))))
-                        (else           ; found a non-definition
-                         (if (null? ids)
-                             (build-sequence no-source
-                                             (map (lambda (x)
-                                                    (expand (cdr x) (car x) 
empty-wrap mod))
-                                                  (cons (cons er (source-wrap 
e w s mod))
-                                                        (cdr body))))
-                             (begin
-                               (if (not (valid-bound-ids? ids))
-                                   (syntax-violation
-                                    #f "invalid or duplicate identifier in 
definition"
-                                    outer-form))
-                               (set-cdr! r (extend-env labels bindings (cdr 
r)))
-                               (build-letrec no-source #t
-                                             (reverse (map syntax->datum 
var-ids))
-                                             (reverse vars)
-                                             (map (lambda (x)
-                                                    (expand (cdr x) (car x) 
empty-wrap mod))
-                                                  (reverse vals))
-                                             (build-sequence no-source
-                                                             (map (lambda (x)
-                                                                    (expand 
(cdr x) (car x) empty-wrap mod))
-                                                                  (cons (cons 
er (source-wrap e w s mod))
-                                                                        (cdr 
body)))))))))))))))))
+                           (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)
diff --git a/test-suite/tests/syntax.test b/test-suite/tests/syntax.test
index 883004a..10bc7b0 100644
--- a/test-suite/tests/syntax.test
+++ b/test-suite/tests/syntax.test
@@ -36,8 +36,10 @@
   "Missing or extra expression")
 (define exception:missing-expr
   "Missing expression")
-(define exception:missing-body-expr
-  "no expressions in body")
+(define exception:empty-body
+  "empty body")
+(define exception:body-should-end-with-expr
+  "body should end with an expression")
 (define exception:extra-expr
   "Extra expression")
 (define exception:illegal-empty-combination
@@ -970,9 +972,30 @@
                      (eq? 'c (a 2) (a 5)))))
            (interaction-environment))))
 
-  (pass-if-syntax-error "missing body expression"
-    exception:missing-body-expr
+  (pass-if-syntax-error "empty body"
+    exception:empty-body
+    (eval '(let () (begin))
+          (interaction-environment)))
+
+  (pass-if-syntax-error "body should end with expression"
+    exception:body-should-end-with-expr
     (eval '(let () (define x #t))
+          (interaction-environment)))
+
+  (pass-if-equal "mixed definitions and expressions" 256
+    ((eval '(lambda (x)
+              (unless (number? x) (error "not a number" x))
+              (define (square x) (* x x))
+              (square (square x)))
+           (interaction-environment))
+     4))
+
+  (pass-if-equal "mixed definitions and expressions 2" 42
+    (eval '(let ()
+             (define (foo) (bar))
+             1
+             (define (bar) 42)
+             (foo))
           (interaction-environment))))
 
 (with-test-prefix "top-level define-values"



reply via email to

[Prev in Thread] Current Thread [Next in Thread]