#lang scheme/base
(require (for-syntax scheme/base
scheme/match
srfi/26/cut
(planet untyped/unlib:3/syntax)
"base.ss"
"persistent-struct-info.ss")
scheme/class
"quick-find-internal.ss"
"sql/sql.ss")
(define-for-syntax (make-quick-find stx count? struct-stx snooze-stx method-stx order-stx)
(let* ([info (with-handlers ([exn? (lambda (exn)
(raise-syntax-error #f "not a persistent struct" stx struct-stx))])
(persistent-struct-info-ref struct-stx))]
[entity-stx (persistent-struct-info-entity-id info)]
[attr-stxs (persistent-struct-info-attribute-ids info)]
[key-stxs (map (lambda (sym)
(string->keyword (symbol->string sym)))
(persistent-struct-info-attribute-names info))]
[arg-stxs
(map (cut datum->syntax #f <>)
(persistent-struct-info-attribute-names info))]
[key+arg-stxs
(let loop ([key-stxs key-stxs] [arg-stxs arg-stxs])
(if (null? key-stxs)
null
(list* (car key-stxs)
#`(#,(car arg-stxs) (void))
(loop (cdr key-stxs) (cdr arg-stxs)))))])
(with-syntax ([struct struct-stx]
[struct-id (make-id struct-stx struct-stx '-id)]
[snooze snooze-stx]
[find-whatever method-stx]
[entity entity-stx]
[(attr ...) attr-stxs]
[(key ...) key-stxs]
[(arg ...) arg-stxs]
[(key+arg ...) key+arg-stxs]
[order order-stx])
(with-syntax ([what (if count? #'(count struct-id) #'struct)])
(syntax/loc stx
(lambda (key+arg ...)
(let-alias ([struct struct])
(send snooze find-whatever
(sql (select #:what what
#:from struct
#:where ,(sql:and (or (void? arg)
(quick-find-expression
(sql:attr struct attr)
arg))
...)
#:order order))))))))))
(define-for-syntax (parse-kws stx kw-stx)
(define order-stx #'())
(let loop ([kw-stx kw-stx])
(syntax-case kw-stx ()
[()
(values order-stx)]
[(kw)
(if (keyword? (syntax->datum #'kw))
(raise-syntax-error #f "no value for keyword" stx #'kw)
(raise-syntax-error #f "not a valid keyword" stx #'kw))]
[(kw val rest ...)
(begin (match (syntax->datum #'kw)
['#:order (set! order-stx #'val)]
[else (raise-syntax-error #f "not a valid keyword" stx #'kw)])
(loop #'(rest ...)))])))
(define-syntax (custom-find-count stx)
(syntax-case stx ()
[(_ struct snooze kw ...)
(make-quick-find stx #t #'struct #'snooze #'find-one #'())]))
(define-syntax (custom-find-one stx)
(syntax-case stx ()
[(_ struct snooze kw ...)
(let-values ([(order-stx) (parse-kws stx #'(kw ...))])
(make-quick-find stx #f #'struct #'snooze #'find-one order-stx))]))
(define-syntax (custom-find-all stx)
(syntax-case stx ()
[(_ struct snooze kw ...)
(let-values ([(order-stx) (parse-kws stx #'(kw ...))])
(make-quick-find stx #f #'struct #'snooze #'find-all order-stx))]))
(define-syntax (custom-g:find stx)
(syntax-case stx ()
[(_ struct snooze kw ...)
(let-values ([(order-stx) (parse-kws stx #'(kw ...))])
(make-quick-find stx #f #'struct #'snooze #'g:find order-stx))]))
(provide custom-find-count
custom-find-one
custom-find-all
custom-g:find)