wisp
 
(Arne Babenhauserheide)
2017-10-10: update examples for doctests and sexped ones

update examples for doctests and sexped ones

diff --git a/examples/doctests-test.w b/examples/doctests-test.w
--- a/examples/doctests-test.w
+++ b/examples/doctests-test.w
@@ -9,17 +9,16 @@ define-module : examples doctests-test
 import : examples doctests
 
 define : foo
-    . "(test 'foo
-        (test-equal \"bar\" (foo)))
-    "
+    . #((tests 
+      ('foo
+        (test-equal "bar" (foo)))))
     . "bar"
 
 define %this-module : current-module
 define : main args
-       . " Testing doctests
-   (test 'mytest
-       (test-assert #t)
-       (test-assert #f))
-"
+       . " Testing doctests"
+       . #((tests ('mytest
+              (test-assert #t)
+              (test-assert #f))))
        doctests-testmod %this-module
 
diff --git a/examples/doctests-testone.scm b/examples/doctests-testone.scm
--- a/examples/doctests-testone.scm
+++ b/examples/doctests-testone.scm
@@ -5,9 +5,9 @@ exec guile -L $(dirname $(dirname $(real
 (import (examples doctests))
 
 (define (foo)
-    "(test 'foo
-        (test-equal \"bar\" (foo)))
-    "
+    #((tests 
+      ('foo
+        (test-equal "bar" (foo)))))
     "bar")
 
 (doctests-testmod (current-module))
diff --git a/examples/doctests.scm b/examples/doctests.scm
--- a/examples/doctests.scm
+++ b/examples/doctests.scm
@@ -1,13 +1,56 @@
 #!/usr/bin/env sh
-exec guile -L $(dirname $(dirname $(realpath "$0"))) -e '(@@ (examples doctests) main)' -s "$0" "$@"
+(# -*- wisp -*-)
+(guile -L $(dirname $(dirname $(realpath "$0"))) -c '(import (language wisp spec))')
+(exec guile -L $(dirname $(dirname $(realpath "$0"))) --language=wisp -e '(@@ (examples doctests) main)' -s "$0" "$@")
 ; !#
 
+;;; doctests --- simple testing by adding procedure-properties with tests.
+
+;;; Usage
+
+;; Add a tests property to a procedure to have simple unit tests.
+
+;; Simple tests:
+;;
+;; (define (A)
+;;     #((tests (test-eqv 'A (A))
+;;              (test-assert #t)))
+;;     'A)
+;;
+;; Named tests:
+;;
+;; (define (A)
+;;     #((tests ('test1 (test-eqv 'A (A))
+;;                      (test-assert #t))
+;;              ('test2 (test-assert #t))))
+;;     'A)
+;;
+;; Allows for docstrings:
+;;
+;; (define (A)
+;;     "returns 'A"
+;;     #((tests (test-eqv 'A (A))
+;;              (test-assert #t)))
+;;     'A)
+
+;; For writing the test before the implementation, start with the test and #f:
+
+;; (define (A)
+;;     #((tests (test-eqv 'A (A))))
+;;     #f)
+
+;; With wisp, you currently need to use the literal #((tests (...)))
+;; TODO: add array parsing to wisp following quoting with ':
+;;       # a b → #(a b) and # : a b c → #((a b))
+
+
 (define-module (examples doctests)
               #:export (doctests-testmod))
 
 (import (ice-9 optargs)
          (ice-9 rdelim)
          (ice-9 match)
+         (ice-9 pretty-print)
          (oop goops)
          (texinfo reflection))
 
@@ -35,19 +78,7 @@ exec guile -L $(dirname $(dirname $(real
                  (loop (string-drop s 1) (+ i 1))))))
 
 (define (doctests-extract-from-string s)
-       "Extract all test calls from a given string.
-
-          This is an example test:
-
-          (test 'mytest
-              (define v (make-vector 5 99))
-              (test-assert (vector? v))
-              (test-eqv 99 (vector-ref v 2))
-              (vector-set! v 2 7)
-              (test-eqv 7 (vector-ref v 2)))
-          (test 'mytest2
-              (test-assert #t))
-"
+       "Extract all test calls from a given string."
        (let lp
            ((str s)
              (tests (list)))
@@ -65,50 +96,85 @@ exec guile -L $(dirname $(dirname $(real
                                      (λ () (read)))
                                  tests))))))))
 
+(define (subtract a b)
+    "Subtract B from A."
+    #((tests (test-eqv 3 (subtract 5 2))))
+    (- a b))
+
 (define (doctests-testmod mod)
-       "Execute all doctests in the current module"
+       "Execute all doctests in the current module
+
+          This procedure provides an example test:"
+       #((tests 
+            ('mytest
+              (define v (make-vector 5 99))
+              (test-assert (vector? v))
+              (test-eqv 99 (vector-ref v 2))
+              (vector-set! v 2 7)
+              (test-eqv 7 (vector-ref v 2)))
+            ('mytest2
+              (test-assert #t))))
+       ;; thanks to Vítor De Araújo: https://lists.gnu.org/archive/html/guile-user/2017-08/msg00003.html
        (let*
            ((names (module-map (λ (sym var) sym) mod))
              (filename
-                 (if (module-filename mod) (string-join (string-split (module-filename mod) #\/) "-")
+                 (if (module-filename mod) (string-join (string-split (module-filename mod) #\/ ) "-")
                      (string-join (cons "._" (map symbol->string (module-name mod))) "-")))
-             (docstrings
-                 (map (λ (x) (if (procedure? x) (procedure-documentation x)))
+             (doctests
+                 (map (λ (x) (if (procedure? x) (procedure-property x 'tests)))
                      (map (λ (x) (module-ref mod x)) names))))
            (let loop
                ((names names)
-                 (docstrings docstrings))
-               (when (not (null? docstrings))
-                   (when (string? (car docstrings))
-                       (let*
-                           ((name (car names))
-                             (docstring (car docstrings)))
-                           (let loop-tests
-                              ((doctests (doctests-extract-from-string (car docstrings))))
-                              (when (and (list? doctests) (not (null? doctests)))
-                                 (let*
-                                   ((doctest (car doctests))
-                                     (testid
-                                        (if (not (list? doctest))
-                                             #f
-                                             (string-join (list filename (symbol->string name) (symbol->string (primitive-eval (car (cdr doctest)))))
-                                                         "--")))
-                                     (cleaned
-                                         (if (not (list? doctest))
-                                           '#f
-                                           (append
-                                               (cons 'begin
-                                                   (cons '(import (srfi srfi-64))
-                                                       (cons
-                                                           (list 'test-begin testid)
-                                                           (cdr (cdr doctest)))))
-                                               (list (list 'test-end testid))))))
-                                   (when cleaned
-                                       (let ()
-                                           (eval cleaned mod))
-                                       (newline))
-                                   (loop-tests (cdr doctests)))))))
-                   (loop (cdr names) (cdr docstrings))))))
+                 (doctests doctests))
+               ;; pretty-print doctests
+               ;; newline
+               (when (pair? doctests)
+                   (let*
+                       ((name (car names))
+                         (doctest (car doctests)))
+                       (let loop-tests
+                          ((doctest doctest))
+                          (when (and (pair? doctest) (car doctest) (pair? (car doctest)))
+                             ;; pretty-print : car doctest
+                             ;; newline
+                             (let*
+                               (
+                                 (testid
+                                    (match doctest
+                                      (((('quote id) tests ...) moretests ...)
+                                        (string-join (list filename (symbol->string name) (symbol->string id))
+                                                     "--"))
+                                      ((tests ...)
+                                        (string-join (list filename (symbol->string name))
+                                                     "--"))))
+                                 (body
+                                     (match doctest
+                                      (((('quote id) test tests ...) moretests ...)
+                                        (cons test tests))
+                                      ((tests ...)
+                                        tests)))
+                                 (cleaned
+                                        (cons 'begin
+                                            (cons '(import (srfi srfi-64)) 
+                                                (cons 
+                                                    (list 'test-begin (or testid ""))
+                                                    (append
+                                                        body
+                                                        (list (list 'test-end (or testid "")))))))))
+                               ;; pretty-print testid
+                               ;; pretty-print body
+                               ;; pretty-print cleaned
+                               ;; newline
+                               (when cleaned
+                                   (let ()
+                                       (eval cleaned mod))
+                                   (newline))
+                               (match doctest
+                                      (((('quote id) tests ...) moretests ...)
+                                        (loop-tests moretests))
+                                      ((tests ...)
+                                        #t))))))
+                   (loop (cdr names) (cdr doctests))))))
 
 (define %this-module (current-module))
 (define (main args)