From a46326c300ce26a381e875dc58b1dbccc9e5ef8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Georges=20Dup=C3=A9ron?= Date: Tue, 31 Jan 2017 06:08:37 +0100 Subject: [PATCH] Improved #%app support for ddd --- ddd-forms.rkt | 12 ++++---- ddd.rkt | 20 +++++++++---- test/test-ddd-forms.rkt | 65 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 82 insertions(+), 15 deletions(-) diff --git a/ddd-forms.rkt b/ddd-forms.rkt index d822992..18dea4f 100644 --- a/ddd-forms.rkt +++ b/ddd-forms.rkt @@ -27,7 +27,7 @@ -v (-nest* before after - (datum->syntax before `(,@(syntax->list before) ,-v . ,after)) + #`(#,@(syntax->list before) #,-v . #,after) (stx-cdr -ooo*) (add1 depth)))) @@ -48,7 +48,7 @@ (define-syntax-class ooo (pattern {~and ooo {~literal …}})) - (define-splicing-syntax-class ooo* + (define-splicing-syntax-class ooo+ #:attributes (ooo*) (pattern {~seq {~and ooo {~literal …}} …+} #:with ooo* #'(ooo …))) @@ -68,15 +68,15 @@ (define-splicing-syntax-class stmt #:literals (define define/with-syntax) - (pattern {~seq (define name:id e:expr) :ooo*} + (pattern {~seq (define name:id e:expr) :ooo+} #:with expanded #`(-define name #,(nest* (ddd %) e ooo*))) - (pattern {~seq (define/with-syntax pat e:expr) :ooo*} + (pattern {~seq (define/with-syntax pat e:expr) :ooo+} #:with expanded #`(-define/with-syntax #,(nest* (% …) pat ooo*) #,(nest* (ddd %) e ooo*))) - (pattern {~seq e:not-macro-expr :ooo*} + (pattern {~seq e :ooo+} ;#:with expanded #`(apply values #,(ddd* e ooo*)) #:with expanded (ddd* e ooo*)) (pattern other @@ -90,7 +90,7 @@ (begin-for-syntax (define-splicing-syntax-class arg - (pattern {~seq e:expr ooo*:ooo*} + (pattern {~seq e:expr ooo*:ooo+} #:with expanded (ddd* e ooo*)) (pattern other #:with expanded #'(#%app list other)))) diff --git a/ddd.rkt b/ddd.rkt index 046d7a3..ccd2726 100644 --- a/ddd.rkt +++ b/ddd.rkt @@ -81,6 +81,16 @@ (quote-syntax #,(x-pvar-present-marker #'present-variables)) body)) +(define (map#f* f l*) + (cond [(andmap (λ (l) (eq? l #f)) l*) + '(#f)] + [(andmap (or/c null? #f) l*) + '()] + [else (let ([cars (map (λ (l) (if l (car l) #f)) l*)] + [cdrs (map (λ (l) (if l (cdr l) #f)) l*)]) + (cons (apply f cars) + (map#f* f cdrs)))])) + (define-syntax/case (ddd body) () (define/with-syntax (pvar …) (remove-duplicates @@ -96,7 +106,7 @@ (define-temp-ids "~aᵢ" (pvar …)) (define/with-syntax f #`(#%plain-lambda (pvarᵢ …) - (shadow pvar pvarᵢ) … + (shadow pvar pvarᵢ) … ;; TODO: find a way to make the variable marked as "missing" if it is #f ? So that it triggers an error if used outside of ?? (let-values () (detect-present-pvars (pvar …) body)))) @@ -150,10 +160,10 @@ [(list #f pv pvᵢ #f _) #'#f]) present?+pvars))) - #'(map (λ (iterated-pvarᵢ …) - (expanded-f filling-pvar …)) - (attribute* iterated-pvar) - …)) + #'(map#f* (λ (iterated-pvarᵢ …) + (expanded-f filling-pvar …)) + (list (attribute* iterated-pvar) + …))) (define-syntax/case (shadow pvar new-value) () (match (attribute-info #'pvar '(pvar attr)) diff --git a/test/test-ddd-forms.rkt b/test/test-ddd-forms.rkt index 596e2a5..0769ad2 100644 --- a/test/test-ddd-forms.rkt +++ b/test/test-ddd-forms.rkt @@ -174,7 +174,6 @@ x … …]) '(1 2 3 4 5 6)) -#| ;; TODO: expr … inside begin and let (check-equal? (syntax-case #'((1 2 3) (4 5)) () [((x …) …) @@ -182,7 +181,65 @@ (list (length (syntax->list #'(x …))) (+ (syntax-e #'x) 3) …) …)]) - '([3 (4 5 6)] - [2 (7 8)])) -|# + '([3 4 5 6] + [2 7 8])) +(check-equal? (syntax-parse #'([1 2 3] [4 5 6]) + [([x …] …) + x … …]) + '(1 2 3 4 5 6)) +(check-equal? (syntax-parse #'([1 2 3] [4 5 6]) + [([x …] …) + (x …) …]) + '((1 2 3) (4 5 6))) +(check-equal? (syntax-parse #'([1 2 3] [4 5 6]) + [([x …] …) + ((list x) …) …]) + '(((1) (2) (3)) ((4) (5) (6)))) +(check-equal? (syntax-parse #'([1 2 3] [4 5 6]) + [([x …] …) + ((+ x 10) …) …]) + '((11 12 13) (14 15 16))) +(check-equal? (syntax-parse #'([1 2 3] [4 5 6]) + [([x …] …) + (begin ((+ x 10) …) …)]) + '((11 12 13) (14 15 16))) +(check-equal? (syntax-parse #'([1 2 3] [4 5 6]) + [([x …] …) + (define/with-syntax y (+ x 10)) … … + y … …]) + '(11 12 13 14 15 16)) + +;; Implicit apply with (+ y … …) +(check-equal? (syntax-parse #'([1 2 3] [4 5 6]) + [([x …] …) + (define/with-syntax y (+ x 10)) … … + (+ y … …)]) + 81) + +;; Implicit apply with (+ (* x 2) … …) +(check-equal? (syntax-parse #'([1 2 3] [4 5 6]) + [([x …] …) + (+ (* x 2) … …)]) + 42) + +;; TODO: (define ) … … should register the variable with current-pvars. +#;(syntax-parse #'([1 2 3] [4 5 6]) + [([x …] …) + (define y (+ x 10)) … … + y … …]) + + + +#lang racket + +(require subtemplate/ddd-forms + stxparse-info/case + stxparse-info/parse + rackunit + syntax/macro-testing + phc-toolkit/untyped) + +(syntax-parse #'([1 2 3] #:kw [4 5 6]) + [({~and {~or [x …] #:kw}} …) + ((x …) …)]) \ No newline at end of file