gen-match:
- use begin-with-definitions for code clarity - rename some variables - better contracts (comments) test-structure: - delete unused field update-counts: - general reformatting - delete dead code - refactoring to eliminate duplication
This commit is contained in:
parent
c702686b01
commit
32e8e72175
|
@ -19,11 +19,7 @@
|
||||||
(lib "etc.ss")
|
(lib "etc.ss")
|
||||||
"match-error.ss")
|
"match-error.ss")
|
||||||
|
|
||||||
|
;; mark-patlist : listof[x] -> listof[(cons x #f)]
|
||||||
|
|
||||||
;;!(function mark-patlist
|
|
||||||
;; (form (mark-patlist clauses) -> marked-clause-list)
|
|
||||||
;; (contract list -> list))
|
|
||||||
;; This function takes each clause from the match expression and
|
;; This function takes each clause from the match expression and
|
||||||
;; pairs it with the dummy value #f. This value will be set! when
|
;; pairs it with the dummy value #f. This value will be set! when
|
||||||
;; the pattern matcher compiles a possible successful match for
|
;; the pattern matcher compiles a possible successful match for
|
||||||
|
@ -61,13 +57,13 @@
|
||||||
;; are in essense partially evaluated tests. The cdr of the
|
;; are in essense partially evaluated tests. The cdr of the
|
||||||
;; result is a function which takes a failure function and a list
|
;; result is a function which takes a failure function and a list
|
||||||
;; of let-bound expressions and returns a success-function.
|
;; of let-bound expressions and returns a success-function.
|
||||||
(define (test-list-with-success-func exp car-patlist stx success-func)
|
(define (test-list-with-success-func exp pat/mark stx success-func)
|
||||||
(define-values (pat body fail-sym) (parse-clause (car car-patlist)))
|
(define-values (pat body fail-sym) (parse-clause (car pat/mark)))
|
||||||
(define (success fail let-bound)
|
(define (success fail let-bound)
|
||||||
(if (not success-func)
|
(if (not success-func)
|
||||||
(lambda (sf bv)
|
(lambda (sf bv)
|
||||||
;; mark this pattern as reached
|
;; mark this pattern as reached
|
||||||
(set-cdr! car-patlist #t)
|
(set-cdr! pat/mark #t)
|
||||||
(with-syntax ([fail-var fail-sym]
|
(with-syntax ([fail-var fail-sym]
|
||||||
[(bound-vars ...) (map car bv)]
|
[(bound-vars ...) (map car bv)]
|
||||||
[(args ...) (map (lambda (b) (subst-bindings (cdr b) let-bound)) bv)]
|
[(args ...) (map (lambda (b) (subst-bindings (cdr b) let-bound)) bv)]
|
||||||
|
@ -80,7 +76,7 @@
|
||||||
#'(let ([bound-vars args] ...) . body))))
|
#'(let ([bound-vars args] ...) . body))))
|
||||||
(lambda (sf bv)
|
(lambda (sf bv)
|
||||||
;; mark this pattern as reached
|
;; mark this pattern as reached
|
||||||
(set-cdr! car-patlist #t)
|
(set-cdr! pat/mark #t)
|
||||||
(let ((bv (map
|
(let ((bv (map
|
||||||
(lambda (bind)
|
(lambda (bind)
|
||||||
(cons (car bind)
|
(cons (car bind)
|
||||||
|
@ -120,38 +116,38 @@
|
||||||
;; about a match (namely the bound match variables) is at the bottom
|
;; about a match (namely the bound match variables) is at the bottom
|
||||||
;; of the recursion tree. The success function must take two arguments
|
;; of the recursion tree. The success function must take two arguments
|
||||||
;; and it should return a syntax object.
|
;; and it should return a syntax object.
|
||||||
(define/opt (gen-match exp patlist stx [success-func #f])
|
(define/opt (gen-match exp patlist stx [success-func #f])
|
||||||
(when (stx-null? patlist)
|
(begin-with-definitions
|
||||||
(match:syntax-err stx "null clause list"))
|
(when (stx-null? patlist)
|
||||||
(let* (;; We set up the list of
|
(match:syntax-err stx "null clause list"))
|
||||||
;; clauses so that one can mark that they have been "reached".
|
;; We set up the list of
|
||||||
[marked-clauses (mark-patlist patlist)]
|
;; clauses so that one can mark that they have been "reached".
|
||||||
[failure-func #'(match-failure)]
|
(define marked-clauses (mark-patlist patlist))
|
||||||
;; iterate through list and render each pattern to a list of partially compiled tests
|
(define failure-func #'(match-failure))
|
||||||
;; and success functions.
|
;; iterate through list and render each pattern to a list of partially compiled tests
|
||||||
;; These are partially compiled
|
;; and success functions.
|
||||||
;; because the test structures containa a function that needs to
|
;; These are partially compiled
|
||||||
;; be coupled with the other functions of the other test
|
;; because the test structures containa a function that needs to
|
||||||
;; structures before actual compilation results.
|
;; be coupled with the other functions of the other test
|
||||||
[rendered-list (map (lambda (clause) (test-list-with-success-func
|
;; structures before actual compilation results.
|
||||||
exp clause stx success-func))
|
(define rendered-list (map (lambda (clause) (test-list-with-success-func
|
||||||
marked-clauses)]
|
exp clause stx success-func))
|
||||||
[_ (begin
|
marked-clauses))
|
||||||
(update-counts rendered-list)
|
(update-counts rendered-list)
|
||||||
(tag-negate-tests rendered-list)
|
(tag-negate-tests rendered-list)
|
||||||
(update-binding-counts rendered-list))]
|
(update-binding-counts rendered-list)
|
||||||
;; couple the partially compiled tests together into the final result.
|
;; couple the partially compiled tests together into the final result.
|
||||||
[compiled-exp
|
(define compiled-exp
|
||||||
((meta-couple (reorder-all-lists rendered-list)
|
((meta-couple (reorder-all-lists rendered-list)
|
||||||
(lambda (sf bv) failure-func)
|
(lambda (sf bv) failure-func)
|
||||||
'()
|
'()
|
||||||
'())
|
'())
|
||||||
'() '())]
|
'() '()))
|
||||||
;; Also wrap the final compilation in syntax which binds the
|
;; Also wrap the final compilation in syntax which binds the
|
||||||
;; match-failure function.
|
;; match-failure function.
|
||||||
[compiled-match
|
(define compiled-match
|
||||||
#`(let ([match-failure (lambda () #,(quasisyntax/loc stx (match:error #,exp)))])
|
#`(let ([match-failure (lambda () #,(quasisyntax/loc stx (match:error #,exp)))])
|
||||||
#,compiled-exp)])
|
#,compiled-exp))
|
||||||
(unreachable marked-clauses stx)
|
(unreachable marked-clauses stx)
|
||||||
compiled-match))
|
compiled-match))
|
||||||
)
|
)
|
|
@ -31,7 +31,6 @@
|
||||||
;; of bind-exp-stx
|
;; of bind-exp-stx
|
||||||
;; bind-count - is the number of times in the bind-exp is found in the
|
;; bind-count - is the number of times in the bind-exp is found in the
|
||||||
;; test list in which this test is a member
|
;; test list in which this test is a member
|
||||||
;; times-used-neg - ??? (this appears to never be used)
|
|
||||||
;; used-set-neg - ???
|
;; used-set-neg - ???
|
||||||
;; closest-shape-tst - ???
|
;; closest-shape-tst - ???
|
||||||
;; equal-set - ???
|
;; equal-set - ???
|
||||||
|
@ -43,7 +42,6 @@
|
||||||
bind-exp-stx
|
bind-exp-stx
|
||||||
bind-exp
|
bind-exp
|
||||||
bind-count
|
bind-count
|
||||||
times-used-neg
|
|
||||||
used-set-neg
|
used-set-neg
|
||||||
closest-shape-tst
|
closest-shape-tst
|
||||||
equal-set)
|
equal-set)
|
||||||
|
@ -65,7 +63,7 @@
|
||||||
;; comp - the compilation function which will finish the compilation
|
;; comp - the compilation function which will finish the compilation
|
||||||
;; after tests have been reordered
|
;; after tests have been reordered
|
||||||
(define (make-shape-test test exp comp)
|
(define (make-shape-test test exp comp)
|
||||||
(make-test test comp #t 0 '() exp (syntax-object->datum exp) 1 0 '() #f '()))
|
(make-test test comp #t 0 '() exp (syntax-object->datum exp) 1 '() #f '()))
|
||||||
|
|
||||||
;;!(function make-reg-test
|
;;!(function make-reg-test
|
||||||
;; (form (make-shape-test test exp comp) -> test-struct)
|
;; (form (make-shape-test test exp comp) -> test-struct)
|
||||||
|
@ -81,7 +79,7 @@
|
||||||
;; comp - the compilation function which will finish the compilation
|
;; comp - the compilation function which will finish the compilation
|
||||||
;; after tests have been reordered
|
;; after tests have been reordered
|
||||||
(define (make-reg-test test exp comp)
|
(define (make-reg-test test exp comp)
|
||||||
(make-test test comp #f 0 '() exp (syntax-object->datum exp) 1 0 '() #f '()))
|
(make-test test comp #f 0 '() exp (syntax-object->datum exp) 1 '() #f '()))
|
||||||
|
|
||||||
;;!(function make-act-test
|
;;!(function make-act-test
|
||||||
;; (form (make-shape-test test exp comp) -> test-struct)
|
;; (form (make-shape-test test exp comp) -> test-struct)
|
||||||
|
@ -99,7 +97,7 @@
|
||||||
;; comp - the compilation function which will finish the compilation
|
;; comp - the compilation function which will finish the compilation
|
||||||
;; after tests have been reordered
|
;; after tests have been reordered
|
||||||
(define (make-act act-name exp comp)
|
(define (make-act act-name exp comp)
|
||||||
(make-test act-name comp #f -1 '() exp (syntax-object->datum exp) 1 -1 '() #f '()))
|
(make-test act-name comp #f -1 '() exp (syntax-object->datum exp) 1 '() #f '()))
|
||||||
|
|
||||||
;;!(function action-test?
|
;;!(function action-test?
|
||||||
;; (form (action-test? test) -> bool)
|
;; (form (action-test? test) -> bool)
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
(require "test-structure.scm"
|
(require "test-structure.scm"
|
||||||
"match-helper.ss"
|
"match-helper.ss"
|
||||||
|
(lib "etc.ss")
|
||||||
(lib "list.ss"))
|
(lib "list.ss"))
|
||||||
|
|
||||||
;;!(function test-filter
|
;;!(function test-filter
|
||||||
|
@ -17,14 +18,6 @@
|
||||||
|
|
||||||
(define (test-filter tlist)
|
(define (test-filter tlist)
|
||||||
(filter (lambda (t) (not (= -1 (test-times-used t)))) tlist))
|
(filter (lambda (t) (not (= -1 (test-times-used t)))) tlist))
|
||||||
#;(define test-filter
|
|
||||||
(lambda (tlist)
|
|
||||||
(if (null? tlist)
|
|
||||||
'()
|
|
||||||
(if (= -1 (test-times-used (car tlist)))
|
|
||||||
(test-filter (cdr tlist))
|
|
||||||
(cons (car tlist)
|
|
||||||
(test-filter (cdr tlist)))))))
|
|
||||||
|
|
||||||
|
|
||||||
;; !(function inverse-in
|
;; !(function inverse-in
|
||||||
|
@ -33,30 +26,26 @@
|
||||||
;; This function checks to see if any of the members of the test-list
|
;; This function checks to see if any of the members of the test-list
|
||||||
;; would be eliminated by the function if the test was in the test so far
|
;; would be eliminated by the function if the test was in the test so far
|
||||||
;; list. This is the opposite of what the in function does.
|
;; list. This is the opposite of what the in function does.
|
||||||
(define inverse-in
|
(define (inverse-in test test-list)
|
||||||
(lambda (test test-list)
|
(or (pos-inverse-in test test-list)
|
||||||
(or (pos-inverse-in test test-list)
|
(neg-inverse-in test test-list)))
|
||||||
(neg-inverse-in test test-list))))
|
|
||||||
|
|
||||||
(define pos-inverse-in
|
(define (pos-inverse-in test test-list)
|
||||||
(lambda (test test-list)
|
(let ([test-with-implied (cons test (implied test))])
|
||||||
(let ((test-with-implied (cons test (implied test))))
|
(ormap (lambda (t) (in t test-with-implied))
|
||||||
(ormap (lambda (t) (in t test-with-implied))
|
test-list)))
|
||||||
test-list)
|
|
||||||
)))
|
|
||||||
|
|
||||||
(define neg-inverse-in
|
(define (neg-inverse-in test test-list)
|
||||||
(lambda (test test-list)
|
(let ([test-with-implied (cons test (implied test))])
|
||||||
(let ((test-with-implied (cons test (implied test))))
|
(ormap (lambda (t) (in `(not ,t) test-with-implied))
|
||||||
(ormap (lambda (t) (in `(not ,t) test-with-implied))
|
test-list)))
|
||||||
test-list)
|
|
||||||
)))
|
|
||||||
|
|
||||||
(define logical-member
|
(define (logical-member item lst)
|
||||||
(lambda (item lst)
|
(ormap (lambda (cur)
|
||||||
(ormap (lambda (cur)
|
(logical-equal? item cur))
|
||||||
(logical-equal? item cur))
|
lst))
|
||||||
lst)))
|
|
||||||
|
|
||||||
(define (logical-equal? a b)
|
(define (logical-equal? a b)
|
||||||
(or (equal? a b) #t
|
(or (equal? a b) #t
|
||||||
|
@ -72,132 +61,87 @@
|
||||||
(eq? (car a) 'list?)
|
(eq? (car a) 'list?)
|
||||||
(eq? (car b) 'null?)
|
(eq? (car b) 'null?)
|
||||||
(equal? (cadr a) (cadr b)))))
|
(equal? (cadr a) (cadr b)))))
|
||||||
;; this implements the above code
|
|
||||||
|
|
||||||
#;(define logical-equal?
|
;; truncate-list : int listof[int] -> listof[int]
|
||||||
(lambda x
|
;; truncate-list-neg : int listof[int] -> listof[int]
|
||||||
(if (pair? x)
|
;; truncate-list removes all elements of a list after the element at least as large as p
|
||||||
(let ((exp8163 (cdr x)))
|
;; truncate-list-neg removes the found element as well
|
||||||
(if (and (pair? exp8163) (null? (cdr exp8163)))
|
(define-values (truncate-list truncate-list-neg)
|
||||||
(if (equal? (car exp8163) (car x))
|
(let ([mk (lambda (pos-f)
|
||||||
#t
|
(define (f p l)
|
||||||
(let ((exp8164 (car x)))
|
(cond [(null? l)
|
||||||
(if (and (pair? exp8164) (equal? (car exp8164) 'list?))
|
'()]
|
||||||
(let ((exp8165 (cdr exp8164)))
|
[(>= p (car l))
|
||||||
(if (and (pair? exp8165) (null? (cdr exp8165)))
|
(pos-f p)]
|
||||||
(let ((exp8166 (car exp8163)))
|
[else
|
||||||
(if (and (pair? exp8166) (equal? (car exp8166) 'null?))
|
(cons (car l)
|
||||||
(let ((exp8167 (cdr exp8166)))
|
(f p (cdr l)))]))
|
||||||
(if (and (pair? exp8167)
|
f)])
|
||||||
(null? (cdr exp8167))
|
(values (mk list) (mk (lambda (x) '())))))
|
||||||
(equal? (car exp8167) (car exp8165)))
|
|
||||||
((lambda (x) #t) (car exp8165))
|
|
||||||
((lambda (else) #f) x)))
|
|
||||||
((lambda (else) #f) x)))
|
|
||||||
((lambda (else) #f) x)))
|
|
||||||
((lambda (else) #f) x))))
|
|
||||||
((lambda (else) #f) x)))
|
|
||||||
((lambda (else) #f) x))))
|
|
||||||
|
|
||||||
(define truncate-list
|
|
||||||
(lambda (pos used-set-neg)
|
|
||||||
(cond ((null? used-set-neg)
|
|
||||||
'())
|
|
||||||
((>= pos (car used-set-neg))
|
|
||||||
(list pos))
|
|
||||||
(else
|
|
||||||
(cons (car used-set-neg)
|
|
||||||
(truncate-list pos (cdr used-set-neg)))))))
|
|
||||||
|
|
||||||
(define truncate-list-neg
|
|
||||||
(lambda (pos used-set-neg)
|
|
||||||
(cond ((null? used-set-neg)
|
|
||||||
'())
|
|
||||||
((>= pos (car used-set-neg))
|
|
||||||
'())
|
|
||||||
(else
|
|
||||||
(cons (car used-set-neg)
|
|
||||||
(truncate-list-neg pos (cdr used-set-neg)))))))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;!(function update-count
|
;; update-count : test listof[test] int -> void
|
||||||
;; (form (update-count test tests-rest pos) -> void)
|
|
||||||
;; (contract (test-struct list integer) -> void))
|
|
||||||
;; This function updates the test-times-used and test-used-set
|
;; This function updates the test-times-used and test-used-set
|
||||||
;; fields of the test structs. These fields are essential to
|
;; fields of the test structs. These fields are essential to
|
||||||
;; determining the order of the tests.
|
;; determining the order of the tests.
|
||||||
(define update-count
|
(define (update-count test tests-rest pos mem-table)
|
||||||
(lambda (test tests-rest pos mem-table)
|
(let loop ([l tests-rest]
|
||||||
(let loop ((l tests-rest)
|
[p (add1 pos)])
|
||||||
(p (add1 pos)))
|
|
||||||
(if (null? l)
|
(if (null? l)
|
||||||
(begin
|
(hash-table-get mem-table (test-tst test)
|
||||||
;; memoize
|
(lambda ()
|
||||||
(hash-table-get mem-table (test-tst test)
|
(hash-table-put!
|
||||||
(lambda ()
|
mem-table
|
||||||
(hash-table-put!
|
(test-tst test)
|
||||||
mem-table
|
(list (test-used-set test)
|
||||||
(test-tst test) (list (test-used-set test)
|
(test-used-set-neg test)))))
|
||||||
(test-used-set-neg test)))))
|
(let ([entry-pair
|
||||||
)
|
|
||||||
(let ((entry-pair
|
|
||||||
(hash-table-get mem-table (test-tst test)
|
(hash-table-get mem-table (test-tst test)
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(when (
|
(when (logical-member (test-tst test) (car l))
|
||||||
;member
|
|
||||||
logical-member
|
|
||||||
;inverse-in
|
|
||||||
(test-tst test) (car l))
|
|
||||||
(set-test-times-used! test (add1 (test-times-used test)))
|
(set-test-times-used! test (add1 (test-times-used test)))
|
||||||
(set-test-used-set! test (cons p (test-used-set test)))
|
(set-test-used-set! test (cons p (test-used-set test)))
|
||||||
(set-test-equal-set! test (cons p (test-equal-set test)))
|
(set-test-equal-set! test (cons p (test-equal-set test))))
|
||||||
)
|
|
||||||
(when (neg-inverse-in (test-tst test) (car l))
|
(when (neg-inverse-in (test-tst test) (car l))
|
||||||
(set-test-used-set-neg! test (cons p (test-used-set-neg test))))
|
(set-test-used-set-neg! test (cons p (test-used-set-neg test))))
|
||||||
(loop (cdr l) (add1 p))
|
(loop (cdr l) (add1 p))))])
|
||||||
))))
|
|
||||||
(when (and (list? entry-pair) (not (null? entry-pair)))
|
(when (and (list? entry-pair) (not (null? entry-pair)))
|
||||||
(let ((trun-used (truncate-list pos (car entry-pair))))
|
(let ([trun-used (truncate-list pos (car entry-pair))])
|
||||||
(set-test-used-set! test trun-used)
|
(set-test-used-set! test trun-used)
|
||||||
(set-test-equal-set! test trun-used)
|
(set-test-equal-set! test trun-used)
|
||||||
(set-test-times-used! test (length trun-used))
|
(set-test-times-used! test (length trun-used))
|
||||||
(set-test-used-set-neg! test (truncate-list-neg pos (cadr entry-pair)))))
|
(set-test-used-set-neg! test (truncate-list-neg pos (cadr entry-pair)))))))))
|
||||||
)))))
|
|
||||||
|
|
||||||
;;!(function update-counts
|
;; update-counts : listof[(cons test any)] -> void
|
||||||
;; (form (update-counts render-list) -> void)
|
|
||||||
;; (contract list -> void))
|
|
||||||
;; This function essentially calls update-count on every test in
|
;; This function essentially calls update-count on every test in
|
||||||
;; all of the test lists.
|
;; all of the test lists.
|
||||||
(define update-counts
|
(define (update-counts render-list)
|
||||||
(lambda (render-list)
|
(let* ([mem-table (make-hash-table 'equal)]
|
||||||
(let* ((mem-table (make-hash-table 'equal))
|
[test-master-list (map (compose test-filter car) render-list)]
|
||||||
(test-master-list (map test-filter
|
[test-so-far-lists ;; horrible name
|
||||||
(map car render-list)))
|
|
||||||
(test-so-far-lists ;; horrible name
|
|
||||||
(map
|
(map
|
||||||
(lambda (tl)
|
(lambda (tl) (map test-tst (test-filter tl)))
|
||||||
(let ((f (map test-tst (test-filter tl))))
|
test-master-list)])
|
||||||
f))
|
(let loop ([tml test-master-list]
|
||||||
test-master-list)))
|
[tsf test-so-far-lists]
|
||||||
(let loop ((tml test-master-list)
|
[pos 1])
|
||||||
(tsf test-so-far-lists)
|
|
||||||
(pos 1))
|
|
||||||
(if (null? tml)
|
(if (null? tml)
|
||||||
'()
|
(void)
|
||||||
(begin
|
(begin
|
||||||
(for-each (lambda (t)
|
(for-each
|
||||||
(set-test-times-used! t 1)
|
(lambda (t)
|
||||||
(set-test-used-set!
|
(set-test-times-used! t 1)
|
||||||
t
|
(set-test-used-set!
|
||||||
(cons pos (test-used-set t)))
|
t
|
||||||
(set-test-equal-set!
|
(cons pos (test-used-set t)))
|
||||||
t
|
(set-test-equal-set!
|
||||||
(cons pos (test-equal-set t)))
|
t
|
||||||
(update-count t (cdr tsf) pos mem-table))
|
(cons pos (test-equal-set t)))
|
||||||
(car tml))
|
(update-count t (cdr tsf) pos mem-table))
|
||||||
(loop (cdr tml) (cdr tsf) (add1 pos))))))))
|
(car tml))
|
||||||
|
(loop (cdr tml) (cdr tsf) (add1 pos)))))))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user