wisp
 
(Arne Babenhauserheide)
2017-07-28: doctests: add preparsed scheme-versions and replace / in module-

doctests: add preparsed scheme-versions and replace / in module-filename by -

diff --git a/examples/doctests-test.scm b/examples/doctests-test.scm
new file mode 100755
--- /dev/null
+++ b/examples/doctests-test.scm
@@ -0,0 +1,19 @@
+#!/usr/bin/env sh
+exec guile -L $(dirname $(dirname $(realpath "$0"))) -e '(@@ (examples doctests-test) main)' -s "$0" "$@"
+; !#
+
+(define-module (examples doctests-test))
+
+(import (examples doctests))
+
+(define %this-module (current-module))
+(define (main args)
+       " Testing doctests
+   (test \"mytest\"
+       (test-assert #t)
+       (test-assert #f))
+"
+       (doctests-testmod %this-module))
+
+
+
diff --git a/examples/doctests.scm b/examples/doctests.scm
new file mode 100755
--- /dev/null
+++ b/examples/doctests.scm
@@ -0,0 +1,118 @@
+#!/usr/bin/env sh
+exec guile -L $(dirname $(dirname $(realpath "$0"))) -e '(@@ (examples doctests) main)' -s "$0" "$@"
+; !#
+
+(define-module (examples doctests)
+              #:export (doctests-testmod))
+
+(import (ice-9 optargs)
+         (ice-9 rdelim)
+         (ice-9 match)
+         (oop goops)
+         (texinfo reflection))
+
+; define basic dir
+(define* (dir #:key (all? #f))
+   (if all?
+      (map (λ (x) (cons (module-name x)
+                        (module-map (λ (sym var) sym) (resolve-interface (module-name x)))))
+           (cons (current-module) (module-uses (current-module))))
+      (module-map (λ (sym var) sym) (current-module))))
+; add support for giving the module as argument
+(define-generic dir)
+(define-method (dir (all? <boolean>)) (dir #:all? all?))
+(define-method (dir (m <list>)) (module-map (λ (sym var) sym) (resolve-interface m)))
+; add support for using modules directly (interfaces are also modules, so this catches both)
+(define-method (dir (m <module>)) (module-map (λ (sym var) sym) m))
+
+(define (string-index s fragment)
+       "return the index of the first character of the FRAGMENT in string S."
+       (let loop ((s s) (i 0))
+           (if (= 0 (string-length s))
+              #f
+              (if (string-prefix? fragment s)
+                 i
+                 (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))
+"
+       (let lp
+           ((str s)
+             (tests (list)))
+           (if (string-null? str)
+              (reverse tests)
+              (let ((idx (string-index str "(test")))
+                  (if (not idx)
+                      (reverse tests)
+                      (let ((sub (substring str idx)))
+                          (lp ; recurse with the rest of the string
+                             (with-input-from-string sub
+                                 (λ () (read) (read-string)))
+                             (cons
+                                 (with-input-from-string sub
+                                     (λ () (read)))
+                                 tests))))))))
+
+(define (doctests-testmod mod)
+       "Execute all doctests in the current module"
+       (let*
+           ((names (module-map (λ (sym var) sym) mod))
+             (filename
+                 (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)))
+                     (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) (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))))))
+
+(define %this-module (current-module))
+(define (main args)
+         (doctests-testmod %this-module))
+
+
+
diff --git a/examples/doctests.w b/examples/doctests.w
--- a/examples/doctests.w
+++ b/examples/doctests.w
@@ -69,10 +69,10 @@ define : doctests-extract-from-string s
 
 define : doctests-testmod mod
        . "Execute all doctests in the current module"
-       let* 
+       let*
            : names : module-map (λ (sym var) sym) mod
              filename
-                 if (module-filename mod) (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)))