~ chicken-core (chicken-5) 83198fca2a540203d11542312c5e1bf7ba915396
commit 83198fca2a540203d11542312c5e1bf7ba915396 Author: Peter Bex <peter@more-magic.net> AuthorDate: Fri Jun 17 17:17:01 2016 +0200 Commit: Evan Hanson <evhan@foldling.org> CommitDate: Thu Jun 23 21:47:27 2016 +1200 Fix several hygiene issues in DSSSL expansions (#806). The expansion of DSSSL lambda list would take "optional", "let*" and "let-optionals*" from the current syntactic environment, which might not have it or a different definition, depending on the user's import statements. Now we explicitly take them from the default macro environment or the chicken macro environment, depending on the macro to use. Signed-off-by: Evan Hanson <evhan@foldling.org> diff --git a/NEWS b/NEWS index f5948cec..2a2268ca 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,12 @@ - The default error handler now truncates very long condition messages (thanks to Lemonboy). +- Syntax expander + - DSSSL lambda lists have improved hygiene, so they don't need + the chicken or scheme modules to be imported in full (#806). + - The let-optionals* macro no longer needs "quote", "car" and "cdr" + to be imported and bound to their default values (#806). + 4.11.0 - Security fixes diff --git a/chicken-syntax.scm b/chicken-syntax.scm index 79251957..ec9aff31 100644 --- a/chicken-syntax.scm +++ b/chicken-syntax.scm @@ -723,7 +723,9 @@ (##sys#extend-macro-environment 'let-optionals* - `((null? . ,(##sys#primitive-alias 'null?))) + `((null? . ,(##sys#primitive-alias 'null?)) + (car . ,(##sys#primitive-alias 'car)) + (cdr . ,(##sys#primitive-alias 'cdr))) (##sys#er-transformer (lambda (form r c) (##sys#check-syntax 'let-optionals* form '(_ _ list . _)) @@ -736,17 +738,17 @@ (let ((rvar (r 'tmp))) `(##core#let ((,rvar ,args)) - ,(let loop ([args rvar] [vardefs var/defs]) + ,(let loop ((args rvar) (vardefs var/defs)) (if (null? vardefs) `(##core#let () ,@body) - (let ([head (car vardefs)]) + (let ((head (car vardefs))) (if (pair? head) (let ((rvar2 (r 'tmp2))) `(##core#let ((,(car head) (##core#if (,%null? ,args) ,(cadr head) (,%car ,args))) (,rvar2 (##core#if (,%null? ,args) - '() + (##core#quote ()) (,%cdr ,args))) ) ,(loop rvar2 (cdr vardefs)) ) ) `(##core#let ((,head ,args)) ,@body) ) ) ) ) ) ) )))) diff --git a/expand.scm b/expand.scm index 3739d609..133bd258 100644 --- a/expand.scm +++ b/expand.scm @@ -336,17 +336,18 @@ [else (loop (cdr llist))] ) ) ) ) (define ##sys#expand-extended-lambda-list - (let ([reverse reverse]) + (let ((reverse reverse)) (lambda (llist0 body errh se) (define (err msg) (errh msg llist0)) (define (->keyword s) (string->keyword (##sys#slot s 1))) - (let ([rvar #f] - [hasrest #f] - (%let* (macro-alias 'let* se)) + (let ((rvar #f) + (hasrest #f) + ;; These might not exist in se, use default or chicken env: + (%let* (macro-alias 'let* ##sys#default-macro-environment)) (%lambda '##core#lambda) - (%opt (macro-alias 'optional se)) - (%let-optionals* (macro-alias 'let-optionals* se)) - (%let (macro-alias 'let se))) + (%opt (macro-alias 'optional ##sys#chicken-macro-environment)) + (%let-optionals* (macro-alias 'let-optionals* ##sys#chicken-macro-environment)) + (%let '##core#let)) (let loop ([mode 0] ; req=0, opt=1, rest=2, key=3, end=4 [req '()] [opt '()] diff --git a/tests/syntax-tests.scm b/tests/syntax-tests.scm index 48e2116f..1004f71a 100644 --- a/tests/syntax-tests.scm +++ b/tests/syntax-tests.scm @@ -247,7 +247,7 @@ ;;; strip-syntax on renamed module identifiers, as well as core identifiers (module foo (bar) - (import chicken scheme) + (import scheme) (define bar 1)) @@ -489,7 +489,7 @@ ;;; incorrect lookup for keyword variables in DSSSL llists (module broken-keyword-var () - (import scheme chicken) + (import scheme (only chicken assert)) ((lambda (#!key string) (assert (not string))))) ; refered to R5RS `string' ;;; Missing check for keyword and optional variable types in DSSSL llists @@ -517,7 +517,7 @@ (define x 99) (module primitive-assign () - (import scheme chicken) + (import scheme (only chicken assert setter)) (let ((x 100)) (set! x 20) (assert (= x 20))) (set! setter 123)) @@ -627,7 +627,7 @@ (module m2 (s3 s4) - (import chicken scheme) + (import scheme) (define-syntax s3 (syntax-rules () ((_ x) (list x)))) @@ -844,18 +844,31 @@ (f (eval '(lambda ((x 0) #!rest r1) 'foo))) (f (eval '(lambda (x #!rest (r1 0)) 'foo))) +;; "optional" expansion should not rely on user imports (hygiene) +(t '(1 2) + (eval '(module x () + (import (only scheme lambda list)) + ((lambda (x #!optional (y 0)) (list x y)) 1 2)))) + ;; Dotted list syntax can be mixed in (t '(1 2 3 4 (5 6)) ((lambda (x y #!optional o1 o2 . r) (list x y o1 o2 r)) 1 2 3 4 5 6)) +;; More DSSSL hygiene issues, from #806 +(module dsssl-extended-lambda-list-hygiene () + (import (prefix scheme s/)) + (s/define (foo #!optional bar #!rest qux #!key baz) + (s/list bar baz qux))) + ;;; import not seen, if explicitly exported and renamed: (module rfoo (rbar rbaz) -(import scheme chicken) +(import scheme) (define (rbaz x) - (print x)) + (display x) + (newline) ) (define-syntax rbar (syntax-rules () @@ -1047,7 +1060,7 @@ ;; an identifier to something imported for the runtime environment (module foonumbers (+) - (import (except scheme +) chicken) + (import (except scheme +) (only chicken error)) (define (+ . _) (error "failed."))) (import foonumbers) @@ -1106,7 +1119,7 @@ take ;; definitions, causing the module to be unresolvable. (module foo () - (import chicken scheme) + (import scheme) (define-syntax bar (syntax-rules () ((_) (begin (define req 1) (display req) (newline))))) @@ -1118,7 +1131,7 @@ take ;; and some Schemes (at least Gauche) behave the same way. I think it's ;; broken, since it's unhygienic. #;(module foo () - (import chicken scheme) + (import scheme) (define req 1) (define-syntax bar (syntax-rules ()Trap