matcher.scm 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Mike Sperber
  3. ; Combinators for predicates, useful for test suites.
  4. (define-record-type matcher :matcher
  5. (make-matcher predicate
  6. sexpr)
  7. matcher?
  8. (predicate matcher-predicate)
  9. (sexpr matcher-sexpr))
  10. (define-record-discloser :matcher
  11. (lambda (m)
  12. (list 'matcher (matcher-sexpr m))))
  13. (define (matches? matcher val)
  14. ((matcher-predicate matcher) val))
  15. (define (is p? . rest)
  16. (cond ((pair? rest)
  17. (let ((val (car rest)))
  18. (make-matcher (lambda (x)
  19. (p? x val))
  20. `(is ,p? ,val))))
  21. ((procedure? p?)
  22. (make-matcher p? `(is ,p?)))
  23. (else (make-matcher (lambda (x)
  24. (equal? x p?))
  25. `(is ,p?)))))
  26. (define (anything)
  27. (make-matcher (lambda (x) #t)
  28. `anything))
  29. (define (opposite matcher)
  30. (make-matcher (lambda (x)
  31. (not (matches? matcher x)))
  32. `(not ,(matcher-sexpr matcher))))
  33. (define (is-true)
  34. (make-matcher (lambda (x) x)
  35. 'is-true))
  36. (define (is-false)
  37. (make-matcher (lambda (x) (not x))
  38. 'is-false))
  39. (define (is-null)
  40. (make-matcher (lambda (x) (null? x))
  41. 'is-false))
  42. (define (is-within val epsilon)
  43. (make-matcher (lambda (x)
  44. (and (number? x)
  45. (< (magnitude (- val x )) epsilon)))
  46. `(is-within ,val ,epsilon)))
  47. (define (member-of list)
  48. (make-matcher (lambda (x) (member x list))
  49. `(is-member ,list)))
  50. (define (all-of . matchers)
  51. (make-matcher (lambda (x)
  52. (every? (lambda (matcher)
  53. (matches? matcher x))
  54. matchers))
  55. `(all-of ,@(map matcher-sexpr matchers))))
  56. (define (any-of . matchers)
  57. (make-matcher (lambda (x)
  58. (any? (lambda (matcher)
  59. (matches? matcher x))
  60. matchers))
  61. `(any-of ,@(map matcher-sexpr matchers))))
  62. (define (list-where-all matcher)
  63. (make-matcher (lambda (l)
  64. (and (list? l)
  65. (every? (lambda (x)
  66. (matches? matcher x))
  67. l)))
  68. `(list-where-each ,matcher)))
  69. (define (list-where-any matcher)
  70. (make-matcher (lambda (l)
  71. (and (list? l)
  72. (any? (lambda (x)
  73. (matches? matcher x))
  74. l)))
  75. `(list-where-any ,matcher)))
  76. (define (list-of . matchers)
  77. (let ((count (length matchers)))
  78. (make-matcher (lambda (x)
  79. (and (list? x)
  80. (let loop ((matchers matchers)
  81. (els x))
  82. (cond
  83. ((null? matchers) (null? els))
  84. ((null? els) #f)
  85. (else
  86. (and (matches? (car matchers) (car els))
  87. (loop (cdr matchers) (cdr els))))))))
  88. `(list-of ,@matchers))))
  89. (define (vector-of . matchers)
  90. (let* ((matchers (list->vector matchers))
  91. (count (vector-length matchers)))
  92. (make-matcher (lambda (x)
  93. (and (vector? x)
  94. (= count (vector-length x))
  95. (let loop ((i 0))
  96. (if (= i count)
  97. #t
  98. (and (matches? (vector-ref matchers i))
  99. (loop (+ 1 i)))))))
  100. `(vector-of ,matchers))))
  101. (define (pair-of car-matcher cdr-matcher)
  102. (make-matcher (lambda (x)
  103. (and (pair? x)
  104. (matches? car-matcher (car x))
  105. (matches? cdr-matcher (cdr x))))
  106. `(pair-of ,car-matcher ,cdr-matcher)))