-;; -*- lisp -*-
+;;;; -*- Mode: Lisp; indent-tabs-mode: nil -*-
-(in-package :it.bese.FiveAM)
+(in-package :it.bese.fiveam)
;;;; ** Random (QuickCheck-ish) testing
(for-all (((a b) (gen-two-integers)))
(is (integerp a))
(is (integerp b)))"
- (with-unique-names (test-lambda-args)
+ (with-gensyms (test-lambda-args)
`(perform-random-testing
(list ,@(mapcar #'second bindings))
(lambda (,test-lambda-args)
(throw 'run-once
(list :guard-conditions-failed))))))))
-;;;; *** Implementation
+;;;; *** Implementation
;;;; We could just make FOR-ALL a monster macro, but having FOR-ALL be
;;;; a preproccessor for the perform-random-testing function is
(double-float most-positive-double-float)
(long-float most-positive-long-float)))
(bound (or bound (max most-positive (- most-negative)))))
- (coerce
+ (coerce
(ecase (random 2)
(0 ;; generate a positive number
(random (min most-positive bound)))
(- (random (min (- most-negative) bound)))))
type))))
-(defun gen-character (&key (code (gen-integer :min 0 :max (1- char-code-limit)))
+(defun gen-character (&key (code-limit char-code-limit)
+ (code (gen-integer :min 0 :max (1- code-limit)))
(alphanumericp nil))
"Returns a generator of characters.
non-NIL, limits the returned chars to those which pass
alphanumericp."
(lambda ()
- (if alphanumericp
- (loop
- for count upfrom 0
- for char = (code-char (funcall code))
- until (alphanumericp char)
- when (= 1000 count)
- do (error "After 1000 iterations ~S has still not generated an alphanumeric character :(."
- code)
- finally (return char))
- (code-char (funcall code)))))
+ (loop
+ for count upfrom 0
+ for char = (code-char (funcall code))
+ until (and char
+ (or (not alphanumericp)
+ (alphanumericp char)))
+ when (= 1000 count)
+ do (error "After 1000 iterations ~S has still not generated ~:[a valid~;an alphanumeric~] character :(."
+ code alphanumericp)
+ finally (return char))))
(defun gen-string (&key (length (gen-integer :min 0 :max 80))
(elements (gen-character))
repeat (funcall length)
collect (funcall elements))))
+(defun gen-tree (&key (size 20)
+ (elements (gen-integer :min -10 :max 10)))
+ "Returns a generator which producs random trees. SIZE control
+the approximate size of the tree, but don't try anything above
+ 30, you have been warned. ELEMENTS must be a generator which
+will produce the elements."
+ (labels ((rec (&optional (current-depth 0))
+ (let ((key (random (+ 3 (- size current-depth)))))
+ (cond ((> key 2)
+ (list (rec (+ current-depth 1))
+ (rec (+ current-depth 1))))
+ (t (funcall elements))))))
+ (lambda ()
+ (rec))))
+
(defun gen-buffer (&key (length (gen-integer :min 0 :max 50))
(element-type '(unsigned-byte 8))
(elements (gen-integer :min 0 :max (1- (expt 2 8)))))