unfold pat:and to uncover more factoring opportunities

Side clauses introduce pat:and, very common in stxclasses.
This commit is contained in:
Ryan Culpepper 2013-02-28 17:53:20 -05:00
parent d5068278f4
commit 34c1bdfc97

View File

@ -22,6 +22,13 @@
;; ============================================================ ;; ============================================================
(begin-for-syntax
;; controls debugging output for optimization successes and failures
(define DEBUG-OPT-SUCCEED #f)
(define DEBUG-OPT-FAIL #f))
;; ============================================================
(provide define-syntax-class (provide define-syntax-class
define-splicing-syntax-class define-splicing-syntax-class
define-integrable-syntax-class define-integrable-syntax-class
@ -448,9 +455,13 @@ Conventions:
#'(try k ...)] #'(try k ...)]
[(parse:S* ins rows ks) [(parse:S* ins rows ks)
;; Split into uniform sequences of rows according to pattern in column1 ;; Split into uniform sequences of rows according to pattern in column1
(with-syntax ([((parser sub-rows sub-ks) ...) (let ([ins (syntax->list #'ins)]
(split-S* (syntax->list #'rows) (syntax->list #'ks))]) [rows (map syntax->list (syntax->list #'rows))]
#'(try (parser ins sub-rows sub-ks) ...))])) [ks (syntax->list #'ks)])
(let-values ([(ins rows) (unfold-and-patterns ins rows)])
(with-syntax ([ins ins]
[((parser sub-rows sub-ks) ...) (split-S* rows ks)])
#'(try (parser ins sub-rows sub-ks) ...))))]))
(define-syntax (parse:S*/pairs stx) (define-syntax (parse:S*/pairs stx)
(syntax-case stx () (syntax-case stx ()
@ -458,7 +469,7 @@ Conventions:
;; First pattern in each row is pat:pair ;; First pattern in each row is pat:pair
(with-syntax ([((#s(pat:pair _ head tail) . row) ...) #'rows] (with-syntax ([((#s(pat:pair _ head tail) . row) ...) #'rows]
[((x cx pr es) . ins) #'ins]) [((x cx pr es) . ins) #'ins])
(when #t (when DEBUG-OPT-SUCCEED
(when (> (length (syntax->list #'rows)) 1) (when (> (length (syntax->list #'rows)) 1)
(eprintf "** pairs\n"))) (eprintf "** pairs\n")))
#'(let-values ([(datum tcx) #'(let-values ([(datum tcx)
@ -483,17 +494,52 @@ Conventions:
(with-syntax ([((pat1 . row) ...) #'rows] (with-syntax ([((pat1 . row) ...) #'rows]
[((x cx pr es) . ins) #'ins]) [((x cx pr es) . ins) #'ins])
(with-syntax ([pat1 (stx-car #'(pat1 ...))]) (with-syntax ([pat1 (stx-car #'(pat1 ...))])
(when #t (when DEBUG-OPT-SUCCEED
(when (> (length (syntax->list #'rows)) 1) (when (> (length (syntax->list #'rows)) 1)
(eprintf "** same: ~e\n" (syntax->datum #'pat1)))) (eprintf "** same: ~e\n" (syntax->datum #'pat1))))
#'(parse:S x cx pat1 pr es (parse:S* ins (row ...) ks))))])) #'(parse:S x cx pat1 pr es (parse:S* ins (row ...) ks))))]))
(begin-for-syntax (begin-for-syntax
(define (unfold-and-patterns ins rows)
;; unfold-and : pattern (listof pattern) -> (values pattern (listof pattern))
(define (unfold-and p onto)
(match (stx-e p)
[(pat:and _as subpatterns)
;; pat:and is worth unfolding if first subpattern is not pat:action
(let* ([subpatterns (syntax->list subpatterns)]
[first-sub (car subpatterns)]
[rest-subs (cdr subpatterns)])
(cond [(not (pat:action? (stx-e first-sub)))
(when DEBUG-OPT-SUCCEED
(eprintf ">> unfolding: ~e\n" (syntax->datum p)))
(unfold-and first-sub
(*append rest-subs onto))]
[else (values p onto)]))]
[_ (values p onto)]))
(define (*append a b) (if (null? b) a (append a b)))
(define (make-and-pattern subs)
(cond [(null? subs) (create-pat:any)] ;; shouldn't happen
[(null? (cdr subs)) (car subs)]
[else
(let ([attrs 'unused]) ;; NOTE: attrs unused at this point, and it's a pain to recalc
(make-pat:and attrs subs))]))
(let-values ([(col1 col2)
(for/lists (col1 col2) ([row (in-list rows)])
(unfold-and (car row) null))])
(cond [(ormap pair? col2)
(values (cons (car ins) ins)
(for/list ([row (in-list rows)]
[col1 (in-list col1)]
[col2 (in-list col2)])
(list* col1 (make-and-pattern col2) (cdr row))))]
[else (values ins rows)])))
(define (split-S* rows ks) (define (split-S* rows ks)
(cond [(null? rows) (cond [(null? rows)
null] null]
[else [else
(define row1 (syntax->list (car rows))) (define row1 (stx->list (car rows)))
(define pat1 (car row1)) (define pat1 (car row1))
(define k1 (car ks)) (define k1 (car ks))
;; Now accumulate rows starting with patterns like pat1 ;; Now accumulate rows starting with patterns like pat1
@ -503,7 +549,7 @@ Conventions:
(cons (list parser (reverse rrows) (reverse rks)) (cons (list parser (reverse rrows) (reverse rks))
(split-S* rows ks))] (split-S* rows ks))]
[else [else
(define row1 (syntax->list (car rows))) (define row1 (stx->list (car rows)))
(define pat1 (car row1)) (define pat1 (car row1))
(define k1 (car ks)) (define k1 (car ks))
(cond [(keep? pat1) (cond [(keep? pat1)
@ -528,7 +574,7 @@ Conventions:
(lambda (x) (lambda (x)
(pattern-equal? pat1 x)) (pattern-equal? pat1 x))
(lambda (x) (lambda (x)
(when #t (when DEBUG-OPT-FAIL
(when (pattern-equal? pat1 x) (when (pattern-equal? pat1 x)
(eprintf "** cannot factor out ~e\n" (syntax->datum x)))) (eprintf "** cannot factor out ~e\n" (syntax->datum x))))
#f)))])) #f)))]))
@ -688,7 +734,7 @@ Conventions:
(pattern-equal? (ehpat-head a) (ehpat-head b)))] (pattern-equal? (ehpat-head a) (ehpat-head b)))]
;; FIXME: more? ;; FIXME: more?
[else #f]))) [else #f])))
(when #t (when DEBUG-OPT-FAIL
(when (and (equal? (syntax->datum a) (syntax->datum b)) (when (and (equal? (syntax->datum a) (syntax->datum b))
(eq? result #f)) (eq? result #f))
(eprintf "** pattern-equal? failed on ~e\n" (syntax->datum a)))) (eprintf "** pattern-equal? failed on ~e\n" (syntax->datum a))))