commit 1ad9f691aa0755ed4e073f64fa357cb325816aec parent fe3eec2b4453c149ded37e6bfca9a4535e3de40a Author: Georges Dupéron <georges.duperon@gmail.com> Date: Thu, 1 Jun 2017 16:47:05 +0200 Sketched a "def" form, which implicitly does pattern matching and defines functions and macros alike. Diffstat:
| A | def.rkt | | | 59 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 59 insertions(+), 0 deletions(-)
diff --git a/def.rkt b/def.rkt @@ -0,0 +1,58 @@ +#lang typed/racket +(require syntax/parse + phc-toolkit/percent + (for-syntax syntax/parse)) + +(begin-for-syntax + (define-syntax-class parse-args + (pattern rest:id + #:with sig #'rest + #:with {extract ...} #'{}) + (pattern ({~or {~literal syntax} {~literal unsyntax}} . rest) + ;; The rest would need to be an stx, but that's normally impossible + ;; (unless there was some extension to #%app and function + ;; definitions which allowed this). + #:with sig (raise-syntax-error + "Unexpected syntax pattern in a tail position") + #:with {extract ...} #'{}) + (pattern (({~literal syntax} hd) . tl:parse-args) + #:with (tmp) (generate-temporaries #'(hd)) + #:with sig #'(tmp . tl.sig) + #:with {extract ...} #`{#'hd = tmp tl.extract ...}) + (pattern (({~literal unsyntax} hd:parse-args) . tl:parse-args) + #:with (tmp) (generate-temporaries #'(hd)) + #:with sig #'(tmp . tl.sig) + #:with {extract ...} #'{hd.sig = (syntax->datum tmp) + hd.extract ... + tl.extract ...}) + (pattern (hd:id . tl:parse-args) + #:with sig #'(hd . tl.sig) + #:with {extract ...} #'{tl.extract ...}) + (pattern {~and last ()} + #:with sig #'last + #:with {extract ...} #'{}))) + +(define-syntax def + (syntax-parser + [(_ ({~literal syntax} name:id) . body) + #'(define-syntax name + (syntax-parser + [self:id . body]))] + [(_ (name:id . args:parse-args) . body) + #`(define (name . args.sig) + (% args.extract ... + . body))])) + +#;{ + (def (foo #'(aa . bb) x) + #`(#,x bb . aa)) + + (def (bar #,(aa . bb) x) + (list x bb aa)) + + (module+ test + (require rackunit) + (check-equal? (syntax->datum + (foo #'(xx . yy) 42)) + '(42 yy . xx))) + } +\ No newline at end of file