[plt-scheme] Fun with paren-shape
> [(+ n 3) : n is (< n 10) (even? n)]
(3 5 7 9 11)
> [(+ n 3) : n is (< n 10)]
(3 4 5 6 7 8 9 10 11 12)
> [(* n n) : n is (< n 10) (odd? n)]
(1 9 25 49 81)
Is there a better keyword than "is"?
/Jens Axel
(module index mzscheme
(provide (rename my-app #%app))
(require-for-syntax (lib "stx.ss" "syntax"))
(define (interval n m)
(cond
[(>= n m) '()]
[(< n m) (cons n (interval (+ n 1) m))]))
(define-syntax (my-app stx)
(define (bracket-shaped? stx)
(equal? (syntax-property stx 'paren-shape) #\[))
(define (brackets? parens)
(syntax-case parens ()
[(x) (bracket-shaped? parens)]
[_ #f]))
(define (range? stx)
(syntax-case* stx (..) module-or-top-identifier=?
[(a .. b) (bracket-shaped? stx)]
[_ #f]))
(define (handle-brackets exprs)
; vector brackets
(let loop ([exprs exprs]
[prev-exprs '()])
(cond
[(null? exprs)
(reverse prev-exprs)]
[(null? (cdr exprs))
(loop (cdr exprs) (cons (car exprs) prev-exprs))]
[(not (brackets? (cadr exprs)))
(loop (cdr exprs) (cons (car exprs) prev-exprs))]
[else
(loop (cddr exprs)
(cons (quasisyntax/loc (cadr exprs)
(vector-ref #,(car exprs) #,@(cadr exprs)))
prev-exprs))])))
(define (handle-ranges exprs)
(let loop ([exprs exprs]
[prev-exprs '()])
(cond
[(null? exprs)
(reverse prev-exprs)]
[(not (range? (car exprs)))
(loop (cdr exprs) (cons (car exprs) prev-exprs))]
[else
(with-syntax ([[from .. to] (car exprs)])
(loop (cdr exprs)
(cons (syntax/loc (car exprs)
(interval from to))
prev-exprs)))])))
(syntax-case* stx (.. : is) module-or-top-identifier=?
[(_ a .. b)
(bracket-shaped? stx)
(quasisyntax/loc stx
(interval a b))]
[(_ expr : n is while-pred-expr)
(bracket-shaped? stx)
(quasisyntax/loc stx
(let loop ([n 0])
(if while-pred-expr
(cons expr (loop (+ n 1)))
'())))]
[(_ expr : n is while-pred-expr filter-expr)
(bracket-shaped? stx)
(quasisyntax/loc stx
(let loop ([n 0])
(if while-pred-expr
(if filter-expr
(cons expr (loop (+ n 1)))
(loop (+ n 1)))
'())))]
[(_ n : while-pred-expr)
(bracket-shaped? stx)
(quasisyntax/loc stx
(let loop ([n 0])
(if while-pred-expr
(cons n (loop (+ n 1)))
'())))]
[(_ n : while-pred-expr filter-expr)
(bracket-shaped? stx)
(quasisyntax/loc stx
(let loop ([n 0])
(if while-pred-expr
(if filter-expr
(cons n (loop (+ n 1)))
(loop (+ n 1)))
'())))]
[(_ expr . more )
(or (ormap brackets? (cddr (syntax->list stx)))
(ormap range? (cdr (syntax->list stx))))
(with-syntax ([(expr ...)
(handle-ranges
(handle-brackets
(cdr (syntax->list stx))))])
(quasisyntax/loc stx
(#%app expr ...)))]
[(_ . more)
(syntax/loc stx
(#%app . more))])))