[plt-scheme] Fun with paren-shape
Okay, last abuse of syntax today. Promise!
{n -> (+ n 1)} is (lambda (n) (+ n 1)
> (map {n -> (+ n 3)} [1 .. 5])
(4 5 6 7)
> (map {n m -> (list (+ n 1) m)}
[1 .. 3] [2 .. 4])
((2 2) (3 3))
/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 (set-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=?
[{_ n ... -> expr}
(set-shaped? stx)
(quasisyntax/loc stx
(lambda (n ...) expr))]
[[_ 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))])))
(require index)