You could use (splicing) syntax class to help with normalization:

#lang racket

(require syntax/parse/define
         (for-syntax syntax/parse
                     racket/syntax))

(begin-for-syntax
  (define-splicing-syntax-class methods-cls
    #:attributes (methods)
    (pattern (~seq #:methods (method:expr ...))
             #:with methods #'(list 'method ...))
    (pattern (~seq #:method method:expr)
             #:with methods #'(list 'method)))

  (define-syntax-class route-cls
    (pattern (route:string
              handler:id
              (~alt (~optional ms:methods-cls
                               #:name "#:method, or #:methods option")
                    (~optional (~seq #:when guard-e:expr)
                               #:name "#:when option")) ...)
             #:with methods #`#,(or (attribute ms.methods) #'(list))
             #:with guard #`#,(attribute guard-e))))

(define-simple-macro (routes :route-cls ...)
  #:with name (format-id this-syntax "axio-routes")
  (define name (list (list route handler methods guard) ...)))

(define (foo-handler) 0)
(define (bar-handler) 0)
(define (baz-handler) 0)
(define (use-bar-handler?) 0)

(routes
 ("/foo" foo-handler #:method put)
 ("/bar" bar-handler #:methods (put update) #:when use-bar-handler?)
 ("/baz" baz-handler))

axio-routes


On Mon, Aug 19, 2019 at 1:56 PM Brian Adkins <br...@lojic.com> wrote:

> (define-syntax (routes stx)
>   (syntax-parse stx
>     [ (routes (element ...) ...)
>       (with-syntax ([ name  (format-id stx "axio-routes") ])
>         #'(define name (list (route-element element ...) ...)))]))
>
> (define-syntax (route-element stx)
>   (syntax-parse stx
>     [ (route-element route:string
>                      handler:id
>                      (~alt (~optional (~or* (~seq #:methods (methods:expr
> ...))
>                                             (~seq #:method method:expr))
>                                       #:name "#:method, or #:methods
> option")
>                            (~optional (~seq #:when guard:expr)
>                                       #:name "#:when option"))
>                      ...)
>       (with-syntax ([ method-list (let ([ m  (attribute method)  ]
>                                         [ ms (attribute methods) ])
>                                     (cond [ m    (list m) ]
>                                           [ ms   ms       ]
>                                           [ else '()      ]))]
>                     [ guard-func (let ([ fun (attribute guard) ])
>                                    (if fun
>                                        fun
>                                        #f)) ])
>         #'(list route handler 'method-list guard-func))]))
>
> (routes
>  ("/foo" foo-handler #:method put)
>  ("/bar" bar-handler #:methods (put update) #:when use-bar-handler?)
>  ("/baz" baz-handler))
>
> axio-routes
>
> ==>  '(("/foo" #<procedure:foo-handler> (put) #f) ("/bar"
> #<procedure:bar-handler> (put update) #<procedure:use-bar-handler?>)
> ("/baz" #<procedure:baz-handler> () #f))
>
> I know it ain't pretty yet, but it works now, so I can enhance it later. I
> should probably use a struct for each route vs. a list.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/ffc7ec25-f663-4d1d-a3d6-d3097d9c3963%40googlegroups.com
> <https://groups.google.com/d/msgid/racket-users/ffc7ec25-f663-4d1d-a3d6-d3097d9c3963%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CADcuegsvZ21nJTcpFzMRU0fTjyXtbUY-ZoDDT9A%2BN5qJHnFsxg%40mail.gmail.com.

Reply via email to